1 package com.atlassian.activeobjects.plugin;
2
3 import com.atlassian.activeobjects.ActiveObjectsPluginException;
4 import com.atlassian.activeobjects.EntitiesValidator;
5 import com.atlassian.activeobjects.admin.PluginInfo;
6 import com.atlassian.activeobjects.admin.PluginToTablesMapping;
7 import com.atlassian.activeobjects.config.ActiveObjectsConfiguration;
8 import com.atlassian.activeobjects.config.ActiveObjectsConfigurationFactory;
9 import com.atlassian.activeobjects.external.ActiveObjectsUpgradeTask;
10 import com.atlassian.activeobjects.osgi.OsgiServiceUtils;
11 import com.atlassian.plugin.Plugin;
12 import com.atlassian.plugin.PluginParseException;
13 import com.atlassian.plugin.descriptors.AbstractModuleDescriptor;
14 import com.atlassian.plugin.module.ContainerManagedPlugin;
15 import com.atlassian.plugin.module.ModuleFactory;
16 import com.atlassian.plugin.osgi.factory.OsgiPlugin;
17 import com.google.common.base.Function;
18 import com.google.common.collect.Iterables;
19 import com.google.common.collect.Lists;
20 import com.google.common.collect.Sets;
21 import net.java.ao.RawEntity;
22 import net.java.ao.schema.TableNameConverter;
23 import org.dom4j.Element;
24 import org.osgi.framework.Bundle;
25 import org.osgi.framework.ServiceRegistration;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import java.util.List;
30 import java.util.Set;
31
32 import static com.google.common.base.Preconditions.checkNotNull;
33 import static com.google.common.collect.Lists.newLinkedList;
34
35
36
37
38
39
40
41
42
43 public class ActiveObjectModuleDescriptor extends AbstractModuleDescriptor<Object> {
44
45 private final Logger logger = LoggerFactory.getLogger(this.getClass());
46
47 private final ActiveObjectsConfigurationFactory configurationFactory;
48 private final OsgiServiceUtils osgiUtils;
49 private final EntitiesValidator entitiesValidator;
50 private final PluginToTablesMapping pluginToTablesMapping;
51
52
53
54
55 private ServiceRegistration activeObjectsConfigurationServiceRegistration;
56 private ServiceRegistration tableNameConverterServiceRegistration;
57
58 private ActiveObjectsConfiguration configuration;
59
60 ActiveObjectModuleDescriptor(ModuleFactory moduleFactory,
61 ActiveObjectsConfigurationFactory configurationFactory,
62 OsgiServiceUtils osgiUtils,
63 PluginToTablesMapping pluginToTablesMapping,
64 EntitiesValidator entitiesValidator) {
65 super(moduleFactory);
66 this.configurationFactory = checkNotNull(configurationFactory);
67 this.osgiUtils = checkNotNull(osgiUtils);
68 this.pluginToTablesMapping = checkNotNull(pluginToTablesMapping);
69 this.entitiesValidator = checkNotNull(entitiesValidator);
70 }
71
72 @Override
73 public void init(Plugin plugin, Element element) throws PluginParseException {
74 super.init(plugin, element);
75
76 final Set<Class<? extends RawEntity<?>>> entities = getEntities(element);
77 final List<ActiveObjectsUpgradeTask> upgradeTasks = getUpgradeTasks(element);
78 configuration = getActiveObjectsConfiguration(getNameSpace(element), entities, upgradeTasks);
79
80 final Set<Class<? extends RawEntity<?>>> entityClasses = entitiesValidator.check(entities, configuration.getNameConverters());
81 recordTables(entityClasses, configuration.getNameConverters().getTableNameConverter());
82 }
83
84 private List<ActiveObjectsUpgradeTask> getUpgradeTasks(Element element) {
85 final List<Element> upgradeTask = getSubElements(element, "upgradeTask");
86
87 final List<Class<ActiveObjectsUpgradeTask>> classes = Lists.transform(upgradeTask, new Function<Element, Class<ActiveObjectsUpgradeTask>>() {
88 @Override
89 public Class<ActiveObjectsUpgradeTask> apply(Element utElement) {
90 final String upgradeTaskClass = utElement.getText().trim();
91 logger.debug("Found upgrade task class <{}>", upgradeTaskClass);
92 return getUpgradeTaskClass(upgradeTaskClass);
93 }
94 });
95
96 if (!(getPlugin() instanceof ContainerManagedPlugin)) {
97 throw new ActiveObjectsPluginException("Plugin " + getPlugin().getKey() + " " + getPlugin().getClass().getCanonicalName() + " is not a ContainerManagedPlugin, cannot wire context");
98 }
99 final ContainerManagedPlugin plugin = (ContainerManagedPlugin) getPlugin();
100 return Lists.transform(classes, new Function<Class<ActiveObjectsUpgradeTask>, ActiveObjectsUpgradeTask>() {
101 @Override
102 public ActiveObjectsUpgradeTask apply(Class<ActiveObjectsUpgradeTask> upgradeTaskClass) {
103 return plugin.getContainerAccessor().createBean(upgradeTaskClass);
104 }
105 });
106 }
107
108 private Class<ActiveObjectsUpgradeTask> getUpgradeTaskClass(String upgradeTask) {
109 try {
110 return getPlugin().loadClass(upgradeTask, getClass());
111 } catch (ClassNotFoundException e) {
112 throw new ActiveObjectsPluginException(e);
113 }
114 }
115
116 private void recordTables(final Set<Class<? extends RawEntity<?>>> entityClasses, final TableNameConverter tableNameConverter) {
117 pluginToTablesMapping.add(PluginInfo.of(getPlugin()), Lists.transform(newLinkedList(entityClasses), new Function<Class<? extends RawEntity<?>>, String>() {
118 @Override
119 public String apply(Class<? extends RawEntity<?>> from) {
120 return tableNameConverter.getName(from);
121 }
122 }));
123 }
124
125 @Override
126 public void enabled() {
127 super.enabled();
128
129 if (tableNameConverterServiceRegistration == null) {
130 tableNameConverterServiceRegistration = osgiUtils.registerService(getBundle(), TableNameConverter.class, configuration.getNameConverters().getTableNameConverter());
131 }
132 if (activeObjectsConfigurationServiceRegistration == null) {
133 activeObjectsConfigurationServiceRegistration = osgiUtils.registerService(getBundle(), ActiveObjectsConfiguration.class, configuration);
134 }
135 }
136
137 @Override
138 public void disabled() {
139 unregister(activeObjectsConfigurationServiceRegistration);
140 activeObjectsConfigurationServiceRegistration = null;
141 unregister(tableNameConverterServiceRegistration);
142 tableNameConverterServiceRegistration = null;
143 super.disabled();
144 }
145
146 @Override
147 public Object getModule() {
148 return null;
149 }
150
151 public ActiveObjectsConfiguration getConfiguration() {
152 return configuration;
153 }
154
155 private ActiveObjectsConfiguration getActiveObjectsConfiguration(String namespace, Set<Class<? extends RawEntity<?>>> entities, List<ActiveObjectsUpgradeTask> upgradeTasks) {
156 return configurationFactory.getConfiguration(getBundle(), namespace, entities, upgradeTasks);
157 }
158
159 private void unregister(ServiceRegistration serviceRegistration) {
160 if (serviceRegistration != null) {
161 try {
162 serviceRegistration.unregister();
163 } catch (IllegalStateException ignored) {
164 logger.debug("Service has already been unregistered", ignored);
165 }
166 }
167 }
168
169
170
171
172
173
174
175 private String getNameSpace(Element element) {
176 final String custom = element.attributeValue("namespace");
177 return custom != null ? custom : getBundle().getSymbolicName();
178 }
179
180 private Set<Class<? extends RawEntity<?>>> getEntities(Element element) {
181 return Sets.newHashSet(Iterables.transform(getEntityClassNames(element), new Function<String, Class<? extends RawEntity<?>>>() {
182 public Class<? extends RawEntity<?>> apply(String entityClassName) {
183 return getEntityClass(entityClassName);
184 }
185 }));
186 }
187
188 private Class<? extends RawEntity<?>> getEntityClass(String entityClassName) {
189 try {
190 return getPlugin().loadClass(entityClassName, getClass());
191 } catch (ClassNotFoundException e) {
192 throw new ActiveObjectsPluginException(e);
193 }
194 }
195
196 private Iterable<String> getEntityClassNames(Element element) {
197 return Iterables.transform(getSubElements(element, "entity"), new Function<Element, String>() {
198 public String apply(Element entityElement) {
199 final String entityClassName = entityElement.getText().trim();
200 logger.debug("Found entity class <{}>", entityClassName);
201 return entityClassName;
202 }
203 });
204 }
205
206 private Bundle getBundle() {
207 return ((OsgiPlugin) getPlugin()).getBundle();
208 }
209
210 @SuppressWarnings("unchecked")
211 private static List<Element> getSubElements(Element element, String name) {
212 return element.elements(name);
213 }
214 }