1 package com.atlassian.plugin.metadata;
2
3 import com.atlassian.plugin.ModuleDescriptor;
4 import com.atlassian.plugin.Plugin;
5 import com.google.common.collect.ImmutableSet;
6 import org.apache.commons.io.IOUtils;
7 import org.apache.commons.lang.StringUtils;
8
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.net.URL;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.Enumeration;
15 import java.util.List;
16 import java.util.Set;
17
18 import static org.apache.commons.io.IOUtils.readLines;
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 public class ClasspathFilePluginMetadata implements PluginMetadata, RequiredPluginProvider
35 {
36 final static String APPLICATION_PROVIDED_PLUGINS_FILENAME = "application-provided-plugins.txt";
37 final static String APPLICATION_REQUIRED_PLUGINS_FILENAME = "application-required-plugins.txt";
38 final static String APPLICATION_REQUIRED_MODULES_FILENAME = "application-required-modules.txt";
39
40 private final Set<String> providedPluginKeys;
41 private final Set<String> requiredPluginKeys;
42 private final Set<String> requiredModuleKeys;
43 private final ClassLoader classLoader;
44
45 public ClasspathFilePluginMetadata()
46 {
47 this(ClasspathFilePluginMetadata.class.getClassLoader());
48 }
49
50 ClasspathFilePluginMetadata(ClassLoader classLoader)
51 {
52 this.classLoader = classLoader;
53 this.providedPluginKeys = getStringsFromFile(APPLICATION_PROVIDED_PLUGINS_FILENAME);
54 this.requiredPluginKeys = getStringsFromFile(APPLICATION_REQUIRED_PLUGINS_FILENAME);
55 this.requiredModuleKeys = getStringsFromFile(APPLICATION_REQUIRED_MODULES_FILENAME);
56 }
57
58 public boolean applicationProvided(final Plugin plugin)
59 {
60 return providedPluginKeys.contains(plugin.getKey());
61 }
62
63 public boolean required(final Plugin plugin)
64 {
65 return requiredPluginKeys.contains(plugin.getKey());
66 }
67
68 public boolean required(final ModuleDescriptor<?> module)
69 {
70 return requiredModuleKeys.contains(module.getCompleteKey());
71 }
72
73 public Set<String> getRequiredPluginKeys()
74 {
75 return requiredPluginKeys;
76 }
77
78 public Set<String> getRequiredModuleKeys()
79 {
80 return requiredModuleKeys;
81 }
82
83 private Set<String> getStringsFromFile(final String fileName)
84 {
85 final ImmutableSet.Builder<String> stringsFromFiles = ImmutableSet.builder();
86
87 final Collection<InputStream> fileInputStreams = getInputStreamsForFilename(fileName);
88 try
89 {
90 for (InputStream fileInputStream : fileInputStreams)
91 {
92 if (fileInputStream != null)
93 {
94 try
95 {
96 @SuppressWarnings ("unchecked")
97 final List<String> lines = readLines(fileInputStream);
98
99
100
101
102 for (String line : lines)
103 {
104 final String processedLine = processedLine(line);
105 if (processedLine != null)
106 {
107 stringsFromFiles.add(processedLine.intern());
108 }
109 }
110 }
111 catch (final IOException e)
112 {
113 throw new RuntimeException(e);
114 }
115 }
116 }
117 }
118 finally
119 {
120 for (InputStream fileInputStream : fileInputStreams)
121 {
122 IOUtils.closeQuietly(fileInputStream);
123 }
124 }
125 return stringsFromFiles.build();
126 }
127
128
129
130
131
132
133
134
135
136 private String processedLine(String rawLine)
137 {
138 if (rawLine == null)
139 {
140 return null;
141 }
142
143 final String trimmedLine = rawLine.trim();
144
145 if (StringUtils.isBlank(trimmedLine))
146 {
147 return null;
148 }
149
150
151 if (trimmedLine.startsWith("#"))
152 {
153 return null;
154 }
155 return trimmedLine;
156 }
157
158 Collection<InputStream> getInputStreamsForFilename(final String fileName)
159 {
160 final Collection<InputStream> inputStreams = new ArrayList<InputStream>();
161 final Class<ClasspathFilePluginMetadata> clazz = ClasspathFilePluginMetadata.class;
162 final String resourceName = clazz.getPackage().getName().replace(".", "/") + "/" + fileName;
163 try
164 {
165 final Enumeration<URL> urlEnumeration = classLoader.getResources(resourceName);
166 while (urlEnumeration.hasMoreElements())
167 {
168 inputStreams.add(urlEnumeration.nextElement().openStream());
169 }
170 }
171 catch (final IOException e)
172 {
173
174 for (InputStream inputStream : inputStreams)
175 {
176 IOUtils.closeQuietly(inputStream);
177 }
178 throw new RuntimeException(e);
179 }
180 return inputStreams;
181 }
182
183 }