Package com.atlassian.labs.speakeasy.commonjs.descriptor

Source Code of com.atlassian.labs.speakeasy.commonjs.descriptor.GeneratedDescriptorsManager

package com.atlassian.labs.speakeasy.commonjs.descriptor;

import com.atlassian.labs.speakeasy.commonjs.CommonJsModules;
import com.atlassian.labs.speakeasy.commonjs.util.JsDoc;
import com.atlassian.labs.speakeasy.util.DefaultPluginModuleTracker;
import com.atlassian.labs.speakeasy.util.PluginModuleTracker;
import com.atlassian.plugin.ModuleDescriptor;
import com.atlassian.plugin.PluginAccessor;
import com.atlassian.plugin.event.PluginEventManager;
import com.google.common.collect.Sets;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import static com.google.common.collect.Sets.newHashSet;
import static org.apache.commons.collections.SetUtils.unmodifiableSet;
import static org.dom4j.DocumentHelper.createElement;

/**
*
*/
class GeneratedDescriptorsManager
{
    private final CommonJsModulesDescriptor descriptor;
    private final Bundle pluginBundle;
    private final CommonJsModules modules;

    private final DefaultPluginModuleTracker<CommonJsModules,CommonJsModulesDescriptor> modulesTracker;

    private final Set<String> unresolvedExternalDependencies;
    private final Set<String> resolvedExternalModules;

    private Set<ServiceRegistration> registrations;
    private final Logger log = LoggerFactory.getLogger(GeneratedDescriptorsManager.class);

    GeneratedDescriptorsManager(Bundle pluginBundle, CommonJsModules modules, PluginAccessor pluginAccessor,
                                PluginEventManager pluginEventManager, CommonJsModulesDescriptor descriptor)
    {
        this.pluginBundle = pluginBundle;
        this.modules = modules;
        this.descriptor = descriptor;
        this.unresolvedExternalDependencies = new HashSet<String>(modules.getExternalModuleDependencies());
        this.resolvedExternalModules = new CopyOnWriteArraySet<String>();
        modulesTracker = new DefaultPluginModuleTracker<CommonJsModules, CommonJsModulesDescriptor>(pluginAccessor, pluginEventManager,
                CommonJsModulesDescriptor.class, new PluginModuleTracker.Customizer<CommonJsModules, CommonJsModulesDescriptor>()
                {
                    public CommonJsModulesDescriptor adding(CommonJsModulesDescriptor descriptor)
                    {
                        if (descriptor.getModule() != null)
                        {
                            maybeRegisterDescriptors(descriptor);
                            return descriptor;
                        }
                        return null;
                    }

                    public void removed(CommonJsModulesDescriptor descriptor)
                    {
                        maybeUnregisterDescriptors(descriptor);
                    }
                });
    }

    public Set<String> getUnresolvedExternalDependencies()
    {
        return unmodifiableSet(unresolvedExternalDependencies);
    }

    private synchronized void maybeRegisterDescriptors(CommonJsModulesDescriptor descriptor)
    {
        if (registrations == null)
        {
            if (unresolvedExternalDependencies.removeAll(descriptor.getModule().getPublicModuleIds()))
            {
                resolvedExternalModules.add(descriptor.getModulesWebResourceCompleteKey());
            }

            if (unresolvedExternalDependencies.isEmpty())
            {
                Set<ServiceRegistration> regs = new HashSet<ServiceRegistration>();
                regs.add(registerBatchedModulesDescriptor());
                regs.addAll(registerEachModuleDescriptor());
                registrations = regs;
            }
            else
            {
                log.debug("Not exposing '{}' as there are unresolved module dependencies: {}", GeneratedDescriptorsManager.this.descriptor.getCompleteKey(), unresolvedExternalDependencies);
            }
        }
    }

    private synchronized void maybeUnregisterDescriptors(CommonJsModulesDescriptor descriptor)
    {
        unresolvedExternalDependencies.addAll(Sets.intersection(descriptor.getModule().getPublicModuleIds(), resolvedExternalModules));

        if (!unresolvedExternalDependencies.isEmpty() && registrations != null)
        {
            // todo: try to resolve the dependency from the remaining descriptors instead of assuming it is gone
            unregisterServiceRegistrations();
            registrations = null;
        }
    }

    public synchronized void close()
    {
        modulesTracker.close();
        if (registrations != null)
        {
            unregisterServiceRegistrations();
        }
        registrations = null;
    }

    private void unregisterServiceRegistrations()
    {
        for (ServiceRegistration reg : registrations)
        {
            reg.unregister();
        }
    }

    private Set<ServiceRegistration> registerEachModuleDescriptor()
    {
        Set<ServiceRegistration> registrations = new HashSet<ServiceRegistration>();
        for (String id : modules.getModuleIds())
        {
            ModuleDescriptor webResourceModuleDescriptor = descriptor.createIndividualModuleDescriptor();

            Element root = createElement("web-resource");
            Element dep = root.addElement("dependency");
            dep.setText(descriptor.getCompleteKey() + "-modules");
            JsDoc jsDoc = modules.getModule(id).getJsDoc();
            addAnnotatedContext(root, jsDoc);
            Element jsTransform = getJsTransformation(root);
            Element trans = jsTransform.addElement("transformer");
            trans.addAttribute("key", "commonjs-module-entry");
            trans.addAttribute("moduleId", id);
            trans.addAttribute("fullModuleKey", descriptor.getCompleteKey());

            Element res = root.addElement("resource");
            res.addAttribute("type", "download");
            res.addAttribute("name", id + ".js");
            res.addAttribute("location", modules.getModulePath(id));

            webResourceModuleDescriptor.init(descriptor.getPlugin(), createDescriptorElement(id, root));

            ServiceRegistration reg =
                    pluginBundle.getBundleContext().registerService(ModuleDescriptor.class.getName(), webResourceModuleDescriptor, null);
            registrations.add(reg);
        }
        return registrations;
    }

    private void addAnnotatedContext(Element root, JsDoc jsDoc)
    {
        String jsDocContext = jsDoc.getAttribute("context");
        if (jsDocContext != null)
        {
            for (String ctxRaw : jsDocContext.split(","))
            {
                Element ctxElement = root.addElement("context");
                ctxElement.setText(ctxRaw.trim());
            }
        }
    }

    private void addAnnotatedDependencies(Element root, String pluginKey, JsDoc jsDoc)
    {
        String jsDocDependencies = jsDoc.getAttribute("dependency");
        if (jsDocDependencies != null)
        {
            for (String depRaw : jsDocDependencies.split(","))
            {
                Element depElement = root.addElement("dependency");
                String dep = depRaw.trim();
                if (!dep.contains(":"))
                {
                    depElement.setText(pluginKey + ":" + dep);
                }
                else
                {
                    depElement.setText(dep);
                }
            }
        }
    }



    private Element getJsTransformation(Element root)
    {
        for (Element trans : new ArrayList<Element>(root.elements("transformation")))
        {
            if ("js".equals(trans.attributeValue("extension")))
            {
                return trans;
            }
        }
        Element trans = root.addElement("transformation");
        trans.addAttribute("extension", "js");
        return trans;
    }

    private Element createDescriptorElement(String id, Element root)
    {
        root.addAttribute("key", id.replace('/', '_'));
        if (log.isDebugEnabled())
        {
            StringWriter out = new StringWriter();
            OutputFormat format = OutputFormat.createPrettyPrint();
            try
            {
                new XMLWriter( out, format ).write(root);
            }
            catch (IOException e)
            {
                e.printStackTrace()//To change body of catch statement use File | Settings | File Templates.
            }
            log.debug("Generated descriptor:\n" + out.toString());
        }
        return root;
    }

    private ServiceRegistration registerBatchedModulesDescriptor()
    {
        ModuleDescriptor webResourceModuleDescriptor = descriptor.createIndividualModuleDescriptor();

        Element root = createElement("web-resource");
        for (Element child : new HashSet<Element>(descriptor.getOriginalElement().elements()))
        {
            root.add(child.createCopy());
        }
        Element depElement = root.addElement("dependency");
        depElement.setText("com.atlassian.labs.speakeasy-plugin:yabble");
        Element jsTransform = getJsTransformation(root);
        Element trans = jsTransform.addElement("transformer");
        trans.addAttribute("key", "commonjs-module");
        trans.addAttribute("fullModuleKey", descriptor.getCompleteKey());

        for (String id : modules.getModuleIds())
        {
            Element res = root.addElement("resource");
            res.addAttribute("type", "download");
            res.addAttribute("name", id + ".js");
            res.addAttribute("location", modules.getModulePath(id));
            JsDoc jsDoc = modules.getModule(id).getJsDoc();
            addAnnotatedDependencies(root, descriptor.getPluginKey(), jsDoc);
        }


        for (String dep : resolvedExternalModules)
        {
            Element extDep = root.addElement("dependency");
            extDep.setText(dep);
        }
       
        for (String resourcePath : modules.getResources())
        {
            Element res = root.addElement("resource");
            res.addAttribute("type", "download");
            res.addAttribute("name", resourcePath);
            res.addAttribute("location", descriptor.getLocation() + "/" + resourcePath);
        }

        Element muTrans = root.addElement("transformation");
        muTrans.addAttribute("extension", "mu");
        trans = muTrans.addElement("transformer");
        trans.addAttribute("key", "template");

        String generatedModuleKey = descriptor.getKey() + "-modules";

        Element cssTrans = root.addElement("transformation");
        cssTrans.addAttribute("extension", "css");
        trans = cssTrans.addElement("transformer");
        trans.addAttribute("key", "cssVariables");
        trans.addAttribute("fullModuleKey", descriptor.getPluginKey() + ":" + generatedModuleKey);
       
        webResourceModuleDescriptor.init(descriptor.getPlugin(),
                createDescriptorElement(generatedModuleKey, root));
        return pluginBundle.getBundleContext().registerService(ModuleDescriptor.class.getName(), webResourceModuleDescriptor, null);
    }
}
TOP

Related Classes of com.atlassian.labs.speakeasy.commonjs.descriptor.GeneratedDescriptorsManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.