Prof. Dr. Th. Letschert

CS5233 Components – Models and Engineering - Komponententechnologien - Master of Science (Informatik)

Working with Jars (and other files using NIO)

Seite 1 © Th Letschert Jars http://download.oracle.com/javase/tutorial/deployment/jar/index.html

Jar Files Jar files : most important de-facto components in the Java biotope Jar file : in format Zip file : format for (compressed) archive file with (compressed) content files

Jar Tool command line tool /bin/jar create / manipulate / extract from jar files

Seite 2 Th Letschert Jars / Jar Tool

Jar Tool / common operations Create jar c[v0M]f jarfile inputfiles Options: jar c[v0]mf manifest jarfile inputfiles c create v verbose output 0 no compression Update M no manifest file jar u[v0M]f jarfile inputfiles f specify name of jar file jar u[v0]mf manifest jarfile inputfiles m specify name of manifest file u update Extract files x extract t display table of contents jar x[v]f jarfile [inputfiles]

List contents jar t[v]f jarfile [inputfiles]

Seite 3 Th Letschert Jars / Meta Information

Meta-Information a jar file may contain a directory META-INF containing “meta information”

META-INF the directory for meta information contains information relevant for configuration purposes files / directories that are recognized by standard Java tools: – META-INF/MANIFEST.MF – META-INF/INDEX.LIST – META-INF/x.SF – META-INF/x.DSA – META-INF/services/

Seite 4 Th Letschert Jars / Meta Information Manifest-Version: 1.0 Created-By: 1.7.0-ea () Manifest file MANIFEST.MF Example: Default manifest created by /bin/jar Text file (UTF-8) structured into name – value pairs. Has to start with the main attribute – Manifest-Version version number of the manifest specification Additional main-attributes may follow – Created-By vendor of the java implementation – Signature-Version the signature version – Class-Path space separated list of relative urls that extend the class path – Main-Class main class in case the jar file defines a standalone application – Extension-Name the name of the extension (the jar file contains an extension) – … etc. ….

Per entry attributes may follow after an empty line These are attributes that refer to a single entry of the jar file Example: Content-type of a file

Seite 5 Th Letschert Jars / Working with Jars

Package java.util.jar Provides classes for reading and writing jar files. Class java.util.jar.JarFile read the contents of a jar file Class java.util.jar.JarInputStream read the contents of a jar file from an input stream Class java.util.jar.JarOutputStream write the contents of a jar file to an output stream

Package java.net Class java.net.JarURLConnection subclass of URLConnection read data identified by a jar-url

Seite 6 Th Letschert Jars / Working with Jars

JarFile Example: read and display content of a jar file

import java.io.IOException; import java.util.Enumeration; import java.util.Scanner; import java.util.jar.*;

public class ReadJar {

public static void main(String[] args) throws IOException { Scanner scan = new Scanner(System.in); // get jar file's name String jarName = scan.next();

// display content JarFile jarFile = new JarFile(jarName); Enumeration entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); System.out.println(jarEntry.getName()); }

// display manifest Manifest manifest = jarFile.getManifest(); for (Object mainAttr: manifest.getMainAttributes().keySet()) { System.out.println( mainAttr + " -> " + manifest.getMainAttributes().getValue((Attributes.Name) mainAttr)); } }

}

Seite 7 Th Letschert Jars / Working with Jars

JarFile Example: read and display content of a jar Manifest (1)

import java.io.IOException; import java.io.InputStream; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; file handling relies on nio-2 import java.util.Map; features of Java 7 import java.util.jar.Attributes; import java.util.jar.JarInputStream; import java.util.jar.Manifest;

public class Test { public static void main(String[] args) throws IOException {

Path path = FileSystems.getDefault().getPath("/tmp/ajar.jar"); InputStream fis = Files.newInputStream(path);

JarInputStream jis = new JarInputStream(fis);

Manifest manifest = jis.getManifest();

... next Slide ...

} }

Seite 8 Th Letschert Jars / Working with Jars

JarFile Example: read and display content of a jar Manifest (2)

System.out.println("Main Entries:"); for (Object mainAttr: manifest.getMainAttributes().keySet()) { System.out.println( mainAttr + " -> " + manifest.getMainAttributes().getValue((Attributes.Name) mainAttr)); } System.out.println();

System.out.println("Entries:"); Map manifestEntries = manifest.getEntries(); for(String key : manifestEntries.keySet() ) { System.out.println("entry key: " + key); System.out.println("entry values: "); Attributes attrs = manifestEntries.get(key); for (Object o : attrs.keySet()) { System.out.println(" " + o + " => " + attrs.getValue((Attributes.Name)o)); } }

Main Entries: Manifest-Version: 1.0 Manifest-Version -> 1.0 Blubber-bla: wusch schlabber -> Schlapp schlabber: Schlapp Blubber-bla -> wusch Entries: Name: /p_269/CoreBuilder.class entry key: /p_269/CoreBuilder.class Bu-Bu: true entry values: Sealed: false Manifest file Sealed => false Bu-Bu => true Output

Seite 9 Th Letschert Jars / Working with Jars

JarFile Example: unzip jar file (1)

import java.io.File; import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.PathMatcher; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.util.Enumeration; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile;

public class ExtractJar { public static void main(String[] args) throws IOException { Path jarPath = FileSystems.getDefault().getPath("/tmp/Scratch/ajar.jar"); // check jar if (! Files.exists(jarPath) || ! Files.isReadable(jarPath) || Files.isDirectory(jarPath) ) { throw new IOException("not a readable file"); } PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + "*.jar"); Path filePath = jarPath.getFileName(); if (filePath == null || ! matcher.matches(filePath)) { throw new IOException(" file does not exist or is not a jar file"); } if ( ! Files.probeContentType(jarPath).equals("application/x-java-archive") ) { throw new IOException("no jar content " + Files.probeContentType(jarPath)); } } ... next Slide ... }

Seite 10 Th Letschert Jars / Working with Jars

JarFile Example: unzip jar file (2)

// determine directory to inflate into Path dirPath = jarPath.getParent(); String fileNameWithoutExt = ((filePath.toString()).split("\\."))[0]; Path inflatePath = dirPath.resolve(fileNameWithoutExt); System.out.println("inflate in directory " + inflatePath);

// create inflate dir, previously delete it recursively if it already exists deleteRecursive(inflatePath); Set perms = PosixFilePermissions.fromString("rwxr-x---"); Files.createDirectory(inflatePath, PosixFilePermissions.asFileAttribute(perms));

//inflate jar content to dir JarFile jarFile = new JarFile(new File(jarPath.toString())); Enumeration entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); Path destPath = inflatePath.resolve( FileSystems.getDefault().getPath(jarEntry.getName())); if (jarEntry.getName().endsWith("/")) { // directory Files.createDirectories(destPath); continue; } Files.createDirectories(destPath.getParent()); Files.copy(jarFile.getInputStream(jarEntry), destPath); }

Seite 11 Th Letschert Jars / Working with Jars

JarFile Example: unzip jar file (3)

/** * Delete a file or recursively a directory * @param path the file or directory * @throws IOException if something went wrong */ private static void deleteRecursive(Path path) throws IOException { if (Files.isDirectory(path)) { DirectoryStream stream = Files.newDirectoryStream(path); for (Path entry: stream) { deleteRecursive(entry); } Files.deleteIfExists(path); } }

helper function for deletion

Seite 12 Th Letschert Jars / Jar URL

Jar URL identifies resources within a jar file defined by Java API specification Syntax : jar:!/[] where is a non-jar url (e.g. a file url: file://[host]/path a http url, or ftp url)

Examples (from Java API doc.): A Jar entry jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class A Jar file jar:http://www.foo.com/bar/baz.jar!/ A Jar directory jar:http://www.foo.com/bar/baz.jar!/COM/foo/

Seite 13 Th Letschert Jars / Working with Jars

Example: load and execute runnable jar file (1)

import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.JarURLConnection; import java.net.URL; import java.net.URLClassLoader; import java.util.Scanner; import java.util.jar.Attributes;

public class JarExecuter {

public static void main(String[] args) throws IOException, ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {

Scanner scan = new Scanner(System.in); // get jar file's name // something like // /some/directory/HelloWorld.jar

String jarName = scan.next();

... next slide ...

}

}

Seite 14 Th Letschert Jars / Working with Jars

Example: load and execute runnable jar file (2)

//The syntax of a JAR URL is:jar:!/{entry} // The terminating !/ separator indicates that the URL refers to an entire JAR file URL url = new URL("jar:file:" + jarName + "!/");

URLClassLoader urlLoader = new URLClassLoader(new URL[] { url });

JarURLConnection uc = (JarURLConnection)url.openConnection(); Attributes attr = uc.getMainAttributes(); if (attr != null) { String mainClassName = attr.getValue(Attributes.Name.MAIN_CLASS); if (mainClassName != null) { Class c = urlLoader.loadClass(mainClassName); Method m = c.getMethod("main", new Class[] { args.getClass() }); m.setAccessible(true); int mods = m.getModifiers(); if (m.getReturnType() != void.class || !Modifier.isStatic(mods) || !Modifier.isPublic(mods)) { throw new NoSuchMethodException("main"); } try { m.invoke(null, new Object[] { args }); } catch (IllegalAccessException e) { // never reached } } }

Seite 15 Th Letschert