PageRenderTime 34ms CodeModel.GetById 21ms app.highlight 11ms RepoModel.GetById 0ms app.codeStats 0ms

/activeobjects-plugin/src/main/java/com/atlassian/activeobjects/plugin/ActiveObjectModuleDescriptor.java

https://bitbucket.org/activeobjects/ao-plugin
Java | 214 lines | 167 code | 30 blank | 17 comment | 8 complexity | 7b1ae533fb711d54c3839139ee19966e MD5 | raw file
Possible License(s): Apache-2.0
  1package com.atlassian.activeobjects.plugin;
  2
  3import com.atlassian.activeobjects.ActiveObjectsPluginException;
  4import com.atlassian.activeobjects.EntitiesValidator;
  5import com.atlassian.activeobjects.admin.PluginInfo;
  6import com.atlassian.activeobjects.admin.PluginToTablesMapping;
  7import com.atlassian.activeobjects.config.ActiveObjectsConfiguration;
  8import com.atlassian.activeobjects.config.ActiveObjectsConfigurationFactory;
  9import com.atlassian.activeobjects.external.ActiveObjectsUpgradeTask;
 10import com.atlassian.activeobjects.osgi.OsgiServiceUtils;
 11import com.atlassian.plugin.Plugin;
 12import com.atlassian.plugin.PluginParseException;
 13import com.atlassian.plugin.descriptors.AbstractModuleDescriptor;
 14import com.atlassian.plugin.module.ContainerManagedPlugin;
 15import com.atlassian.plugin.module.ModuleFactory;
 16import com.atlassian.plugin.osgi.factory.OsgiPlugin;
 17import com.google.common.base.Function;
 18import com.google.common.collect.Iterables;
 19import com.google.common.collect.Lists;
 20import com.google.common.collect.Sets;
 21import net.java.ao.RawEntity;
 22import net.java.ao.schema.TableNameConverter;
 23import org.dom4j.Element;
 24import org.osgi.framework.Bundle;
 25import org.osgi.framework.ServiceRegistration;
 26import org.slf4j.Logger;
 27import org.slf4j.LoggerFactory;
 28
 29import java.util.List;
 30import java.util.Set;
 31
 32import static com.google.common.base.Preconditions.checkNotNull;
 33import static com.google.common.collect.Lists.newLinkedList;
 34
 35/**
 36 * <p>The module descriptor for active objects.</p>
 37 * <p>This parses the 'ao' module definition and registers a 'bundle specific'
 38 * {@link com.atlassian.activeobjects.config.ActiveObjectsConfiguration configuration}
 39 * as an OSGi service.</p>
 40 * <p>This configuration is then looked up when the active object service is requested by the given bundle
 41 * through a &lt;component-import ... &gt; module to configure the service appropriately.</p>
 42 */
 43public 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     * The service registration for the active objects configuration, defined by this plugin.
 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; // no module
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     * The table name space is either the custom namespace set by the product, or the bundle symbolic name
171     *
172     * @param element the 'ao' descriptor element
173     * @return the name space for names
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}