/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.aries.application.repository.generator; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Method; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import org.apache.aries.application.management.spi.repository.RepositoryGenerator; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.Constants; import org.osgi.framework.Filter; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.framework.launch.Framework; import org.osgi.framework.launch.FrameworkFactory; import org.osgi.service.packageadmin.PackageAdmin; import org.osgi.util.tracker.ServiceTracker; public class AriesRepositoryGenerator { private Framework framework = null; private List<String> ignoreList = new ArrayList<String>(); private List<ServiceTracker> srs = new ArrayList<ServiceTracker>(); public static final long DEFAULT_TIMEOUT = 60000; public static final String ERROR_LEVEL = "ERROR"; public static final String DEFAULT_REPO_NAME="repository.xml"; /** * Start OSGi framework and install the necessary bundles * @return * @throws BundleException */ public BundleContext startFramework() throws BundleException{ ServiceLoader<FrameworkFactory> factoryLoader = ServiceLoader.load(FrameworkFactory.class, getClass().getClassLoader()); Iterator<FrameworkFactory> factoryIterator = factoryLoader.iterator(); //Map<String, String> osgiPropertyMap = new HashMap<String, String>(); if (!!!factoryIterator.hasNext()) { System.out.println( "Unable to locate the osgi jar"); } try { FrameworkFactory frameworkFactory = factoryIterator.next(); framework = frameworkFactory.newFramework(Collections.EMPTY_MAP); } catch (ServiceConfigurationError sce) { sce.printStackTrace(); } framework.init(); framework.start(); // install the bundles in the current directory Collection<Bundle> installedBundles = new ArrayList<Bundle>(); File bundleDir = new File("."); File[] jars = bundleDir.listFiles(); try { for (File jar : jars) { if (jar.isFile() && (jar.getName().endsWith(".jar"))) { String location = URLDecoder.decode(jar.toURI().toURL().toExternalForm(), "UTF-8"); if (shouldInstall(location, getIgnoreList())) { installedBundles.add(framework.getBundleContext().installBundle( "reference:" + location)); } } } } catch (Exception e) { e.printStackTrace(); } ServiceReference paRef = framework.getBundleContext().getServiceReference(PackageAdmin.class.getCanonicalName()); if (paRef != null) { try { PackageAdmin admin = (PackageAdmin) framework.getBundleContext().getService(paRef); admin.resolveBundles(installedBundles.toArray(new Bundle[installedBundles.size()])); } finally { framework.getBundleContext().ungetService(paRef); } } else { System.out.println("Unable to find the service reference for package admin"); } //start the bundles //loop through the list of installed bundles to start them for (Bundle bundle : installedBundles) { try { if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) == null) { //start the bundle using its activiation policy bundle.start(Bundle.START_ACTIVATION_POLICY); } else { //nothing to start, we have got a fragment } } catch (BundleException e) { e.printStackTrace(); continue; } } return framework.getBundleContext(); } private void stopFramework() throws Exception{ for (ServiceTracker st : srs) { if (st != null) { st.close(); } } if (framework != null) { framework.stop(); } } private Object getOsgiService(BundleContext bc, String className) { ServiceTracker tracker = null; try { String flt = "(" + Constants.OBJECTCLASS + "=" + className + ")"; Filter osgiFilter = FrameworkUtil.createFilter(flt); tracker = new ServiceTracker(bc, osgiFilter, null); tracker.open(); // add tracker to the list of trackers we close at tear down srs.add(tracker); Object x = tracker.waitForService(DEFAULT_TIMEOUT); if (x == null) { throw new RuntimeException("Gave up waiting for service " + flt); } return x; } catch (InvalidSyntaxException e) { throw new IllegalArgumentException("Invalid filter", e); } catch (InterruptedException e) { throw new RuntimeException(e); } } public static void usage() { System.out.println("Invalid parameter specifed. See program usage below."); System.out.println("========================= Usage ==============================="); System.out.println("Parameter list: [Reporsitory File Location] url1 [url2 url3 ...]"); System.out.println(); System.out.println("The parameter of the repository file location is the location for the genenerated reporsitory xml, e.g. /test/rep/repo.xml. It must end with .xml. If the parameter is not present, it will generate a repository.xml in the current directory."); System.out.println(); System.out.println("The paremater of url1 [url2 url 3 ...] is a list of urls. If the url starts with file:, it can be a directory, which means all jar or war files in that directory to be included in the reposiotry."); System.out.println("==============================================================="); } /** * Execute this program using * java -jar thisbundlename arg0 arg1... * arg0 can be the location of the repository xml or a url * arg1... a list of url. If there is a file url, all jar/wars under the url are to be included. * e.g. file:///c:/temp/, all jars/wars under temp or its subdirectory are to be included. * @param args */ public static void main(String[] args) { String[] urlArray = args; if (args.length == 0){ usage(); System.exit(0); } else { AriesRepositoryGenerator generator = new AriesRepositoryGenerator(); // set the system property for logging if not set in the command line String loggerLevelProp = "org.ops4j.pax.logging.DefaultServiceLog.level"; if (System.getProperty(loggerLevelProp) == null) { System.setProperty(loggerLevelProp, ERROR_LEVEL); } FileOutputStream fout = null; try { BundleContext ctx = generator.startFramework(); // get the object of repositoryGenerator and call its method File xmlFile = new File(DEFAULT_REPO_NAME); if (args[0].endsWith(".xml")) { xmlFile = new File(args[0]); // get the directors File parentDir = xmlFile.getAbsoluteFile().getParentFile(); if (!!!parentDir.exists()) { parentDir.mkdirs(); } // put the rest of the args to the list of urls if (args.length >1) { urlArray = Arrays.copyOfRange(args, 1, args.length); } else { usage(); System.exit(0); } } // Use reflection to get around the class loading issue fout = new FileOutputStream(xmlFile); Object repoGen = generator.getOsgiService(ctx, RepositoryGenerator.class.getName()); Class gen= repoGen.getClass(); Method m = gen.getDeclaredMethod("generateRepository", new Class[]{String[].class, OutputStream.class}); m.invoke(repoGen, urlArray, fout); generator.stopFramework(); System.out.println("The reporsitory xml was generated successfully under " + xmlFile.getAbsolutePath() + "."); } catch (Exception e) { e.printStackTrace(); System.exit(0); } finally { try { if (fout != null) fout.close(); } catch (IOException e) { fout = null; } } } } /** * Return whether to install the specified bundle * @param location bundle location * @param ignoreList the ignore list containing the bundles to be ignored * @return */ private boolean shouldInstall(String location, List<String> ignoreList) { String name = location.substring(location.lastIndexOf('/') + 1); //check that it isn't one of the files we should ignore boolean inIgnoreList = false; for (String prefix : ignoreList) { //we check for _ in case of version and .jar in case of a prefix.*.jar we should allow if (name.startsWith(prefix + "-") || name.startsWith(prefix + ".jar")) { inIgnoreList = true; break; } } return !!!inIgnoreList; } private List<String> getIgnoreList() { ignoreList.add("osgi"); ignoreList.add("org.apache.aries.application.obr.generator"); return ignoreList; } }