PageRenderTime 25ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/src/net/java/sip/communicator/launcher/SIPCommunicator.java

https://gitlab.com/yorty.ruiz/jitsi
Java | 441 lines | 252 code | 46 blank | 143 comment | 73 complexity | c9c8c4cacd01baaf2d4587efccdb493b MD5 | raw file
  1. /*
  2. * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
  3. *
  4. * Copyright @ 2015 Atlassian Pty Ltd
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package net.java.sip.communicator.launcher;
  19. import java.awt.*;
  20. import java.io.*;
  21. import net.java.sip.communicator.impl.version.*;
  22. import net.java.sip.communicator.util.*;
  23. import net.java.sip.communicator.util.launchutils.*;
  24. import org.apache.felix.main.*;
  25. /**
  26. * Starts the SIP Communicator.
  27. *
  28. * @author Yana Stamcheva
  29. * @author Lyubomir Marinov
  30. * @author Emil Ivov
  31. * @author Sebastien Vincent
  32. */
  33. public class SIPCommunicator
  34. {
  35. /**
  36. * Legacy home directory names that we can use if current dir name is the
  37. * currently active name (overridableDirName).
  38. */
  39. private static final String[] LEGACY_DIR_NAMES
  40. = { ".sip-communicator", "SIP Communicator" };
  41. /**
  42. * The name of the property that stores the home dir for cache data, such
  43. * as avatars and spelling dictionaries.
  44. */
  45. public static final String PNAME_SC_CACHE_DIR_LOCATION =
  46. "net.java.sip.communicator.SC_CACHE_DIR_LOCATION";
  47. /**
  48. * The name of the property that stores the home dir for application log
  49. * files (not history).
  50. */
  51. public static final String PNAME_SC_LOG_DIR_LOCATION =
  52. "net.java.sip.communicator.SC_LOG_DIR_LOCATION";
  53. /**
  54. * Name of the possible configuration file names (used under macosx).
  55. */
  56. private static final String[] LEGACY_CONFIGURATION_FILE_NAMES
  57. = {
  58. "sip-communicator.properties",
  59. "jitsi.properties",
  60. "sip-communicator.xml",
  61. "jitsi.xml"
  62. };
  63. /**
  64. * The currently active name.
  65. */
  66. private static final String OVERRIDABLE_DIR_NAME = "Jitsi";
  67. /**
  68. * The name of the property that stores our home dir location.
  69. */
  70. public static final String PNAME_SC_HOME_DIR_LOCATION
  71. = "net.java.sip.communicator.SC_HOME_DIR_LOCATION";
  72. /**
  73. * The name of the property that stores our home dir name.
  74. */
  75. public static final String PNAME_SC_HOME_DIR_NAME
  76. = "net.java.sip.communicator.SC_HOME_DIR_NAME";
  77. /**
  78. * Starts the SIP Communicator.
  79. *
  80. * @param args command line args if any
  81. * @throws Exception whenever it makes sense.
  82. */
  83. public static void main(String[] args)
  84. throws Exception
  85. {
  86. String version = System.getProperty("java.version");
  87. String vmVendor = System.getProperty("java.vendor");
  88. String osName = System.getProperty("os.name");
  89. setSystemProperties(osName);
  90. /*
  91. * SC_HOME_DIR_* are specific to the OS so make sure they're configured
  92. * accordingly before any other application-specific logic depending on
  93. * them starts (e.g. Felix).
  94. */
  95. setScHomeDir(osName);
  96. // this needs to be set before any DNS lookup is run
  97. File f
  98. = new File(
  99. System.getProperty(PNAME_SC_HOME_DIR_LOCATION),
  100. System.getProperty(PNAME_SC_HOME_DIR_NAME)
  101. + File.separator
  102. + ".usednsjava");
  103. if(f.exists())
  104. {
  105. System.setProperty(
  106. "sun.net.spi.nameservice.provider.1",
  107. "dns,dnsjava");
  108. }
  109. if (version.startsWith("1.5") || vmVendor.startsWith("Gnu") ||
  110. vmVendor.startsWith("Free"))
  111. {
  112. String os = "";
  113. if (osName.startsWith("Mac"))
  114. os = ChangeJVMFrame.MAC_OSX;
  115. else if (osName.startsWith("Linux"))
  116. os = ChangeJVMFrame.LINUX;
  117. else if (osName.startsWith("Windows"))
  118. os = ChangeJVMFrame.WINDOWS;
  119. ChangeJVMFrame changeJVMFrame = new ChangeJVMFrame(os);
  120. Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
  121. changeJVMFrame.setLocation(
  122. screenSize.width/2 - changeJVMFrame.getWidth()/2,
  123. screenSize.height/2 - changeJVMFrame.getHeight()/2);
  124. changeJVMFrame.setVisible(true);
  125. return;
  126. }
  127. //first - pass the arguments to our arg handler
  128. LaunchArgHandler argHandler = LaunchArgHandler.getInstance();
  129. int argHandlerRes = argHandler.handleArgs(args);
  130. if ( argHandlerRes == LaunchArgHandler.ACTION_EXIT
  131. || argHandlerRes == LaunchArgHandler.ACTION_ERROR)
  132. {
  133. System.exit(argHandler.getErrorCode());
  134. }
  135. //lock our config dir so that we would only have a single instance of
  136. //sip communicator, no matter how many times we start it (use mainly
  137. //for handling sip: uris after starting the application)
  138. if ( argHandlerRes != LaunchArgHandler.ACTION_CONTINUE_LOCK_DISABLED )
  139. {
  140. switch (new SipCommunicatorLock().tryLock(args))
  141. {
  142. case SipCommunicatorLock.LOCK_ERROR:
  143. System.err.println("Failed to lock Jitsi's "
  144. +"configuration directory.\n"
  145. +"Try launching with the --multiple param.");
  146. System.exit(SipCommunicatorLock.LOCK_ERROR);
  147. break;
  148. case SipCommunicatorLock.ALREADY_STARTED:
  149. System.out.println(
  150. "Jitsi is already running and will "
  151. +"handle your parameters (if any).\n"
  152. +"Launch with the --multiple param to override this "
  153. +"behaviour.");
  154. //we exit with success because for the user that's what it is.
  155. System.exit(SipCommunicatorLock.SUCCESS);
  156. break;
  157. case SipCommunicatorLock.SUCCESS:
  158. //Successfully locked, continue as normal.
  159. break;
  160. }
  161. }
  162. String currentVersion =
  163. VersionImpl.VERSION_MAJOR + "." + VersionImpl.VERSION_MINOR;
  164. File jitsiVersion
  165. = new File(new File(
  166. System.getProperty(PNAME_SC_CACHE_DIR_LOCATION),
  167. System.getProperty(PNAME_SC_HOME_DIR_NAME)),
  168. ".lastversion");
  169. if (jitsiVersion.exists())
  170. {
  171. BufferedReader r = new BufferedReader(new FileReader(jitsiVersion));
  172. String lastVersion = r.readLine();
  173. r.close();
  174. if (!currentVersion.equals(lastVersion))
  175. {
  176. File felixCache =
  177. new File(new File(
  178. System.getProperty(PNAME_SC_CACHE_DIR_LOCATION),
  179. System.getProperty(PNAME_SC_HOME_DIR_NAME)),
  180. "sip-communicator.bin");
  181. if (felixCache.exists())
  182. {
  183. deleteRecursive(felixCache);
  184. }
  185. }
  186. }
  187. FileWriter fw = new FileWriter(jitsiVersion);
  188. fw.write(currentVersion);
  189. fw.close();
  190. //there was no error, continue;
  191. System.setOut(new ScStdOut(System.out));
  192. Main.main(new String[0]);
  193. }
  194. /**
  195. * Recursively delete a directory.
  196. * @param f The directory to the delete.
  197. * @throws IOException
  198. */
  199. private static void deleteRecursive(File f) throws IOException
  200. {
  201. if (f.isDirectory())
  202. {
  203. for (File c : f.listFiles())
  204. {
  205. deleteRecursive(c);
  206. }
  207. }
  208. f.delete();
  209. }
  210. /**
  211. * Sets the system properties net.java.sip.communicator.SC_HOME_DIR_LOCATION
  212. * and net.java.sip.communicator.SC_HOME_DIR_NAME (if they aren't already
  213. * set) in accord with the OS conventions specified by the name of the OS.
  214. *
  215. * Please leave the access modifier as package (default) to allow launch-
  216. * wrappers to call it.
  217. *
  218. * @param osName the name of the OS according to which the SC_HOME_DIR_*
  219. * properties are to be set
  220. */
  221. static void setScHomeDir(String osName)
  222. {
  223. /*
  224. * Though we'll be setting the SC_HOME_DIR_* property values depending
  225. * on the OS running the application, we have to make sure we are
  226. * compatible with earlier releases i.e. use
  227. * ${user.home}/.sip-communicator if it exists (and the new path isn't
  228. * already in use).
  229. */
  230. String profileLocation = System.getProperty(PNAME_SC_HOME_DIR_LOCATION);
  231. String cacheLocation = System.getProperty(PNAME_SC_CACHE_DIR_LOCATION);
  232. String logLocation = System.getProperty(PNAME_SC_LOG_DIR_LOCATION);
  233. String name = System.getProperty(PNAME_SC_HOME_DIR_NAME);
  234. boolean isHomeDirnameForced = name != null;
  235. if (profileLocation == null
  236. || cacheLocation == null
  237. || logLocation == null
  238. || name == null)
  239. {
  240. String defaultLocation = System.getProperty("user.home");
  241. String defaultName = ".jitsi";
  242. // Whether we should check legacy names
  243. // 1) when such name is not forced we check
  244. // 2) if such is forced and is the overridableDirName check it
  245. // (the later is the case with name transition SIP Communicator
  246. // -> Jitsi, check them only for Jitsi)
  247. boolean chekLegacyDirNames
  248. = (name == null) || name.equals(OVERRIDABLE_DIR_NAME);
  249. if (osName.startsWith("Mac"))
  250. {
  251. if (profileLocation == null)
  252. profileLocation =
  253. System.getProperty("user.home") + File.separator
  254. + "Library" + File.separator
  255. + "Application Support";
  256. if (cacheLocation == null)
  257. cacheLocation =
  258. System.getProperty("user.home") + File.separator
  259. + "Library" + File.separator
  260. + "Caches";
  261. if (logLocation == null)
  262. logLocation =
  263. System.getProperty("user.home") + File.separator
  264. + "Library" + File.separator
  265. + "Logs";
  266. if (name == null)
  267. name = "Jitsi";
  268. }
  269. else if (osName.startsWith("Windows"))
  270. {
  271. /*
  272. * Primarily important on Vista because Windows Explorer opens
  273. * in %USERPROFILE% so .sip-communicator is always visible. But
  274. * it may be a good idea to follow the OS recommendations and
  275. * use APPDATA on pre-Vista systems as well.
  276. */
  277. if (profileLocation == null)
  278. profileLocation = System.getenv("APPDATA");
  279. if (cacheLocation == null)
  280. cacheLocation = System.getenv("LOCALAPPDATA");
  281. if (logLocation == null)
  282. logLocation = System.getenv("LOCALAPPDATA");
  283. if (name == null)
  284. name = "Jitsi";
  285. }
  286. /* If there're no OS specifics, use the defaults. */
  287. if (profileLocation == null)
  288. profileLocation = defaultLocation;
  289. if (cacheLocation == null)
  290. cacheLocation = profileLocation;
  291. if (logLocation == null)
  292. logLocation = profileLocation;
  293. if (name == null)
  294. name = defaultName;
  295. /*
  296. * As it was noted earlier, make sure we're compatible with previous
  297. * releases. If the home dir name is forced (set as system property)
  298. * doesn't look for the default dir.
  299. */
  300. if (!isHomeDirnameForced
  301. && (new File(profileLocation, name).isDirectory() == false)
  302. && new File(defaultLocation, defaultName).isDirectory())
  303. {
  304. profileLocation = defaultLocation;
  305. name = defaultName;
  306. }
  307. // if we need to check legacy names and there is no current home dir
  308. // already created
  309. if(chekLegacyDirNames
  310. && !checkHomeFolderExist(profileLocation, name, osName))
  311. {
  312. // now check whether a legacy dir name exists and use it
  313. for(int i = 0; i < LEGACY_DIR_NAMES.length; i++)
  314. {
  315. String dir = LEGACY_DIR_NAMES[i];
  316. // check the platform specific directory
  317. if(checkHomeFolderExist(profileLocation, dir, osName))
  318. {
  319. name = dir;
  320. break;
  321. }
  322. // now check it and in the default location
  323. if(checkHomeFolderExist(defaultLocation, dir, osName))
  324. {
  325. name = dir;
  326. profileLocation = defaultLocation;
  327. break;
  328. }
  329. }
  330. }
  331. System.setProperty(PNAME_SC_HOME_DIR_LOCATION, profileLocation);
  332. System.setProperty(PNAME_SC_CACHE_DIR_LOCATION, cacheLocation);
  333. System.setProperty(PNAME_SC_LOG_DIR_LOCATION, logLocation);
  334. System.setProperty(PNAME_SC_HOME_DIR_NAME, name);
  335. }
  336. // when we end up with the home dirs, make sure we have log dir
  337. new File(new File(logLocation, name), "log").mkdirs();
  338. }
  339. /**
  340. * Checks whether home folder exists. Special situation checked under
  341. * macosx, due to created folder of the new version of the updater we may
  342. * end up with our settings in 'SIP Communicator' folder and having 'Jitsi'
  343. * folder created by the updater(its download location). So we check not
  344. * only the folder exist but whether it contains any of the known
  345. * configuration files in it.
  346. *
  347. * @param parent the parent folder
  348. * @param name the folder name to check.
  349. * @param osName OS name
  350. * @return whether folder exists.
  351. */
  352. static boolean checkHomeFolderExist(
  353. String parent, String name, String osName)
  354. {
  355. if(osName.startsWith("Mac"))
  356. {
  357. for(int i = 0; i < LEGACY_CONFIGURATION_FILE_NAMES.length; i++)
  358. {
  359. String f = LEGACY_CONFIGURATION_FILE_NAMES[i];
  360. if(new File(new File(parent, name), f).exists())
  361. return true;
  362. }
  363. return false;
  364. }
  365. return new File(parent, name).isDirectory();
  366. }
  367. /**
  368. * Sets some system properties specific to the OS that needs to be set at
  369. * the very beginning of a program (typically for UI related properties,
  370. * before AWT is launched).
  371. *
  372. * @param osName OS name
  373. */
  374. private static void setSystemProperties(String osName)
  375. {
  376. // setup here all system properties that need to be initialized at
  377. // the very beginning of an application
  378. if(osName.startsWith("Windows"))
  379. {
  380. // disable Direct 3D pipeline (used for fullscreen) before
  381. // displaying anything (frame, ...)
  382. System.setProperty("sun.java2d.d3d", "false");
  383. }
  384. else if(osName.startsWith("Mac"))
  385. {
  386. // On Mac OS X when switch in fullscreen, all the monitors goes
  387. // fullscreen (turns black) and only one monitors has images
  388. // displayed. So disable this behavior because somebody may want
  389. // to use one monitor to do other stuff while having other ones with
  390. // fullscreen stuff.
  391. System.setProperty("apple.awt.fullscreencapturealldisplays",
  392. "false");
  393. }
  394. }
  395. }