下面列出了怎么用java.util.jar.JarOutputStream的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public void createArchive(String path, String archiveName, Manifest manifest) {
File file = new File(getAbsolutePath(path), archiveName);
try {
if (!(file.createNewFile() || file.isFile())) {
throw new IOException("Cannot create file " + file);
}
FileOutputStream fileStream = new FileOutputStream(file);
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
ZipOutputStream zipStream = manifest != null ? new JarOutputStream(fileStream, manifest) : new ZipOutputStream(fileStream);
mapArchiveStreams.put(file.getPath(), zipStream);
} catch (IOException ex) {
DecompilerContext.getLogger().writeMessage("Cannot create archive " + file, ex);
}
}
private void createRuntimeConfigJar(Path dir, Map<String, LocalFile> localFiles) throws IOException {
LOG.debug("Create and copy {}", Constants.Files.RUNTIME_CONFIG_JAR);
// Jar everything under the given directory, which contains different files needed by AM/runnable containers
Location location = createTempLocation(Constants.Files.RUNTIME_CONFIG_JAR);
try (
JarOutputStream jarOutput = new JarOutputStream(location.getOutputStream());
DirectoryStream<Path> stream = Files.newDirectoryStream(dir)
) {
for (Path path : stream) {
jarOutput.putNextEntry(new JarEntry(path.getFileName().toString()));
Files.copy(path, jarOutput);
jarOutput.closeEntry();
}
}
LOG.debug("Done {}", Constants.Files.RUNTIME_CONFIG_JAR);
localFiles.put(Constants.Files.RUNTIME_CONFIG_JAR,
createLocalFile(Constants.Files.RUNTIME_CONFIG_JAR, location, true));
}
private static URL urlForJarWithEntries(String service, String... lines) throws IOException {
File jar = File.createTempFile("SimpleServiceLoaderTest", "jar");
jar.deleteOnExit();
try (JarOutputStream out = new JarOutputStream(new FileOutputStream(jar))) {
JarEntry jarEntry = new JarEntry("META-INF/services/" + service);
out.putNextEntry(jarEntry);
// It would be bad practice to use try-with-resources below, because closing the PrintWriter
// would close the JarOutputStream.
PrintWriter writer = new PrintWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
for (String line : lines) {
writer.println(line);
}
writer.flush();
}
return jar.toURI().toURL();
}
@Override
protected void setUp() throws Exception {
super.setUp();
System.setProperty("org.netbeans.core.modules.NbInstaller.noAutoDeps", "true");
Manifest man = new Manifest ();
man.getMainAttributes ().putValue ("Manifest-Version", "1.0");
man.getMainAttributes ().putValue ("OpenIDE-Module", "org.test.FormatDependency/1");
String req = "org.openide.modules.ModuleFormat1, org.openide.modules.ModuleFormat2";
man.getMainAttributes ().putValue ("OpenIDE-Module-Requires", req);
clearWorkDir();
moduleJarFile = new File(getWorkDir(), "ModuleFormatTest.jar");
JarOutputStream os = new JarOutputStream(new FileOutputStream(moduleJarFile), man);
os.putNextEntry (new JarEntry ("empty/test.txt"));
os.close ();
}
@Test
public void sourceJarClash() throws IOException {
Path sourcesa = temporaryFolder.newFile("sourcesa.jar").toPath();
try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(sourcesa))) {
jos.putNextEntry(new JarEntry("Test.java"));
jos.write("class Test { public static final String CONST = \"ONE\"; }".getBytes(UTF_8));
}
Path sourcesb = temporaryFolder.newFile("sourcesb.jar").toPath();
try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(sourcesb))) {
jos.putNextEntry(new JarEntry("Test.java"));
jos.write("class Test { public static final String CONST = \"TWO\"; }".getBytes(UTF_8));
}
Path output = temporaryFolder.newFile("output.jar").toPath();
try {
Main.compile(
optionsWithBootclasspath()
.setSourceJars(ImmutableList.of(sourcesa.toString(), sourcesb.toString()))
.setOutput(output.toString())
.build());
fail();
} catch (TurbineError e) {
assertThat(e).hasMessageThat().contains("error: duplicate declaration of Test");
}
}
/**
* Create jar file with specified files. If a specified file does not exist,
* a new jar entry will be created with the file name itself as the content.
*/
public static void createJar(String dest, String... files)
throws IOException {
try (JarOutputStream jos = new JarOutputStream(
new FileOutputStream(dest), new Manifest())) {
for (String file : files) {
System.out.println(String.format("Adding %s to %s",
file, dest));
// add an archive entry, and write a file
jos.putNextEntry(new JarEntry(file));
try (FileInputStream fis = new FileInputStream(file)) {
fis.transferTo(jos);
} catch (FileNotFoundException e) {
jos.write(file.getBytes());
}
}
}
System.out.println();
}
public NonIncrementalJarDexArchiveHook(Path targetPath) throws IOException {
this.targetPath = targetPath;
if (Files.isRegularFile(targetPath)) {
// we should read this file
this.readOnlyZipFile = new ZipFile(targetPath.toFile());
} else {
// we are creating this file
this.jarOutputStream =
new JarOutputStream(
new BufferedOutputStream(
Files.newOutputStream(
targetPath,
StandardOpenOption.WRITE,
StandardOpenOption.CREATE_NEW)));
}
}
private static void loadInstrumentationAgent(String myName, byte[] buf) throws Exception {
// Create agent jar file on the fly
Manifest m = new Manifest();
m.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
m.getMainAttributes().put(new Attributes.Name("Agent-Class"), myName);
m.getMainAttributes().put(new Attributes.Name("Can-Redefine-Classes"), "true");
File jarFile = File.createTempFile("agent", ".jar");
jarFile.deleteOnExit();
JarOutputStream jar = new JarOutputStream(new FileOutputStream(jarFile), m);
jar.putNextEntry(new JarEntry(myName.replace('.', '/') + ".class"));
jar.write(buf);
jar.close();
String pid = Long.toString(ProcessTools.getProcessId());
System.out.println("Our pid is = " + pid);
VirtualMachine vm = VirtualMachine.attach(pid);
vm.loadAgent(jarFile.getAbsolutePath());
}
/**
* Make a new ByteClassLoader.
*
* @param jar_name Basename of jar file to be read/written by this classloader.
* @param read If true, read classes from jar file instead of from parameter.
* @param write If true, write classes to jar files for offline study/use.
*
* @throws FileNotFoundException
* @throws IOException
*/
public ByteClassLoader(String jar_name, boolean read, boolean write)
throws FileNotFoundException, IOException {
super(read
? new URL[]{new URL("file:" + jar_name + ".jar")}
: new URL[0]);
this.read = read;
this.jar_name = jar_name;
this.jos = write
? new JarOutputStream(
new BufferedOutputStream(
new FileOutputStream(jar_name + ".jar"))) : null;
if (read && write) {
throw new Error("At most one of read and write may be true.");
}
}
static void generateLargeJar(File result, File source) throws IOException {
if (result.exists()) {
result.delete();
}
try (JarOutputStream copyTo = new JarOutputStream(new FileOutputStream(result));
JarFile srcJar = new JarFile(source)) {
for (JarEntry je : Collections.list(srcJar.entries())) {
copyTo.putNextEntry(je);
if (!je.isDirectory()) {
copyStream(srcJar.getInputStream(je), copyTo);
}
copyTo.closeEntry();
}
int many = Short.MAX_VALUE * 2 + 2;
for (int i = 0 ; i < many ; i++) {
JarEntry e = new JarEntry("F-" + i + ".txt");
copyTo.putNextEntry(e);
}
copyTo.flush();
copyTo.close();
}
}
private File writeJarFile(String name, JEntry... entries) throws IOException {
File f = new File(getWorkDir(), name);
JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(f));
try {
for (JEntry entry : entries) {
JarEntry jarEntry = new JarEntry(entry.name);
jarOut.putNextEntry(jarEntry);
jarOut.write(entry.content.getBytes("UTF-8"));
jarOut.closeEntry();
}
}
finally {
jarOut.close();
}
return f;
}
/**
* Create jar file with specified files. If a specified file does not exist,
* a new jar entry will be created with the file name itself as the content.
*/
public static void createJar(String dest, String... files)
throws IOException {
try (JarOutputStream jos = new JarOutputStream(
new FileOutputStream(dest), new Manifest())) {
for (String file : files) {
System.out.println(String.format("Adding %s to %s",
file, dest));
// add an archive entry, and write a file
jos.putNextEntry(new JarEntry(file));
try (FileInputStream fis = new FileInputStream(file)) {
Utils.transferTo(fis, jos);
} catch (FileNotFoundException e) {
jos.write(file.getBytes());
}
}
}
System.out.println();
}
/**
* Make a new ByteClassLoader.
*
* @param jar_name Basename of jar file to be read/written by this classloader.
* @param read If true, read classes from jar file instead of from parameter.
* @param write If true, write classes to jar files for offline study/use.
*
* @throws FileNotFoundException
* @throws IOException
*/
public ByteClassLoader(String jar_name, boolean read, boolean write)
throws FileNotFoundException, IOException {
super(read
? new URL[]{new URL("file:" + jar_name + ".jar")}
: new URL[0]);
this.read = read;
this.jar_name = jar_name;
this.jos = write
? new JarOutputStream(
new BufferedOutputStream(
new FileOutputStream(jar_name + ".jar"))) : null;
if (read && write) {
throw new Error("At most one of read and write may be true.");
}
}
public static void createActivityDex(String superClassName,
String targetClassName, File saveTo, String pluginId, String pkgName)
throws IOException {
byte[] dex = createActivityDex(superClassName, targetClassName,
pluginId, pkgName);
if (saveTo.getName().endsWith(".dex")) {
FileUtil.writeToFile(dex, saveTo);
} else {
JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(
saveTo));
jarOut.putNextEntry(new JarEntry(DexFormat.DEX_IN_JAR_NAME));
jarOut.write(dex);
jarOut.closeEntry();
jarOut.close();
}
}
/**
* Merges two jars. The first jar will get merged into the output jar.
* A running set of jar entries is kept so that duplicates are skipped.
* This has the side-effect that the first instance of a given entry will be added
* and all subsequent entries are skipped.
*
* @param jin The input jar
* @param jout The output jar
* @param entries The set of existing entries. Note that this set will be mutated as part of this call.
* @return The set of entries.
* @throws IOException
*/
private Set<String> copy(JarInputStream jin, JarOutputStream jout, Set<String> entries) throws IOException {
byte[] buffer = new byte[1024];
for(JarEntry entry = jin.getNextJarEntry(); entry != null; entry = jin.getNextJarEntry()) {
if(entries.contains(entry.getName())) {
continue;
}
LOG.debug("Merging jar entry {}", entry.getName());
entries.add(entry.getName());
jout.putNextEntry(entry);
int len = 0;
while( (len = jin.read(buffer)) > 0 ) {
jout.write(buffer, 0, len);
}
}
return entries;
}
private File changeManifest(File orig, String manifest) throws IOException {
File f = new File(getWorkDir(), orig.getName());
Manifest mf = new Manifest(new ByteArrayInputStream(manifest.getBytes("utf-8")));
mf.getMainAttributes().putValue("Manifest-Version", "1.0");
JarOutputStream os = new JarOutputStream(new FileOutputStream(f), mf);
JarFile jf = new JarFile(orig);
Enumeration<JarEntry> en = jf.entries();
InputStream is;
while (en.hasMoreElements()) {
JarEntry e = en.nextElement();
if (e.getName().equals("META-INF/MANIFEST.MF")) {
continue;
}
os.putNextEntry(e);
is = jf.getInputStream(e);
FileUtil.copy(is, os);
is.close();
os.closeEntry();
}
os.close();
return f;
}
static void copyJarFile(JarInputStream in, JarOutputStream out) throws IOException {
if (in.getManifest() != null) {
ZipEntry me = new ZipEntry(JarFile.MANIFEST_NAME);
out.putNextEntry(me);
in.getManifest().write(out);
out.closeEntry();
}
byte[] buffer = new byte[1 << 14];
for (JarEntry je; (je = in.getNextJarEntry()) != null; ) {
out.putNextEntry(je);
for (int nr; 0 < (nr = in.read(buffer)); ) {
out.write(buffer, 0, nr);
}
}
in.close();
markJarFile(out); // add PACK200 comment
}
/**
* Adds the class file bytes for a given class to a JAR stream.
*/
static void add(JarOutputStream jar, Class<?> c) throws IOException {
String name = c.getName();
String classAsPath = name.replace('.', '/') + ".class";
jar.putNextEntry(new JarEntry(classAsPath));
InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath);
int nRead;
byte[] buf = new byte[1024];
while ((nRead = stream.read(buf, 0, buf.length)) != -1) {
jar.write(buf, 0, nRead);
}
jar.closeEntry();
}
private static void addToJar(JarOutputStream jar, File dir, String prefix) throws IOException {
File[] content;
prefix = prefix == null ? "" : prefix;
if (dir.isDirectory()) {
content = dir.listFiles();
for (int i = 0, l = content.length; i < l; ++i) {
if (content[i].isDirectory()) {
jar.putNextEntry(new ZipEntry(prefix + (prefix.equals("") ? "" : "/") + content[i].getName() + "/"));
addToJar(jar, content[i], prefix + (prefix.equals("") ? "" : "/") + content[i].getName());
} else {
addToJarWriteFile(jar, content[i], prefix);
}
}
} else {
addToJarWriteFile(jar, dir, prefix);
}
}
/**
* Create a jar with just a manifest containing a Main-Class entry for SurefireBooter and a Class-Path entry for all
* classpath elements. Copied from surefire (ForkConfiguration#createJar())
*
* @param classPath List<String> of all classpath elements.
* @return
* @throws IOException
*/
private File createJar( List<String> classPath, String mainClass )
throws IOException
{
File file = File.createTempFile( "maven-exec", ".jar" );
file.deleteOnExit();
FileOutputStream fos = new FileOutputStream( file );
JarOutputStream jos = new JarOutputStream( fos );
jos.setLevel( JarOutputStream.STORED );
JarEntry je = new JarEntry( "META-INF/MANIFEST.MF" );
jos.putNextEntry( je );
Manifest man = new Manifest();
// we can't use StringUtils.join here since we need to add a '/' to
// the end of directory entries - otherwise the jvm will ignore them.
StringBuilder cp = new StringBuilder();
for ( String el : classPath )
{
// NOTE: if File points to a directory, this entry MUST end in '/'.
cp.append( new URL( new File( el ).toURI().toASCIIString() ).toExternalForm() + " " );
}
man.getMainAttributes().putValue( "Manifest-Version", "1.0" );
man.getMainAttributes().putValue( "Class-Path", cp.toString().trim() );
man.getMainAttributes().putValue( "Main-Class", mainClass );
man.write( jos );
jos.close();
return file;
}
protected void addSymLinks( Iterator nodes, JarOutputStream jarOut ) throws IOException {
jarOut.putNextEntry( new ZipEntry( "symlinks.sh" ) );
final PrintWriter out = new PrintWriter( jarOut );
out.println( "#!/bin/sh" );
while( nodes.hasNext() ) {
VarNode v = (VarNode) nodes.next();
VarNode rep = (VarNode) v.getReplacement();
if( v != rep ) {
out.println( "ln -s n"+rep.getNumber()+".html n"+v.getNumber()+".html" );
}
}
out.flush();
}
public static Path createJarFile(Path jarfile, Path dir, Path file) throws IOException {
// create the target directory
Path parent = jarfile.getParent();
if (parent != null)
Files.createDirectories(parent);
List<Path> entries = Files.find(dir.resolve(file), Integer.MAX_VALUE,
(p, attrs) -> attrs.isRegularFile())
.map(dir::relativize)
.collect(Collectors.toList());
try (OutputStream out = Files.newOutputStream(jarfile);
JarOutputStream jos = new JarOutputStream(out)) {
for (Path entry : entries) {
// map the file path to a name in the JAR file
Path normalized = entry.normalize();
String name = normalized
.subpath(0, normalized.getNameCount()) // drop root
.toString()
.replace(File.separatorChar, '/');
jos.putNextEntry(new JarEntry(name));
Files.copy(dir.resolve(entry), jos);
}
}
return jarfile;
}
public void copyJarFile(String sourceFileLocationWithFileName, String destinationDirectory)
throws IOException, URISyntaxException {
File sourceFile = new File(getClass().getResource(sourceFileLocationWithFileName).toURI());
File destinationFileDirectory = new File(destinationDirectory);
JarFile jarFile = new JarFile(sourceFile);
String fileName = jarFile.getName();
String fileNameLastPart = fileName.substring(fileName.lastIndexOf(File.separator));
File destinationFile = new File(destinationFileDirectory, fileNameLastPart);
JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(destinationFile));
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
InputStream inputStream = jarFile.getInputStream(jarEntry);
//jarOutputStream.putNextEntry(jarEntry);
//create a new jarEntry to avoid ZipException: invalid jarEntry compressed size
jarOutputStream.putNextEntry(new JarEntry(jarEntry.getName()));
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = inputStream.read(buffer)) != -1) {
jarOutputStream.write(buffer, 0, bytesRead);
}
inputStream.close();
jarOutputStream.flush();
jarOutputStream.closeEntry();
}
jarOutputStream.close();
}
static void createJAR(File cluster, String moduleName, Class metaInfHandler)
throws IOException {
File xml = new File(new File(new File(cluster, "config"), "Modules"), moduleName + ".xml");
File jar = new File(new File(cluster, "modules"), moduleName + ".jar");
xml.getParentFile().mkdirs();
jar.getParentFile().mkdirs();
Manifest mf = new Manifest();
mf.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
mf.getMainAttributes().putValue("OpenIDE-Module", moduleName.replace('-', '.'));
mf.getMainAttributes().putValue("OpenIDE-Module-Public-Packages", "-");
JarOutputStream os = new JarOutputStream(new FileOutputStream(jar), mf);
os.putNextEntry(new JarEntry("META-INF/services/org.netbeans.CLIHandler"));
os.write(metaInfHandler.getName().getBytes());
os.close();
FileWriter w = new FileWriter(xml);
w.write(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!DOCTYPE module PUBLIC \"-//NetBeans//DTD Module Status 1.0//EN\"\n" +
" \"http://www.netbeans.org/dtds/module-status-1_0.dtd\">\n" +
"<module name=\"" + moduleName.replace('-', '.') + "\">\n" +
" <param name=\"autoload\">false</param>\n" +
" <param name=\"eager\">false</param>\n" +
" <param name=\"enabled\">true</param>\n" +
" <param name=\"jar\">modules/" + moduleName + ".jar</param>\n" +
" <param name=\"release\">2</param>\n" +
" <param name=\"reloadable\">false</param>\n" +
" <param name=\"specversion\">3.4.0.1</param>\n" +
"</module>\n");
w.close();
}
void run(File inFile, JarOutputStream jstream) throws IOException {
// %%% maybe memory-map the file, and pass it straight into unpacker
ByteBuffer mappedFile = null;
try (FileInputStream fis = new FileInputStream(inFile)) {
run(fis, jstream, mappedFile);
}
// Note: caller is responsible to finish with jstream.
}
private File createModule(String fileName, String... attribs) throws IOException {
File d = new File(getWorkDir(), "modules");
d.mkdirs();
File m = new File(d, fileName);
FileOutputStream out = new FileOutputStream(m);
Manifest man = new Manifest();
for (int i = 0; i < attribs.length; i += 2) {
man.getMainAttributes().putValue(attribs[i], attribs[i + 1]);
}
JarOutputStream os = new JarOutputStream(out, man);
os.close();
return m;
}
/**
* Executes the creation of the Jar file.
*
* @throws IOException if the Jar cannot be written or any of the entries cannot be read.
*/
public void execute() throws IOException {
try (OutputStream os = Files.newOutputStream(jarPath);
BufferedOutputStream bos = new BufferedOutputStream(os);
JarOutputStream out = new JarOutputStream(bos)) {
// Create the manifest entry in the Jar file
writeManifestEntry(out, manifestContent());
for (Map.Entry<String, Path> entry : jarEntries.entrySet()) {
copyEntry(out, entry.getKey(), entry.getValue());
}
}
}
private static void initNextEntry(String filePath, JarOutputStream jarFile) throws IOException {
// ensure to close the previous entry if it exists
jarFile.closeEntry();
JarEntry entry = new JarEntry(filePath);
// ensure the output is deterministic by always setting the same timestamp for all files.
entry.setTime(FIXED_TIMESTAMP);
jarFile.putNextEntry(entry);
}
private void createJar(File file, String... manifestLines) throws Exception {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Manifest-Version: 1.0\n");
for (String line : manifestLines) {
stringBuilder.append(line).append("\n");
}
InputStream is = new ByteArrayInputStream(stringBuilder.toString().getBytes("UTF-8"));
try {
new JarOutputStream(new FileOutputStream(file), new Manifest(is)).close();
} finally {
is.close();
}
}
protected void addSingleFile(String source, Path destination, String jobId, Job job, FileSystem fs) throws IOException {
try (FSDataOutputStream hadoopOutputStream = fs.create(destination, false); InputStream urlInputStream = new URL(source).openStream()) {
// Copy raw file to hadoop
if (!(urlInputStream instanceof JarInputStream)) {
ByteStreams.copy(urlInputStream, hadoopOutputStream);
}
// Copy jar file to hadoop - Wildfly VFS returns files as JarInputStreams
else {
JarInputStream jarInputStream = (JarInputStream) urlInputStream;
try (JarOutputStream jarOutputStream = new JarOutputStream(hadoopOutputStream)) {
for (JarEntry jarEntry = jarInputStream.getNextJarEntry(); jarEntry != null; jarEntry = jarInputStream.getNextJarEntry()) {
jarOutputStream.putNextEntry(jarEntry);
ByteStreams.copy(urlInputStream, jarOutputStream);
}
}
}
// Add the jar to the job classpath
log.trace("Adding {} to the classpath for job {}", source, jobId);
job.addFileToClassPath(destination);
} catch (IOException e) {
// If the file already exists, ignore error
if (!e.getMessage().endsWith("already exists"))
throw e;
}
}