2 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * - Neither the name of the Git Development Community nor the
19 * names of its contributors may be used to endorse or promote
20 * products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 package org
.spearce
.jgit
.pgm
.build
;
41 import java
.io
.FileInputStream
;
42 import java
.io
.IOException
;
43 import java
.io
.InputStream
;
44 import java
.util
.ArrayList
;
45 import java
.util
.Enumeration
;
46 import java
.util
.HashMap
;
47 import java
.util
.List
;
49 import java
.util
.zip
.ZipEntry
;
50 import java
.util
.zip
.ZipFile
;
51 import java
.util
.zip
.ZipOutputStream
;
53 import org
.kohsuke
.args4j
.CmdLineException
;
54 import org
.kohsuke
.args4j
.CmdLineParser
;
55 import org
.kohsuke
.args4j
.Option
;
56 import org
.kohsuke
.args4j
.spi
.MapOptionHandler
;
59 * Combines multiple JAR and directory sources into a single JAR file.
61 * This is a crude command line utility to combine multiple JAR files into a
62 * single JAR file, without first needing to unpack the individual JARs.
64 * The output ZIP stream is sent to standard out and can be redirected onto the
65 * end of a shell script which starts the JRE.
67 public class JarLinkUtil
{
69 * Combine multiple JARs.
72 * the command line arguments indicating the files to pack.
74 * a source file could not be read.
76 public static void main(final String
[] argv
) throws IOException
{
77 final JarLinkUtil util
= new JarLinkUtil();
78 final CmdLineParser clp
= new CmdLineParser(util
);
80 clp
.parseArgument(argv
);
81 } catch (CmdLineException e
) {
82 clp
.printSingleLineUsage(System
.err
);
88 @Option(name
= "-include", required
= true)
89 private List
<File
> includes
= new ArrayList
<File
>();
91 @Option(name
= "-file", handler
= MapOptionHandler
.class)
92 private Map
<String
, String
> files
= new HashMap
<String
, String
>();
94 private final Map
<String
, File
> chosenSources
= new HashMap
<String
, File
>();
96 private long creationTime
;
98 private ZipOutputStream zos
;
100 private JarLinkUtil() {
101 // Command line utility only.
104 private void run() throws IOException
{
105 for (final File src
: includes
) {
109 scanDirectory(src
, src
, "");
111 for (final Map
.Entry
<String
, String
> e
: files
.entrySet())
112 chosenSources
.put(e
.getKey(), new File(e
.getValue()));
114 creationTime
= System
.currentTimeMillis();
115 zos
= new ZipOutputStream(System
.out
);
118 for (final File src
: includes
) {
122 appendDirectory(src
, src
, "");
124 for (final String name
: files
.keySet())
125 appendFile(chosenSources
.get(name
), name
);
130 private void scanJar(final File jarPath
) throws IOException
{
131 final ZipFile zf
= new ZipFile(jarPath
);
132 final Enumeration
<?
extends ZipEntry
> e
= zf
.entries();
133 while (e
.hasMoreElements())
134 chosenSources
.put(e
.nextElement().getName(), jarPath
);
138 private void scanDirectory(final File rootPath
, final File dirPath
,
139 final String pfx
) throws IOException
{
140 final File
[] entries
= dirPath
.listFiles();
143 for (final File e
: entries
) {
144 if (e
.getName().equals(".") || e
.getName().equals(".."))
148 scanDirectory(rootPath
, e
, pfx
+ e
.getName() + "/");
150 chosenSources
.put(pfx
+ e
.getName(), rootPath
);
154 private void appendJar(final File jarPath
) throws IOException
{
155 final ZipFile zf
= new ZipFile(jarPath
);
156 final Enumeration
<?
extends ZipEntry
> e
= zf
.entries();
157 while (e
.hasMoreElements()) {
158 final ZipEntry ze
= e
.nextElement();
159 final String name
= ze
.getName();
160 if (chosenSources
.get(name
) == jarPath
)
161 appendEntry(name
, ze
.getSize(), ze
.getTime(), zf
162 .getInputStream(ze
));
167 private void appendDirectory(final File rootDir
, final File dirPath
,
168 final String pfx
) throws IOException
{
169 final File
[] entries
= dirPath
.listFiles();
172 for (final File e
: entries
) {
173 if (e
.getName().equals(".") || e
.getName().equals(".."))
177 appendDirectory(rootDir
, e
, pfx
+ e
.getName() + "/");
178 else if (chosenSources
.get(pfx
+ e
.getName()) == rootDir
)
179 appendFile(e
, pfx
+ e
.getName());
183 private void appendFile(final File path
, final String name
)
185 final long len
= path
.length();
186 final InputStream is
= new FileInputStream(path
);
187 appendEntry(name
, len
, creationTime
, is
);
190 private void appendEntry(final String name
, final long len
,
191 final long time
, final InputStream is
) throws IOException
{
192 final ZipEntry ze
= new ZipEntry(name
);
195 zos
.putNextEntry(ze
);
197 final byte[] buf
= new byte[4096];
199 while ((n
= is
.read(buf
)) >= 0)
200 zos
.write(buf
, 0, n
);