1 package com.atlassian.plugin.osgi.factory.transform;
2
3 import com.atlassian.plugin.osgi.hostcomponents.HostComponentRegistration;
4 import com.atlassian.plugin.osgi.factory.transform.stage.*;
5 import com.atlassian.plugin.JarPluginArtifact;
6 import com.atlassian.plugin.PluginArtifact;
7 import org.apache.commons.lang.Validate;
8 import org.apache.log4j.Logger;
9
10 import java.io.*;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.zip.ZipEntry;
16 import java.util.zip.ZipInputStream;
17 import java.util.zip.ZipOutputStream;
18
19
20
21
22 public class DefaultPluginTransformer implements PluginTransformer
23 {
24 private static final Logger log = Logger.getLogger(DefaultPluginTransformer.class);
25
26 private final String pluginDescriptorPath;
27 private final List<TransformStage> stages;
28
29
30
31
32
33
34
35 public DefaultPluginTransformer(String pluginDescriptorPath)
36 {
37 this(pluginDescriptorPath, new ArrayList<TransformStage>()
38 {{
39 add(new AddBundleOverridesStage());
40 add(new ComponentImportSpringStage());
41 add(new ComponentSpringStage());
42 add(new HostComponentSpringStage());
43 add(new ModuleTypeSpringStage());
44 add(new GenerateManifestStage());
45 }});
46 }
47
48
49
50
51
52
53
54
55 public DefaultPluginTransformer(String pluginDescriptorPath, List<TransformStage> stages)
56 {
57 Validate.notNull(pluginDescriptorPath, "The plugin descriptor path is required");
58 Validate.notNull(stages, "A list of stages is required");
59 this.pluginDescriptorPath = pluginDescriptorPath;
60 this.stages = Collections.unmodifiableList(new ArrayList<TransformStage>(stages));
61 }
62
63
64
65
66
67
68
69
70
71 public File transform(File pluginJar, List<HostComponentRegistration> regs) throws PluginTransformationException
72 {
73 return transform(new JarPluginArtifact(pluginJar), regs);
74 }
75
76
77
78
79
80
81
82
83
84 public File transform(PluginArtifact pluginArtifact, List<HostComponentRegistration> regs) throws PluginTransformationException
85 {
86 Validate.notNull(pluginArtifact, "The plugin artifact is required");
87 Validate.notNull(regs, "The host component registrations are required");
88 TransformContext context = new TransformContext(regs, pluginArtifact, pluginDescriptorPath);
89 for (TransformStage stage : stages)
90 {
91 stage.execute(context);
92 }
93
94
95 try
96 {
97 if (log.isDebugEnabled())
98 {
99 StringBuilder sb = new StringBuilder();
100 sb.append("Overriding files in ").append(pluginArtifact.toString()).append(":\n");
101 for (Map.Entry<String, byte[]> entry : context.getFileOverrides().entrySet())
102 {
103 sb.append("==").append(entry.getKey()).append("==\n");
104 sb.append(new String(entry.getValue()));
105 }
106 log.debug(sb.toString());
107 }
108 return addFilesToExistingZip(pluginArtifact.toFile(), context.getFileOverrides());
109 }
110 catch (IOException e)
111 {
112 throw new PluginTransformationException("Unable to add files to plugin jar");
113 }
114 }
115
116
117
118
119
120
121
122
123
124
125 static File addFilesToExistingZip(File zipFile,
126 Map<String, byte[]> files) throws IOException
127 {
128
129 File tempFile = File.createTempFile(zipFile.getName(), null);
130
131 byte[] buf = new byte[1024];
132
133 ZipInputStream zin = new ZipInputStream(new FileInputStream(zipFile));
134 ZipOutputStream out = new ZipOutputStream(new FileOutputStream(tempFile));
135
136 ZipEntry entry = zin.getNextEntry();
137 while (entry != null)
138 {
139 String name = entry.getName();
140 if (!files.containsKey(name))
141 {
142
143 out.putNextEntry(new ZipEntry(name));
144
145 int len;
146 while ((len = zin.read(buf)) > 0)
147 out.write(buf, 0, len);
148 }
149 entry = zin.getNextEntry();
150 }
151
152 zin.close();
153
154 for (Map.Entry<String, byte[]> fentry : files.entrySet())
155 {
156 InputStream in = new ByteArrayInputStream(fentry.getValue());
157
158 out.putNextEntry(new ZipEntry(fentry.getKey()));
159
160 int len;
161 while ((len = in.read(buf)) > 0)
162 {
163 out.write(buf, 0, len);
164 }
165
166 out.closeEntry();
167 in.close();
168 }
169
170 out.close();
171 return tempFile;
172 }
173
174
175 }