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