1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 package org.openoffice.setup.InstallerHelper; 29 30 import org.openoffice.setup.InstallData; 31 import org.openoffice.setup.SetupData.PackageDescription; 32 import org.openoffice.setup.Util.Converter; 33 import org.openoffice.setup.Util.ExecuteProcess; 34 import org.openoffice.setup.Util.LogManager; 35 import org.openoffice.setup.Util.SystemManager; 36 import java.io.File; 37 import java.util.Enumeration; 38 import java.util.HashMap; 39 import java.util.Vector;public class LinuxHelper { 40 41 public LinuxHelper() { 42 super(); 43 } 44 45 private void getPackageNamesContent(PackageDescription packageData, Vector packageNames) { 46 if (( packageData.getPackageName() != null ) && ( ! packageData.getPackageName().equals(""))) { 47 packageNames.add(packageData.getPackageName() + "=" + packageData.getFullPackageName()); 48 } 49 50 for (Enumeration e = packageData.children(); e.hasMoreElements(); ) { 51 PackageDescription child = (PackageDescription) e.nextElement(); 52 getPackageNamesContent(child, packageNames); 53 } 54 } 55 56 private String getPackageNameFromRpm(PackageDescription packageData, InstallData installData) { 57 String fullPackageName = null; 58 String packagePath = installData.getPackagePath(); 59 60 if (( packageData.getPkgSubdir() != null ) && ( ! packageData.getPkgSubdir().equals("") )) { 61 File completePackageFile = new File(packagePath, packageData.getPkgSubdir()); 62 packagePath = completePackageFile.getPath(); 63 } 64 65 String rpmFileName = packageData.getPackageName(); 66 File rpmFile = new File(packagePath, rpmFileName); 67 68 if ( rpmFile.exists() ) { 69 String rpmCommand = "rpm -qp " + rpmFile.getPath(); 70 String[] rpmCommandArray = new String[3]; 71 rpmCommandArray[0] = "rpm"; 72 rpmCommandArray[1] = "-qp"; 73 rpmCommandArray[2] = rpmFile.getPath(); 74 75 Vector returnVector = new Vector(); 76 Vector returnErrorVector = new Vector(); 77 int returnValue = ExecuteProcess.executeProcessReturnVector(rpmCommandArray, returnVector, returnErrorVector); 78 String returnString = (String) returnVector.get(0); 79 80 String log = rpmCommand + "<br><b>Returns: " + returnString + "</b><br>"; 81 LogManager.addCommandsLogfileComment(log); 82 83 fullPackageName = returnString; 84 85 } else { 86 System.err.println("Error: Could not find file " + rpmFile.getPath()); 87 } 88 89 return fullPackageName; 90 } 91 92 private boolean checkPackageExistence(PackageDescription packageData, InstallData installData) { 93 boolean fileExists = false; 94 95 String packagePath = installData.getPackagePath(); 96 97 if (( packageData.getPkgSubdir() != null ) && ( ! packageData.getPkgSubdir().equals("") )) { 98 File completePackageFile = new File(packagePath, packageData.getPkgSubdir()); 99 packagePath = completePackageFile.getPath(); 100 } 101 102 String rpmFileName = packageData.getPackageName(); 103 104 File rpmFile = new File(packagePath, rpmFileName); 105 if ( rpmFile.exists() ) { 106 fileExists = true; 107 } 108 109 return fileExists; 110 } 111 112 private HashMap analyzeVersionString(String versionString) { 113 114 boolean errorOccured = false; 115 116 Integer micro = null; 117 Integer minor = null; 118 Integer major = null; 119 Integer release = null; 120 121 String microString = null; 122 String minorString = null; 123 String majorString = null; 124 String releaseString = null; 125 126 int pos = versionString.lastIndexOf("_"); // this is a jre RPM (1.5.0_06) 127 128 if ( pos > -1 ) { 129 try { 130 releaseString = versionString.substring(pos+1, versionString.length()); 131 versionString = versionString.substring(0, pos); 132 } catch (IndexOutOfBoundsException ex) { 133 System.err.println("Error: Could not get substring from " + versionString); 134 errorOccured = true; 135 } 136 try { 137 int releaseInt = Integer.parseInt(releaseString); 138 release = new Integer(releaseInt); 139 } catch (NumberFormatException ex) { 140 System.err.println("Error: Could not convert " + releaseString + " to integer"); 141 errorOccured = true; 142 } 143 } 144 145 // Problem: Some rpms have "2.3" instead of "2.3.0" 146 String compareString = versionString; 147 pos = compareString.lastIndexOf("."); // returns "-1", if not found 148 if ( pos > -1 ) { 149 String substring = compareString.substring(0, pos); 150 pos = substring.lastIndexOf("."); // returns "-1", if not found 151 if ( pos == -1 ) { 152 versionString = versionString + ".0"; 153 // System.err.println("Warning: Changing from " + compareString + " to " + versionString); 154 } 155 } else { 156 versionString = versionString + ".0.0"; 157 } 158 159 // the standard analyzing mechanism 160 pos = versionString.lastIndexOf("."); // returns "-1", if not found 161 162 if ( pos > -1 ) 163 { 164 try { 165 microString = versionString.substring(pos+1, versionString.length()); 166 versionString = versionString.substring(0, pos); 167 } catch (IndexOutOfBoundsException ex) { 168 System.err.println("Error: Could not get substring from " + versionString); 169 errorOccured = true; 170 } 171 172 pos = versionString.lastIndexOf("."); 173 if ( pos > -1 ) { 174 try { 175 minorString = versionString.substring(pos+1, versionString.length()); 176 majorString = versionString.substring(0, pos); 177 } catch (IndexOutOfBoundsException ex) { 178 System.err.println("Error: Could not get substring from " + versionString); 179 errorOccured = true; 180 } 181 try { 182 int microInt = Integer.parseInt(microString); 183 int minorInt = Integer.parseInt(minorString); 184 int majorInt = Integer.parseInt(majorString); 185 micro = new Integer(microInt); 186 minor = new Integer(minorInt); 187 major = new Integer(majorInt); 188 } catch (NumberFormatException ex) { 189 System.err.println("Error: Could not convert " + microString + "," + 190 minorString + " or " + majorString + " to integer"); 191 errorOccured = true; 192 } 193 } 194 } 195 196 // if ( microString == null ) { microString = ""; } 197 // if ( majorString == null ) { majorString = ""; } 198 // if ( releaseString == null ) { releaseString = ""; } 199 // if ( minorString == null ) { minorString = ""; } 200 // System.err.println("Major " + majorString + " Minor: " + minorString + " Micro: " + microString + " Release: " + releaseString); 201 202 if ( errorOccured ) { 203 micro = null; 204 minor = null; 205 major = null; 206 release = null; 207 } 208 209 HashMap hashRpm = new HashMap(); 210 211 hashRpm.put("micro", micro); 212 hashRpm.put("minor", minor); 213 hashRpm.put("major", major); 214 hashRpm.put("release", release); 215 216 // If one of this values is "null", procedure "compareTwoRpms" always delivers false. 217 // This means, that the installed package is not older. 218 219 // System.err.println("Analyzed: " + "micro: " + hashRpm.get("micro").toString() + " minor: " + hashRpm.get("minor").toString() + " major: " + hashRpm.get("major").toString()); 220 221 return hashRpm; 222 } 223 224 private HashMap analyzeReleaseString(HashMap hashRpm, String releaseString) { 225 int release; 226 227 try { 228 release = Integer.parseInt(releaseString); 229 Integer releaseObj = new Integer(release); 230 hashRpm.put("release", releaseObj); 231 } 232 catch (NumberFormatException ex) { 233 // JRE often contain a string like "FCS" 234 // System.err.println("Error: Could not convert " + releaseString + " to integer"); 235 hashRpm.put("release", null); 236 } 237 238 return hashRpm; 239 } 240 241 public int getInstalledMinor(String version) { 242 243 int minor = 0; 244 int pos = version.indexOf("."); 245 if ( pos > -1 ) { 246 String reduced = version.substring(pos + 1, version.length()); 247 248 pos = reduced.indexOf("."); 249 if ( pos > -1 ) { 250 reduced = reduced.substring(0, pos); 251 minor = Integer.parseInt(reduced); 252 } 253 } 254 255 return minor; 256 } 257 258 private boolean compareTwoRpms(HashMap hash1, HashMap hash2) { 259 boolean hash1IsOlder = false; 260 261 if (( hash1.get("major") != null ) && ( hash2.get("major") != null )) { 262 if ( ((Integer)hash1.get("major")).intValue() < ((Integer)hash2.get("major")).intValue() ) { 263 hash1IsOlder = true; 264 } else { 265 if (( hash1.get("minor") != null ) && ( hash2.get("minor") != null )) { 266 if ( ((Integer)hash1.get("minor")).intValue() < ((Integer)hash2.get("minor")).intValue() ) { 267 hash1IsOlder = true; 268 } else { 269 if (( hash1.get("micro") != null ) && ( hash2.get("micro") != null )) { 270 if ( ((Integer)hash1.get("micro")).intValue() < ((Integer)hash2.get("micro")).intValue() ) { 271 hash1IsOlder = true; 272 } else { 273 if (( hash1.get("release") != null ) && ( hash2.get("release") != null )) { 274 if ( ((Integer)hash1.get("release")).intValue() < ((Integer)hash2.get("release")).intValue() ) { 275 hash1IsOlder = true; 276 } 277 } 278 } 279 } 280 } 281 } 282 } 283 } 284 285 return hash1IsOlder; 286 } 287 288 public boolean compareVersionAndRelease(String versionString, String releaseString, PackageDescription packageData, boolean checkIfInstalledIsOlder) { 289 // version and release are gotten from the rpm database. packageData contains 290 // the information about the rpm, that shall be installed. It has to be installed, 291 // if the installed product defined by version and release is older. 292 // version is something like "2.0.3", release something like "164". 293 // An exception is the jre package, where version is "1.5.0_06" and release "fcs". 294 295 HashMap installedRpm = analyzeVersionString(versionString); 296 if ( installedRpm.get("release") == null ) { 297 installedRpm = analyzeReleaseString(installedRpm, releaseString); 298 } 299 300 // System.err.println("Package: " + packageData.getPackageName()); 301 // String outputString = "Installed RPM: "; 302 // if ( installedRpm.get("major") != null ) { outputString = outputString + " major: " + installedRpm.get("major").toString(); } 303 // else { outputString = outputString + " major is null"; } 304 // if ( installedRpm.get("minor") != null ) { outputString = outputString + " minor: " + installedRpm.get("minor").toString(); } 305 // else { outputString = outputString + " minor is null"; } 306 // if ( installedRpm.get("micro") != null ) { outputString = outputString + " micro: " + installedRpm.get("micro").toString(); } 307 // else { outputString = outputString + " micro is null"; } 308 // if ( installedRpm.get("release") != null ) { outputString = outputString + " release: " + installedRpm.get("release").toString(); } 309 // else { outputString = outputString + " release is null"; } 310 // System.err.println(outputString); 311 312 HashMap notInstalledRpm = analyzeVersionString(packageData.getPkgVersion()); 313 if ( notInstalledRpm.get("release") == null ) { 314 notInstalledRpm = analyzeReleaseString(notInstalledRpm, packageData.getPkgRelease()); 315 } 316 317 // outputString = "Not installed RPM: "; 318 // if ( notInstalledRpm.get("major") != null ) { outputString = outputString + " major: " + notInstalledRpm.get("major").toString(); } 319 // else { outputString = outputString + " major is null"; } 320 // if ( notInstalledRpm.get("minor") != null ) { outputString = outputString + " minor: " + notInstalledRpm.get("minor").toString(); } 321 // else { outputString = outputString + " minor is null"; } 322 // if ( notInstalledRpm.get("micro") != null ) { outputString = outputString + " micro: " + notInstalledRpm.get("micro").toString(); } 323 // else { outputString = outputString + " micro is null"; } 324 // if ( notInstalledRpm.get("release") != null ) { outputString = outputString + " release: " + notInstalledRpm.get("release").toString(); } 325 // else { outputString = outputString + " release is null"; } 326 // System.err.println(outputString); 327 328 boolean firstIsOlder = false; 329 330 if ( checkIfInstalledIsOlder ) { 331 firstIsOlder = compareTwoRpms(installedRpm, notInstalledRpm); 332 // System.err.println("Result: Installed RPM is older: " + firstIsOlder); 333 } else { 334 firstIsOlder = compareTwoRpms(notInstalledRpm, installedRpm); 335 // System.err.println("Result: Not installed RPM is older: " + firstIsOlder); 336 } 337 338 return firstIsOlder; 339 } 340 341 public void getLinuxPackageNamesFromRpmquery(PackageDescription packageData, InstallData installData) { 342 343 if ((packageData.getPackageName() != null) && ( ! packageData.getPackageName().equals(""))) { 344 345 boolean rpmExists = checkPackageExistence(packageData, installData); 346 347 if ( rpmExists ) { 348 // Full package name not defined in xpd file 349 if (( packageData.getFullPackageName() == null ) || ( packageData.getFullPackageName().equals(""))) { 350 // Now it is possible to query the rpm database for the packageName, if it is not defined in xpd file! 351 String fullPackageName = getPackageNameFromRpm(packageData, installData); 352 if ( fullPackageName != null ) { 353 packageData.setFullPackageName(fullPackageName); 354 } else { 355 System.err.println("Error: Linux package name not defined in xpd file and could not be determined: " 356 + packageData.getPackageName()); 357 } 358 } 359 packageData.setPkgExists(true); 360 361 } else { 362 packageData.setPkgExists(false); 363 } 364 365 } 366 367 for (Enumeration e = packageData.children(); e.hasMoreElements(); ) { 368 PackageDescription child = (PackageDescription) e.nextElement(); 369 getLinuxPackageNamesFromRpmquery(child, installData); 370 } 371 } 372 373 public String getLinuxDatabasePath(InstallData data) { 374 String databasePath = null; 375 String installDir = data.getInstallDir(); 376 String databaseDir = installDir; 377 // String databaseDir = SystemManager.getParentDirectory(installDir); 378 String linuxDatabaseName = ".RPM_OFFICE_DATABASE"; 379 File databaseFile = new File(databaseDir, linuxDatabaseName); 380 databasePath = databaseFile.getPath(); 381 return databasePath; 382 } 383 384 public void investigateDebian(InstallData data) { 385 386 // First check: Is this a Debian system? 387 388 String dpkgFile = "/usr/bin/dpkg"; 389 390 if ( new File(dpkgFile).exists() ) { 391 392 data.setIsDebianSystem(true); 393 394 // Second check: If this is a Debian system, is "--force-debian" required? Older 395 // versions do not support "--force-debian". 396 397 // String rpmQuery = "rpm --help; 398 String[] rpmQueryArray = new String[2]; 399 rpmQueryArray[0] = "rpm"; 400 rpmQueryArray[1] = "--help"; 401 402 Vector returnVector = new Vector(); 403 Vector returnErrorVector = new Vector(); 404 int returnValue = ExecuteProcess.executeProcessReturnVector(rpmQueryArray, returnVector, returnErrorVector); 405 406 // Checking if the return vector contains the string "force-debian" 407 408 for (int i = 0; i < returnVector.size(); i++) { 409 String line = (String) returnVector.get(i); 410 if ( line.indexOf("force-debian") > -1 ) { 411 data.setUseForceDebian(true); 412 } 413 } 414 } 415 } 416 417 public void getLinuxFileInfo(PackageDescription packageData) { 418 // analyzing a string like "openoffice-core01-2.0.3-159" as "name-version-release" 419 InstallData data = InstallData.getInstance(); 420 if ( packageData.pkgExists() ) { 421 if (( packageData.getFullPackageName() != null ) && ( ! packageData.getFullPackageName().equals(""))) { 422 String longName = packageData.getFullPackageName(); 423 424 int pos = longName.lastIndexOf("-"); 425 if (data.isInstallationMode()) { 426 // not saving at uninstallation, because it can be updated without GUI installer 427 packageData.setPkgRelease(longName.substring(pos+1, longName.length())); 428 } 429 longName = longName.substring(0, pos); 430 431 pos = longName.lastIndexOf("-"); 432 if (data.isInstallationMode()) { 433 // not saving at uninstallation, because it can be updated without GUI installer 434 packageData.setPkgVersion(longName.substring(pos+1, longName.length())); 435 } 436 packageData.setPkgRealName(longName.substring(0, pos)); 437 } 438 } 439 440 for (Enumeration e = packageData.children(); e.hasMoreElements(); ) { 441 PackageDescription child = (PackageDescription) e.nextElement(); 442 getLinuxFileInfo(child); 443 } 444 445 } 446 447 public void setFullPackageNameAtUninstall(PackageDescription packageData, HashMap packageNames) { 448 449 if (( packageData.getPackageName() != null ) && ( ! packageData.getPackageName().equals(""))) { 450 if (( packageData.getFullPackageName() == null ) || ( packageData.getFullPackageName().equals(""))) { 451 String packageName = packageData.getPackageName(); 452 // Does this always exist? Should not be required! 453 // But is there another way to get the packageNames, without this file? 454 // During installation the packageNames can be determined by querying the rpm file 455 // -> this is not possible during uninstallation 456 String fullPackageName = (String) packageNames.get(packageName); 457 packageData.setFullPackageName(fullPackageName); 458 } 459 } 460 461 for (Enumeration e = packageData.children(); e.hasMoreElements(); ) { 462 PackageDescription child = (PackageDescription) e.nextElement(); 463 setFullPackageNameAtUninstall(child, packageNames); 464 } 465 } 466 467 public String getRelocationString(PackageDescription packageData, String packageName) { 468 String relocationString = null; 469 470 if ( packageData.isRelocatable() ) { 471 // String rpmQuery = "rpm -qp --qf %{PREFIXES}" + " " + packageName; 472 String[] rpmQueryArray = new String[5]; 473 rpmQueryArray[0] = "rpm"; 474 rpmQueryArray[1] = "-qp"; 475 rpmQueryArray[2] = "--qf"; 476 rpmQueryArray[3] = "%{PREFIXES}"; 477 rpmQueryArray[4] = packageName; 478 479 Vector returnVector = new Vector(); 480 Vector returnErrorVector = new Vector(); 481 int returnValue = ExecuteProcess.executeProcessReturnVector(rpmQueryArray, returnVector, returnErrorVector); 482 relocationString = (String) returnVector.get(0); 483 } 484 485 return relocationString; 486 } 487 488 public void createPackageNameFileAtPostinstall(InstallData data, PackageDescription packageData) { 489 490 // The file "packageNames" must not be an own database! It must be possible to install 491 // and deinstall RPMs without this GUI installer. Therefore the file packageNames is 492 // not always up to date. Nevertheless it makes the deinstallation faster, because of 493 // all packages, whose "real" package name is not defined in xpd files (for example 494 // "openoffice-core01-2.0.3-159.rpm" hat the "real" name "openoffice-core01" that is 495 // used for deinstallation) this can be read in this file. Otherwise it would be 496 // neccessary to determine the "real" name with a database question. 497 // The version and release that are also stored in file "packageNames" must not be 498 // used for deinstallation because they are probably not up to date. 499 500 File destDir = new File(data.getInstallDefaultDir(), data.getProductDir()); 501 File uninstallDir = new File(destDir, data.getUninstallDirName()); 502 String fileName = "packageNames"; 503 File packageNamesFile = new File(uninstallDir, fileName); 504 Vector packageNames = new Vector(); 505 getPackageNamesContent(packageData, packageNames); 506 SystemManager.saveCharFileVector(packageNamesFile.getPath(), packageNames); 507 } 508 509 public HashMap readPackageNamesFile() { 510 // package names are stored in file "packageNames" in data.getInfoRoot() directory 511 String fileName = "packageNames"; 512 InstallData data = InstallData.getInstance(); 513 File dir = data.getInfoRoot(); 514 File file = new File(dir, fileName); 515 Vector fileContent = SystemManager.readCharFileVector(file.getPath()); 516 HashMap map = Converter.convertVectorToHashmap(fileContent); 517 return map; 518 } 519 520 public void saveModulesLogFile(InstallData data) { 521 if ( data.logModuleStates() ) { 522 Vector logContent = LogManager.getModulesLogFile(); 523 File destDir = new File(data.getInstallDefaultDir(), data.getProductDir()); 524 File uninstallDir = new File(destDir, data.getUninstallDirName()); 525 File modulesLogFile = new File(uninstallDir, "moduleSettingsLog.txt"); 526 SystemManager.saveCharFileVector(modulesLogFile.getPath(), logContent); 527 } 528 } 529 530 public String fixInstallationDirectory(String installDir) { 531 // inject a second slash to the last path segment to avoid rpm 3 concatenation bug 532 int lastSlashPos = installDir.lastIndexOf('/'); 533 String sub1 = installDir.substring(0,lastSlashPos); 534 String sub2 = installDir.substring(lastSlashPos); 535 String fixedInstallDir = sub1 + "/" + sub2; 536 // fixedInstallDir.replaceAll(" ", "%20"); 537 return fixedInstallDir; 538 } 539 540 } 541