OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [util/] [jar/] [Manifest.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* Manifest.java -- Reads, writes and manipulaties jar manifest files
2
   Copyright (C) 2000, 2004 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
package java.util.jar;
39
 
40
import java.io.BufferedReader;
41
import java.io.BufferedWriter;
42
import java.io.IOException;
43
import java.io.InputStream;
44
import java.io.InputStreamReader;
45
import java.io.OutputStream;
46
import java.io.OutputStreamWriter;
47
import java.io.PrintWriter;
48
import java.util.Hashtable;
49
import java.util.Iterator;
50
import java.util.Map;
51
 
52
/**
53
 * Reads, writes and manipulaties jar manifest files.
54
 * XXX
55
 *
56
 * @since 1.2
57
 * @author Mark Wielaard (mark@klomp.org)
58
 */
59
public class Manifest implements Cloneable
60
{
61
  // Fields
62
 
63
  /** The main attributes of the manifest (jar file). */
64
  private final Attributes mainAttr;
65
 
66
  /** A map of atrributes for all entries described in this Manifest. */
67
  private final Map entries;
68
 
69
  // Constructors
70
 
71
  /**
72
   * Creates a new empty Manifest.
73
   */
74
  public Manifest()
75
  {
76
    mainAttr = new Attributes();
77
    entries = new Hashtable();
78
  }
79
 
80
  /**
81
   * Creates a Manifest from the supplied input stream.
82
   *
83
   * @see #read(InputStream)
84
   * @see #write(OutputStream)
85
   *
86
   * @param in the input stream to read the manifest from
87
   * @exception IOException when an i/o exception occurs or the input stream
88
   * does not describe a valid manifest
89
   */
90
  public Manifest(InputStream in) throws IOException
91
  {
92
    this();
93
    read(in);
94
  }
95
 
96
  /**
97
   * Creates a Manifest from another Manifest.
98
   * Makes a deep copy of the main attributes, but a shallow copy of
99
   * the other entries. This means that you can freely add, change or remove
100
   * the main attributes or the entries of the new manifest without effecting
101
   * the original manifest, but adding, changing or removing attributes from
102
   * a particular entry also changes the attributes of that entry in the
103
   * original manifest.
104
   *
105
   * @see #clone()
106
   * @param man the Manifest to copy from
107
   */
108
  public Manifest(Manifest man)
109
  {
110
    mainAttr = new Attributes(man.getMainAttributes());
111
    entries = new Hashtable(man.getEntries());
112
  }
113
 
114
  // Methods
115
 
116
  /**
117
   * Gets the main attributes of this Manifest.
118
   */
119
  public Attributes getMainAttributes()
120
  {
121
    return mainAttr;
122
  }
123
 
124
  /**
125
   * Gets a map of entry Strings to Attributes for all the entries described
126
   * in this manifest. Adding, changing or removing from this entries map
127
   * changes the entries of this manifest.
128
   */
129
  public Map getEntries()
130
  {
131
    return entries;
132
  }
133
 
134
  /**
135
   * Returns the Attributes associated with the Entry.
136
   * <p>
137
   * Implemented as:
138
   * <code>return (Attributes)getEntries().get(entryName)</code>
139
   *
140
   * @param entryName the name of the entry to look up
141
   * @return the attributes associated with the entry or null when none
142
   */
143
  public Attributes getAttributes(String entryName)
144
  {
145
    return (Attributes) getEntries().get(entryName);
146
  }
147
 
148
  /**
149
   * Clears the main attributes and removes all the entries from the
150
   * manifest.
151
   */
152
  public void clear()
153
  {
154
    mainAttr.clear();
155
    entries.clear();
156
  }
157
 
158
  /**
159
   * XXX
160
   */
161
  public void read(InputStream in) throws IOException
162
  {
163
    BufferedReader br =
164
      new BufferedReader(new InputStreamReader(in, "8859_1"));
165
    read_main_section(getMainAttributes(), br);
166
    read_individual_sections(getEntries(), br);
167
  }
168
 
169
  // Private Static methods for reading the Manifest file from BufferedReader
170
 
171
  private static void read_main_section(Attributes attr,
172
                                        BufferedReader br) throws IOException
173
  {
174
    // According to the spec we should actually call read_version_info() here.
175
    read_attributes(attr, br);
176
    // Explicitly set Manifest-Version attribute if not set in Main
177
    // attributes of Manifest.
178
    if (attr.getValue(Attributes.Name.MANIFEST_VERSION) == null)
179
            attr.putValue(Attributes.Name.MANIFEST_VERSION, "0.0");
180
  }
181
 
182
  /**
183
   * Pedantic method that requires the next attribute in the Manifest to be
184
   * the "Manifest-Version". This follows the Manifest spec closely but
185
   * reject some jar Manifest files out in the wild.
186
   */
187
  private static void read_version_info(Attributes attr,
188
                                        BufferedReader br) throws IOException
189
  {
190
    String version_header = Attributes.Name.MANIFEST_VERSION.toString();
191
    try
192
      {
193
        String value = expect_header(version_header, br);
194
        attr.putValue(Attributes.Name.MANIFEST_VERSION, value);
195
      }
196
    catch (IOException ioe)
197
      {
198
        throw new JarException("Manifest should start with a " +
199
                               version_header + ": " + ioe.getMessage());
200
      }
201
  }
202
 
203
  private static String expect_header(String header, BufferedReader br)
204
    throws IOException
205
  {
206
    String s = br.readLine();
207
    if (s == null)
208
      {
209
        throw new JarException("unexpected end of file");
210
      }
211
    return expect_header(header, br, s);
212
  }
213
 
214
  private static String expect_header(String header, BufferedReader br,
215
                                      String s) throws IOException
216
  {
217
    try
218
      {
219
        String name = s.substring(0, header.length() + 1);
220
        if (name.equalsIgnoreCase(header + ":"))
221
          {
222
            String value_start = s.substring(header.length() + 2);
223
            return read_header_value(value_start, br);
224
          }
225
      }
226
    catch (IndexOutOfBoundsException iobe)
227
      {
228
      }
229
    // If we arrive here, something went wrong
230
    throw new JarException("unexpected '" + s + "'");
231
  }
232
 
233
  private static String read_header_value(String s, BufferedReader br)
234
    throws IOException
235
  {
236
    boolean try_next = true;
237
    while (try_next)
238
      {
239
        // Lets see if there is something on the next line
240
        br.mark(1);
241
        if (br.read() == ' ')
242
          {
243
            s += br.readLine();
244
          }
245
        else
246
          {
247
            br.reset();
248
            try_next = false;
249
          }
250
      }
251
    return s;
252
  }
253
 
254
  private static void read_attributes(Attributes attr,
255
                                      BufferedReader br) throws IOException
256
  {
257
    String s = br.readLine();
258
    while (s != null && (!s.equals("")))
259
      {
260
        read_attribute(attr, s, br);
261
        s = br.readLine();
262
      }
263
  }
264
 
265
  private static void read_attribute(Attributes attr, String s,
266
                                     BufferedReader br) throws IOException
267
  {
268
    try
269
      {
270
        int colon = s.indexOf(": ");
271
        String name = s.substring(0, colon);
272
        String value_start = s.substring(colon + 2);
273
        String value = read_header_value(value_start, br);
274
        attr.putValue(name, value);
275
      }
276
    catch (IndexOutOfBoundsException iobe)
277
      {
278
        throw new JarException("Manifest contains a bad header: " + s);
279
      }
280
  }
281
 
282
  private static void read_individual_sections(Map entries,
283
                                               BufferedReader br) throws
284
    IOException
285
  {
286
    String s = br.readLine();
287
    while (s != null && (!s.equals("")))
288
      {
289
        Attributes attr = read_section_name(s, br, entries);
290
        read_attributes(attr, br);
291
        s = br.readLine();
292
      }
293
  }
294
 
295
  private static Attributes read_section_name(String s, BufferedReader br,
296
                                              Map entries) throws JarException
297
  {
298
    try
299
      {
300
        String name = expect_header("Name", br, s);
301
        Attributes attr = new Attributes();
302
        entries.put(name, attr);
303
        return attr;
304
      }
305
    catch (IOException ioe)
306
      {
307
        throw new JarException
308
          ("Section should start with a Name header: " + ioe.getMessage());
309
      }
310
  }
311
 
312
  /**
313
   * XXX
314
   */
315
  public void write(OutputStream out) throws IOException
316
  {
317
    PrintWriter pw =
318
      new PrintWriter(new
319
                      BufferedWriter(new OutputStreamWriter(out, "8859_1")));
320
    write_main_section(getMainAttributes(), pw);
321
    pw.println();
322
    write_individual_sections(getEntries(), pw);
323
    if (pw.checkError())
324
      {
325
        throw new JarException("Error while writing manifest");
326
      }
327
  }
328
 
329
  // Private Static functions for writing the Manifest file to a PrintWriter
330
 
331
  private static void write_main_section(Attributes attr,
332
                                         PrintWriter pw) throws JarException
333
  {
334
    write_version_info(attr, pw);
335
    write_main_attributes(attr, pw);
336
  }
337
 
338
  private static void write_version_info(Attributes attr, PrintWriter pw)
339
  {
340
    // First check if there is already a version attribute set
341
    String version = attr.getValue(Attributes.Name.MANIFEST_VERSION);
342
    if (version == null)
343
      {
344
        version = "1.0";
345
      }
346
    write_header(Attributes.Name.MANIFEST_VERSION.toString(), version, pw);
347
  }
348
 
349
  private static void write_header(String name, String value, PrintWriter pw)
350
  {
351
    pw.print(name + ": ");
352
 
353
    int last = 68 - name.length();
354
    if (last > value.length())
355
      {
356
        pw.println(value);
357
      }
358
    else
359
      {
360
        pw.println(value.substring(0, last));
361
      }
362
    while (last < value.length())
363
      {
364
        pw.print(" ");
365
        int end = (last + 69);
366
        if (end > value.length())
367
          {
368
            pw.println(value.substring(last));
369
          }
370
        else
371
          {
372
            pw.println(value.substring(last, end));
373
          }
374
        last = end;
375
      }
376
  }
377
 
378
  private static void write_main_attributes(Attributes attr, PrintWriter pw)
379
    throws JarException
380
  {
381
    Iterator it = attr.entrySet().iterator();
382
    while (it.hasNext())
383
      {
384
        Map.Entry entry = (Map.Entry) it.next();
385
        // Don't print the manifest version again
386
        if (!Attributes.Name.MANIFEST_VERSION.equals(entry.getKey()))
387
          {
388
            write_attribute_entry(entry, pw);
389
          }
390
      }
391
  }
392
 
393
  private static void write_attribute_entry(Map.Entry entry, PrintWriter pw)
394
    throws JarException
395
  {
396
    String name = entry.getKey().toString();
397
    String value = entry.getValue().toString();
398
 
399
    if (name.equalsIgnoreCase("Name"))
400
      {
401
        throw new JarException("Attributes cannot be called 'Name'");
402
      }
403
    if (name.startsWith("From"))
404
      {
405
        throw new
406
          JarException("Header cannot start with the four letters 'From'" +
407
                       name);
408
      }
409
    write_header(name, value, pw);
410
  }
411
 
412
  private static void write_individual_sections(Map entries, PrintWriter pw)
413
    throws JarException
414
  {
415
 
416
    Iterator it = entries.entrySet().iterator();
417
    while (it.hasNext())
418
      {
419
        Map.Entry entry = (Map.Entry) it.next();
420
        write_header("Name", entry.getKey().toString(), pw);
421
        write_entry_attributes((Attributes) entry.getValue(), pw);
422
        pw.println();
423
      }
424
  }
425
 
426
  private static void write_entry_attributes(Attributes attr, PrintWriter pw)
427
    throws JarException
428
  {
429
    Iterator it = attr.entrySet().iterator();
430
    while (it.hasNext())
431
      {
432
        Map.Entry entry = (Map.Entry) it.next();
433
        write_attribute_entry(entry, pw);
434
      }
435
  }
436
 
437
  /**
438
   * Makes a deep copy of the main attributes, but a shallow copy of
439
   * the other entries. This means that you can freely add, change or remove
440
   * the main attributes or the entries of the new manifest without effecting
441
   * the original manifest, but adding, changing or removing attributes from
442
   * a particular entry also changes the attributes of that entry in the
443
   * original manifest. Calls <CODE>new Manifest(this)</CODE>.
444
   */
445
  public Object clone()
446
  {
447
    return new Manifest(this);
448
  }
449
 
450
  /**
451
   * Checks if another object is equal to this Manifest object.
452
   * Another Object is equal to this Manifest object if it is an instance of
453
   * Manifest and the main attributes and the entries of the other manifest
454
   * are equal to this one.
455
   */
456
  public boolean equals(Object o)
457
  {
458
    return (o instanceof Manifest) &&
459
      (mainAttr.equals(((Manifest) o).mainAttr)) &&
460
      (entries.equals(((Manifest) o).entries));
461
  }
462
 
463
  /**
464
   * Calculates the hash code of the manifest. Implemented by a xor of the
465
   * hash code of the main attributes with the hash code of the entries map.
466
   */
467
  public int hashCode()
468
  {
469
    return mainAttr.hashCode() ^ entries.hashCode();
470
  }
471
 
472
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.