1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.tika.mime;
18
19 import java.util.ArrayList;
20
21
22
23
24 public final class MimeType implements Comparable<MimeType> {
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public static boolean isValid(String name) {
42 if (name == null) {
43 throw new IllegalArgumentException("Name is missing");
44 }
45
46 boolean slash = false;
47 for (int i = 0; i < name.length(); i++) {
48 char ch = name.charAt(i);
49 if (ch <= ' ' || ch >= 127 || ch == '(' || ch == ')' ||
50 ch == '<' || ch == '>' || ch == '@' || ch == ',' ||
51 ch == ';' || ch == ':' || ch == '\\' || ch == '"' ||
52 ch == '[' || ch == ']' || ch == '?' || ch == '=') {
53 return false;
54 } else if (ch == '/') {
55 if (slash || i == 0 || i + 1 == name.length()) {
56 return false;
57 }
58 slash = true;
59 }
60 }
61 return slash;
62 }
63
64
65
66
67 private final MimeTypes registry;
68
69
70
71
72 private final String name;
73
74
75
76
77 private String description = "";
78
79
80
81
82
83 private MimeType superType = null;
84
85
86 private final ArrayList<Magic> magics = new ArrayList<Magic>();
87
88
89 private final ArrayList<RootXML> rootXML = new ArrayList<RootXML>();
90
91
92 private int minLength = 0;
93
94
95
96
97
98
99
100
101
102
103
104 MimeType(MimeTypes registry, String name) {
105 if (registry == null) {
106 throw new IllegalArgumentException("Registry is missing");
107 }
108 if (!MimeType.isValid(name) || !name.equals(name.toLowerCase())) {
109 throw new IllegalArgumentException("Media type name is invalid");
110 }
111 this.registry = registry;
112 this.name = name;
113 }
114
115
116
117
118
119
120 public String getName() {
121 return name;
122 }
123
124
125
126
127
128
129 public MimeType getSuperType() {
130 return superType;
131 }
132
133 public void setSuperType(MimeType type) throws MimeTypeException {
134 if (type == null) {
135 throw new IllegalArgumentException("MimeType is missing");
136 }
137 if (type.registry != registry) {
138 throw new IllegalArgumentException("MimeType is from a different registry");
139 }
140 if (this.isDescendantOf(type)) {
141
142 } else if (this == type) {
143 throw new MimeTypeException(
144 "Media type can not inherit itself: " + type);
145 } else if (type.isDescendantOf(this)) {
146 throw new MimeTypeException(
147 "Media type can not inherit its descendant: " + type);
148 } else if (superType == null) {
149 superType = type;
150 } else if (type.isDescendantOf(superType)) {
151 superType = type;
152 } else {
153 throw new MimeTypeException(
154 "Conflicting media type inheritance: " + type);
155 }
156 }
157
158 public boolean isDescendantOf(MimeType type) {
159 if (type == null) {
160 throw new IllegalArgumentException("MimeType is missing");
161 }
162 synchronized (registry) {
163 for (MimeType t = superType; t != null; t = t.superType) {
164 if (t == type) {
165 return true;
166 }
167 }
168 return false;
169 }
170 }
171
172
173
174
175
176
177 public String getDescription() {
178 return description;
179 }
180
181
182
183
184
185
186 public void setDescription(String description) {
187 if (description == null) {
188 throw new IllegalArgumentException("Description is missing");
189 }
190 this.description = description;
191 }
192
193
194
195
196
197
198
199
200 public void addAlias(String alias) throws MimeTypeException {
201 if (isValid(alias)) {
202 alias = alias.toLowerCase();
203 if (!name.equals(alias)) {
204 registry.addAlias(this, alias);
205 }
206 } else {
207 throw new MimeTypeException("Invalid media type alias: " + alias);
208 }
209 }
210
211
212
213
214
215
216
217 void addRootXML(String namespaceURI, String localName) {
218 rootXML.add(new RootXML(this, namespaceURI, localName));
219 }
220
221 boolean matchesXML(String namespaceURI, String localName) {
222 for (RootXML xml : rootXML) {
223 if (xml.matches(namespaceURI, localName)) {
224 return true;
225 }
226 }
227 return false;
228 }
229
230 boolean hasRootXML() {
231 return (rootXML.size() > 0);
232 }
233
234 RootXML[] getRootXMLs() {
235 return rootXML.toArray(new RootXML[rootXML.size()]);
236 }
237
238 Magic[] getMagics() {
239 return magics.toArray(new Magic[magics.size()]);
240 }
241
242 void addMagic(Magic magic) {
243 if (magic == null) {
244 return;
245 }
246 magics.add(magic);
247 }
248
249 int getMinLength() {
250 return minLength;
251 }
252
253 public boolean hasMagic() {
254 return (magics.size() > 0);
255 }
256
257 public boolean matchesMagic(byte[] data) {
258 for (int i = 0; i < magics.size(); i++) {
259 Magic magic = magics.get(i);
260 if (magic.eval(data)) {
261 return true;
262 }
263 }
264 return false;
265 }
266
267 public boolean matches(byte[] data) {
268 return matchesMagic(data);
269 }
270
271
272
273
274
275 class RootXML {
276
277 private MimeType type = null;
278
279 private String namespaceURI = null;
280
281 private String localName = null;
282
283 RootXML(MimeType type, String namespaceURI, String localName) {
284 if (isEmpty(namespaceURI) && isEmpty(localName)) {
285 throw new IllegalArgumentException(
286 "Both namespaceURI and localName cannot be empty");
287 }
288 this.type = type;
289 this.namespaceURI = namespaceURI;
290 this.localName = localName;
291 }
292
293 boolean matches(String namespaceURI, String localName) {
294
295 if (!isEmpty(this.namespaceURI)) {
296 if (!this.namespaceURI.equals(namespaceURI)) {
297 return false;
298 }
299 }
300 else{
301
302
303 if(!isEmpty(namespaceURI)){
304 return false;
305 }
306 }
307
308
309 if (!isEmpty(this.localName)) {
310 if (!this.localName.equals(localName)) {
311 return false;
312 }
313 }
314 else{
315
316
317 if(!isEmpty(localName)){
318 return false;
319 }
320 }
321 return true;
322 }
323
324
325
326
327 private boolean isEmpty(String str) {
328 return (str == null) || (str.equals(""));
329 }
330
331 MimeType getType() {
332 return type;
333 }
334
335 String getNameSpaceURI() {
336 return namespaceURI;
337 }
338
339 String getLocalName() {
340 return localName;
341 }
342
343 public String toString() {
344 return type + ", " + namespaceURI + ", " + localName;
345 }
346 }
347
348
349
350 public int compareTo(MimeType type) {
351 if (type == null) {
352 throw new IllegalArgumentException("MimeType is missing");
353 }
354 if (type == this) {
355 return 0;
356 } else if (this.isDescendantOf(type)) {
357 return 1;
358 } else if (type.isDescendantOf(this)) {
359 return -1;
360 } else if (superType != null) {
361 return superType.compareTo(type);
362 } else if (type.superType != null) {
363 return compareTo(type.superType);
364 } else {
365 return name.compareTo(type.name);
366 }
367 }
368
369
370
371
372
373
374
375
376 public String toString() {
377 return name;
378 }
379
380 }