PageRenderTime 5394ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

/peaberry/src/main/java/org/ops4j/peaberry/osgi/Activator.java

https://github.com/sonatype/sonatype-peaberry
Java | 157 lines | 94 code | 27 blank | 36 comment | 7 complexity | 0963c9d9fef2821b047a401670f5610f MD5 | raw file
  1. /**
  2. * Copyright (C) 2008 Stuart McCulloch
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.ops4j.peaberry.osgi;
  17. import static com.google.inject.name.Names.named;
  18. import static java.lang.Math.max;
  19. import static org.ops4j.peaberry.Peaberry.CACHE_GENERATIONS_HINT;
  20. import static org.ops4j.peaberry.Peaberry.CACHE_INTERVAL_HINT;
  21. import static org.ops4j.peaberry.Peaberry.osgiModule;
  22. import static org.ops4j.peaberry.Peaberry.service;
  23. import static org.osgi.framework.Bundle.ACTIVE;
  24. import static org.osgi.framework.Bundle.STARTING;
  25. import org.ops4j.peaberry.ServiceUnavailableException;
  26. import org.ops4j.peaberry.cache.AbstractServiceImport;
  27. import org.ops4j.peaberry.cache.CachingServiceRegistry;
  28. import org.osgi.framework.Bundle;
  29. import org.osgi.framework.BundleActivator;
  30. import org.osgi.framework.BundleContext;
  31. import com.google.inject.AbstractModule;
  32. import com.google.inject.Guice;
  33. import com.google.inject.Inject;
  34. import com.google.inject.Injector;
  35. import com.google.inject.Key;
  36. import com.google.inject.TypeLiteral;
  37. import com.google.inject.name.Named;
  38. /**
  39. * OSGi {@link BundleActivator} that manages a cleanup thread for peaberry.
  40. *
  41. * @author mcculls@gmail.com (Stuart McCulloch)
  42. * @author rinsvind@gmail.com (Todor Boev)
  43. */
  44. public final class Activator
  45. implements BundleActivator {
  46. /**
  47. * Default to one minute between flushes of the service cache.
  48. */
  49. private static final String CACHE_INTERVAL_DEFAULT = "60000";
  50. /**
  51. * Default to three flushes before unused services are released.
  52. */
  53. private static final String CACHE_GENERATIONS_DEFAULT = "3";
  54. /**
  55. * Cleans up registered {@link CachingServiceRegistry}s at a fixed interval.
  56. */
  57. public static class ImportManager
  58. implements Runnable {
  59. private final Bundle bundle;
  60. private final int interval;
  61. private final int generations;
  62. // dynamic list of currently active caching registries
  63. private final Iterable<CachingServiceRegistry> registries;
  64. @Inject
  65. public ImportManager(final BundleContext context,
  66. @Named(CACHE_INTERVAL_HINT) final int interval,
  67. @Named(CACHE_GENERATIONS_HINT) final int generations,
  68. final Iterable<CachingServiceRegistry> registries) {
  69. bundle = context.getBundle();
  70. this.interval = max(100, interval);
  71. this.generations = max(1, generations);
  72. this.registries = registries;
  73. }
  74. public final void run() {
  75. int gen = 0;
  76. do {
  77. // generation was flushed, safe to re-use
  78. AbstractServiceImport.setCacheGeneration(gen);
  79. try {
  80. Thread.sleep(interval);
  81. } catch (final InterruptedException e) {/* wake-up */} // NOPMD
  82. // rotate to the next generation
  83. gen = (gen + 1) % generations;
  84. // flush out any unused services in this generation
  85. for (final CachingServiceRegistry i : registries) {
  86. try {
  87. i.flush(gen);
  88. } catch (final ServiceUnavailableException e) {/* already gone */} // NOPMD
  89. }
  90. } while ((bundle.getState() & (STARTING | ACTIVE)) != 0);
  91. }
  92. }
  93. private Thread cleanupThread;
  94. public void start(final BundleContext context) {
  95. final Injector injector = Guice.createInjector(osgiModule(context), new AbstractModule() {
  96. @Override
  97. protected void configure() {
  98. bindConstant().annotatedWith(named(CACHE_INTERVAL_HINT)).to(
  99. osgiProperty(CACHE_INTERVAL_HINT, CACHE_INTERVAL_DEFAULT));
  100. bindConstant().annotatedWith(named(CACHE_GENERATIONS_HINT)).to(
  101. osgiProperty(CACHE_GENERATIONS_HINT, CACHE_GENERATIONS_DEFAULT));
  102. // eat our own cat-food: lookup registered caching registries from OSGi
  103. bind(new TypeLiteral<Iterable<CachingServiceRegistry>>() {}).toProvider(
  104. service(CachingServiceRegistry.class).multiple());
  105. }
  106. private String osgiProperty(final String name, final String defaultValue) {
  107. final String value = context.getProperty(name);
  108. return null == value ? defaultValue : value;
  109. }
  110. });
  111. // negative flush interval means no timeout, so no need to create a thread
  112. if (injector.getInstance(Key.get(int.class, named(CACHE_INTERVAL_HINT))) >= 0) {
  113. cleanupThread = new Thread(injector.getInstance(ImportManager.class), "Peaberry [cleanup]");
  114. cleanupThread.setPriority(Thread.MIN_PRIORITY);
  115. cleanupThread.setDaemon(true);
  116. cleanupThread.start();
  117. }
  118. }
  119. public void stop(final BundleContext ctx)
  120. throws InterruptedException {
  121. if (null != cleanupThread) {
  122. cleanupThread.interrupt();
  123. try {
  124. cleanupThread.join();
  125. } finally {
  126. cleanupThread = null;
  127. }
  128. }
  129. }
  130. }