1 package com.atlassian.plugin.spring.scanner.runtime.impl;
2
3 import org.osgi.framework.Bundle;
4 import org.osgi.framework.BundleContext;
5 import org.slf4j.Logger;
6 import org.springframework.beans.BeansException;
7 import org.springframework.beans.PropertyValues;
8 import org.springframework.beans.factory.DisposableBean;
9 import org.springframework.beans.factory.InitializingBean;
10 import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
11 import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
12
13 import java.beans.PropertyDescriptor;
14 import java.io.PrintWriter;
15 import java.io.StringWriter;
16 import java.util.Dictionary;
17 import java.util.Enumeration;
18
19 import static java.lang.String.format;
20 import static java.util.Objects.requireNonNull;
21 import static org.slf4j.LoggerFactory.getLogger;
22
23
24
25
26
27 public class DevModeBeanInitialisationLoggerBeanPostProcessor
28 implements InstantiationAwareBeanPostProcessor, InitializingBean, DestructionAwareBeanPostProcessor, DisposableBean {
29
30
31
32
33
34
35 public static final String ATLASSIAN_DEV_MODE = "atlassian.dev.mode";
36
37 private static final String BUNDLE_LOGGER_NAME_FORMAT = "com.atlassian.plugin.spring.scanner.%s";
38
39 private final Bundle bundle;
40 private final Logger bundleLogger;
41
42 public DevModeBeanInitialisationLoggerBeanPostProcessor(final BundleContext bundleContext) {
43 this.bundle = requireNonNull(bundleContext.getBundle());
44 this.bundleLogger = getLogger(format(BUNDLE_LOGGER_NAME_FORMAT, bundleContext.getBundle().getSymbolicName()));
45 }
46
47 @Override
48 public Object postProcessBeforeInitialization(Object bean, String beanName) {
49 return bean;
50 }
51
52 @Override
53 public Object postProcessAfterInitialization(Object bean, String beanName) {
54 logBeanDetail("AfterInitialisation", bean.getClass(), beanName);
55 return bean;
56 }
57
58 @Override
59 public Object postProcessBeforeInstantiation(Class beanClass, String beanName) {
60 logBeanDetail("BeforeInstantiation", beanClass, beanName);
61 return null;
62 }
63
64 @Override
65 public boolean postProcessAfterInstantiation(Object bean, String beanName) {
66 return true;
67 }
68
69 @Override
70 public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
71 return pvs;
72 }
73
74 @Override
75 public void postProcessBeforeDestruction(final Object bean, final String beanName) throws BeansException {
76 logBeanDetail("BeforeDestruction", bean.getClass(), beanName);
77 }
78
79 private void logBeanDetail(String stage, Class beanClass, String beanName) {
80 bundleLogger.debug("{} [bean={}, type={}]", stage, beanName, beanClass.getName());
81 }
82
83 @Override
84 public void afterPropertiesSet() {
85
86 logInDevMode("Spring context started for bundle: {} id({}) v({}) {}",
87 bundle.getSymbolicName(), bundle.getBundleId(), bundle.getVersion(), bundle.getLocation());
88 if (bundleLogger.isTraceEnabled()) {
89 final StringWriter sw = new StringWriter();
90 final PrintWriter out = new PrintWriter(sw);
91
92 out.format("\tBundle Headers :\n");
93 final Dictionary headers = bundle.getHeaders();
94 final Enumeration keys = headers.keys();
95 while (keys.hasMoreElements()) {
96 final Object key = keys.nextElement();
97 final Object value = headers.get(key);
98 out.format("\t\t%s: %s\n", key, value);
99 }
100
101 bundleLogger.trace(sw.toString());
102 }
103 }
104
105 @Override
106 public void destroy() {
107 logInDevMode("Spring context destroyed for bundle: {} id({}) v({})",
108 bundle.getSymbolicName(), bundle.getBundleId(), bundle.getVersion());
109 }
110
111 private void logInDevMode(final String message, final Object... arguments) {
112 if (isDevMode()) {
113
114
115 bundleLogger.warn(message, arguments);
116 }
117 }
118
119 private static boolean isDevMode() {
120 return Boolean.getBoolean(ATLASSIAN_DEV_MODE);
121 }
122 }