View Javadoc
1   package com.atlassian.plugin.util.resource;
2   
3   import com.google.common.base.Splitter;
4   import org.slf4j.Logger;
5   import org.slf4j.LoggerFactory;
6   
7   import java.io.File;
8   import java.io.IOException;
9   import java.io.InputStream;
10  import java.net.MalformedURLException;
11  import java.net.URL;
12  import java.util.ArrayList;
13  import java.util.Collections;
14  import java.util.List;
15  
16  /**
17   * Loads resources from directories configured via the system property {@code plugin.resource.directories}, which should
18   * be a comma-delimited list of file paths that contain resources to load.
19   *
20   * @since 2.2.0
21   */
22  public class AlternativeDirectoryResourceLoader implements AlternativeResourceLoader {
23      private static final Logger log = LoggerFactory.getLogger(AlternativeDirectoryResourceLoader.class);
24      private static final Splitter splitter = Splitter.on(',').trimResults().omitEmptyStrings();
25  
26      public static final String PLUGIN_RESOURCE_DIRECTORIES = "plugin.resource.directories";
27  
28      private volatile String pluginResourceSystemProperty = "";
29      private volatile List<File> resourceDirectories = Collections.emptyList();
30  
31      public AlternativeDirectoryResourceLoader() {
32          getPluginResourceDirs();
33      }
34  
35      private List<File> getPluginResourceDirs() {
36          String dirs = System.getProperty(PLUGIN_RESOURCE_DIRECTORIES, "");
37          //
38          // has the system property changed since we last read it
39          if (!dirs.equals(pluginResourceSystemProperty)) {
40              List<File> tmp = new ArrayList<>();
41              for (String dir : splitter.split(dirs)) {
42                  File file = new File(dir);
43                  if (file.exists()) {
44                      log.debug("Found alternative resource directory " + dir);
45                      tmp.add(file);
46                  } else {
47                      log.warn("Resource directory " + dir + ", which resolves to " + file.getAbsolutePath() + " does not exist");
48                  }
49              }
50              // caching the system property means we don't do the file lookup every time
51              // but we can tell then it changes on next read
52              pluginResourceSystemProperty = dirs;
53              resourceDirectories = tmp;
54          }
55          return resourceDirectories;
56      }
57  
58  
59      /**
60       * Retrieve the URL of the resource from the directories.
61       *
62       * @param path the name of the resource to be loaded
63       *
64       * @return The URL to the resource, or null if the resource is not found
65       */
66      public URL getResource(String path) {
67          for (File dir : getPluginResourceDirs()) {
68              File file = new File(dir, path);
69              if (file.exists()) {
70                  try {
71                      return file.toURI().toURL();
72                  } catch (MalformedURLException e) {
73                      log.error("Malformed URL: " + file.toString(), e);
74                  }
75              } else {
76                  log.debug("File " + file + " not found, ignoring");
77              }
78          }
79          return null;
80      }
81  
82      /**
83       * Load a given resource from the directories.
84       *
85       * @param name The name of the resource to be loaded.
86       *
87       * @return An InputStream for the resource, or null if the resource is not found.
88       */
89      public InputStream getResourceAsStream(String name) {
90          URL url = getResource(name);
91          if (url != null) {
92              try {
93                  return url.openStream();
94              } catch (IOException e) {
95                  log.error("Unable to open URL " + url, e);
96              }
97          }
98          return null;
99      }
100 
101     /**
102      * @return the current list of alternate resource directories
103      */
104     public List<File> getResourceDirectories() {
105         return getPluginResourceDirs();
106     }
107 
108 
109 }