1 package com.atlassian.plugin.loaders;
2
3 import com.atlassian.plugin.DefaultPluginArtifactFactory;
4 import com.atlassian.plugin.Plugin;
5 import com.atlassian.plugin.PluginException;
6 import com.atlassian.plugin.PluginInternal;
7 import com.atlassian.plugin.event.PluginEventManager;
8 import com.atlassian.plugin.factories.PluginFactory;
9 import com.atlassian.plugin.loaders.classloading.DeploymentUnit;
10 import com.atlassian.plugin.loaders.classloading.EmptyScanner;
11 import com.atlassian.plugin.loaders.classloading.ForwardingScanner;
12 import com.atlassian.plugin.loaders.classloading.Scanner;
13 import org.apache.commons.io.FileUtils;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16
17 import java.io.File;
18 import java.io.IOException;
19 import java.net.URL;
20 import java.nio.file.Files;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import static com.atlassian.plugin.ReferenceMode.PERMIT_REFERENCE;
25 import static com.google.common.base.Preconditions.checkArgument;
26 import static com.google.common.base.Preconditions.checkNotNull;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 public class BundledPluginLoader extends ScanningPluginLoader {
43 private static final Logger log = LoggerFactory.getLogger(BundledPluginLoader.class);
44
45
46
47
48 public static String getListSuffix() {
49 return ".list";
50 }
51
52 private BundledPluginLoader(
53 final Scanner scanner,
54 final List<PluginFactory> pluginFactories,
55 final PluginEventManager eventManager) {
56 super(new NonRemovingScanner(scanner), pluginFactories, new DefaultPluginArtifactFactory(PERMIT_REFERENCE),
57 eventManager);
58 }
59
60
61
62
63
64
65
66
67
68
69 public BundledPluginLoader(
70 final File source,
71 final List<PluginFactory> pluginFactories,
72 final PluginEventManager eventManager) {
73 this(buildSourceScanner(source), pluginFactories, eventManager);
74 }
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 public BundledPluginLoader(
93 final URL zipUrl,
94 final File pluginPath,
95 final List<PluginFactory> pluginFactories,
96 final PluginEventManager eventManager) {
97 this(buildZipScanner(zipUrl, pluginPath), pluginFactories, eventManager);
98 }
99
100 @Override
101 protected Plugin postProcess(final Plugin plugin) {
102 if (plugin instanceof PluginInternal) {
103 ((PluginInternal) plugin).setBundledPlugin(true);
104 } else {
105 log.warn("unable to set bundled attribute on plugin '" + plugin + "' as it is of class " + plugin.getClass().getCanonicalName());
106 }
107 return plugin;
108 }
109
110 private static Scanner buildScannerCommon(final File file) {
111 if (file.isDirectory()) {
112
113 return new DirectoryScanner(file);
114 } else if (file.isFile() && file.getName().endsWith(getListSuffix())) {
115
116 final List<File> files = readListFile(file);
117 return new FileListScanner(files);
118 } else {
119
120 return null;
121 }
122 }
123
124 private static Scanner buildSourceScanner(final File source) {
125 checkNotNull(source, "Source must not be null");
126 final Scanner scanner = buildScannerCommon(source);
127 if (null == scanner) {
128 log.error("Cannot build a scanner for source '{}'", source);
129
130
131 return new EmptyScanner();
132 } else {
133 return scanner;
134 }
135 }
136
137 private static Scanner buildZipScanner(final URL url, final File pluginPath) {
138
139 checkArgument(null != url, "Bundled plugins url cannot be null");
140
141
142 Scanner scanner = null;
143
144
145
146 final File file = FileUtils.toFile(url);
147 if (null != file) {
148 scanner = buildScannerCommon(file);
149 }
150
151 if (null == scanner) {
152
153 com.atlassian.plugin.util.FileUtils.conditionallyExtractZipFile(url, pluginPath);
154 scanner = new DirectoryScanner(pluginPath);
155 }
156
157 return scanner;
158 }
159
160 private static List<File> readListFile(final File file) {
161 try {
162 final List<String> fnames = Files.readAllLines(file.toPath());
163 final List<File> files = new ArrayList<>();
164 for (final String fname : fnames) {
165 files.add(new File(fname));
166 }
167 return files;
168 } catch (IOException e) {
169 throw new IllegalStateException("Unable to read list from " + file, e);
170 }
171 }
172
173
174
175
176
177
178
179 private static class NonRemovingScanner extends ForwardingScanner {
180 NonRemovingScanner(final Scanner scanner) {
181 super(scanner);
182 }
183
184 @Override
185 public void remove(final DeploymentUnit unit) throws PluginException {
186
187 }
188 }
189 }