/* * Copyright (C) 2012 Brockmann Consult GmbH (info@brockmann-consult.de) * * 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/ */ package com.bc.ceres.core.runtime.internal; import com.bc.ceres.core.CoreException; import com.bc.ceres.core.runtime.ProxyConfig; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.text.MessageFormat; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import static com.bc.ceres.core.runtime.Constants.MODULE_MANIFEST_NAME; public class ModuleReader { private Logger logger; public static final String[] NO_LIBS = new String[0]; public ModuleReader(Logger logger) { this.logger = logger; } public ModuleImpl readFromLocation(File locationFile) throws CoreException { final ModuleImpl module; if (locationFile.isDirectory()) { module = readFromManifest(new File(locationFile, MODULE_MANIFEST_NAME)); } else { try { ZipFile zipFile = new ZipFile(locationFile); try { ZipEntry entry = zipFile.getEntry(MODULE_MANIFEST_NAME); if (entry == null) { throw new CoreException( String.format("Manifest [%s] not found in [%s]", MODULE_MANIFEST_NAME, locationFile.getName())); } InputStream inputStream = zipFile.getInputStream(entry); module = readFromManifest(inputStream); } finally { zipFile.close(); } } catch (IOException e) { throw new CoreException( String.format("Failed to read manifest [%s] from [%s]", MODULE_MANIFEST_NAME, locationFile.getName()), e); } } initModule(module, UrlHelper.fileToUrl(locationFile), locationFile); return module; } public ModuleImpl readFromLocation(URL locationUrl) throws CoreException { final URL manifestUrl = UrlHelper.locationToManifestUrl(locationUrl); if (manifestUrl == null) { throw new CoreException("Not a module URL: [" + locationUrl + "]"); } final ModuleImpl module = readFromManifest(manifestUrl, ProxyConfig.NULL); initModule(module, locationUrl, UrlHelper.urlToFile(locationUrl)); return module; } public ModuleImpl readFromManifest(InputStream inputStream) throws CoreException { // Note: inputStream is closed in readFromXML return new ModuleManifestParser().parse(inputStream); } public ModuleImpl readFromManifest(File manifestFile) throws CoreException { try { final Reader reader = new FileReader(manifestFile); // Note: reader is closed in readFromXML return new ModuleManifestParser().parse(reader); } catch (FileNotFoundException e) { throw new CoreException("Module manifest [" + manifestFile + "] not found", e); } } public ModuleImpl readFromManifest(URL manifestUrl, ProxyConfig proxyConfig) throws CoreException { try { final URLConnection urlConnection = UrlHelper.openConnection(manifestUrl, proxyConfig, "GET"); final InputStream stream = urlConnection.getInputStream(); // Note: stream is closed in readFromXML return new ModuleManifestParser().parse(stream); } catch (IOException e) { throw new CoreException("Failed to read module manifest from [" + manifestUrl + "]", e); } } private void initModule(ModuleImpl module, URL locationUrl, File locationFile) { module.setLocation(locationUrl); module.setImpliciteLibs(NO_LIBS); module.setImpliciteNativeLibs(NO_LIBS); if (locationFile != null) { module.setContentLength(locationFile.length()); module.setLastModified(locationFile.lastModified()); if (locationFile.isDirectory()) { File implicitLibDir = new File(locationFile, "lib"); if (implicitLibDir.exists() && implicitLibDir.isDirectory()) { String[] libs = scanImpliciteLibs(implicitLibDir); for (int i = 0; i < libs.length; i++) { libs[i] = "lib/" + libs[i]; } module.setImpliciteLibs(libs); } if (module.isNative()) { String[] nativeLibs = scanImpliciteNativeLibs(locationFile); module.setImpliciteNativeLibs(nativeLibs); } } } logger.info(MessageFormat.format("Module [{0}] read from [{1}].", module.getSymbolicName(), module.getLocation())); } private static String[] scanImpliciteLibs(File dir) { return new DirScanner(dir, true, true).scan(new JarFilenameFilter()); } private static String[] scanImpliciteNativeLibs(File dir) { // todo - see FileHelper for similar OS dependent construct --> try to generyfy this in a class 'OS' FilenameFilter ff; String osNameLC = System.getProperty("os.name", "").toLowerCase(); if (osNameLC.contains("windows")) { ff = new FilenameFilter() { public boolean accept(File dir, String name) { return name.toLowerCase().endsWith(".dll"); } }; } else if (osNameLC.contains("mac os x")) { ff = new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".jnilib") || name.endsWith(".dylib"); } }; } else { ff = new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".so"); } }; } // first search for native libraries in architecture specific directories Platform currentPlatform = Platform.getCurrentPlatform(); if (currentPlatform != null) { String platformPath = Platform.getSourcePathPrefix(currentPlatform.getId(), currentPlatform.getBitCount()); File platformDir = new File(dir, platformPath); if (platformDir.exists() && platformDir.isDirectory()) { String[] result = new DirScanner(platformDir, true, true).scan(ff); if (result.length > 0) { String[] fullResult = new String[result.length]; for (int i = 0; i < fullResult.length; i++) { fullResult[i] = platformPath + "/" + result[i]; } return fullResult; } } } return new DirScanner(dir, true, true).scan(ff); } }