1 /* 2 * Copyright (C) Azureus Software, Inc, All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details ( see the LICENSE file ). 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 */ 18 19 package org.gudy.azureus2.platform.unix; 20 21 import java.io.*; 22 import java.lang.reflect.Constructor; 23 import java.lang.reflect.Method; 24 import java.util.ArrayList; 25 import java.util.Iterator; 26 import java.util.regex.Matcher; 27 import java.util.regex.Pattern; 28 29 import org.gudy.azureus2.core3.config.COConfigurationManager; 30 import org.gudy.azureus2.core3.util.Constants; 31 import org.gudy.azureus2.core3.util.Debug; 32 import org.gudy.azureus2.core3.util.FileUtil; 33 34 import com.aelitis.azureus.core.impl.AzureusCoreSingleInstanceClient; 35 36 import org.gudy.azureus2.plugins.PluginManager; 37 38 public class ScriptBeforeStartup 39 { 40 private static PrintStream sysout; 41 42 private static Object display; 43 main(String[] args)44 public static void main(String[] args) { 45 // Set transitory so not everything gets loaded up. (such as the AEDiagnostic's tidy flag) 46 System.setProperty("transitory.startup", "1"); 47 48 // Since stdout will be in a shell script, redirect any stdout not coming 49 // from us to stderr 50 sysout = System.out; 51 try { 52 System.setOut(new PrintStream(new FileOutputStream("/dev/stderr"))); 53 } catch (FileNotFoundException e) { 54 } 55 56 String mi_str = System.getProperty(PluginManager.PR_MULTI_INSTANCE); 57 boolean mi = mi_str != null && mi_str.equalsIgnoreCase("true"); 58 59 if (!mi) { 60 boolean argsSent = new AzureusCoreSingleInstanceClient().sendArgs(args, 500); 61 if (argsSent) { 62 // azureus was open.. 63 String msg = "Passing startup args to already-running " + Constants.APP_NAME + " java process listening on [127.0.0.1: " + Constants.INSTANCE_PORT + "]"; 64 log(msg); 65 sysout.println("exit"); 66 67 return; 68 } 69 } 70 71 // If the after shutdown script didn't run or crapped out, then 72 // don't run again.. 73 String scriptAfterShutdown = COConfigurationManager.getStringParameter( 74 "scriptaftershutdown", null); 75 76 COConfigurationManager.removeParameter("scriptaftershutdown.exit"); 77 COConfigurationManager.removeParameter("scriptaftershutdown"); 78 COConfigurationManager.save(); 79 if (scriptAfterShutdown != null) { 80 log("Script after " + Constants.APP_NAME + " shutdown did not run.. running now"); 81 82 sysout.println(scriptAfterShutdown); 83 84 if (scriptAfterShutdown.indexOf("$0") < 0) { 85 // doesn't have a restart.. add one 86 sysout.println("echo \"Restarting Azureus..\""); 87 sysout.println("$0\n"); 88 } 89 // exit is a requirement 90 sysout.println("exit"); 91 92 return; 93 } 94 95 String moz = getNewGreDir(); 96 97 if (moz != null) { 98 String s = "export MOZILLA_FIVE_HOME=\"" + moz + "\"\n" 99 + "if [ \"$LD_LIBRARY_PATH x\" = \" x\" ] ; then\n" 100 + " export LD_LIBRARY_PATH=$MOZILLA_FIVE_HOME;\n" + "else\n" 101 + " export LD_LIBRARY_PATH=$MOZILLA_FIVE_HOME:$LD_LIBRARY_PATH\n" 102 + "fi\n"; 103 sysout.println(s); 104 log("setting LD_LIBRARY_PATH to: $LD_LIBRARY_PATH"); 105 log("setting MOZILLA_FIVE_HOME to: $MOZILLA_FIVE_HOME"); 106 } else { 107 log("Usable browser found"); 108 } 109 } 110 getNewGreDir()111 public static String getNewGreDir() { 112 // SWT does a pretty awesome job at finding GRE, most cases this will work 113 if (canOpenBrowser()) { 114 return null; 115 } 116 117 // TODO: Store last successful dir somewhere and check that first 118 // COConfigurationManager probably a bad idea, since that may load 119 // Logger and who knows what other libraries 120 String grePath = null; 121 final String[] confList = { 122 "/etc/gre64.conf", 123 "/etc/gre.d/gre64.conf", 124 "/etc/gre.conf", 125 "/etc/gre.d/gre.conf", 126 "/etc/gre.d/xulrunner.conf", 127 "/etc/gre.d/libxul0d.conf" 128 }; 129 130 log("Auto-scanning for GRE/XULRunner. You can skip this by appending the GRE path to LD_LIBRARY_PATH and setting MOZILLA_FIVE_HOME."); 131 try { 132 Pattern pat = Pattern.compile("GRE_PATH=(.*)", Pattern.CASE_INSENSITIVE); 133 for (int i = 0; i < confList.length; i++) { 134 File file = new File(confList[i]); 135 if (file.isFile() && file.canRead()) { 136 log(" checking " + file + " for GRE_PATH"); 137 String fileText = FileUtil.readFileAsString(file, 16384); 138 if (fileText != null) { 139 Matcher matcher = pat.matcher(fileText); 140 if (matcher.find()) { 141 String possibleGrePath = matcher.group(1); 142 if (isValidGrePath(new File(possibleGrePath))) { 143 grePath = possibleGrePath; 144 break; 145 } 146 } 147 } 148 } 149 } 150 151 if (grePath == null) { 152 final ArrayList possibleDirs = new ArrayList(); 153 File libDir = new File("/usr"); 154 libDir.listFiles(new FileFilter() { 155 public boolean accept(File pathname) { 156 if (pathname.getName().startsWith("lib")) { 157 possibleDirs.add(pathname); 158 } 159 return false; 160 } 161 }); 162 possibleDirs.add(new File("/usr/local")); 163 possibleDirs.add(new File("/opt")); 164 165 final String[] possibleDirNames = { 166 "mozilla", 167 "firefox", 168 "seamonkey", 169 "xulrunner", 170 }; 171 172 FileFilter ffIsPossibleDir = new FileFilter() { 173 public boolean accept(File pathname) { 174 String name = pathname.getName().toLowerCase(); 175 for (int i = 0; i < possibleDirNames.length; i++) { 176 if (name.startsWith(possibleDirNames[i])) { 177 return true; 178 } 179 } 180 return false; 181 } 182 }; 183 184 for (Iterator iter = possibleDirs.iterator(); iter.hasNext();) { 185 File dir = (File) iter.next(); 186 187 File[] possibleFullDirs = dir.listFiles(ffIsPossibleDir); 188 189 for (int i = 0; i < possibleFullDirs.length; i++) { 190 log(" checking " + possibleFullDirs[i] + " for GRE"); 191 if (isValidGrePath(possibleFullDirs[i])) { 192 grePath = possibleFullDirs[i].getAbsolutePath(); 193 break; 194 } 195 } 196 if (grePath != null) { 197 break; 198 } 199 } 200 } 201 202 if (grePath != null) { 203 log("GRE found at " + grePath + "."); 204 System.setProperty("org.eclipse.swt.browser.XULRunnerPath", grePath); 205 } 206 } catch (Throwable t) { 207 log("Error trying to find suitable GRE: " 208 + Debug.getNestedExceptionMessage(t)); 209 grePath = null; 210 } 211 212 if (!canOpenBrowser()) { 213 log("Can't create browser. Will try to set LD_LIBRARY_PATH and hope " 214 + Constants.APP_NAME + " has better luck."); 215 } 216 217 return grePath; 218 } 219 canOpenBrowser()220 private static boolean canOpenBrowser() { 221 try { 222 Class claDisplay = Class.forName("org.eclipse.swt.widgets.Display"); 223 if (display != null) { 224 display = claDisplay.newInstance(); 225 } 226 Class claShell = Class.forName("org.eclipse.swt.widgets.Shell"); 227 Constructor shellConstruct = claShell.getConstructor(new Class[] { 228 claDisplay, 229 }); 230 Object shell = shellConstruct.newInstance(new Object[] { 231 display 232 }); 233 234 Class claBrowser = Class.forName("org.eclipse.swt.browser.Browser"); 235 Constructor[] constructors = claBrowser.getConstructors(); 236 for (int i = 0; i < constructors.length; i++) { 237 if (constructors[i].getParameterTypes().length == 2) { 238 Object browser = constructors[i].newInstance(new Object[] { 239 shell, 240 new Integer(0) 241 }); 242 243 Method methSetUrl = claBrowser.getMethod("setUrl", new Class[] { 244 String.class 245 }); 246 methSetUrl.invoke(browser, new Object[] { 247 "about:blank" 248 }); 249 250 break; 251 } 252 } 253 Method methDisposeShell = claShell.getMethod("dispose", new Class[] {}); 254 methDisposeShell.invoke(shell, new Object[] {}); 255 256 return true; 257 } catch (Throwable e) { 258 log("Browser check failed with: " + Debug.getNestedExceptionMessage(e)); 259 return false; 260 } 261 262 } 263 isValidGrePath(File dir)264 private static boolean isValidGrePath(File dir) { 265 if (!dir.isDirectory()) { 266 return false; 267 } 268 269 if (new File(dir, "components/libwidget_gtk.so").exists() 270 || new File(dir, "libwidget_gtk.so").exists()) { 271 log(" Can not use GRE from " + dir 272 + " as it's too old (GTK2 version required)."); 273 return false; 274 } 275 276 // newer GRE doesn't have libwidget at all, but older ones do, and it's 277 // gtk2, we are good to go 278 if (new File(dir, "components/libwidget_gtk2.so").exists() 279 || new File(dir, "libwidget_gtk2.so").exists()) { 280 return true; 281 } 282 283 if (!new File(dir, "components/libxpcom.so").exists() 284 && !new File(dir, "libxpcom.so").exists()) { 285 log(" Can not use GRE from " + dir + " because it's missing libxpcom.so."); 286 return false; 287 } 288 289 return true; 290 } 291 log(String string)292 private static void log(String string) { 293 sysout.println("echo \"" + string.replaceAll("\"", "\\\"") + "\""); 294 } 295 } 296