/** * Checks whether the dependencies among the given Packs. Specifically it checks that no pack * point to a non existent pack and also that there are no circular dependencies in the packs. * * @param packs - List<Pack> representing the packs in the installation */ public void checkDependencies(List packs) throws CompilerException { // Because we use package names in the configuration file we assosiate // the names with the objects Map names = new HashMap(); for (int i = 0; i < packs.size(); i++) { PackInfo pack = (PackInfo) packs.get(i); names.put(pack.getPack().name, pack); } int result = dfs(packs, names); // @todo More informative messages to include the source of the error if (result == -2) parseError("Circular dependency detected"); else if (result == -1) parseError("A dependency doesn't exist"); }
/** * Look for an IzPack resource either in the compiler jar, or within IZPACK_HOME. The path must * not be absolute. The path must use '/' as the fileSeparator (it's used to access the jar file). * If the resource is not found, a CompilerException is thrown indicating fault in the parent * element. * * @param path the relative path (using '/' as separator) to the resource. * @param desc the description of the resource used to report errors * @return a URL to the resource. */ public URL findIzPackResource(String path, String desc) throws CompilerException { URL url = getClass().getResource("/" + path); if (url == null) { File resource = new File(path); if (!resource.isAbsolute()) resource = new File(IZPACK_HOME, path); if (!resource.exists()) // fatal parseError(desc + " not found: " + resource); try { url = resource.toURL(); } catch (MalformedURLException how) { parseError(desc + "(" + resource + ")", how); } } return url; }
/** * Returns a newly created instance of the output stream which should be used by this pack * compressor. This method do not declare the return value as FilterOutputStream although there * must be an constructor with a slave output stream as argument. This is done in this way because * some encoding streams from third party are only implemented as "normal" output stream. * * @param slave output stream to be used as slave * @return a newly created instance of the output stream which should be used by this pack * compressor * @throws Exception */ protected OutputStream getOutputInstance(OutputStream slave) throws Exception { if (needsBufferedOutputStream()) { slave = new BufferedOutputStream(slave); } Object[] params = resolveConstructorParams(slave); if (constructor == null) { loadClass(getEncoderClassName()); } if (constructor == null) { return (null); } Object instance = null; instance = constructor.newInstance(params); if (!OutputStream.class.isInstance(instance)) { compiler.parseError( "'" + getEncoderClassName() + "' must be derived from " + OutputStream.class.toString()); } return ((OutputStream) instance); }
/** * Loads the given class from the previos setted container paths. * * @param className full qualified name of the class to be loaded * @throws Exception */ public void loadClass(String className) throws Exception { if (getEncoderClassName() == null) { return; } Class<Object> encoder = null; if (getContainerPaths() == null) { // May be class files are in the compiler.jar. encoder = (Class<Object>) Class.forName(className); } if (encoder == null) { String[] rawPaths = getContainerPaths(); URL[] uRLs = new URL[rawPaths.length]; Object instance = null; int i; int j = 0; for (i = 0; i < rawPaths.length; ++i) { if (rawPaths[i] == null) { continue; } String jarPath = compiler.replaceProperties(rawPaths[i]); URL url = compiler.findIzPackResource(jarPath, "Pack compressor jar file"); if (url != null) { uRLs[j++] = url; if (getClass().getResource("/" + jarPath) != null) { // Oops, standalone, URLClassLoader will not work ... // Write the jar to a temp file. InputStream in = null; FileOutputStream outFile = null; byte[] buffer = new byte[5120]; File tf = null; try { tf = File.createTempFile("izpj", ".jar"); tf.deleteOnExit(); outFile = new FileOutputStream(tf); in = getClass().getResourceAsStream("/" + jarPath); long bytesCopied = 0; int bytesInBuffer; while ((bytesInBuffer = in.read(buffer)) != -1) { outFile.write(buffer, 0, bytesInBuffer); bytesCopied += bytesInBuffer; } } finally { if (in != null) { in.close(); } if (outFile != null) { outFile.close(); } } url = tf.toURL(); } } } if (j > 0) { if (j < uRLs.length) { URL[] nurl = new URL[j]; for (i = 0; i < j; ++i) { nurl[i] = uRLs[i]; } uRLs = nurl; } // Use the class loader of the interface as parent, else // compile will fail at using it via an Ant task. URLClassLoader ucl = new URLClassLoader(uRLs, PackCompressor.class.getClassLoader()); encoder = (Class<Object>) ucl.loadClass(className); } } if (encoder != null) { // Be aware, paramsClasses should be defined earlier! For // default in the constructor of this class. constructor = encoder.getDeclaredConstructor(paramsClasses); } else { compiler.parseError("Cannot find defined compressor " + className); } }