View Javadoc

1   /*
2   jMimeMagic(TM) is a Java library for determining the content type of files or
3   streams.
4   
5   Copyright (C) 2004 David Castro
6   
7   This library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Lesser General Public
9   License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11  
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  Lesser General Public License for more details.
16  
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library; if not, write to the Free Software
19  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  
21  For more information, please email arimus@users.sourceforge.net
22  */
23  package net.sf.jmimemagic;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  import java.nio.ByteBuffer;
29  
30  import java.util.ArrayList;
31  import java.util.Collection;
32  import java.util.HashMap;
33  import java.util.Iterator;
34  import java.util.Map;
35  
36  
37  /***
38   * This class represents a single match test
39   *
40   * @author $Author: arimus $
41   * @version $Revision: 1.10 $
42   */
43  public class MagicMatch implements Cloneable
44  {
45      private static Log log = LogFactory.getLog(MagicMatch.class);
46      private String mimeType = null;
47      private String extension = null;
48      private String description = null;
49      private ByteBuffer test = null;
50      private int offset = 0;
51      private int length = 0;
52  
53      // possible types:
54      //     byte, short, long, string, date, beshort, belong, bedate, leshort,
55      //     lelong, ledate, regex
56      private String type = "";
57      private long bitmask = 0xFFFFFFFFL;
58      private char comparator = '\0';
59      private ArrayList subMatches = new ArrayList(0);
60      private Map properties;
61  
62      /*** 
63       * constructor 
64       */
65      public MagicMatch()
66      {
67          log.debug("instantiated");
68      }
69  
70      /***
71       * print information about this match
72       *
73       * @return DOCUMENT ME!
74       */
75      public String print()
76      {
77          StringBuffer string = new StringBuffer();
78          string.append("\n");
79          string.append("mime type: ").append(mimeType).append("\n");
80          string.append("description: ").append(description).append("\n");
81          string.append("extension: ").append(extension).append("\n");
82          string.append("offset: ").append(offset).append("\n");
83          string.append("length: ").append(length).append("\n");
84          string.append("test: ").append(new String(test.array())).append("\n");
85          string.append("type: ").append(type).append("\n");
86          string.append("comparator: ").append(comparator).append("\n");
87          string.append("bitmask: ").append(bitmask);
88  
89          return string.toString();
90      }
91  
92      /***
93       * set the mime type for this magic match
94       *
95       * @param value DOCUMENT ME!
96       */
97      public void setMimeType(String value)
98      {
99          mimeType = value;
100     }
101 
102     /***
103      * get the magic match for this magic match
104      *
105      * @return the mime type for this magic match
106      */
107     public String getMimeType()
108     {
109         return mimeType;
110     }
111 
112     /***
113      * set the extension for this magic match
114      *
115      * @param value DOCUMENT ME!
116      */
117     public void setExtension(String value)
118     {
119         extension = value;
120     }
121 
122     /***
123      * get the extension for this magic match
124      *
125      * @return the extension for this magic match
126      */
127     public String getExtension()
128     {
129         return extension;
130     }
131 
132     /***
133      * set the description for this magic match
134      *
135      * @param value DOCUMENT ME!
136      */
137     public void setDescription(String value)
138     {
139         description = value;
140     }
141 
142     /***
143      * get the description for this magic match
144      *
145      * @return the description for thie magic match
146      */
147     public String getDescription()
148     {
149         return description;
150     }
151 
152     /***
153      * set the test value for thie magic match
154      *
155      * @param value DOCUMENT ME!
156      */
157     public void setTest(ByteBuffer value)
158     {
159         test = value;
160     }
161 
162     /***
163      * get the test value for this magic match
164      *
165      * @return DOCUMENT ME!
166      */
167     public ByteBuffer getTest()
168     {
169         return test;
170     }
171 
172     /***
173      * set the offset in the stream we are comparing to the test value for this magic match
174      *
175      * @param value DOCUMENT ME!
176      */
177     public void setOffset(int value)
178     {
179         this.offset = value;
180     }
181 
182     /***
183      * get the offset in the stream we are comparing to the test value for this magic match
184      *
185      * @return the offset for this magic match
186      */
187     public int getOffset()
188     {
189         return offset;
190     }
191 
192     /***
193      * set the length we are restricting the comparison to for this magic match
194      *
195      * @param value DOCUMENT ME!
196      */
197     public void setLength(int value)
198     {
199         this.length = value;
200     }
201 
202     /***
203      * get the length we are restricting the comparison to for this magic match
204      *
205      * @return DOCUMENT ME!
206      */
207     public int getLength()
208     {
209         return length;
210     }
211 
212     /***
213      * set the type of match to perform for this magic match
214      *
215      * @param value DOCUMENT ME!
216      */
217     public void setType(String value)
218     {
219         this.type = value;
220     }
221 
222     /***
223      * get the type of match for this magic match
224      *
225      * @return DOCUMENT ME!
226      */
227     public String getType()
228     {
229         return type;
230     }
231 
232     /***
233      * set the bitmask that will be applied for this magic match
234      *
235      * @param value DOCUMENT ME!
236      */
237     public void setBitmask(String value)
238     {
239         if (value != null) {
240             this.bitmask = Long.decode(value).intValue();
241         }
242     }
243 
244     /***
245      * get the bitmask that will be applied for this magic match
246      *
247      * @return the bitmask for this magic match
248      */
249     public long getBitmask()
250     {
251         return bitmask;
252     }
253 
254     /***
255      * set the comparator for this magic match
256      *
257      * @param value DOCUMENT ME!
258      */
259     public void setComparator(String value)
260     {
261         this.comparator = value.charAt(0);
262     }
263 
264     /***
265      * get the comparator for this magic match
266      *
267      * @return the comparator for this magic match
268      */
269     public char getComparator()
270     {
271         return comparator;
272     }
273 
274     /***
275      * set the properties for this magic match
276      *
277      * @param properties DOCUMENT ME!
278      */
279     public void setProperties(Map properties)
280     {
281         this.properties = properties;
282     }
283 
284     /***
285      * get the properties for this magic match
286      *
287      * @return the properties for this magic match
288      */
289     public Map getProperties()
290     {
291         return properties;
292     }
293 
294     /***
295      * add a submatch to this magic match
296      *
297      * @param m a magic match
298      */
299     public void addSubMatch(MagicMatch m)
300     {
301         log.debug("adding submatch '" + m.getDescription() + "' to '" + getDescription() + "'");
302         subMatches.add(m);
303     }
304 
305     /***
306      * set all submatches
307      *
308      * @param a a collection of submatches
309      */
310     public void setSubMatches(Collection a)
311     {
312         log.debug("setting submatches for '" + getDescription() + "'");
313         subMatches.clear();
314         subMatches.addAll(a);
315     }
316 
317     /***
318      * get all submatches for this magic match
319      *
320      * @return a collection of submatches
321      */
322     public Collection getSubMatches()
323     {
324         return subMatches;
325     }
326 
327     /***
328      * determine if this match or any submatches has the description
329      *
330      * @param desc DOCUMENT ME!
331      *
332      * @return whether or not the description matches
333      */
334     public boolean descriptionMatches(String desc)
335     {
336         if ((description != null) && description.equals(desc)) {
337             return true;
338         }
339 
340         Collection submatches = getSubMatches();
341         Iterator i = submatches.iterator();
342         MagicMatch m = null;
343 
344         while (i.hasNext()) {
345             m = (MagicMatch) i.next();
346 
347             if (m.descriptionMatches(desc)) {
348                 return true;
349             }
350         }
351 
352         return false;
353     }
354 
355     /***
356      * determine if this match or any submatches has the description
357      *
358      * @param desc DOCUMENT ME!
359      *
360      * @return whether or not the description matches
361      */
362     public boolean mimeTypeMatches(String desc)
363     {
364         if ((mimeType != null) && mimeType.equals(desc)) {
365             return true;
366         }
367 
368         Collection submatches = getSubMatches();
369         Iterator i = submatches.iterator();
370         MagicMatch m = null;
371 
372         while (i.hasNext()) {
373             m = (MagicMatch) i.next();
374 
375             if (m.mimeTypeMatches(desc)) {
376                 return true;
377             }
378         }
379 
380         return false;
381     }
382 
383     /***
384      * DOCUMENT ME!
385      *
386      * @return DOCUMENT ME!
387      *
388      * @throws CloneNotSupportedException DOCUMENT ME!
389      */
390     protected Object clone()
391         throws CloneNotSupportedException
392     {
393         MagicMatch clone = new MagicMatch();
394         clone.setBitmask(Long.toString(bitmask, 8));
395         clone.setComparator("" + comparator);
396         clone.setDescription(description);
397         clone.setExtension(extension);
398         clone.setLength(length);
399         clone.setMimeType(mimeType);
400         clone.setOffset(offset);
401 
402         // these properties should only be String types, so we shouldn't have to clone them
403         HashMap m = new HashMap();
404         m.putAll(properties);
405         clone.setProperties(m);
406 
407         Iterator i = subMatches.iterator();
408         ArrayList a = new ArrayList();
409 
410         while (i.hasNext()) {
411             MagicMatch mm = (MagicMatch) i.next();
412             a.add(mm);
413         }
414 
415         clone.setSubMatches(a);
416 
417         clone.setTest(test);
418         clone.setType(type);
419 
420         // TODO Auto-generated method stub
421         return clone;
422     }
423 }