/* * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved. * * 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 org.osgi.impl.bundle.bindex.cli; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.net.URL; import java.nio.file.Files; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.jar.Manifest; import org.kohsuke.args4j.CmdLineException; import org.kohsuke.args4j.CmdLineParser; import org.osgi.framework.BundleContext; import org.osgi.framework.launch.Framework; import org.osgi.service.indexer.ResourceAnalyzer; import org.osgi.service.indexer.ResourceIndexer; import org.osgi.service.indexer.impl.KnownBundleAnalyzer; import org.osgi.service.indexer.impl.RepoIndex; import org.osgi.util.tracker.ServiceTracker; import de.kalpatec.pojosr.framework.PojoServiceRegistryFactoryImpl; import de.kalpatec.pojosr.framework.launch.ClasspathScanner; import de.kalpatec.pojosr.framework.launch.PojoServiceRegistryFactory; @SuppressWarnings("restriction") public class Index { /** the program name */ static final String PROGRAM_NAME = "repoindex"; public static final String DEFAULT_FILENAME_UNCOMPRESSED = "index.xml"; public static final String DEFAULT_FILENAME_COMPRESSED = DEFAULT_FILENAME_UNCOMPRESSED + ".gz"; /** * Main entry point. See -help for options. * * @param args Program arguments */ public static void main(String args[]) { try { // Configure PojoSR Map<String,Object> pojoSrConfig = new HashMap<String,Object>(); pojoSrConfig.put(PojoServiceRegistryFactory.BUNDLE_DESCRIPTORS, new ClasspathScanner()); // Start PojoSR 'framework' Framework framework = new PojoServiceRegistryFactoryImpl().newFramework(pojoSrConfig); framework.init(); framework.start(); // Look for indexer and run index generation ServiceTracker<ResourceIndexer,ResourceIndexer> tracker = new ServiceTracker<ResourceIndexer,ResourceIndexer>( framework.getBundleContext(), ResourceIndexer.class, null); tracker.open(); ResourceIndexer index = tracker.waitForService(1000); if (index == null) throw new IllegalStateException("Timed out waiting for ResourceIndexer service."); // Process arguments Set<File> fileList = new LinkedHashSet<File>(); Map<String,String> config = new HashMap<String,String>(); File outputFile = processArgs(args, System.err, config, fileList, framework.getBundleContext()); if (outputFile == null) { System.exit(1); } boolean verbose = Boolean.parseBoolean(config.get(ResourceIndexer.VERBOSE)); if (verbose) { printCopyright(System.err); } try (@SuppressWarnings("null") OutputStream fos = Files.newOutputStream(outputFile.toPath())) { index.index(fileList, fos, config); } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); System.err.println(e.getMessage()); System.exit(1); } // We really need to ensure all non-daemon threads -- which may have // been started by a bundle -- are terminated. System.exit(0); } private static File processArgs(String[] args, PrintStream err, Map<String,String> config, Collection< ? super File> fileList, BundleContext context) throws Exception { /* * Parse the command line */ CommandLineOptions commandLineOptions = new CommandLineOptions(); CmdLineParser parser = new CmdLineParser(commandLineOptions); try { parser.parseArgument(args); } catch (CmdLineException e) { err.printf("Error during command-line parsing: %s%n", e.getLocalizedMessage()); commandLineOptions.help = true; } /* * Process command-line options */ /* print usage when so requested and exit */ if (commandLineOptions.help) { try { /* can't be covered by a test */ int cols = Integer.parseInt(System.getenv("COLUMNS")); //$NON-NLS-1$ if (cols > 80) { parser.setUsageWidth(cols); } } catch (NumberFormatException e) { /* swallow, can't be covered by a test */ } CommandLineOptions.usage(err, PROGRAM_NAME, parser); return null; } KnownBundleAnalyzer knownBundleAnalyzer = null; config.put(ResourceIndexer.REPOSITORY_NAME, commandLineOptions.repositoryName); if (commandLineOptions.stylesheetURL != null) { config.put(ResourceIndexer.STYLESHEET, commandLineOptions.stylesheetURL.toString()); } File output = commandLineOptions.outputFile; if (commandLineOptions.verbose) { config.put(ResourceIndexer.VERBOSE, Boolean.TRUE.toString()); } if (commandLineOptions.rootURL != null) { config.put(ResourceIndexer.ROOT_URL, commandLineOptions.rootURL.toString()); } config.put(ResourceIndexer.URL_TEMPLATE, commandLineOptions.resourceUrlTemplate); if (commandLineOptions.licenseURL != null) { config.put(ResourceIndexer.LICENSE_URL, commandLineOptions.licenseURL.toString()); } if (commandLineOptions.pretty) { config.put(ResourceIndexer.PRETTY, Boolean.TRUE.toString()); } if (commandLineOptions.overrideBuiltinKnownBundles) { knownBundleAnalyzer = new KnownBundleAnalyzer(new Properties()); } File knownBundlesExtraFile = commandLineOptions.knownBundlePropertiesFile; if (commandLineOptions.incrementOverride) { config.put(RepoIndex.REPOSITORY_INCREMENT_OVERRIDE, ""); } if (commandLineOptions.fileList.isEmpty()) { fileList.clear(); } else { for (File file : commandLineOptions.fileList) { fileList.add(new File(file.toURI().normalize().getPath())); } } if (knownBundleAnalyzer == null) knownBundleAnalyzer = new KnownBundleAnalyzer(); if (knownBundlesExtraFile != null) { Properties props = loadPropertiesFile(knownBundlesExtraFile); knownBundleAnalyzer.setKnownBundlesExtra(props); } context.registerService(ResourceAnalyzer.class.getName(), knownBundleAnalyzer, null); return output; } private static Properties loadPropertiesFile(File knownBundles) throws FileNotFoundException, IOException { Properties props = new Properties(); try (InputStream stream = Files.newInputStream(knownBundles.toPath())) { props.load(stream); } return props; } public static void printCopyright(PrintStream out) throws IOException { String version = ""; String copyright = ""; Enumeration<URL> urls = Index.class.getClassLoader().getResources("META-INF/MANIFEST.MF"); while (urls.hasMoreElements()) { URL url = urls.nextElement(); Manifest m = new Manifest(url.openStream()); String bsn = m.getMainAttributes().getValue("Bundle-SymbolicName"); if (bsn != null && bsn.equals("org.osgi.impl.bundle.repoindex.cli")) { version = m.getMainAttributes().getValue("Bundle-Version"); copyright = m.getMainAttributes().getValue("Bundle-Copyright"); break; } } out.println("RepoIndex | Resource Indexer v" + version); out.println(copyright); } }