1
16package org.tp23.antinstaller.selfextract;
17
18import java.awt.HeadlessException;
19import java.io.BufferedOutputStream;
20import java.io.File;
21import java.io.FileFilter;
22import java.io.FileInputStream;
23import java.io.FileNotFoundException;
24import java.io.FileOutputStream;
25import java.io.IOException;
26import java.net.URL;
27import java.util.ArrayList;
28import java.util.jar.JarEntry;
29import java.util.jar.JarFile;
30import java.util.jar.JarInputStream;
31
32import javax.swing.JOptionPane;
33import javax.swing.UIManager;
34
35import org.tp23.antinstaller.InstallException;
36import org.tp23.antinstaller.renderer.swing.plaf.LookAndFeelFactory;
37import org.tp23.antinstaller.runtime.ExecInstall;
38import org.tp23.antinstaller.runtime.exe.FilterChain;
39import org.tp23.antinstaller.runtime.exe.FilterFactory;
40
41
49public class SelfExtractor {
50
51 public static final String CONFIG_RESOURCE = "/org/tp23/antinstaller/runtime/exe/selfextractor.fconfig";
52
53 private File extractDir;
54 private File archiveFile;
55 private boolean overwrite = true;
56
57 private static int DEFAULT_BUFFER_SIZE = 1024;
58 private int BUFFER_SIZE = DEFAULT_BUFFER_SIZE;
59 private static boolean graphicsEnv = false;
60 private static String lookAndFeel = null;
61
62
69 public static File getEnclosingJar(Object reference) {
70 String thisClass = "/" + reference.getClass().getName().replace('.','/') + ".class";
71 URL jarUrl = reference.getClass().getResource(thisClass);
72 String stringForm = jarUrl.toString();
73
75 File file = null;
76 int endIdx = stringForm.indexOf("!/");
77 if(endIdx != -1){
78 String unescaped = null;
79 String fileNamePart = stringForm.substring("jar:file:".length(), endIdx);
80 file = new File(fileNamePart);
81 if ( ! file.exists()) {
82 unescaped = unescape(fileNamePart);
84 file = new File(unescaped);
85 }
86 return file;
87 }
88 throw new RuntimeException("Failed expanding Jar.");
89 }
90
91
95 public SelfExtractor() {
96 }
97
98
02 public void init(){
03 System.out.println("Loading self extractor...");
04 archiveFile = getEnclosingJar(this);
05 makeTempDir();
06 try {
07 JarFile thisJar = new JarFile(archiveFile);
08 lookAndFeel = thisJar.getManifest().getMainAttributes().getValue("Look-And-Feel");
09 lookAndFeel = LookAndFeelFactory.getLafFromToken(lookAndFeel);
10 if(lookAndFeel != null) {
11 UIManager.setLookAndFeel(lookAndFeel);
12 }
13 }
14 catch (Throwable ex) {
15 }
17 }
18
19
23 protected File makeTempDir(){
24 String tempDir = System.getProperty("java.io.tmpdir");
25 extractDir = new File(tempDir, "antinstall");
26 int idx = 0;
27 while (extractDir.exists()) {
28 extractDir = new File(tempDir, "antinstall" + (idx++));
29 }
30 extractDir.mkdirs();
31 extractDir.deleteOnExit();
32 return extractDir;
33 }
34
35
41 public SelfExtractor(int newBufferSize) {
42 BUFFER_SIZE = newBufferSize;
43 archiveFile = getEnclosingJar(this);
44 }
45
46
51 public void setExtractDir(File newExtractDir) {
52 extractDir = newExtractDir;
53 }
54
55
59 public void setArchiveFile(File newArchiveFile) {
60 archiveFile = newArchiveFile;
61 }
62
63
68 public File getExtractDir() {
69 return extractDir;
70 }
71
72
76 public boolean isOverwrite() {
77 return overwrite;
78 }
79
80
85 public void setOverwrite(boolean overwrite) {
86 this.overwrite = overwrite;
87 }
88
89
93 public File getArchiveFile() {
94 return archiveFile;
95 }
96
97
07 public ArrayList getList(boolean vebose) throws FileNotFoundException, IOException {
08 JarInputStream zis = new JarInputStream(new FileInputStream(archiveFile));
09 JarEntry entry = null;
10 ArrayList result = new ArrayList();
11 while ( (entry = zis.getNextJarEntry()) != null) {
12 if (vebose) {
13 System.out.println(entry.getName());
14 }
15 result.add(entry.getName());
16 }
17 return result;
18 }
19
20
25 public int getFileCount() throws FileNotFoundException, IOException {
26 JarInputStream zis = new JarInputStream(new FileInputStream(archiveFile));
27 int count = 0;
28 while ( zis.getNextJarEntry() != null) {
29 count++;
30 }
31 return count;
32 }
33
34
43 public ArrayList extract(boolean vebose, boolean isX) throws FileNotFoundException, IOException {
44 int fileCount = getFileCount();
45 ProgressIndicator indicator = null;
46 if(isX){
47 try {
48 indicator = new ProgressIndicator(fileCount);
49 indicator.show();
50 }
51 catch ( Exception exc ) {
52
56 graphicsEnv = false;
57 isX = false;
58 }
59
60 }
61 JarInputStream zis = new JarInputStream(new FileInputStream(archiveFile));
62 JarEntry entry = null;
63 ArrayList result = new ArrayList();
64 while ( (entry = zis.getNextJarEntry()) != null) {
65 if (vebose) {
66 System.out.println("Extracting:" + entry.getName());
67 }
68 result.add(extract(zis, entry));
69 if (isX) {
70 indicator.tick();
71 }
72 }
73 if (isX) {
74 indicator.hide();
75 }
76 zis.close();
77 return result;
78 }
79
80
81
82
91 private File extract(JarInputStream zis, JarEntry entry) throws FileNotFoundException, IOException {
92 createPath(entry.getName());
93 File fileToUse = new File(extractDir, entry.getName());
94 if (fileToUse.exists()) {
95 if (!overwrite) {
96 return fileToUse;
97 }
98 }
99 else {
00 fileToUse.createNewFile();
01 }
02 if (fileToUse.isDirectory()) {
03 return fileToUse;
04 }
05
06 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileToUse), BUFFER_SIZE);
07 byte[] bytes = new byte[BUFFER_SIZE];
08 int len = 0;
09 while ( (len = zis.read(bytes)) >= 0) {
10 bos.write(bytes, 0, len);
11 }
12 bos.close();
13 zis.closeEntry();
14 return fileToUse;
15 }
16
17
23 private void createPath(String entryName) throws IOException {
24 int slashIdx = entryName.lastIndexOf('/');
25 if (slashIdx >= 0) {
26 String firstPath = entryName.substring(0, slashIdx);
28 File dir = new File(extractDir, firstPath);
29 if (!dir.exists()) {
30 dir.mkdirs();
31 }
32 }
33 }
34
35
40 public static void main(String[] args) {
41 testX();
42 SelfExtractor extractor = null;
46 try {
47 boolean verbose = false;
48 extractor = new SelfExtractor();
49 extractor.init();
50 extractor.extract(verbose, graphicsEnv);
51 }
52 catch (Exception e) {
53 e.printStackTrace();
54 String tempDir = "unknown";
55 if(extractor != null){
56 tempDir = extractor.getExtractDir().getAbsolutePath();
57 }
58 String warning = "Could not extract Jar file to directory:" + tempDir;
59 printXorTextWarning(warning);
60 }
61
62 try {
63 FilterChain chain = FilterFactory.factory(CONFIG_RESOURCE);
64 ExecInstall installExec = new ExecInstall(chain);
65 installExec.parseArgs(args, false);
66 installExec.setInstallRoot(extractor.getExtractDir());
67 installExec.setTempRoot(extractor.getExtractDir());
69
70 installExec.exec();
71 }
72 catch (InstallException e1) {
73 System.out.println("Cant load filter chain:/org/tp23/antinstaller/runtime/exe/selfextractor.fconfig");
74 e1.printStackTrace();
75 }
76 }
77
78
83 protected static void testX(){
84 try {
85 java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
86 try {
87 boolean headless = java.awt.GraphicsEnvironment.isHeadless();
88 if(headless) {
89 graphicsEnv = false;
90 return;
91 }
92 } catch (Throwable e) {
93 }
95 graphicsEnv = true;
96 }
97 catch (Throwable e) {
98 }
00 }
01
02
06 protected boolean isGraphicsEnv(){
07 return graphicsEnv;
08 }
09
10 protected static void printXorTextWarning(String warning){
11 if(graphicsEnv){
12 try {
13 JOptionPane.showMessageDialog(null, warning);
14 }
15 catch( HeadlessException headlessExc ) {
16 graphicsEnv = false;
17 System.out.println(warning);
18 }
19 }
20 else {
21 System.out.println(warning);
22 }
23 }
24
25 public static int deleteRecursive(File directory) {
26 int count = 0;
27 File[] files = directory.listFiles(new FileFilter() {
28 public boolean accept(File file) {
29 return!file.isDirectory();
30 }
31 });
32 for (int i = 0; i < files.length; i++) {
33 files[i].delete();
34 count++;
35 }
36 File[] dirs = directory.listFiles(new FileFilter() {
37 public boolean accept(File file) {
38 return file.isDirectory();
39 }
40 });
41 for (int i = 0; i < dirs.length; i++) {
42 count += deleteRecursive(dirs[i]);
43 }
44 directory.delete();
45 return count;
46 }
47
48
52 private static String unescape(final String s) {
53 StringBuffer sb = new StringBuffer(s.length());
54
55 for (int i = 0; i < s.length(); i++) {
56 char c = s.charAt(i);
57 switch (c) {
58 case '%': {
59 try {
60 sb.append( (char) Integer.parseInt(s.substring(i + 1, i + 3), 16));
61 i += 2;
62 break;
63 }
64 catch (NumberFormatException nfe) {
65 throw new IllegalArgumentException();
66 }
67 catch (StringIndexOutOfBoundsException siob) {
68 String end = s.substring(i);
69 sb.append(end);
70 if (end.length() == 2) i++;
71 }
72 break;
73 }
74 default: {
75 sb.append(c);
76 break;
77 }
78 }
79 }
80 return sb.toString();
81 }
82
83}
84