View Javadoc

1   package org.apache.maven.surefire.booter;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  
23  import java.io.*;
24  import java.util.StringTokenizer;
25  import java.util.zip.ZipEntry;
26  import java.util.zip.ZipOutputStream;
27  
28  /**
29   * Constructs a jar containing only a META-INF/MANIFEST.MF with specified attributes.
30   */
31  public class ManifestJarWriter
32  {
33  
34      /**
35       * The max length of a line in a Manifest
36       */
37      public static final int MAX_LINE_LENGTH = 72;
38  
39      /**
40       * Max length of a line section which is continued. Need to allow
41       * for the CRLF.
42       */
43      public static final int MAX_SECTION_LENGTH = MAX_LINE_LENGTH - 2;
44  
45      /**
46       * The End-Of-Line marker in manifests
47       */
48      public static final String EOL = "\r\n";
49  
50      private PrintWriter writer;
51  
52      public ManifestJarWriter( File jarFile )
53          throws IOException
54      {
55  
56          FileOutputStream fos = new FileOutputStream( jarFile );
57          ZipOutputStream zos = new ZipOutputStream( fos );
58          zos.setLevel( ZipOutputStream.STORED );
59          ZipEntry ze;
60          ze = new ZipEntry( "META-INF/MANIFEST.MF" );
61          zos.putNextEntry( ze );
62          writer = new PrintWriter( zos );
63      }
64  
65      /**
66       * Write a single attribute value out.  Should handle multiple lines of attribute value.
67       *
68       * @param name  the attribute name, e.g. "Main-Class"
69       * @param value the attribute value
70       * @throws java.io.IOException if the attribute value cannot be written
71       */
72      public void writeValue( String name, String value )
73          throws IOException
74      {
75          String nameValue = name + ": " + value;
76  
77          StringTokenizer tokenizer = new StringTokenizer( nameValue, "\n\r" );
78  
79          String prefix = "";
80  
81          while ( tokenizer.hasMoreTokens() )
82          {
83              writeLine( prefix + tokenizer.nextToken() );
84              prefix = " ";
85          }
86      }
87  
88      /**
89       * Write a single Manifest line. Should handle more than 72 characters of line
90       *
91       * @param line the manifest line to be written
92       * @throws java.io.IOException if the attribute line cannot be written
93       */
94      private void writeLine( String line )
95          throws IOException
96      {
97          while ( line.getBytes().length > MAX_LINE_LENGTH )
98          {
99              // try to find a MAX_LINE_LENGTH byte section
100             int breakIndex = MAX_SECTION_LENGTH;
101             String section = line.substring( 0, breakIndex );
102             while ( section.getBytes().length > MAX_SECTION_LENGTH && breakIndex > 0 )
103             {
104                 breakIndex--;
105                 section = line.substring( 0, breakIndex );
106             }
107             if ( breakIndex == 0 )
108             {
109                 throw new IOException( "Unable to write manifest line " + line );
110             }
111             writer.print( section + EOL );
112             line = " " + line.substring( breakIndex );
113         }
114         writer.print( line + EOL );
115     }
116 
117     public void close()
118     {
119         writer.flush();
120         writer.close();
121     }
122 
123 }