KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jdesktop > jdic > packager > impl > WinMsiUtility


1 /*
2  * Copyright (C) 2004 Sun Microsystems, Inc. All rights reserved. Use is
3  * subject to license terms.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the Lesser GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA.
19  */

20
21 package org.jdesktop.jdic.packager.impl;
22
23 import java.util.ArrayList JavaDoc;
24 import java.util.TreeMap JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.io.IOException JavaDoc;
27
28 /**
29  * WinMsiUtility provide some high level Msi APIs.
30  */

31 public class WinMsiUtility {
32
33     /**
34      * Flag for success operation.
35      */

36     private static final int ERROR_SUCCESS = WinMsiWrapper.ERROR_SUCCESS;
37     /**
38      * Flag for failed operation.
39      */

40     private static final int ERROR_FAIL = -1;
41     /**
42      * Field index for licensed welcome index in table welcomemsg.
43      */

44     private static final int LICENSED_WELCOME_MSG_FIELD_INDEX = 2;
45     /**
46      * Field index for non licensed welcome index in table welcomemsg.
47      */

48     private static final int NON_LICENSED_WELCOME_MSG_FIELD_INDEX = 3;
49
50     /**
51      * Sets the property field of summary information stream.
52      *
53      * @param msiFilePath The msi database file path.
54      * @param uiProperty Specify the property field to be changed.
55      * @param strValue Specify the property field value.
56      * @throws IOException If failed to sets the property field.
57      */

58     public static void setSummaryInfoProperty(String JavaDoc msiFilePath,
59                                               int uiProperty,
60                                               String JavaDoc strValue)
61                                               throws IOException JavaDoc {
62         //Handle to the database elements
63
int hDatabase = 0, hSummaryInfo = 0;
64         try {
65             //Opens the MSI database
66
hDatabase = openDatabase(msiFilePath);
67             //Database has been sucessfully opened
68
hSummaryInfo = openSummaryInfo(hDatabase);
69             WinMsiWrapper.winMsiSummaryInfoSetProperty(hSummaryInfo,
70                                                        uiProperty,
71                                                        strValue);
72             WinMsiWrapper.winMsiSummaryInfoPersist(hSummaryInfo);
73             WinMsiWrapper.winMsiDatabaseCommit(hDatabase);
74         } finally {
75             WinMsiWrapper.winMsiCloseHandle(hSummaryInfo);
76             WinMsiWrapper.winMsiCloseHandle(hDatabase);
77             WinMsiWrapper.winMsiCloseAllHandles();
78         }
79     }
80
81     /**
82      * Set the MSI fields property in the given table.
83      *
84      * @param msiFilePath The MSI file path.
85      * @param tableName The table to be checked
86      * @param keyFieldName Name of the key field
87      * @param valueIndex index of the value column
88      * @param isBinary Specify whether we set the binary stream or text field
89      * property
90      * @param map TreeMap containing the key-value pair to be replaced with
91      * @throws IOException If failed to set the MSI field property.
92      */

93     public static void winMsiSetProperty(String JavaDoc msiFilePath,
94                                          String JavaDoc tableName,
95                                          String JavaDoc keyFieldName,
96                                          int valueIndex,
97                                          boolean isBinary,
98                                          TreeMap JavaDoc map) throws IOException JavaDoc {
99         ///////////////////////////////////////////////////////////////
100
//Parameter checking first
101
//table name should not be null
102
if (tableName == null) {
103             throw new IllegalArgumentException JavaDoc("MSI table name can't be null");
104         }
105         //keyFieldName should not be null
106
if (keyFieldName == null) {
107             throw new IllegalArgumentException JavaDoc(
108                     "MSI key field name can't be null");
109         }
110         //valueIndex should not be <= 0
111
if (valueIndex <= 0) {
112             throw new IllegalArgumentException JavaDoc("MSI value index can't be null");
113         }
114         //map should not be null
115
if (map == null) {
116             throw new IllegalArgumentException JavaDoc("map data can't be null!");
117         }
118         //If the map contains no data, just return.
119
if (map.size() == 0) {
120             return;
121         }
122         ///////////////////////////////////////////////////////////////
123
//Begin processing
124
//Handle to the database elements
125
int hDatabase = 0;
126         int hView = 0;
127         int hRecord = 0;
128         //flag to indicate if one record has been replaced, default to false
129
boolean recordsReplaced = false;
130         try {
131             //Opens the MSI database
132
hDatabase = openDatabase(msiFilePath);
133             //Database has been sucessfully opened
134
Iterator JavaDoc it = map.keySet().iterator();
135             String JavaDoc keyName = null;
136             String JavaDoc newKeyValue = null;
137             while (it.hasNext()) {
138                 keyName = (String JavaDoc) it.next();
139                 newKeyValue = (String JavaDoc) map.get(keyName);
140                 if (isBinary) {
141                     //To set the file stream, a file validation check is needed
142
WinUtility.checkFileValid(newKeyValue);
143                 }
144                 String JavaDoc fieldNames = "*";
145                 String JavaDoc criterial = " where "
146                                    + keyFieldName + " = '" + keyName + "'";
147                 hView = openView(hDatabase, tableName, fieldNames, criterial);
148                 hRecord = getRecord(hView);
149                 if (hRecord != 0) {
150                     //We've got non-null record here
151
setRecordProperty(hView, hRecord, valueIndex,
152                                     isBinary, newKeyValue);
153                     recordsReplaced = true;
154                 }
155             }
156             //Only commit the database if
157
//1. All the fields has been successfuly replaced.
158
//2. There is an actual record field replacement.
159
if (recordsReplaced) {
160                 WinMsiWrapper.winMsiDatabaseCommit(hDatabase);
161             }
162         } finally {
163             closeView(hView);
164             WinMsiWrapper.winMsiCloseHandle(hDatabase);
165             WinMsiWrapper.winMsiCloseAllHandles();
166         }
167     }
168
169     /**
170      * Generated the MSI transform MST file based on the given MSI files.
171      *
172      * @param database The given MSI file.
173      * @param databaseReference The given MSI file as the transform reference.
174      * @param transformFile The target transform file.
175      *
176      * @throws IOException If failed to generate the transform file.
177      */

178     public static void generateTransform(String JavaDoc database,
179                                          String JavaDoc databaseReference,
180                                          String JavaDoc transformFile)
181                                          throws IOException JavaDoc {
182         int hDatabase = 0;
183         int hDatabaseReference = 0;
184         try {
185             hDatabase = openDatabase(database);
186             hDatabaseReference = openDatabase(databaseReference);
187             WinMsiWrapper.winMsiDatabaseGenerateTransform(hDatabase,
188                                                           hDatabaseReference,
189                                                           transformFile);
190             WinMsiWrapper.winMsiCreateTransformSummaryInfo(hDatabase,
191                                                            hDatabaseReference,
192                                                            transformFile);
193         } finally {
194             WinMsiWrapper.winMsiCloseHandle(hDatabase);
195             WinMsiWrapper.winMsiCloseHandle(hDatabaseReference);
196         }
197     }
198
199     /**
200      * Running sql on the given MSI database.
201      *
202      * @param msiFilePath The given MSI database file path.
203      * @param sqlStrings The given sql string.
204      *
205      * @throws IOException If failed to run the sql.
206      */

207     public static void runSql(String JavaDoc msiFilePath, ArrayList JavaDoc sqlStrings)
208                             throws IOException JavaDoc {
209         int hDatabase = 0;
210         int hView = 0;
211         try {
212             hDatabase = openDatabase(msiFilePath);
213             int[] result = new int[] {0, 0};
214             String JavaDoc sqlString;
215             for (Iterator JavaDoc i = sqlStrings.iterator(); i.hasNext();) {
216                 sqlString = (String JavaDoc) i.next();
217                 result = WinMsiWrapper.winMsiDatabaseOpenView(hDatabase,
218                                                               sqlString);
219                 hView = result[1];
220                 WinMsiWrapper.winMsiViewExecute(hView, 0);
221             }
222             WinMsiWrapper.winMsiDatabaseCommit(hDatabase);
223         } finally {
224             closeView(hView);
225             WinMsiWrapper.winMsiCloseHandle(hDatabase);
226             WinMsiWrapper.winMsiCloseAllHandles();
227         }
228     }
229
230     /**
231      * Add a record with binary fields.
232      *
233      * @param msiFilePath The given msi file path.
234      * @param tableName The given table name.
235      * @param fieldNames The field names.
236      * @param fieldProperties The fields properties
237      * ('String' for general field,
238      * 'stream' for binary field).
239      * @param fieldValues The value of the field (For general field, it should
240      * be the string value, for binary field, it should
241      * be the file name).
242      *
243      * @throws IOException If failed to add the binary record.
244      */

245     public static void addBinaryRecord(String JavaDoc msiFilePath,
246                                        String JavaDoc tableName,
247                                        String JavaDoc[] fieldNames,
248                                        String JavaDoc[] fieldProperties,
249                                        String JavaDoc[] fieldValues)
250                                        throws IOException JavaDoc {
251        int hMsiDatabase = 0;
252        int hView = 0;
253        int hRecord = 0;
254        try {
255             hMsiDatabase = openDatabase(msiFilePath);
256             String JavaDoc fieldsName = fieldNames[0];
257             for (int i = 1; i < fieldNames.length; i++) {
258                 fieldsName += ", " + fieldNames[i];
259             }
260             hView = openView(hMsiDatabase, tableName, fieldsName, "");
261             hRecord = WinMsiWrapper.winMsiCreateRecord(fieldNames.length);
262             for (int i = 0; i < fieldNames.length; i++) {
263                 if ((fieldProperties[i].compareToIgnoreCase("String")) == 0) {
264                     WinMsiWrapper.winMsiRecordSetString(hRecord, i + 1,
265                                                         fieldValues[i]);
266                     WinMsiWrapper.winMsiViewExecute(hView, hRecord);
267                 }
268                 if ((fieldProperties[i].compareToIgnoreCase("Stream")) == 0) {
269                     WinMsiWrapper.winMsiRecordSetStream(hRecord, i + 1,
270                                                         fieldValues[i]);
271                     WinMsiWrapper.winMsiViewModify(
272                                   hView,
273                                   WinMsiWrapper.MSIMODIFY_ASSIGN,
274                                   hRecord);
275                 }
276             }
277            WinMsiWrapper.winMsiDatabaseCommit(hMsiDatabase);
278        } finally {
279            WinMsiWrapper.winMsiCloseHandle(hRecord);
280            closeView(hView);
281            WinMsiWrapper.winMsiCloseHandle(hMsiDatabase);
282        }
283     }
284     /**
285      * Incorporate the mst file into the msi database "_Storages" table with
286      * the name as fieldsName.
287      * @param msiFilePath Given msi file path.
288      * @param mstFilePath Given mst file path.
289      * @param fieldName Given field name.
290      * @throws IOException If failed to incorporate the MST file.
291      */

292     public static void incorporateMST(String JavaDoc msiFilePath,
293                                       String JavaDoc mstFilePath,
294                                       String JavaDoc fieldName)
295                                       throws IOException JavaDoc {
296         String JavaDoc[] fieldNames = new String JavaDoc[] {"Name", "Data"};
297         String JavaDoc tableName = "_Storages";
298         String JavaDoc[] fieldProperties = new String JavaDoc[] {"String", "Stream"};
299         String JavaDoc[] fieldValues = new String JavaDoc[] {fieldName, mstFilePath};
300         addBinaryRecord(msiFilePath, tableName, fieldNames,
301                         fieldProperties, fieldValues);
302     }
303
304     /**
305      * Import a table from a table txt file representation.
306      * @param msiFilePath The msi file path.
307      * @param folderPath The directory where the txt file locates.
308      * @param txtTableName The txt file name.
309      * @throws IOException If failed to import the table from the file.
310      */

311     public static void importTableFromFile(String JavaDoc msiFilePath,
312                                            String JavaDoc folderPath,
313                                            String JavaDoc txtTableName)
314                                            throws IOException JavaDoc {
315        int hDatabase = 0;
316        try {
317            hDatabase = openDatabase(msiFilePath);
318            WinMsiWrapper.winMsiDatabaseImport(hDatabase,
319                                               folderPath,
320                                               txtTableName);
321            WinMsiWrapper.winMsiDatabaseCommit(hDatabase);
322        } finally {
323            WinMsiWrapper.winMsiCloseHandle(hDatabase);
324        }
325     }
326
327     /**
328      * Appy the MST transform onto the MSI file.
329      * @param msiFilePath The specified MSI path.
330      * @param mstFilePath The specified MST path.
331      * @throws IOException If failed to apply the transform.
332      */

333     public static void applyMstToMsi(String JavaDoc msiFilePath,
334                                      String JavaDoc mstFilePath)
335                                      throws IOException JavaDoc {
336         int[] result = new int[] {0, 0};
337         try {
338             result = WinMsiWrapper.winMsiOpenDatabase(
339                                         msiFilePath,
340                                         WinMsiWrapper.MSIDBOPEN_TRANSACT);
341             //Get the database handle if succeed
342
int hDatabase = result[1];
343             WinMsiWrapper.winMsiDatabaseApplyTransform(hDatabase, mstFilePath);
344             WinMsiWrapper.winMsiDatabaseCommit(hDatabase);
345             WinMsiWrapper.winMsiCloseHandle(hDatabase);
346         } catch (IOException JavaDoc e) {
347             System.out.println(e);
348         }
349     }
350
351     /**
352      * Sets the record value field with the new value.
353      * @param hView The given view.
354      * @param hRecord The given record.
355      * @param valueIndex The value column index.
356      * @param isBinary Specify whether the field is binary field.
357      * @param newValue New value to be replaced with.
358      * @throws IOException If fail to set the record property.
359      */

360     private static void setRecordProperty(int hView,
361                                           int hRecord,
362                                           int valueIndex,
363                                           boolean isBinary,
364                                           String JavaDoc newValue)
365                                           throws IOException JavaDoc {
366         try {
367             if (isBinary) {
368                 WinMsiWrapper.winMsiRecordSetStream(hRecord,
369                                                     valueIndex,
370                                                     newValue);
371             } else {
372                 WinMsiWrapper.winMsiRecordSetString(hRecord,
373                                                     valueIndex,
374                                                     newValue);
375             }
376             WinMsiWrapper.winMsiViewModify(hView,
377                                            WinMsiWrapper.MSIMODIFY_REPLACE,
378                                            hRecord);
379         } finally {
380             WinMsiWrapper.winMsiCloseHandle(hRecord);
381         }
382     }
383
384     /**
385      * Opens the given databse.
386      * @param msiFilePath Database file path.
387      * @return The handle to the opened MSI database.
388      * @throws IOException If fail to open the MSI database.
389      */

390     private static int openDatabase(String JavaDoc msiFilePath) throws IOException JavaDoc {
391         int[] result = new int[] {ERROR_FAIL, 0};
392         result = WinMsiWrapper.winMsiOpenDatabase(
393                                msiFilePath,
394                                WinMsiWrapper.MSIDBOPEN_TRANSACT);
395         //return the database handle if succeed
396
return result[1];
397     }
398
399     /**
400      * Opens the msi summary information stream.
401      * @param hDatabase Handle of the msi database opened.
402      * @return The summary information stream handle.
403      * @throws IOException If failed to open the Summary Info stream.
404      */

405     private static int openSummaryInfo(int hDatabase) throws IOException JavaDoc {
406         int[] result = new int[] {ERROR_FAIL, 0};
407         result = WinMsiWrapper.winMsiGetSummaryInformation(hDatabase);
408         //return the summary information stream handle
409
return result[1];
410     }
411
412     /**
413      * Opens a table in the given database.
414      * @param hDatabase The database handle.
415      * @param tableName The name of the table to be opened.
416      * @param fieldNames The fields to be selected.
417      * @param criterial The records selecting criterial.
418      * @return Handle to the opened view.
419      * @throws IOException If fail to open the view.
420      */

421     private static int openView(int hDatabase,
422                                 String JavaDoc tableName,
423                                 String JavaDoc fieldNames,
424                                 String JavaDoc criterial)
425                                 throws IOException JavaDoc {
426         int[] result = new int[] {ERROR_FAIL, 0};
427         //Constructs a sql string
428
String JavaDoc sqlSelectStr = "select " + fieldNames + " from " + tableName
429                               + " " + criterial;
430         result = WinMsiWrapper.winMsiDatabaseOpenView(hDatabase, sqlSelectStr);
431         int hView = result[1];
432         WinMsiWrapper.winMsiViewExecute(hView, 0);
433         return hView;
434     }
435
436     /**
437      * Close the view and view handle.
438      * @param hView Handle to view.
439      * @throws IOException If fail to close the view.
440      */

441     private static void closeView(int hView) throws IOException JavaDoc {
442         WinMsiWrapper.winMsiViewClose(hView);
443         WinMsiWrapper.winMsiCloseHandle(hView);
444     }
445
446     /**
447      * Returns the handle to the record.
448      * @param hView The given view.
449      * @return Handle to the record if succeed.
450      * @throws IOException If fail to get the record.
451      */

452     private static int getRecord(int hView) throws IOException JavaDoc {
453        int[] result;
454        result = WinMsiWrapper.winMsiViewFetch(hView);
455        if (result[0] == WinMsiWrapper.ERROR_NO_MORE_ITEMS) {
456            //No records found, just return zero (indicating null record)
457
return 0;
458        } else {
459            //return a valid record handle if succeed
460
return result[1];
461        }
462     }
463
464     /**
465      * Gets the localized welcome msg according to license display status.
466      * @param msiFilePath The given msi file path.
467      * @param locale The name of the current locale.
468      * @param isShowLicense Whether the license information gets displayed.
469      * @return The localized welcome message (according to isShowLicense).
470      * @throws IOException If failed to get the welcome message.
471      */

472     public static String JavaDoc getWelcomeMsg(String JavaDoc msiFilePath,
473                                         String JavaDoc locale,
474                                         boolean isShowLicense)
475                                         throws IOException JavaDoc {
476         int hDatabase = 0;
477         int hView = 0;
478         int hRecord = 0;
479         try {
480             hDatabase = openDatabase(msiFilePath);
481             String JavaDoc tableName =
482                     MsiPackageGenerator.LOCALIZED_WELCOME_MSG_TABLE_NAME;
483             String JavaDoc fieldNames = "*";
484             String JavaDoc criterial = " where "
485                                + "Locale = '"
486                                + locale
487                                + "'";
488             hView = openView(hDatabase, tableName, fieldNames, criterial);
489             hRecord = getRecord(hView);
490             String JavaDoc welcomeMsg = null;
491             if (isShowLicense) {
492                 welcomeMsg = WinMsiWrapper.winMsiRecordGetString(
493                                 hRecord,
494                                 LICENSED_WELCOME_MSG_FIELD_INDEX);
495             } else {
496                 welcomeMsg = WinMsiWrapper.winMsiRecordGetString(
497                                 hRecord,
498                                 NON_LICENSED_WELCOME_MSG_FIELD_INDEX);
499             }
500             return welcomeMsg;
501         } finally {
502             WinMsiWrapper.winMsiCloseHandle(hRecord);
503             closeView(hView);
504             WinMsiWrapper.winMsiCloseHandle(hDatabase);
505         }
506     }
507
508     /**
509      * Generate a UUID String.
510      * @return String representing the UUID.
511      * @throws IOException If fail to generate the UUID.
512      */

513     public static String JavaDoc genUUID() throws IOException JavaDoc {
514         String JavaDoc oneUUID = WinMsiWrapper.generateUUID();
515         if (oneUUID != null) {
516             return oneUUID.toUpperCase();
517         } else {
518             throw new IOException JavaDoc("Could not generate the UUID.");
519         }
520     }
521 }
522
Popular Tags