1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.felix.bundleplugin;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.util.Arrays;
24 import java.util.HashSet;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.TreeMap;
28 import java.util.TreeSet;
29 import java.util.jar.Attributes;
30 import java.util.jar.Manifest;
31
32 import org.apache.felix.utils.manifest.Parser;
33 import org.osgi.framework.Constants;
34
35 public class ManifestWriter {
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 static byte[] CONTINUE = new byte[] {
60 '\r', '\n', ' '
61 };
62
63 static Set<String> NICE_HEADERS = new HashSet<String>(
64 Arrays.asList(
65 Constants.IMPORT_PACKAGE,
66 Constants.DYNAMICIMPORT_PACKAGE,
67 Constants.IMPORT_SERVICE,
68 Constants.REQUIRE_CAPABILITY,
69 Constants.EXPORT_PACKAGE,
70 Constants.EXPORT_SERVICE,
71 Constants.PROVIDE_CAPABILITY
72 )
73 );
74
75
76
77
78
79
80
81
82
83
84
85 public static void outputManifest(Manifest manifest, OutputStream out, boolean nice) throws IOException {
86 writeEntry(out, "Manifest-Version", "1.0", nice);
87 attributes(manifest.getMainAttributes(), out, nice);
88
89 TreeSet<String> keys = new TreeSet<String>();
90 for (Object o : manifest.getEntries().keySet())
91 keys.add(o.toString());
92
93 for (String key : keys) {
94 write(out, 0, "\r\n");
95 writeEntry(out, "Name", key, nice);
96 attributes(manifest.getAttributes(key), out, nice);
97 }
98 out.flush();
99 }
100
101
102
103
104 private static void writeEntry(OutputStream out, String name, String value, boolean nice) throws IOException {
105 if (nice && NICE_HEADERS.contains(name)) {
106 int n = write(out, 0, name + ": ");
107 String[] parts = Parser.parseDelimitedString(value, ",");
108 if (parts.length > 1) {
109 write(out, 0, "\r\n ");
110 n = 1;
111 }
112 for (int i = 0; i < parts.length; i++) {
113 if (i < parts.length - 1) {
114 write(out, n, parts[i] + ",");
115 write(out, 0, "\r\n ");
116 } else {
117 write(out, n, parts[i]);
118 write(out, 0, "\r\n");
119 }
120 n = 1;
121 }
122 } else {
123 int n = write(out, 0, name + ": ");
124 write(out, n, value);
125 write(out, 0, "\r\n");
126 }
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 private static int write(OutputStream out, int i, String s) throws IOException {
143 byte[] bytes = s.getBytes("UTF8");
144 return write(out, i, bytes);
145 }
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 private static int write(OutputStream out, int width, byte[] bytes) throws IOException {
164 int w = width;
165 for (int i = 0; i < bytes.length; i++) {
166 if (w >= 72) {
167 out.write(CONTINUE);
168 w = 1;
169 }
170 out.write(bytes[i]);
171 w++;
172 }
173 return w;
174 }
175
176
177
178
179
180
181
182
183
184
185
186 private static void attributes(Attributes value, OutputStream out, boolean nice) throws IOException {
187 TreeMap<String,String> map = new TreeMap<String,String>(String.CASE_INSENSITIVE_ORDER);
188 for (Map.Entry<Object,Object> entry : value.entrySet()) {
189 map.put(entry.getKey().toString(), entry.getValue().toString());
190 }
191
192 map.remove("Manifest-Version");
193
194
195 for (Map.Entry<String,String> entry : map.entrySet()) {
196 writeEntry(out, entry.getKey(), entry.getValue(), nice);
197 }
198 }
199 }