1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package net.sourceforge.osgi.deployment.maven.manifest;
23
24 import java.io.DataOutputStream;
25 import java.io.IOException;
26 import java.io.OutputStream;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.List;
30 import java.util.regex.Pattern;
31
32
33
34
35
36
37 public class OrderedManifest {
38
39
40
41
42
43
44 public static final String MANIFEST_VERSION = "Manifest-Version";
45
46
47
48
49 public static final Pattern HEADER_PATTERN = Pattern.compile("[A-Za-z0-9][-a-zA-Z0-9_]+");
50
51
52
53
54 protected static final String CONTENT_TYPE = "Content-Type";
55
56
57
58
59 protected static final ManifestEntry EMPTY_LINE = new ManifestEntry("", "");
60
61 private static final int MAXIMUM_MANIFEST_LINE_WIDTH = 72;
62 private final List< ManifestEntry > m_entries = Collections.synchronizedList(new ArrayList< ManifestEntry >());
63
64
65
66
67
68
69 private static class ManifestEntry {
70 private final String m_name;
71 private final String m_value;
72
73 public ManifestEntry(final String p_name, final String p_value) {
74 if (p_name == null || p_value == null) {
75 throw new IllegalArgumentException("NULL is not allowed as parameter");
76 }
77
78 final boolean nameEmpty = p_name.trim().length() == 0;
79 final boolean nameNotEmpty = p_name.trim().length() > 0;
80 final boolean valueNotEmpty = p_value.trim().length() > 0;
81
82 if (nameEmpty && valueNotEmpty) {
83 throw new IllegalArgumentException("name param was empty, so value param has also to be.");
84 }
85
86 if (nameNotEmpty && !HEADER_PATTERN.matcher(p_name).matches()) {
87 throw new IllegalArgumentException("Header name not matches OSGi specification.");
88 }
89 m_name = p_name;
90 m_value = p_value;
91 }
92
93 public boolean equals(final Object p_obj) {
94 if (p_obj == null) {
95 return false;
96 }
97
98 if (!this.getClass().equals(p_obj.getClass())) {
99 return false;
100 }
101
102 final ManifestEntry obj = (ManifestEntry) p_obj;
103 if (m_name.equals(obj.m_name) && m_value.equals(obj.m_value)) {
104 return true;
105 }
106 return false;
107 }
108
109 public int hashCode() {
110 return m_name.hashCode() + m_value.hashCode();
111 }
112 };
113
114
115
116
117
118
119
120 public final void add(final ManifestEntry p_manifestEntry) {
121 m_entries.add(p_manifestEntry);
122 }
123
124
125
126
127
128
129
130
131
132 public final void add(final String p_header, final String p_value) {
133 m_entries.add(new ManifestEntry(p_header, p_value));
134 }
135
136
137
138
139
140
141
142
143
144 public final void write(final OutputStream p_out) throws IOException {
145 final DataOutputStream dos = new DataOutputStream(p_out);
146
147 for (final ManifestEntry manifestEntry : m_entries) {
148 if (manifestEntry.equals(EMPTY_LINE)) {
149 dos.writeBytes("\r\n");
150 continue;
151 }
152
153 final StringBuffer buffer = new StringBuffer(manifestEntry.m_name);
154 buffer.append(": ");
155
156 String value = manifestEntry.m_value;
157 final byte[] vb = value.getBytes("UTF8");
158
159 value = new String(vb, "UTF8");
160 buffer.append(value);
161
162 buffer.append("\r\n");
163 OrderedManifest.make72Safe(buffer);
164 dos.writeBytes(buffer.toString());
165 }
166 dos.writeBytes("\r\n");
167 dos.flush();
168 }
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184 static void make72Safe(final StringBuffer p_line) {
185 final String lineBreak = "\r\n";
186 final String space = " ";
187 final String lineBreakAndSpace = lineBreak + space;
188
189 int length = p_line.length();
190 if (length > MAXIMUM_MANIFEST_LINE_WIDTH) {
191 int index = MAXIMUM_MANIFEST_LINE_WIDTH - lineBreak.length();
192 while (index < length - 2) {
193 p_line.insert(index, lineBreakAndSpace);
194 index += MAXIMUM_MANIFEST_LINE_WIDTH;
195 length += lineBreakAndSpace.length();
196 }
197 }
198 }
199 }