Package org.emrys.webosgi.launcher.configurator

Source Code of org.emrys.webosgi.launcher.configurator.SimpleConfiguratorImpl

/*******************************************************************************
* Copyright (c) 2007, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.emrys.webosgi.launcher.configurator;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.Manifest;

import org.emrys.webosgi.launcher.configurator.utils.EquinoxUtils;
import org.emrys.webosgi.launcher.configurator.utils.SimpleConfiguratorConstants;
import org.emrys.webosgi.launcher.configurator.utils.SimpleConfiguratorUtils;
import org.emrys.webosgi.launcher.configurator.utils.Utils;
import org.ops4j.pax.url.war.ServiceConstants;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

import aQute.lib.osgi.Analyzer;
import aQute.lib.osgi.Jar;
import aQute.libg.version.Version;

/*
* SimpleConfigurator provides ways to install bundles listed in a file
* accessible by the specified URL and expect states for it in advance without
* actual application.
* In every methods of SimpleConfiguration object,
* 1. A value will be gotten by @{link BundleContext#getProperty(key) with
* {@link SimpleConfiguratorConstants#PROP_KEY_EXCLUSIVE_INSTALLATION} as a key.
* 2. If it equals "true", it will do exclusive installation, which means that
* the bundles will not be listed in the specified url but installed at the time
* of the method call except SystemBundle will be uninstalled. Otherwise, no
* uninstallation will not be done.
*/
public class SimpleConfiguratorImpl implements Configurator {

  private static URL configurationURL = null;
  private static Object configurationLock = new Object();

  private final BundleContext context;
  private ConfigApplier configApplier;
  private final Bundle bundle;

  public SimpleConfiguratorImpl(BundleContext context, Bundle bundle) {
    this.context = context;
    this.bundle = bundle;
  }

  private URL getConfigurationURL() throws IOException {
    String specifiedURL = context
        .getProperty(SimpleConfiguratorConstants.PROP_KEY_CONFIGURL);
    if (specifiedURL == null)
      specifiedURL = "file:"
          + SimpleConfiguratorConstants.CONFIGURATOR_FOLDER + "/"
          + SimpleConfiguratorConstants.CONFIG_LIST;

    try {
      // If it is not a file URL use it as is
      if (!specifiedURL.startsWith("file:"))
        return new URL(specifiedURL);
    } catch (MalformedURLException e) {
      return null;
    }

    try {
      // if it is an absolute file URL, use it as is
      boolean done = false;
      URL url = null;
      String file = specifiedURL;
      while (!done) {
        // TODO what is this while loop for? nested file:file:file:
        // urls?
        try {
          url = Utils.buildURL(file);
          file = url.getFile();
        } catch (java.net.MalformedURLException e) {
          done = true;
        }
      }
      if (url != null && new File(url.getFile()).isAbsolute())
        return url;

      // if it is an relative file URL, then resolve it against the
      // configuration area
      // TODO Support relative file URLs when not on Equinox
      URL[] configURL = EquinoxUtils.getConfigAreaURL(context);
      if (configURL != null) {
        File userConfig = new File(configURL[0].getFile(), url
            .getFile());
        if (configURL.length == 1)
          return userConfig.exists() ? userConfig.toURL() : null;

        File sharedConfig = new File(configURL[1].getFile(), url
            .getFile());
        if (!userConfig.exists())
          return sharedConfig.exists() ? sharedConfig.toURL() : null;

        if (!sharedConfig.exists())
          return userConfig.toURL();

        URI base = EquinoxUtils.getInstallLocationURI(context);

        URL sharedConfigURL = sharedConfig.toURL();
        List sharedBundles = SimpleConfiguratorUtils.readConfiguration(
            sharedConfigURL, base);

        URL userConfigURL = userConfig.toURL();
        List userBundles = SimpleConfiguratorUtils.readConfiguration(
            userConfigURL, base);

        return (userBundles.containsAll(sharedBundles)) ? userConfigURL
            : sharedConfigURL;
      }
    } catch (MalformedURLException e) {
      return null;
    }

    // Last resort
    try {
      return Utils.buildURL(specifiedURL);
    } catch (MalformedURLException e) {
      // Ignore
    }

    return null;
  }

  public void applyConfiguration(URL url, boolean excludeInstall)
      throws IOException {
    synchronized (configurationLock) {
      if (url == null)
        return;
      configurationURL = url;

      if (this.configApplier == null)
        configApplier = new ConfigApplier(context, bundle);
      configApplier.install(url, excludeInstall);
    }
  }

  public void applyConfiguration(URL url) throws IOException {
    applyConfiguration(url, isExclusiveInstallation());
  }

  private boolean isExclusiveInstallation() {
    String value = context
        .getProperty(SimpleConfiguratorConstants.PROP_KEY_EXCLUSIVE_INSTALLATION);
    if (value == null || value.trim().length() == 0)
      value = "true";
    return Boolean.valueOf(value).booleanValue();
  }

  public void applyConfiguration() throws IOException {
    synchronized (configurationLock) {
      configurationURL = getConfigurationURL();
      // if configured url is null, indicating this invoke is install wab
      // apps later. Do not use exclude install mode.
      boolean laterInstallWebapps = configurationURL == null;
      // Scan plugins/ directory and append all plugins at the head of the
      // configuration file.
      configurationURL = appendScanedPlugins(configurationURL);
      applyConfiguration(configurationURL, !laterInstallWebapps);
    }
  }

  private URL appendScanedPlugins(URL configurationURL) throws IOException {
    URI base = EquinoxUtils.getInstallLocationURI(context);
    File newCfgFile = File.createTempFile("bundles", ".info");
    PrintWriter printer = new PrintWriter(newCfgFile, "UTF-8");

    try {
      List<String> bundleSymbleNames = new ArrayList<String>();
      // If the bundles information URL not given, the framework is
      // embedded from a OSGi runtime, and we only need to scan web
      // bundles from WebApps dir.
      if (configurationURL != null) {
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(configurationURL.openStream(),
                "UTF-8"));
        try {
          String line = null;
          while ((line = reader.readLine()) != null) {
            if (!line.trim().startsWith("#")) {
              String[] segs = line.split(",");
              if (segs.length > 2)
                bundleSymbleNames.add(segs[0] + "," + segs[1]);
            }
            printer.println(line);
          }
        } finally {
          reader.close();
        }

        // Scan the default plugins root. /plugins
        scanPlugins(base, "plugins", bundleSymbleNames, printer);
        scanPlugins(base, "deploy", bundleSymbleNames, printer);
      }
      // Scan for .war web application.
      scanWebApps(base, "webapps", bundleSymbleNames, printer);
      printer.flush();
    } finally {

      printer.flush();
      printer.close();
    }
    return newCfgFile.toURI().toURL();
  }

  private void scanWebApps(URI base, String path,
      List<String> bundleSymbolNames, PrintWriter printer)
      throws MalformedURLException, UnsupportedEncodingException {
    URL baseFileURL = new URL(URLDecoder.decode(base.toURL()
        .toExternalForm(), "UTF-8"));
    File fwkInstallDir = new File(baseFileURL.getFile());
    File webAppsDir = new File(fwkInstallDir, path);
    if (!webAppsDir.exists())
      return;

    File[] webAppFiles = webAppsDir.listFiles();
    for (File f : webAppFiles) {
      // Unlike bundle file, the symbolic name and version should be
      // parsed from its MANISFEST.MF file at first.
      String symbolName = null;
      String version = "0.0.0";

      try {
        Jar jar = new Jar(f);
        Manifest manifest = jar.getManifest();
        symbolName = manifest.getMainAttributes().getValue(
            Analyzer.BUNDLE_SYMBOLICNAME);
        version = manifest.getMainAttributes().getValue(
            Analyzer.BUNDLE_VERSION);
        version = new Version(version).toString();
      } catch (Exception e) {
        // e.printStackTrace();
        symbolName = null;
        version = "0.0.0";
      }

      if (symbolName == null || symbolName.length() == 0) {
        String name = f.getName();
        if (f.isFile()) {
          int index = name.lastIndexOf('.');
          if (index > -1 && index > 0)
            name = name.substring(0, index);
        }
        // Use war's file name as wab symblic name.
        symbolName = f.getName();
        symbolName = symbolName.replaceAll("[^a-zA-Z_0-9.-]", "_")
            .replaceAll("(^|\\.)(\\d+)", "$1_$2");
        int index = name.indexOf("_");
        if (index > -1 && index != name.length() - 1) {
          version = name.substring(index + 1);
        }
      }

      // If the bundle with the same symble name and version was
      // configured in specified bundles.info file, skip it.
      if (bundleSymbolNames.contains(symbolName + "," + version))
        continue;
      bundleSymbolNames.add(symbolName + "," + version);

      StringBuffer sb = new StringBuffer();
      sb.append(symbolName);
      sb.append(",");
      sb.append(version);
      sb.append(",");
      sb.append(ServiceConstants.PROTOCOL_WEB_BUNDLE + ":"
          + URLDecoder.decode(f.toURI().toURL().toString(), "UTF-8"));
      sb.append(",");
      sb.append(4);
      sb.append(",");
      sb.append("false");

      printer.println(sb.toString());
    }
  }

  private void scanPlugins(URI base, String path,
      List<String> bundleSymbleNames, PrintWriter printer)
      throws MalformedURLException, UnsupportedEncodingException {
    URL baseFileURL = new URL(URLDecoder.decode(base.toURL()
        .toExternalForm(), "UTF-8"));
    File fwkInstallDir = new File(baseFileURL.getFile());
    File pluginsDir = new File(fwkInstallDir, path);
    if (!pluginsDir.exists())
      return;

    File[] pluginFiles = pluginsDir.listFiles();
    for (File f : pluginFiles) {
      String name = f.getName();
      if (f.isFile()) {
        int index = name.lastIndexOf('.');
        if (index > -1 && index > 0)
          name = name.substring(0, index);
      }

      String symbleName = name;
      String version = "0.0.0";
      int index = name.indexOf("_");
      if (index > -1 && index != name.length() - 1) {
        symbleName = name.substring(0, index);
        version = name.substring(index + 1);
      }
      // If the bundle with the same symble name and version was
      // configured in specified bundles.info file, skip it.
      if (bundleSymbleNames.contains(symbleName + "," + version))
        continue;
      bundleSymbleNames.add(symbleName + "," + version);

      StringBuffer sb = new StringBuffer();
      sb.append(symbleName);
      sb.append(",");
      sb.append(version);
      sb.append(",");
      sb.append(path + "/" + f.getName());
      sb.append(",");
      sb.append(4);
      sb.append(",");
      sb.append("false");

      printer.println(sb.toString());
    }
  }

  public URL getUrlInUse() {
    synchronized (configurationLock) {
      return configurationURL;
    }
  }
}
TOP

Related Classes of org.emrys.webosgi.launcher.configurator.SimpleConfiguratorImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.