xref: /AOO41X/main/javainstaller2/src/JavaSetup/org/openoffice/setup/InstallerHelper/LinuxHelper.java (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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