2 * Copyright 2017 - 2021 ZTE Corporation.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.onap.holmes.common.dropwizard.ioc.bundle;
18 import com.codahale.metrics.health.HealthCheck;
19 import com.fasterxml.jackson.databind.ObjectMapper;
20 import com.google.common.collect.Lists;
21 import io.dropwizard.Configuration;
22 import io.dropwizard.ConfiguredBundle;
23 import io.dropwizard.lifecycle.ServerLifecycleListener;
24 import io.dropwizard.servlets.tasks.Task;
25 import io.dropwizard.setup.Bootstrap;
26 import io.dropwizard.setup.Environment;
27 import org.eclipse.jetty.util.component.LifeCycle;
28 import org.glassfish.hk2.api.ServiceLocator;
29 import org.glassfish.hk2.api.ServiceLocatorFactory;
30 import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
31 import org.glassfish.hk2.utilities.binding.AbstractBinder;
32 import org.glassfish.jersey.servlet.ServletProperties;
33 import org.jvnet.hk2.annotations.Service;
34 import org.onap.holmes.common.dropwizard.ioc.annotation.*;
35 import org.onap.holmes.common.dropwizard.ioc.utils.ServiceBinder;
36 import org.onap.holmes.common.dropwizard.ioc.utils.ServiceLocatorHolder;
37 import org.reflections.Reflections;
38 import org.reflections.scanners.SubTypesScanner;
39 import org.reflections.scanners.TypeAnnotationsScanner;
40 import org.reflections.util.ClasspathHelper;
41 import org.reflections.util.ConfigurationBuilder;
42 import org.reflections.util.FilterBuilder;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 import javax.ws.rs.Path;
47 import javax.ws.rs.ext.Provider;
48 import java.lang.annotation.Annotation;
49 import java.lang.reflect.Field;
50 import java.util.Arrays;
51 import java.util.List;
53 import java.util.stream.Collectors;
56 * complete the integration of hK2 container and dropwizard
61 public class AutoConfigBundle<T extends Configuration> implements ConfiguredBundle<T> {
63 private static final Logger LOG = LoggerFactory.getLogger(AutoConfigBundle.class);
65 private ServiceLocator locator;
66 private Reflections reflections;
67 private Set<Class<?>> services;
69 private Bootstrap<?> bootstrap;
72 AutoConfigBundle(final String packageName) {
73 this(Lists.newArrayList(packageName));
76 AutoConfigBundle(List<String> packageNames) {
77 FilterBuilder filterBuilder = new FilterBuilder();
79 packageNames.stream().forEach(packageName -> filterBuilder.include(FilterBuilder.prefix(packageName)));
80 ConfigurationBuilder reflectionCfg = new ConfigurationBuilder();
82 packageNames.stream().forEach(packageName -> reflectionCfg.addUrls(ClasspathHelper.forPackage(packageName)));
84 reflectionCfg.filterInputsBy(filterBuilder).setScanners(new SubTypesScanner(),
85 new TypeAnnotationsScanner());
86 reflections = new Reflections(reflectionCfg);
88 locator = ServiceLocatorFactory.getInstance().create("dw-hk2");
90 ServiceLocatorHolder.setLocator(locator);
94 public static <T extends Configuration> AutoConfigBundleBuider<T> newBuilder() {
95 return new AutoConfigBundleBuider<T>();
99 public void initialize(final Bootstrap<?> bootstrap) {
101 this.bootstrap = bootstrap;
102 registerPreLoadService();
104 LOG.debug("Intialzing auto config bundle.");
107 private void registerPreLoadService() {
108 registerService(PreLoad.class);
113 public void run(final T configuration, final Environment environment) {
115 registerConfigurationProvider(configuration, environment);
117 registerEnvironment(environment);
118 registerObjectMapper(environment);
120 environment.getApplicationContext().getServletContext()
121 .setAttribute(ServletProperties.SERVICE_LOCATOR, locator);
123 registerService(PreBaseService.class);
124 registerService(BaseService.class);
125 registerService(PostBaseService.class);
126 this.registerService(PreServiceLoad.class);
131 registerLifecycle(environment);
132 registerServerLifecycleListeners(environment);
133 registerJettyLifeCycleListener(environment);
134 registerTasks(environment);
135 registerHealthChecks(environment);
136 registerProviders(environment);
137 registerResources(environment);
139 environment.lifecycle().manage(new ServiceLocatorManaged(locator));
144 private void registerProviders(Environment environment) {
145 reflections.getSubTypesOf(Provider.class).stream().filter(services::contains)
146 .forEach(providerKlass -> {
148 environment.jersey().register(locator.getService(providerKlass));
149 } catch (Exception e) {
153 LOG.info("Registering Dropwizard Provider, class name : {}", providerKlass.getName());
159 private void registerTasks(Environment environment) {
160 reflections.getSubTypesOf(Task.class).stream().filter(services::contains).forEach(taskKlass -> {
162 environment.admin().addTask(locator.getService(taskKlass));
163 } catch (Exception e) {
166 LOG.info("Registering Dropwizard Task, class name : {}", taskKlass.getName());
171 private void registerJettyLifeCycleListener(Environment environment) {
172 reflections.getSubTypesOf(LifeCycle.Listener.class).stream().filter(services::contains)
173 .forEach(lifecycleListenerKlass -> {
175 environment.lifecycle()
176 .addLifeCycleListener(locator.getService(lifecycleListenerKlass));
177 } catch (Exception e) {
180 LOG.info("Registering Dropwizard lifecycleListener, class name : {}",
181 lifecycleListenerKlass.getName());
186 private void registerServerLifecycleListeners(Environment environment) {
188 reflections.getSubTypesOf(ServerLifecycleListener.class).stream().filter(services::contains)
189 .forEach(serverLifecycleListenerKlass -> {
191 environment.lifecycle()
192 .addServerLifecycleListener(locator.getService(serverLifecycleListenerKlass));
193 } catch (Exception e) {
196 LOG.info("Registering Dropwizard serverLifecycleListener, class name : {}",
197 serverLifecycleListenerKlass.getName());
202 private void registerLifecycle(Environment environment) {
203 reflections.getSubTypesOf(LifeCycle.class).stream().filter(services::contains)
204 .forEach(lifeCycleKlass -> {
206 environment.lifecycle().manage(locator.getService(lifeCycleKlass));
207 } catch (Exception e) {
210 LOG.info("Registering Dropwizard LifeCycle, class name : {}", lifeCycleKlass.getName());
214 private void registerObjectMapper(Environment environment) {
216 final ObjectMapper objectMapper = environment.getObjectMapper();
218 ServiceLocatorUtilities.bind(locator, new AbstractBinder() {
220 protected void configure() {
221 bind(objectMapper).to(ObjectMapper.class);
223 LOG.info("Registering Dropwizard objectMapper, class name : {}",
224 objectMapper.getClass().getName());
230 private void registerEnvironment(final Environment environment) {
232 ServiceLocatorUtilities.bind(locator, new AbstractBinder() {
234 protected void configure() {
235 bind(environment).to(Environment.class);
237 LOG.info("Registering Dropwizard environment, class name : {}",
238 environment.getClass().getName());
244 private void registerConfigurationProvider(final T configuration, final Environment environment) {
246 ServiceLocatorUtilities.bind(locator, new AbstractBinder() {
248 protected void configure() {
250 LOG.info("Registering Dropwizard Configuration class name:{}",
251 configuration.getClass().getName());
252 bind((Configuration) configuration).to(Configuration.class);
253 LOG.info("Registering Dropwizard Configuration class name:{}",
254 Configuration.class.getName());
258 registerSubConfigure(configuration, environment);
262 private void registerSubConfigure(final T configuration, final Environment environment) {
263 final List<Field> subDeclaredFields =
264 Arrays.asList(configuration.getClass().getDeclaredFields());
265 List<Field> parentDeclaredFields = Arrays.asList(Configuration.class.getDeclaredFields());
267 List<Field> filtersubDeclaredFields = subDeclaredFields.stream()
268 .filter(subDeclaredField -> !subDeclaredField.getType().isPrimitive())
269 .filter(subDeclaredField -> !subDeclaredField.getType().equals(String.class))
270 .filter(subDeclaredField -> !parentDeclaredFields.contains(subDeclaredField))
271 .collect(Collectors.toList());
273 ServiceLocatorUtilities.bind(locator, new AbstractBinder() {
275 protected void configure() {
276 filtersubDeclaredFields.forEach(subField -> {
277 subField.setAccessible(true);
279 Object subConfig = subField.get(configuration);
280 if (subConfig != null) {
282 LOG.info("Registering Dropwizard Sub Configuration class name {}",
283 subConfig.getClass().getName());
286 } catch (Exception e) {
287 LOG.error("bind sub config:{} fail", subField);
295 private void registerServices() {
296 services = this.reflections.getTypesAnnotatedWith(Service.class, true);
297 if (!services.isEmpty()) {
298 ServiceLocatorUtilities.bind(locator, new ServiceBinder(services));
299 services.forEach(s -> LOG.info("Registering Dropwizard service, class name : {}", s.getName()));
300 recordTimeCost(services);
302 LOG.warn("Registering Dropwizard service is empty");
308 private void registerResources(final Environment environment) {
309 reflections.getTypesAnnotatedWith(Path.class).stream().forEach(resourceClass -> {
311 LOG.info("begin Registering Dropwizard resource, class name : {}", resourceClass.getName());
313 Object resourceObject = locator.getService(resourceClass);
314 if (resourceObject != null) {
315 environment.jersey().register(resourceObject);
316 LOG.info("Registering Dropwizard resource, class name : {}", resourceClass.getName());
318 LOG.warn(resourceClass.getName() + " not use Service annotation");
320 } catch (Exception e) {
326 private void registerHealthChecks(final Environment env) {
327 reflections.getSubTypesOf(HealthCheck.class).stream().filter(services::contains)
328 .forEach(healthCheckKlass -> {
330 env.healthChecks().register(healthCheckKlass.getName(),
331 locator.getService(healthCheckKlass));
332 } catch (Exception e) {
335 LOG.info("Registering Dropwizard healthCheck, class name : {}",
336 healthCheckKlass.getName());
340 private void registerService(Class<? extends Annotation> annotationClazz) {
342 Set<Class<?>> services = this.reflections.getTypesAnnotatedWith(annotationClazz, true);
343 if (!services.isEmpty()) {
344 ServiceLocatorUtilities.bind(locator, new ServiceBinder(services));
345 services.forEach(s -> LOG.info("{} Registering service, class name : {}", annotationClazz.getName(),
347 recordTimeCost(services);
349 LOG.warn("Registering {} service is empty", annotationClazz.getName());
353 private void recordTimeCost(Set<Class<?>> services) {
354 services.stream().filter(serviceClazz -> (serviceClazz.getAnnotation(Lazy.class) == null))
355 .peek(serviceClazz -> LOG.info("active service, class name : {}", serviceClazz.getName()))
356 .forEach(serviceClazz -> {
358 long startTime = System.currentTimeMillis();
359 locator.getService(serviceClazz);
360 LOG.info("active service, class name : {},cost time:{}", serviceClazz.getName(),
361 (System.currentTimeMillis() - startTime));
362 } catch (Exception e) {