package net.sf.latexdraw.installer; import net.sf.latexdraw.util.InstallerLog; import net.sf.latexdraw.util.LPath; import net.sf.latexdraw.util.LSystem; import javax.swing.*; import java.awt.*; import java.io.*; import java.util.logging.Level; public class InstallSlide extends Slide implements Runnable { private static final long serialVersionUID = 1L; private static final String NAME_TEMPLATES_DIR = "templates";//$NON-NLS-1$ private static final String NAME_CACHE_TEMPLATES_DIR = ".cache";//$NON-NLS-1$ private static final String DATA_DIR = "data";//$NON-NLS-1$ public static final String EOL = System.getProperty("line.separator"); //$NON-NLS-1$ /** The path where the jar file is placed. */ private static String PATH_JAR = LPath.INSTANCE.getPathJar(); /** The progress bar of the installation. */ private JProgressBar progressBar; /** The label that can appear during the installation. */ private JLabel labelProgress; /** The thread that installs LaTeXDraw. */ private Thread installThread; /** Used to stop the thread of the installation. */ private boolean continueInstall; protected InstallSlide(final Slide prev, final Slide next, final Installer installer) { super(prev, next, installer); } @Override protected void install() { super.install(); installThread = new Thread(this); installThread.start(); } @Override protected void init() { super.init(); final JPanel p1 = new JPanel(); final JPanel p2 = new JPanel(); setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); p1.setLayout(new BoxLayout(p1, BoxLayout.LINE_AXIS)); progressBar = new JProgressBar(0, 100); progressBar.setMinimumSize(new Dimension(300, 30)); progressBar.setPreferredSize(new Dimension(300, 30)); labelProgress = new JLabel(); p2.add(progressBar); p2.add(labelProgress); p2.setMaximumSize(new Dimension(350, 150)); p2.setMinimumSize(new Dimension(350, 150)); p2.setPreferredSize(new Dimension(350, 150)); p1.setMaximumSize(new Dimension(350, 300)); p1.setMinimumSize(new Dimension(350, 300)); p1.setPreferredSize(new Dimension(350, 300)); p1.add(p2); add(p1); installer.nextB.setEnabled(false); installer.previousB.setEnabled(false); setPanelDimension(); } /** * Creates the program launcher for the OS. * @return true if the creation succeeded. * @since 1.9.2 */ private boolean createProgramLauncher(final String path) { boolean ok; try { if(LSystem.INSTANCE.isLinux()) { final File f = new File("/usr/bin/latexdraw");//$NON-NLS-1$ InstallerLog.getLogger().log(Level.SEVERE, f + " exists? " + f.exists()); if(!f.exists()) { final FileOutputStream fos = new FileOutputStream(f); final Writer osw = new OutputStreamWriter(fos); try { osw.write("#! /bin/sh\n");//$NON-NLS-1$ osw.write("java -jar "+installer.chooseSlide.pathInstall.getText()+File.separator+"latexdraw"+File.separator+"LaTeXDraw.jar $@\n");//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ ok = true; }catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } try { osw.flush(); } catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } try { fos.flush(); } catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } try { osw.close(); } catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } try { fos.close(); } catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } InstallerLog.getLogger().log(Level.INFO, "sh file created? " + ok); if(!f.setReadable(true)) InstallerLog.getLogger().log(Level.SEVERE, "Failed to set sh file readable"); if(!f.setExecutable(true, false)) InstallerLog.getLogger().log(Level.SEVERE, "Failed to set sh file executable"); } else ok = true; } else if(LSystem.INSTANCE.isWindows()) { final File f = new File(PATH_JAR+File.separator+"createShortcut.vbs"); final FileOutputStream fos = new FileOutputStream(f); final Writer osw = new OutputStreamWriter(fos); InstallerLog.getLogger().log(Level.SEVERE, f + " exists? " + f.exists()); try { osw.write("Set shell = WScript.CreateObject(\"WScript.Shell\")"); osw.write(EOL); osw.write("strProg = shell.SpecialFolders(\"Programs\")"); osw.write(EOL); osw.write("Set link= shell.CreateShortcut(strProg+\"\\LaTeXDraw.LNK\")"); osw.write(EOL); osw.write("link.TargetPath = \""); osw.write(path); osw.write("\\LaTeXDraw.jar\""); osw.write(EOL); osw.write("link.Save"); osw.write(EOL); ok = true; }catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } try { osw.flush(); } catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } try { fos.flush(); } catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } try { osw.close(); } catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } try { fos.close(); } catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } if(!f.setReadable(true)) InstallerLog.getLogger().log(Level.SEVERE, "Failed to set vbs file readable"); if(!f.setExecutable(true, false)) InstallerLog.getLogger().log(Level.SEVERE, "Failed to set vbs file executable"); ok = true; try { Runtime.getRuntime().exec(new String[]{"wscript", f.getPath()}); }catch(IOException ex) { ex.printStackTrace(); InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } } else ok = true; } catch(final FileNotFoundException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } catch(final SecurityException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } return ok; } /** * Copy a file. * @param from The current path of the file to move. * @param here The directory where we have to move the file. * @param replace If set to true, the file will replace any file with the same name in "here". * @return True if the move succeeded * @throws FileNotFoundException If "from" is invalid. * @since 1.9.2 */ private boolean copyFile(final String from, final String here, final boolean replace) throws FileNotFoundException { final File source = new File(from); if(!source.exists() || !source.canRead()) throw new FileNotFoundException(); final File dest = new File(here + File.separator + source.getName()); if(dest.exists() && replace) delete(dest); if(!dest.exists()) if(source.isDirectory()) copyFiles(from, here, replace); else return copy(source, dest); return true; } /** * Copy a file into another. * @param source The source file. * @param destination The output file. * @return True if no problem occurred. * @exception IllegalArgumentException If source or destination is null. */ private static boolean copy(final File source, final File destination) { if(destination==null || source==null) throw new IllegalArgumentException(); if(!source.canRead()) return false; FileInputStream sourceFile = null; FileOutputStream destinationFile = null; boolean ok; try { ok = destination.createNewFile(); sourceFile = new FileInputStream(source); destinationFile = new FileOutputStream(destination); final byte buffer[] = new byte[512*1024]; int nbLecture = sourceFile.read(buffer); while(nbLecture!=-1) { destinationFile.write(buffer, 0, nbLecture); nbLecture = sourceFile.read(buffer); } }catch(final Exception ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } try { if(destinationFile!=null) destinationFile.close(); } catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } try { if(sourceFile!=null) sourceFile.close(); } catch(final IOException ex) { ok = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } return ok; } /** * Move a couple of files but never replace an existing file. * @param from The directory where we have to find the files to move. * @param into The destination directory. * @param replace True : the file/directory will be replaced. * @throws FileNotFoundException If a problem occurred with a source file. * @since 1.9.2 */ private boolean copyFiles(final String from, final String into, final boolean replace) throws FileNotFoundException { final File src = new File(from); final File here = new File(into); boolean ok = true; if(!src.exists() || !src.isDirectory() || !src.canRead()) throw new FileNotFoundException(from + " exists? " + src.exists() + " isDir? " + src.isDirectory() + " canRead? " + src.canRead()); final File[] files = src.listFiles(); File dest; here.mkdir(); for(File file : files) { dest = new File(into + File.separator + file.getName()); if(replace) delete(dest); if(!dest.exists()) if(file.isFile()) ok = copy(file, dest) && ok; else { String path = file.getPath(); path = path.substring(path.lastIndexOf(File.separator)); ok = copyFiles(file.getPath(), into+path, replace) && ok; } } return ok; } /** * remove a file or directory even if it is not empty. * @param f The file to remove * @return True if the file/directory was removed. * @since 1.9.2 */ private static boolean delete(final File f) { boolean status = true; try { File fileCur; final String[] lstFile; int idxFile; lstFile = f.list(); if(lstFile==null) { f.delete(); return true; } for(idxFile = 0; idxFile < lstFile.length && status; idxFile++) { fileCur = new File(f, lstFile[idxFile]); if(fileCur.isDirectory()) status = delete(fileCur); else status = fileCur.delete(); } f.delete(); } catch(final SecurityException se) { return false; } return status; } protected boolean isContinueInstall() { return continueInstall; } protected void setContinueInstall(final boolean continueInstall) { this.continueInstall = continueInstall; } @Override public void run() { setContinueInstall(true); progressBar.setValue(progressBar.getMinimum()); LPath.INSTANCE.checkInstallDirectories(); LPath.INSTANCE.checkDirectories(); progressBar.setValue(progressBar.getValue()+20); boolean okInstall = false; boolean okCopying = true; if(!isContinueInstall()) return ; try { okCopying = copyFiles(PATH_JAR+File.separator+DATA_DIR+File.separator+NAME_TEMPLATES_DIR, LPath.PATH_TEMPLATES_SHARED, false); InstallerLog.getLogger().log(Level.INFO, "Templates copied? " + okCopying); okCopying = okCopying && copyFiles(PATH_JAR+File.separator+DATA_DIR+File.separator+NAME_CACHE_TEMPLATES_DIR, LPath.PATH_CACHE_SHARE_DIR, false); InstallerLog.getLogger().log(Level.INFO, "Cache copied? " + okCopying); if(LSystem.INSTANCE.isLinux()){ InstallerLog.getLogger().log(Level.INFO, "Installing on Linux"); InstallerLog.getLogger().log(Level.INFO, LPath.PATH_SHARED+"/images/app/ created? " + new File(LPath.PATH_SHARED+"/images/app/").mkdirs()); okCopying = okCopying && copyFile(PATH_JAR+File.separator+DATA_DIR+File.separator+"gnome"+File.separator+"latexdraw.png", LPath.PATH_SHARED+"/images/app/", false); InstallerLog.getLogger().log(Level.INFO, "png file copied? " + okCopying); okCopying = okCopying && copyFile(PATH_JAR+File.separator+DATA_DIR+File.separator+"gnome"+File.separator+"latexdraw.desktop", "/usr/share/applications/", false); InstallerLog.getLogger().log(Level.INFO, "desktop file copied? " + okCopying); } progressBar.setValue(progressBar.getValue()+20); if(!isContinueInstall()) return ; final String path = installer.chooseSlide.pathInstall.getText() + File.separator + "latexdraw";//$NON-NLS-1$ final File mainDir = new File(path); InstallerLog.getLogger().log(Level.INFO, "Installation path: " + path + ". Exists? " + mainDir.exists()); if(mainDir.exists()) { InstallerLog.getLogger().log(Level.INFO, mainDir + " already exists."); okCopying = delete(mainDir); InstallerLog.getLogger().log(Level.INFO, mainDir + " removed? " + okCopying); } okCopying = mainDir.mkdir(); InstallerLog.getLogger().log(Level.INFO, mainDir + " created? " + okCopying); okCopying = okCopying && mainDir.exists(); InstallerLog.getLogger().log(Level.INFO, mainDir + " exists? " + mainDir.exists()); okCopying = okCopying && copyFile(PATH_JAR+File.separator+DATA_DIR+File.separator+"LaTeXDraw.jar", path, true);//$NON-NLS-1$ InstallerLog.getLogger().log(Level.INFO, mainDir + " jar file copied? " + okCopying); okCopying = okCopying && copyFile(PATH_JAR+File.separator+"license.txt", path, true);//$NON-NLS-1$ InstallerLog.getLogger().log(Level.INFO, mainDir + " license file copied? " + okCopying); okCopying = okCopying && copyFile(PATH_JAR+File.separator+"release_note.txt", path, true);//$NON-NLS-1$ InstallerLog.getLogger().log(Level.INFO, mainDir + " release_note file copied? " + okCopying); okCopying = okCopying && copyFiles(PATH_JAR+File.separator+DATA_DIR+File.separator+"lib", path+File.separator+"lib", true);//$NON-NLS-1$//$NON-NLS-2$ InstallerLog.getLogger().log(Level.INFO, PATH_JAR+File.separator+DATA_DIR+File.separator+"lib" + " libs copied? " + okCopying + " in " + path+File.separator+"lib (exists? " + (new File(path+File.separator+"lib")).exists() + ")"); progressBar.setValue(progressBar.getValue()+30); if(!isContinueInstall()) return ; createProgramLauncher(path); progressBar.setValue(progressBar.getValue()+20); if(!isContinueInstall()) return ; okInstall = okCopying; }catch(final FileNotFoundException ex) { okInstall = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } catch(final SecurityException ex) { okInstall = false; InstallerLog.getLogger().log(Level.SEVERE, ex.toString(), ex); } if(okInstall) { progressBar.setValue(progressBar.getMaximum()); installer.nextB.setEnabled(true); installer.previousB.setEnabled(true); labelProgress.setText("<html><font color=\"green\">" + "Installation succeeded!" + "<br></font></html>");//$NON-NLS-1$//$NON-NLS-3$ } else { labelProgress.setText("<html><font color=\"red\">" + "Installation failed!" + "<br>" + //$NON-NLS-1$//$NON-NLS-3$ "Launch the installer as administrator." + "</font></html>");//$NON-NLS-2$ installer.previousB.setEnabled(true); } setContinueInstall(false); } }