View Javadoc

1   package com.atlassian.plugin.webresource;
2   
3   import com.atlassian.plugin.ModuleDescriptor;
4   
5   import java.util.LinkedHashSet;
6   import java.util.List;
7   import java.util.Stack;
8   import java.util.Collections;
9   import java.util.Set;
10  
11  import org.slf4j.Logger;
12  import org.slf4j.LoggerFactory;
13  
14  class DefaultResourceDependencyResolver implements ResourceDependencyResolver
15  {
16      private static final Logger log = LoggerFactory.getLogger(DefaultResourceDependencyResolver.class);
17  
18      private final WebResourceIntegration webResourceIntegration;
19      private final ResourceBatchingConfiguration batchingConfiguration;
20  
21      private String superBatchVersion;
22      private LinkedHashSet<String> superBatchResources;
23  
24      public DefaultResourceDependencyResolver(WebResourceIntegration webResourceIntegration, ResourceBatchingConfiguration batchingConfiguration)
25      {
26          this.webResourceIntegration = webResourceIntegration;
27          this.batchingConfiguration = batchingConfiguration;
28      }
29  
30      public LinkedHashSet<String> getSuperBatchDependencies()
31      {
32          if (!batchingConfiguration.isSuperBatchingEnabled())
33          {
34              log.warn("Super batching not enabled, but getSuperBatchDependencies() called. Returning empty set.");
35              return new LinkedHashSet<String>();
36          }
37  
38          String version = webResourceIntegration.getSuperBatchVersion();
39          if (superBatchVersion == null || !superBatchVersion.equals(version))
40          {
41              LinkedHashSet<String> webResourceNames = new LinkedHashSet<String>();
42              if (batchingConfiguration.getSuperBatchModuleCompleteKeys() != null)
43              {
44                  for (String moduleKey : batchingConfiguration.getSuperBatchModuleCompleteKeys())
45                  {
46                      resolveDependencies(moduleKey, webResourceNames, Collections.emptySet(), new Stack<String>());
47                  }
48              }
49              synchronized (this)
50              {
51                  superBatchResources = webResourceNames;
52                  superBatchVersion = version;
53              }
54          }
55          return new LinkedHashSet(superBatchResources);
56      }
57  
58      public LinkedHashSet<String> getDependencies(String moduleKey, boolean excludeSuperBatchedResources)
59      {
60          LinkedHashSet<String> orderedResourceKeys = new LinkedHashSet<String>();
61          Set<String> superBatchResources = excludeSuperBatchedResources ? getSuperBatchDependencies() : Collections.<String>emptySet();
62          resolveDependencies(moduleKey, orderedResourceKeys, superBatchResources, new Stack<String>());
63          return orderedResourceKeys;
64      }
65  
66      /**
67       * Adds the resources as well as its dependencies in order to the given ordered set. This method uses recursion
68       * to add a resouce's dependent resources also to the set. You should call this method with a new stack
69       * passed to the last parameter.
70       *
71       * Note that resources already in the given super batch will be exluded when resolving dependencies. You
72       * should pass in an empty set for the super batch to include super batch resources.
73       *
74       * @param moduleKey the module complete key to add as well as its dependencies
75       * @param orderedResourceKeys an ordered list set where the resources are added in order
76       * @param superBatchResources the set of super batch resources to exclude when resolving dependencies
77       * @param stack where we are in the dependency tree
78       */
79      private void resolveDependencies(final String moduleKey, final LinkedHashSet<String> orderedResourceKeys,
80          final Set superBatchResources, final Stack<String> stack)
81      {
82          if (superBatchResources.contains(moduleKey))
83          {
84              log.debug("Not requiring resource: " + moduleKey + " because it is part of a super-batch");
85              return;
86          }
87          if (stack.contains(moduleKey))
88          {
89              log.warn("Cyclic plugin resource dependency has been detected with: " + moduleKey + "\n" + "Stack trace: " + stack);
90              return;
91          }
92  
93          final ModuleDescriptor<?> moduleDescriptor = webResourceIntegration.getPluginAccessor().getEnabledPluginModule(moduleKey);
94          if (!(moduleDescriptor instanceof WebResourceModuleDescriptor))
95          {
96              if (webResourceIntegration.getPluginAccessor().getPluginModule(moduleKey) != null)
97                  log.warn("Cannot include disabled web resource module: " + moduleKey);
98              else
99                  log.warn("Cannot find web resource module for: " + moduleKey);
100             return;
101         }
102 
103         final List<String> dependencies = ((WebResourceModuleDescriptor) moduleDescriptor).getDependencies();
104         if (log.isDebugEnabled())
105         {
106             log.debug("About to add resource [" + moduleKey + "] and its dependencies: " + dependencies);
107         }
108         stack.push(moduleKey);
109         try
110         {
111             for (final String dependency : dependencies)
112             {
113                 if (!orderedResourceKeys.contains(dependency))
114                 {
115                     resolveDependencies(dependency, orderedResourceKeys, superBatchResources, stack);
116                 }
117             }
118         }
119         finally
120         {
121             stack.pop();
122         }
123         orderedResourceKeys.add(moduleKey);
124     }
125 }