示例#1
0
 final ImmutableList<Type> usedInGenericType(Type[] types) {
   ImmutableList.Builder<Type> builder = ImmutableList.builder();
   for (Type type : types) {
     builder.add(usedInGenericType(type));
   }
   return builder.build();
 }
示例#2
0
/** Singleton Wrapper around OSGi module loading and unloading operations. */
public class ModuleManager {

  /*
   * Note for developers: please keep list in alpha-numerical order
   */
  static final List<String> SYSTEM_PACKAGES =
      ImmutableList.<String>builder()
          .add("com.google_voltpatches.common.base;")
          .add("com.google_voltpatches.common.collect;")
          .add("com.google_voltpatches.common.io;")
          .add("com.google_voltpatches.common.net;")
          .add("com.google_voltpatches.common.util.concurrent;")
          .add("jsr166y;")
          .add("org.apache.log4j;")
          .add("org.slf4j;")
          .add("org.voltcore.network;")
          .add("org.voltcore.logging;")
          .add("org.voltcore.utils;")
          .add("org.voltdb;include:=\"VoltType\",")
          .add("org.voltdb.client;")
          .add("org.voltdb.common;exclude=\"Permission\",")
          .add("org.voltdb.importer;")
          .add("org.voltdb.importer.formatter;")
          .add("org.voltdb.types;")
          .build();

  private static final VoltLogger LOG = new VoltLogger("HOST");

  private static final Joiner COMMA_JOINER = Joiner.on(",").skipNulls();

  private static final AtomicReference<File> CACHE_ROOT = new AtomicReference<>();

  private static ModuleManager m_self = null;

  public static void initializeCacheRoot(File cacheRoot) {
    if (CACHE_ROOT.compareAndSet(null, checkNotNull(cacheRoot))) {
      if (!cacheRoot.exists() && !cacheRoot.mkdirs()) {
        throw new SetUpException(
            "Failed to create required OSGI cache directory: " + cacheRoot.getAbsolutePath());
      }
      if (!cacheRoot.isDirectory()
          || !cacheRoot.canRead()
          || !cacheRoot.canWrite()
          || !cacheRoot.canExecute()) {
        throw new SetUpException(
            "Cannot access OSGI cache directory: " + cacheRoot.getAbsolutePath());
      }
      m_self = new ModuleManager(cacheRoot);
    }
  }

  public static void resetCacheRoot() {
    File cacheRoot = CACHE_ROOT.get();
    if (cacheRoot != null && CACHE_ROOT.compareAndSet(cacheRoot, null)) {
      m_self = null;
    }
  }

  private static final Function<String, String> appendVersion =
      new Function<String, String>() {
        @Override
        public String apply(String input) {
          return input + "version=1.0.0";
        }
      };

  public static ModuleManager instance() {
    return m_self;
  }

  static ModularException loggedModularException(Throwable e, String msg, Object... args) {
    ModularException.isCauseFor(e)
        .map(
            me -> {
              throw me;
            });
    LOG.error(String.format(msg, args), e);
    return new ModularException(msg, e, args);
  }

  public static URI bundleURI(File fl) {
    return fl.toPath().toUri();
  }

  private final Framework m_framework;
  private final BundleRef m_bundles;

  private ModuleManager(File cacheRoot) {

    String systemPackagesSpec =
        FluentIterable.from(SYSTEM_PACKAGES).transform(appendVersion).join(COMMA_JOINER);

    Map<String, String> frameworkProps =
        ImmutableMap.<String, String>builder()
            .put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, systemPackagesSpec)
            .put("org.osgi.framework.storage.clean", "onFirstInit")
            .put("felix.cache.rootdir", cacheRoot.getAbsolutePath())
            .put("felix.cache.locking", Boolean.FALSE.toString())
            .build();

    LOG.info("Framework properties are: " + frameworkProps);

    FrameworkFactory frameworkFactory =
        ServiceLoader.load(FrameworkFactory.class).iterator().next();

    m_framework = frameworkFactory.newFramework(frameworkProps);

    try {
      m_framework.start();
    } catch (BundleException e) {
      LOG.error("Failed to start the felix OSGi framework", e);
      throw new SetUpException("Failed to start the felix OSGi framework", e);
    }

    m_bundles = new BundleRef(m_framework);
  }

  /**
   * Gets the service from the given bundle jar uri. Loads and starts the bundle if it isn't yet
   * loaded
   *
   * @param bundleURI bundle jar URI
   * @param svcClazz the service class exposed by the bundle jar
   * @return a reference to an instance of the service class
   */
  public <T> T getService(URI bundleURI, Class<T> svcClazz) {
    return m_bundles.getService(bundleURI, svcClazz);
  }

  public void unload(URI bundleURI) {
    m_bundles.stopBundle(bundleURI);
  }

  public void unload(Set<URI> uris) {
    m_bundles.stopBundles(uris);
  }

  public void uninstall(URI bundleURI) {
    m_bundles.uninstallBundle(bundleURI);
  }

  public void uninstall(Set<URI> uris) {
    m_bundles.uninstallBundles(uris);
  }

  public static class SetUpException extends RuntimeException {

    private static final long serialVersionUID = 8197183357774453653L;

    public SetUpException() {}

    public SetUpException(String message, Throwable cause) {
      super(message, cause);
    }

    public SetUpException(String message) {
      super(message);
    }

    public SetUpException(Throwable cause) {
      super(cause);
    }
  }

  static class BundleRef extends AtomicReference<NavigableMap<URI, Bundle>> {

    private static final long serialVersionUID = -3691039780541403034L;
    static NavigableMap<URI, Bundle> EMPTY_MAP = ImmutableSortedMap.of();

    final Framework m_framework;

    public BundleRef(Framework framework, NavigableMap<URI, Bundle> initialRef) {
      super(initialRef);
      m_framework = framework;
    }

    public BundleRef(Framework framework) {
      this(framework, EMPTY_MAP);
    }

    private Bundle startBundle(URI bundleURI) {
      NavigableMap<URI, Bundle> expect, update;
      Bundle bundle = null;
      do {
        expect = get();
        if (expect.containsKey(bundleURI)) break;

        BundleContext ctx = m_framework.getBundleContext();
        bundle = ctx.getBundle(bundleURI.toASCIIString());
        if (bundle != null) {
          try {
            bundle.update();
          } catch (BundleException e) {
            String msg = e.getMessage();
            throw loggedModularException(e, "Unable to update bundle %s. %s", bundleURI, msg);
          } catch (Throwable t) {
            throw loggedModularException(t, "Unable to update bundle %s", bundleURI);
          }
        } else {
          try {
            bundle = ctx.installBundle(bundleURI.toASCIIString());
          } catch (BundleException e) {
            String msg = e.getMessage();
            throw loggedModularException(e, "Unable to install bundle %s. %s", bundleURI, msg);
          } catch (Throwable t) {
            throw loggedModularException(t, "Unable to instal bundle %s", bundleURI);
          }
        }
        try {
          bundle.start();
        } catch (BundleException e) {
          String msg = e.getMessage();
          throw loggedModularException(e, "Unable to start bundle %s. %s", bundleURI, msg);
        } catch (Throwable t) {
          throw loggedModularException(t, "Unable to start bundle %s", bundleURI);
        }

        update =
            ImmutableSortedMap.<URI, Bundle>naturalOrder()
                .putAll(expect)
                .put(bundleURI, bundle)
                .build();
      } while (!compareAndSet(expect, update));

      return get().get(bundleURI);
    }

    <T> T getService(URI bundleURI, Class<T> svcClazz) {
      Bundle bundle = get().get(bundleURI);
      if (bundle == null) {
        synchronized (this) {
          bundle = startBundle(bundleURI);
        }
      }
      BundleContext ctx = bundle.getBundleContext();
      for (ServiceReference<?> ref : bundle.getRegisteredServices()) {
        if (ref.isAssignableTo(bundle, svcClazz.getName())) {
          return svcClazz.cast(ctx.getService(ref));
        }
      }
      return null;
    }

    Optional<Bundle> stopBundle(URI bundleURI) {
      NavigableMap<URI, Bundle> expect, update;
      do {
        expect = get();
        update =
            ImmutableSortedMap.<URI, Bundle>naturalOrder()
                .putAll(Maps.filterKeys(expect, not(equalTo(bundleURI))))
                .build();
      } while (expect.containsKey(bundleURI) && !compareAndSet(expect, update));

      Bundle bundle = expect.get(bundleURI);
      if (bundle != null) {
        try {
          bundle.stop();
        } catch (BundleException e) {
          throw loggedModularException(e, "Failed to stop bundle %s", bundleURI);
        }
      }
      return Optional.ofNullable(bundle);
    }

    void uninstallBundle(URI bundleURI) {
      stopBundle(bundleURI)
          .ifPresent(
              (Bundle b) -> {
                try {
                  b.uninstall();
                } catch (Throwable t) {
                  throw loggedModularException(t, "Failed to uninstall %s", b.getLocation());
                }
              });
    }

    NavigableMap<URI, Bundle> stopBundles(Set<URI> bundles) {
      NavigableMap<URI, Bundle> expect, update;
      do {
        expect = get();
        update =
            ImmutableSortedMap.<URI, Bundle>naturalOrder()
                .putAll(Maps.filterKeys(expect, not(in(bundles))))
                .build();
      } while (!compareAndSet(expect, update));

      List<URI> couldNotStop = new ArrayList<>();
      NavigableMap<URI, Bundle> stopped = Maps.filterKeys(expect, in(bundles));
      for (Map.Entry<URI, Bundle> e : stopped.entrySet()) {
        URI bundleURI = e.getKey();
        Bundle bundle = e.getValue();
        try {
          bundle.stop();
        } catch (BundleException exc) {
          LOG.error("Failed to stop bundle " + bundleURI, exc);
          couldNotStop.add(bundleURI);
        }
      }
      if (!couldNotStop.isEmpty()) {
        throw new ModularException("Failed to stop bundles %s", couldNotStop);
      }
      return stopped;
    }

    void uninstallBundles(Set<URI> bundles) {
      List<URI> couldNotUninstall = new ArrayList<>();
      for (Map.Entry<URI, Bundle> e : stopBundles(bundles).entrySet()) {
        URI bundleURI = e.getKey();
        Bundle bundle = e.getValue();
        try {
          bundle.uninstall();
        } catch (BundleException exc) {
          LOG.error("Failed to uninstall bundle " + bundleURI, exc);
          couldNotUninstall.add(bundleURI);
        }
        if (!couldNotUninstall.isEmpty()) {
          throw new ModularException("Failed to uninstall bundles %s", couldNotUninstall);
        }
      }
    }
  }

  public static final <T> Predicate<T> in(final Set<T> set) {
    return new Predicate<T>() {
      @Override
      public boolean apply(T m) {
        return set.contains(m);
      }
    };
  }
}