Source Code Cross Referenced for XLETInstallerImpl.java in  » 6.0-JDK-Modules » j2me » com » sun » jumpimpl » module » installer » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » com.sun.jumpimpl.module.installer 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright  1990-2006 Sun Microsystems, Inc. All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0004:         *
0005:         * This program is free software; you can redistribute it and/or
0006:         * modify it under the terms of the GNU General Public License version
0007:         * 2 only, as published by the Free Software Foundation.
0008:         *
0009:         * This program is distributed in the hope that it will be useful, but
0010:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0012:         * General Public License version 2 for more details (a copy is
0013:         * included at /legal/license.txt).
0014:         *
0015:         * You should have received a copy of the GNU General Public License
0016:         * version 2 along with this work; if not, write to the Free Software
0017:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0018:         * 02110-1301 USA
0019:         *
0020:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0021:         * Clara, CA 95054 or visit www.sun.com if you need additional
0022:         * information or have any questions.
0023:         */
0024:
0025:        package com.sun.jumpimpl.module.installer;
0026:
0027:        import com.sun.jump.common.JUMPAppModel;
0028:        import com.sun.jump.common.JUMPApplication; //import com.sun.jump.executive.JUMPUserInputManager;
0029:        import com.sun.jump.module.contentstore.JUMPContentStore;
0030:        import com.sun.jump.module.contentstore.JUMPData;
0031:        import com.sun.jump.module.contentstore.JUMPNode;
0032:        import com.sun.jump.module.contentstore.JUMPStore;
0033:        import com.sun.jump.module.contentstore.JUMPStoreFactory;
0034:        import com.sun.jump.module.contentstore.JUMPStoreHandle;
0035:        import com.sun.jump.module.download.JUMPDownloadDescriptor;
0036:        import com.sun.jump.common.JUMPContent;
0037:        import com.sun.jump.module.installer.JUMPInstallerModule;
0038:        import java.io.BufferedReader;
0039:        import java.io.File;
0040:        import java.io.FileOutputStream;
0041:        import java.io.IOException;
0042:        import java.io.InputStream;
0043:        import java.io.InputStreamReader;
0044:        import java.net.MalformedURLException;
0045:        import java.net.URL;
0046:        import java.util.Enumeration;
0047:        import java.util.Hashtable;
0048:        import java.util.Iterator;
0049:        import java.util.Map;
0050:        import java.util.Properties;
0051:        import java.util.Vector;
0052:        import java.util.jar.JarFile;
0053:        import java.util.zip.ZipEntry;
0054:
0055:        /**
0056:         * XLETInstallerImpl contains the implementation of the JUMPInstallerModule
0057:         * for XLET applications within JUMP.
0058:         * Note: XLET and Main installations within JUMP in CDC behave almost the same.
0059:         * For this reason, MAINInstallerImpl simply subclasses XLETInstallerImpl
0060:         * and overrides a small set of methods to define specific Main application
0061:         * behavior.  In the future, if the behavior of XLET and Main application
0062:         * installation start to differ much more, it may be wise to extract a base
0063:         * class out of this class and create a subclass each for XLETs and Main
0064:         * applications.
0065:         */
0066:        public class XLETInstallerImpl extends JUMPContentStore implements 
0067:                JUMPInstallerModule {
0068:            /**
0069:             * The filename extention for application descriptor files.
0070:             */
0071:            private final static String APP_DESCRIPTOR_EXTENSION = ".app";
0072:            /**
0073:             * The name of the directory to hold XLET and Main applications
0074:             */
0075:            private final static String REPOSITORY_APPS_DIRNAME = "./apps";
0076:            /**
0077:             * The name of the directory to hold XLET and Main icons
0078:             */
0079:            private final static String REPOSITORY_ICONS_DIRNAME = "./icons";
0080:            /**
0081:             * The name of the directory to hold XLET and Main application descriptor files
0082:             */
0083:            private final static String REPOSITORY_DESCRIPTORS_DIRNAME = "./descriptors";
0084:            /**
0085:             * Handle to the content store
0086:             */
0087:            private JUMPStoreHandle storeHandle = null;
0088:            /**
0089:             * The root directory of the content store
0090:             */
0091:            protected String contentStoreDir = null;
0092:            /**
0093:             * Holds the app id -> JUMPApplication object relationship
0094:             */
0095:            private Hashtable installedAppIdHashtable = null;
0096:            private int installedAppIdHashtableKey = 1;
0097:
0098:            /**
0099:             * The keys below are used within application descriptor files only.
0100:             * These keys are not the sames keys as the ones used in the download module.
0101:             */
0102:            private final static String DESCRIPTOR_BUNDLENAME_KEY = "bundle";
0103:            private final static String DESCRIPTOR_APPMODEL_KEY = "type";
0104:            private final static String DESCRIPTOR_JARPATH_KEY = "path";
0105:            private final static String DESCRIPTOR_TITLE_KEY = "title";
0106:            private final static String DESCRIPTOR_ICON_KEY = "icon";
0107:            private final static String DESCRIPTOR_SECURITYLEVEL_KEY = "icon";
0108:            private final static String DESCRIPTOR_ID_KEY = "id";
0109:
0110:            protected final static String DESCRIPTOR_INITIALCLASS_KEY = "xletName";
0111:
0112:            /**
0113:             * Print out messages
0114:             */
0115:            private boolean verbose = false;
0116:
0117:            /**
0118:             *
0119:             */
0120:            private static final boolean ALLOW_MULTIPLE_APP_INSTALLS = false;
0121:
0122:            private String getAvailableAppIdHashKey() {
0123:                int tempHashKey = installedAppIdHashtableKey;
0124:                while (installedAppIdHashtable.containsKey(Integer
0125:                        .toString(tempHashKey))) {
0126:                    if (tempHashKey == Integer.MAX_VALUE) {
0127:                        tempHashKey = 1;
0128:                    } else {
0129:                        tempHashKey++;
0130:                    }
0131:
0132:                    // For the very, very unlikely case that MAX_VALUE applications
0133:                    // are running and we cycled through all integer values.
0134:                    if (tempHashKey == installedAppIdHashtableKey) {
0135:                        return null;
0136:                    }
0137:                }
0138:                installedAppIdHashtableKey = tempHashKey;
0139:                return Integer.toString(tempHashKey);
0140:            }
0141:
0142:            private void addInstalledAppIdEntry(Object key, Object app) {
0143:                // Sanity check
0144:                if (key == null || app == null) {
0145:                    return;
0146:                }
0147:
0148:                int keyVal = Integer.parseInt((String) key);
0149:                if (keyVal < 1) {
0150:                    return;
0151:                } else {
0152:                    installedAppIdHashtableKey = keyVal;
0153:                }
0154:                installedAppIdHashtable.put(key, app);
0155:            }
0156:
0157:            private void removeInstalledAppIdEntry(Object key) {
0158:                if (key == null) {
0159:                    return;
0160:                }
0161:                Object app = installedAppIdHashtable.remove(key);
0162:            }
0163:
0164:            /**
0165:             * Returns an instance of the content store to be used with the installer.
0166:             * @return Instance of JUMPStore
0167:             */
0168:            protected JUMPStore getStore() {
0169:                return JUMPStoreFactory.getInstance().getModule(
0170:                        JUMPStoreFactory.TYPE_FILE);
0171:            }
0172:
0173:            /**
0174:             * Implementation of JUMPInstaler.unload()
0175:             */
0176:            public void unload() {
0177:                contentStoreDir = null;
0178:                verbose = false;
0179:                if (storeHandle != null) {
0180:                    closeStore(storeHandle);
0181:                }
0182:                installedAppIdHashtable.clear();
0183:                installedAppIdHashtable = null;
0184:            }
0185:
0186:            /**
0187:             * load the installer module
0188:             * @param map the configuration data required for loading this service.
0189:             */
0190:            public void load(Map map) {
0191:                // check if verbose mode is used
0192:                String verboseStr = System.getProperty("installer.verbose");
0193:                if (verboseStr == null && map != null) {
0194:                    verboseStr = (String) map.get("installer.verbose");
0195:                }
0196:                if (verboseStr != null
0197:                        && verboseStr.toLowerCase().equals("true")) {
0198:                    verbose = true;
0199:                }
0200:
0201:                // the repository directory should be passed in as a system property
0202:                contentStoreDir = System.getProperty("contentstore.root");
0203:                if (contentStoreDir == null && map != null) {
0204:                    contentStoreDir = (String) map.get("contentstore.root");
0205:                }
0206:                if (contentStoreDir != null) {
0207:                    // remove any ending /'s'
0208:                    if (!contentStoreDir.endsWith("/")) {
0209:                        contentStoreDir = contentStoreDir.concat("/");
0210:                    }
0211:                } else {
0212:                    // default to the current directory
0213:                    contentStoreDir = "./";
0214:                }
0215:
0216:                // Get the store handle from the JUMPContentStoreSubClass.
0217:                storeHandle = openStore(true);
0218:
0219:                // Make sure apps/, icons/, descriptors/ exist under the root
0220:                // of content store.  This is inherited CDC-specific behavior.
0221:                try {
0222:                    // Create the directories within the repository if they don't exist'
0223:                    if (storeHandle.getNode(REPOSITORY_APPS_DIRNAME) == null) {
0224:                        storeHandle.createNode(REPOSITORY_APPS_DIRNAME);
0225:                    }
0226:                    if (storeHandle.getNode(REPOSITORY_ICONS_DIRNAME) == null) {
0227:                        storeHandle.createNode(REPOSITORY_ICONS_DIRNAME);
0228:                    }
0229:                    if (storeHandle.getNode(REPOSITORY_DESCRIPTORS_DIRNAME) == null) {
0230:                        storeHandle.createNode(REPOSITORY_DESCRIPTORS_DIRNAME);
0231:                    }
0232:                } catch (Exception e) {
0233:                    e.printStackTrace();
0234:                }
0235:
0236:                closeStore(storeHandle);
0237:
0238:                // Populate the installedAppIdHashtable to keep track of the installed
0239:                // ids of all currently installed applications of this type
0240:                installedAppIdHashtableKey = 1;
0241:                if (installedAppIdHashtable != null) {
0242:                    installedAppIdHashtable.clear();
0243:                }
0244:                installedAppIdHashtable = new Hashtable();
0245:                JUMPContent[] content = getInstalled();
0246:                if (content != null) {
0247:                    for (int j = 0; j < content.length; j++) {
0248:                        JUMPApplication app = ((JUMPApplication) content[j]);
0249:                        int installedId = app.getId();
0250:                        addInstalledAppIdEntry(Integer.toString(installedId),
0251:                                app);
0252:                    }
0253:                }
0254:            }
0255:
0256:            /**
0257:             * install content specified by the given descriptor and location.
0258:             * @return the installed content
0259:             * @param location URL of content to be installed
0260:             * @param desc object describing the content to be installed
0261:             */
0262:            public JUMPContent[] install(URL location,
0263:                    JUMPDownloadDescriptor desc) {
0264:                // sanity check
0265:                if (location == null
0266:                        || desc == null
0267:                        || !location.getProtocol().equals("file")
0268:                        || desc.getType() != JUMPDownloadDescriptor.TYPE_APPLICATION) {
0269:                    return null;
0270:                }
0271:
0272:                // This is the all important "name" value.  This is the value retrieved
0273:                // from the <name> in the Descriptor file.  This value will be used
0274:                // as the bundle name and is also used to name the jarfile and parent
0275:                // directory in the repository.  We need to restrict the characters used
0276:                // within this name value, which means that all of the characters in the name
0277:                // must be valid filename characters.  This name value is not intended
0278:                // for any display value purposes.  For that, use <ddx:display>.
0279:                // Here's an example.  Let's say the name value is CasinoGames.  Then
0280:                // the resulting jarfile name will be: apps/CasinoGames/CasinoGames.jar.
0281:                // If there is already a pathname that is the same, the jarfile name changes
0282:                // a bit.  We currently do not overwrite the existing duplicate file.  Read
0283:                // below for more details.
0284:                String bundleName = desc.getName();
0285:                if (bundleName == null) {
0286:                    return null;
0287:                }
0288:
0289:                // We need to replace spaces because apparently java doesn't like
0290:                // jarfiles with spaces in the name. Any further string substitutions
0291:                // should be done here.
0292:                bundleName = bundleName.replace(' ', '_');
0293:
0294:                trace(getString("Installing") + bundleName);
0295:
0296:                String jarPathWithinStore = REPOSITORY_APPS_DIRNAME + '/'
0297:                        + bundleName + '/' + bundleName + ".jar";
0298:                String jarPath = null;
0299:                if (ALLOW_MULTIPLE_APP_INSTALLS) {
0300:                    // createUniquePathName ensures that we don't overwrite an existing file by
0301:                    // retrieving a unique name for saving.  If there exists a file of the same
0302:                    // name, using the example above the new name will look something like this:
0303:                    // apps/CasinoGames(2)/CasinoGames(2).jar.
0304:                    jarPath = createUniquePathName(contentStoreDir
0305:                            + jarPathWithinStore);
0306:                } else {
0307:                    jarPath = contentStoreDir + jarPathWithinStore;
0308:                    if (new File(jarPath).exists()) {
0309:                        System.out
0310:                                .println("*** Error installing bundle: A bundle with this name is already installed.");
0311:                        return null;
0312:                    }
0313:                }
0314:
0315:                trace(getString("AttemptingToSave") + jarPath);
0316:
0317:                // Because of the possibility of the filename being modified because of
0318:                // an already exiting file, the bundle name will also need to change.
0319:                // The new bundle name is within the filename itself, so extract the bundle
0320:                // name.  For the example above, the new bundle name will be CasinoGames(2),
0321:                // not CasinoGames.  Again, this is only in the rare case of duplicates.
0322:                // This should be changed if the policy is to overwrite existing filenames.
0323:                int dotindex = jarPath.lastIndexOf('.');
0324:                int fileSeparatorIndex = jarPath.lastIndexOf('/');
0325:                if (dotindex == -1 || fileSeparatorIndex == -1) {
0326:                    return null;
0327:                }
0328:
0329:                // The bundleName because the fileName minus the .jar
0330:                bundleName = jarPath
0331:                        .substring(fileSeparatorIndex + 1, dotindex);
0332:                String parentDir = jarPath.substring(0, fileSeparatorIndex);
0333:
0334:                try {
0335:                    // This is the location of the file passed into the install method
0336:                    File origFile = new File(location.getFile());
0337:                    if (!origFile.exists()) {
0338:                        trace(getString("CannotAccessFile") + ": "
0339:                                + location.getFile());
0340:                        return null;
0341:                    }
0342:
0343:                    // First, create the parent directory for the saved application
0344:                    File destDir = new File(parentDir);
0345:                    destDir.mkdir();
0346:                    if (!destDir.exists()) {
0347:                        trace(destDir.toString() + " "
0348:                                + getString("DoesNotExist"));
0349:                        return null;
0350:                    }
0351:
0352:                    // Move the file from the passed-in location
0353:                    File destFile = new File(jarPath);
0354:                    if (destFile == null) {
0355:                        return null;
0356:                    }
0357:                    boolean result = origFile.renameTo(destFile
0358:                            .getCanonicalFile());
0359:                    if (!result) {
0360:                        trace(getString("CannotMoveFile"));
0361:
0362:                        // The file move didn't work.  A reason for this could be that
0363:                        // the original file and destination file are in two different
0364:                        // filesystems.  Try copying a buffer from the URL input stream.
0365:                        trace(getString("UsingURLInputStream"));
0366:                        byte[] buffer = copyBuffer(location.openStream(), desc
0367:                                .getSize());
0368:                        if (buffer == null) {
0369:                            trace(getString("CannotSaveFile"));
0370:                            return null;
0371:                        }
0372:
0373:                        // Write out to a file within the repository
0374:                        FileOutputStream fos = new FileOutputStream(destFile);
0375:                        if (fos == null) {
0376:                            trace(getString("CannotSaveFile"));
0377:                            return null;
0378:                        }
0379:                        fos.write(buffer);
0380:                        fos.close();
0381:                        origFile.delete();
0382:                    }
0383:                } catch (Exception ex) {
0384:                    ex.printStackTrace();
0385:                    try {
0386:                        storeHandle.deleteNode(parentDir);
0387:                    } catch (IOException e) {
0388:                        e.printStackTrace();
0389:                    }
0390:                    return null;
0391:                }
0392:
0393:                // Now it is time to install the applications into the system
0394:                Properties apps[] = desc.getApplications();
0395:                if (apps == null) {
0396:                    return null;
0397:                }
0398:
0399:                Hashtable installedContentHashtable = new Hashtable();
0400:                for (int i = 0; i < apps.length; i++) {
0401:                    Properties app = apps[i];
0402:
0403:                    // sanity check
0404:                    if (app == null) {
0405:                        continue;
0406:                    }
0407:
0408:                    String appTitle = app.getProperty("JUMPApplication_title");
0409:                    if (appTitle == null) {
0410:                        return null;
0411:                    }
0412:
0413:                    // Properties object to hold application properties to be written to .app file
0414:                    // The key values in this properties object should match the key values
0415:                    // defined for application descriptor files.
0416:                    Properties appProperties = new Properties();
0417:
0418:                    String appIDHashKey = getAvailableAppIdHashKey();
0419:                    if (appIDHashKey == null) {
0420:                        trace("ERROR: Could not obtain an id hash key value.");
0421:                        return null;
0422:                    } else {
0423:                        appProperties.setProperty(DESCRIPTOR_ID_KEY,
0424:                                appIDHashKey);
0425:                    }
0426:
0427:                    // Retrieve the filename of the icon
0428:                    //String iconFileName = app.getIconPath().getFile();
0429:                    String iconFileName = app
0430:                            .getProperty("JUMPApplication_iconPath");
0431:
0432:                    // extract the icon image from the jar file and place it in
0433:                    // the icons/ directory within the app repository
0434:                    String iconPath = extractIconFromJar(jarPath, iconFileName
0435:                            .trim(), appIDHashKey);
0436:
0437:                    // create an app descriptor file in the menu/ directory for
0438:                    // the new app so that the appmanager can recognize it.
0439:                    // make sure the descriptor pathname is uniqe and doesn't exist.
0440:                    String descriptorsDir = REPOSITORY_DESCRIPTORS_DIRNAME + '/';
0441:
0442:                    appProperties.setProperty(DESCRIPTOR_BUNDLENAME_KEY,
0443:                            bundleName);
0444:                    appProperties.setProperty(DESCRIPTOR_APPMODEL_KEY, app
0445:                            .getProperty("JUMPApplication_appModel"));
0446:                    appProperties
0447:                            .setProperty(
0448:                                    getInstallerInitialClassKey(),
0449:                                    app
0450:                                            .getProperty(getPropertyInstallerInitialClassKey()));
0451:                    appProperties.setProperty(DESCRIPTOR_JARPATH_KEY, jarPath);
0452:                    appProperties.setProperty(DESCRIPTOR_TITLE_KEY, appTitle);
0453:                    if (iconPath != null) {
0454:                        appProperties
0455:                                .setProperty(DESCRIPTOR_ICON_KEY, iconPath);
0456:                    }
0457:                    String securityLevel = desc.getSecurityLevel();
0458:                    if (securityLevel != null) {
0459:                        appProperties.setProperty(DESCRIPTOR_SECURITYLEVEL_KEY,
0460:                                securityLevel);
0461:                    }
0462:
0463:                    String appDescriptorPath = descriptorsDir + appTitle + '-'
0464:                            + appIDHashKey + APP_DESCRIPTOR_EXTENSION;
0465:                    if (new File(appDescriptorPath).exists()) {
0466:                        System.out
0467:                                .println("*** Error installing bundle: A descriptor with this name is already installed.");
0468:                        return null;
0469:                    }
0470:                    // create application descriptor file
0471:                    boolean result = createAppDescriptor(appDescriptorPath,
0472:                            appProperties);
0473:                    // create JUMPApplication object for the app
0474:                    if (result) {
0475:                        JUMPApplication module = createJUMPApplication(appDescriptorPath);
0476:                        trace("--> createJUMPApplication returns: "
0477:                                + module.toString());
0478:                        if (module != null) {
0479:                            installedContentHashtable.put(appIDHashKey, module);
0480:                            addInstalledAppIdEntry(appIDHashKey, module);
0481:                        }
0482:                    }
0483:                }
0484:
0485:                // return installed content
0486:                int size = installedContentHashtable.size();
0487:                if (size > 0) {
0488:                    Vector jumpAppObjectsVector = new Vector();
0489:                    JUMPContent content[] = new JUMPContent[size];
0490:                    for (Enumeration e = installedContentHashtable.keys(); e
0491:                            .hasMoreElements();) {
0492:                        Object key = e.nextElement();
0493:                        Object app = installedContentHashtable.get(key);
0494:                        jumpAppObjectsVector.add(app);
0495:                    }
0496:                    return (JUMPContent[]) jumpAppObjectsVector
0497:                            .toArray(new JUMPContent[] {});
0498:                } else {
0499:                    return null;
0500:                }
0501:            };
0502:
0503:            /**
0504:             * Uninstall content.
0505:             * @param content the object to be uninstalled
0506:             */
0507:            public void uninstall(JUMPContent content) {
0508:                // sanity check
0509:                if (content == null) {
0510:                    return;
0511:                }
0512:
0513:                JUMPApplication app = (JUMPApplication) content;
0514:
0515:                String bundleName = getBundleName(app);
0516:                JUMPApplication[] apps = getAppsInBundle(bundleName);
0517:
0518:                if (apps == null || bundleName == null) {
0519:                    return;
0520:                }
0521:
0522:                // Currently, calling JUMPExecutive.getInstance returns null.  Therefore, we
0523:                // cannot use the JUMPUserInputManager APIs until this is fixed.  When this is
0524:                // fixed, the following code can be uncommented.
0525:
0526:                //        if (apps.length > 1) {
0527:                //            JUMPExecutive executive = JUMPExecutive.getInstance();
0528:                //            if (executive == null) {
0529:                //                System.out.println("ERROR: The JUMP Executive instance is null.");
0530:                //                return;
0531:                //            }
0532:                //            JUMPUserInputManager uiManager = executive.getUserInputManager();
0533:                //            String str = "This application belongs to the bundle: " + bundleName + " which contains multiple applications.  Do you wish to remove the bundle and all of its applications?";
0534:                //            boolean rc = uiManager.showDialog(str, null, "OK", "Cancel");
0535:                //            if (!rc) {
0536:                //                return;
0537:                //            }
0538:                //        }
0539:
0540:                if (apps.length > 1) {
0541:                    System.out.print(app.getAppType().toString());
0542:                    System.out.print(": " + app.getTitle()
0543:                            + " is contained within a bundle");
0544:                    System.out
0545:                            .println("that contains the following applications:");
0546:                    System.out.print("  ");
0547:                    for (int i = 0; i < apps.length; i++) {
0548:                        JUMPApplication application = (JUMPApplication) apps[i];
0549:                        System.out.print(application.getTitle());
0550:                        if (i < (apps.length - 1)) {
0551:                            System.out.print(", ");
0552:                        }
0553:                    }
0554:                    System.out.println("");
0555:                    //            String value = System.getProperty("jump.installer.interactive");
0556:                    //            if (value.toLowerCase().equals("true")) {
0557:                    //                System.out.println("Deleting this bundle will remove all of the applications.");
0558:                    //                while ( true ) {
0559:                    //                    String message = "Do you wish to proceed? [y/n]: ";
0560:                    //                    String answer = Utilities.promptUser(message);
0561:                    //                    if (answer.toLowerCase().equals("y")) {
0562:                    //                        break;
0563:                    //                    } else if (answer.toLowerCase().equals("n")){
0564:                    //                        return;
0565:                    //                    } else {
0566:                    //                        System.out.println("ERROR: Illegal response.");
0567:                    //                    }
0568:                    //                }
0569:                    //                
0570:                    //            } else {
0571:                    System.out.println("All applications will be removed.");
0572:                    //            }
0573:                }
0574:
0575:                trace(getString("AttemptingToRemove") + bundleName);
0576:
0577:                // Get the path to the app bundle's jar file, which is assumed
0578:                // to be the first entry in the classpath.
0579:                String jarPath = getAppClasspath(app);
0580:                boolean result1 = removeJarFile(jarPath);
0581:                if (!result1) {
0582:                    trace(getString("CannotRemoveApplicationJar") + ": "
0583:                            + jarPath);
0584:                }
0585:
0586:                // Remove the icon and app descriptor for each app in the bundle
0587:                for (int i = 0; i < apps.length; i++) {
0588:
0589:                    int appId = apps[i].getId();
0590:                    removeInstalledAppIdEntry(Integer.toString(appId));
0591:
0592:                    // Remove the icon and app descriptor for each app
0593:                    boolean result2 = removeAppDescriptor(apps[i]);
0594:                    if (!result2) {
0595:                        trace(getString("CouldNotRemoveAppDescriptor")
0596:                                + apps[i].getTitle());
0597:                    }
0598:
0599:                    boolean result3 = removeIcon(apps[i].getIconPath());
0600:                    if (!result3) {
0601:                        trace(getString("CouldNotRemoveIcon")
0602:                                + apps[i].getTitle());
0603:                    }
0604:
0605:                    if (result1 && result2 && result3) {
0606:                        System.out.println(getString("SuccessfulUninstall")
0607:                                + apps[i].getTitle());
0608:                    }
0609:                }
0610:            };
0611:
0612:            /**
0613:             * Update content from given location.  For XLET and Main applications, the behavior is to uninstall the current bundle and install the new bundle.
0614:             * @param content object to be updated
0615:             * @param location URL location of content to update with
0616:             * @param desc object describing the bundle to update with
0617:             */
0618:            public void update(JUMPContent content, URL location,
0619:                    JUMPDownloadDescriptor desc) {
0620:                uninstall(content);
0621:                install(location, desc);
0622:            };
0623:
0624:            /**
0625:             * Get all installed content of type XLET
0626:             * @return Array of JUMPApplication objects that are XLETs
0627:             */
0628:            public JUMPContent[] getInstalled() {
0629:
0630:                Vector nodeVector = new Vector();
0631:
0632:                storeHandle = openStore(true);
0633:
0634:                // get the listing of all nodes starting at the root.
0635:                JUMPNode.List list = null;
0636:                try {
0637:                    list = (JUMPNode.List) storeHandle
0638:                            .getNode(REPOSITORY_DESCRIPTORS_DIRNAME);
0639:                } catch (IOException e) {
0640:                    trace("Exception in getNode(): " + e.toString());
0641:                }
0642:
0643:                closeStore(storeHandle);
0644:
0645:                if (list == null) {
0646:                    return null;
0647:                }
0648:
0649:                for (Iterator itn = list.getChildren(); itn.hasNext();) {
0650:                    JUMPNode node = (JUMPNode) itn.next();
0651:                    JUMPApplication app = createJUMPApplication(node.getURI());
0652:
0653:                    // Identify only the xlets or main apps, not both at the same time
0654:                    if (app != null
0655:                            && app.getAppType() == getInstallerAppModel()) {
0656:                        nodeVector.add(app);
0657:                    }
0658:                }
0659:                return (JUMPApplication[]) nodeVector
0660:                        .toArray(new JUMPApplication[] {});
0661:            };
0662:
0663:            /**
0664:             * Given the application object, return the name of the bundle the application belongs to
0665:             * @param app application object
0666:             * @return the names of the bundle this application belongs to
0667:             */
0668:            protected String getBundleName(JUMPApplication app) {
0669:                XLETApplication xletApp = (XLETApplication) app;
0670:                return xletApp.getBundle();
0671:            }
0672:
0673:            /**
0674:             * Given the bundle name, return the application objects within the bundle
0675:             * @param bundle name of content bundle
0676:             * @return the application objects belonging to the bundle
0677:             */
0678:            protected JUMPApplication[] getAppsInBundle(String bundle) {
0679:                JUMPApplication[] apps = (JUMPApplication[]) getInstalled();
0680:                Vector appsVector = new Vector();
0681:                for (int i = 0; i < apps.length; i++) {
0682:                    XLETApplication xletApp = (XLETApplication) apps[i];
0683:                    if (xletApp.getBundle().equals(bundle)) {
0684:                        appsVector.add(apps[i]);
0685:                    }
0686:                }
0687:                Object[] objs = appsVector.toArray();
0688:                JUMPApplication[] bundleApps = new JUMPApplication[objs.length];
0689:                for (int i = 0; i < objs.length; i++) {
0690:                    bundleApps[i] = (JUMPApplication) objs[i];
0691:                }
0692:                return bundleApps;
0693:            }
0694:
0695:            private String extractIconFromJar(String jarFile, String iconFile) {
0696:                return (extractIconFromJar(jarFile, iconFile, null));
0697:            }
0698:
0699:            private String extractIconFromJar(String jarFile, String iconFile,
0700:                    String id) {
0701:
0702:                String iconFileName = null;
0703:                String iconFilePath = null;
0704:
0705:                JarFile jar = null;
0706:
0707:                try {
0708:                    jar = new JarFile(jarFile);
0709:                } catch (Exception e) {
0710:                    e.printStackTrace();
0711:                    return null;
0712:                }
0713:
0714:                trace("extractIconFromJar(): jarfile: " + jarFile + "  icon: "
0715:                        + iconFile);
0716:
0717:                ZipEntry entry = jar.getEntry(iconFile);
0718:                if (entry == null) {
0719:                    trace(getString("CouldNotExtract") + iconFile);
0720:                    return null;
0721:                }
0722:
0723:                int index = iconFile.lastIndexOf('/');
0724:                if (index != -1) {
0725:                    iconFileName = iconFile.substring(index + 1, iconFile
0726:                            .length());
0727:                } else {
0728:                    iconFileName = iconFile;
0729:                }
0730:
0731:                if (id != null) {
0732:                    // Get extention of file
0733:                    int dotindex = iconFileName.lastIndexOf('.');
0734:                    if (dotindex == -1) {
0735:                        return null;
0736:                    }
0737:
0738:                    // The path up until the extention.
0739:                    String pathToExtention = iconFileName
0740:                            .substring(0, dotindex);
0741:
0742:                    // The extention
0743:                    String extention = iconFileName.substring(dotindex);
0744:
0745:                    iconFileName = pathToExtention + '-' + id + extention;
0746:                }
0747:
0748:                String iconsDir = contentStoreDir + REPOSITORY_ICONS_DIRNAME
0749:                        + '/';
0750:                iconFilePath = iconsDir + iconFileName;
0751:                if (new File(iconFilePath).exists()) {
0752:                    System.out
0753:                            .println("*** Warning installing bundle: An icon with this name is already installed.");
0754:                    return iconFilePath;
0755:                } else {
0756:                    trace("Saving icon file: " + iconFilePath);
0757:                }
0758:
0759:                try {
0760:
0761:                    InputStream zis = jar.getInputStream(entry);
0762:
0763:                    int size = (int) entry.getSize();
0764:                    // -1 means unknown size.
0765:                    if (size == -1) {
0766:                        trace(getString("IconFileSizeError"));
0767:                        return null;
0768:                    }
0769:
0770:                    byte[] buffer = copyBuffer(zis, size);
0771:
0772:                    File f = new File(iconFilePath);
0773:                    FileOutputStream fos = new FileOutputStream(f);
0774:                    fos.write(buffer);
0775:                    fos.close();
0776:
0777:                    return iconFilePath;
0778:
0779:                } catch (Exception e) {
0780:                    e.printStackTrace();
0781:                }
0782:                return null;
0783:            }
0784:
0785:            /**
0786:             * This is necessary to avoid issues when downloading and installing the
0787:             * same app on the device, or at least an app with the same exact name.
0788:             * Simply concat a number, starting with 2, to the end of the path until
0789:             * a path is found that doesn't already exist.
0790:             */
0791:            private String createUniquePathName(String original) {
0792:
0793:                int NUM = 2;
0794:                int LIMIT = 1000;
0795:
0796:                // Get extention of file
0797:                int dotindex = original.lastIndexOf('.');
0798:                if (dotindex == -1) {
0799:                    return null;
0800:                }
0801:
0802:                // The path up until the extention.
0803:                String pathToExtention = original.substring(0, dotindex);
0804:
0805:                // The extention
0806:                String extention = original.substring(dotindex);
0807:
0808:                // Get the file name minus the extention
0809:                int fileSeparatorIndex = original.lastIndexOf('/');
0810:                String fileName = null;
0811:                if (fileSeparatorIndex != -1) {
0812:                    fileName = original.substring(fileSeparatorIndex + 1,
0813:                            dotindex);
0814:                } else {
0815:                    return null;
0816:                }
0817:
0818:                // First, check if the original name is unique
0819:                String testPath = original;
0820:                File testPathFile = new File(testPath);
0821:                while (testPathFile.exists() && NUM < LIMIT) {
0822:                    String EXTRA = '(' + Integer.toString(NUM) + ')';
0823:                    testPath = pathToExtention + EXTRA + extention;
0824:                    testPathFile = new File(testPath);
0825:
0826:                    // Need to change the parent directory of the file if this
0827:                    // is a jarfile
0828:                    if (testPath.endsWith(".jar")) {
0829:                        String parentPath = testPathFile.getParent();
0830:                        testPath = parentPath + EXTRA + '/' + fileName + EXTRA
0831:                                + extention;
0832:                        testPathFile = new File(testPath);
0833:                    }
0834:                    NUM++;
0835:                }
0836:
0837:                if (NUM == LIMIT) {
0838:                    return null;
0839:                }
0840:
0841:                return testPath;
0842:            }
0843:
0844:            /**
0845:             * Create an application descriptor for the given application
0846:             * values.  The application descriptor gets saved into the
0847:             * application repository's menu directory.
0848:             * @param descriptorPath the path within the content store to store the application descriptor
0849:             * @param props object containing the properties of the application descriptor
0850:             * @return boolean value indicating success or failure
0851:             */
0852:            private boolean createAppDescriptor(String descriptorPath,
0853:                    Properties props) {
0854:
0855:                // Convert the paths to the relative path from the content store root,
0856:                // we don't want to store the absolute path to the persistant store
0857:                removeContentStorePath(props, DESCRIPTOR_ICON_KEY);
0858:                removeContentStorePath(props, DESCRIPTOR_JARPATH_KEY);
0859:
0860:                JUMPData propData = new JUMPData(props);
0861:
0862:                try {
0863:                    storeHandle.createDataNode(descriptorPath, propData);
0864:                } catch (RuntimeException re) {
0865:                    re.printStackTrace();
0866:                    return false;
0867:                } catch (IOException ioe) {
0868:                    ioe.printStackTrace();
0869:                    return false;
0870:                }
0871:
0872:                return true;
0873:            }
0874:
0875:            /**
0876:             * Retrieve an instance of JUMPApplication for the given application or menu.
0877:             */
0878:            private JUMPApplication createJUMPApplication(String descriptorPath) {
0879:
0880:                storeHandle = openStore(true);
0881:                JUMPNode appDescriptorNode = null;
0882:                try {
0883:                    appDescriptorNode = storeHandle.getNode(descriptorPath);
0884:                } catch (IOException e) {
0885:                    e.printStackTrace();
0886:                }
0887:                closeStore(storeHandle);
0888:
0889:                if (appDescriptorNode == null) {
0890:                    trace(getString("AppDescriptorNotFound") + descriptorPath);
0891:                    return null;
0892:                }
0893:
0894:                JUMPData appDescriptorData = null;
0895:                if (appDescriptorNode.containsData()) {
0896:                    appDescriptorData = ((JUMPNode.Data) appDescriptorNode)
0897:                            .getData();
0898:                } else {
0899:                    return null;
0900:                }
0901:
0902:                Properties appDescriptorProps = (Properties) appDescriptorData
0903:                        .getValue();
0904:                JUMPApplication module = null;
0905:
0906:                // First, make sure the app type is correct
0907:                String appType = (String) appDescriptorProps
0908:                        .getProperty(DESCRIPTOR_APPMODEL_KEY);
0909:                if (appType == null
0910:                        || !appType.equals(getInstallerAppModel().getName())) {
0911:                    return null;
0912:                }
0913:
0914:                // Convert back the path to the absolute path
0915:                addContentStorePath(appDescriptorProps, DESCRIPTOR_ICON_KEY);
0916:                addContentStorePath(appDescriptorProps, DESCRIPTOR_JARPATH_KEY);
0917:
0918:                // Now, obtain the values for specific keys
0919:                String classPath = (String) appDescriptorProps
0920:                        .getProperty(DESCRIPTOR_JARPATH_KEY);
0921:                if (classPath == null) {
0922:                    return null;
0923:                }
0924:
0925:                URL classPathURL = null;
0926:                try {
0927:                    classPathURL = new URL("file", null, classPath);
0928:                    if (classPathURL == null) {
0929:                        return null;
0930:                    }
0931:                } catch (MalformedURLException ex) {
0932:                    ex.printStackTrace();
0933:                    return null;
0934:                }
0935:
0936:                String bundleName = (String) appDescriptorProps
0937:                        .getProperty(DESCRIPTOR_BUNDLENAME_KEY);
0938:                if (bundleName == null) {
0939:                    return null;
0940:                }
0941:
0942:                String title = (String) appDescriptorProps
0943:                        .getProperty(DESCRIPTOR_TITLE_KEY);
0944:                if (title == null) {
0945:                    return null;
0946:                }
0947:
0948:                String iconPath = (String) appDescriptorProps
0949:                        .getProperty(DESCRIPTOR_ICON_KEY);
0950:                URL iconPathURL = null;
0951:                if (iconPath != null) {
0952:                    try {
0953:                        iconPathURL = new URL("file", null, iconPath);
0954:                        if (iconPathURL == null) {
0955:                            return null;
0956:                        }
0957:                    } catch (MalformedURLException ex) {
0958:                        ex.printStackTrace();
0959:                        return null;
0960:                    }
0961:                } else {
0962:                    trace("Application: " + title + " doesn't have an icon.");
0963:                }
0964:
0965:                String clazz = (String) appDescriptorProps
0966:                        .getProperty(getInstallerInitialClassKey());
0967:
0968:                String id = (String) appDescriptorProps.getProperty("id");
0969:
0970:                module = createJUMPApplicationObject(bundleName, clazz,
0971:                        classPathURL, title, iconPathURL, Integer.parseInt(id));
0972:
0973:                return module;
0974:            }
0975:
0976:            /**
0977:             * Removes the content store dir path from the property represented by the key.
0978:             * Used when creating .app file from the JUMPApplication properties list,
0979:             * so that .app file in the content sore will not have a full path to store,
0980:             * allowing the store to be moved from one location to another.
0981:             */
0982:            private void removeContentStorePath(Properties props, String key) {
0983:                String value = (String) props.remove(key);
0984:                if (value == null)
0985:                    return;
0986:                props.put(key, value.substring(contentStoreDir.length()));
0987:            }
0988:
0989:            /**
0990:             * Prepends the content store dir path to the property represented by the key.
0991:             * Used when creating JUMPApplication properties from the .app file
0992:             * in the content store, so that the JUMPApplication created have
0993:             * proper absolute path corresponding to the current run's contentstore
0994:             * root location.
0995:             */
0996:            private void addContentStorePath(Properties props, String key) {
0997:                String value = (String) props.remove(key);
0998:                if (value == null)
0999:                    return;
1000:                props.put(key, contentStoreDir + value);
1001:            }
1002:
1003:            /**
1004:             * Create an instance of JUMPApplication
1005:             * @param bundle Name of application bundle that this application belongs to
1006:             * @param clazz Initial class of application
1007:             * @param classPathURL URL of the classpath of this application
1008:             * @param title The user visible title of this application
1009:             * @param iconPathURL URL to the path of the icon for this application
1010:             * @return application object
1011:             */
1012:            protected JUMPApplication createJUMPApplicationObject(
1013:                    String bundle, String clazz, URL classPathURL,
1014:                    String title, URL iconPathURL, int id) {
1015:                return new XLETApplication(contentStoreDir, bundle, clazz,
1016:                        classPathURL, title, iconPathURL, id);
1017:            }
1018:
1019:            /**
1020:             * Return the application type that this installer module can install
1021:             * @return the application type
1022:             */
1023:            protected JUMPAppModel getInstallerAppModel() {
1024:                return JUMPAppModel.XLET;
1025:            }
1026:
1027:            /**
1028:             * Get the key value used to specify an application's initial class
1029:             * @return initial class key value
1030:             */
1031:            protected String getInstallerInitialClassKey() {
1032:                return "xletName";
1033:            }
1034:
1035:            /**
1036:             * Get the key value used to specify an application's initial class from Properties object
1037:             * @return initial class key value
1038:             */
1039:            protected String getPropertyInstallerInitialClassKey() {
1040:                return XLETApplication.INITIAL_CLASS_KEY;
1041:            }
1042:
1043:            /**
1044:             * Remove the jar file from the content store.
1045:             * The current implementation uses java.util.File methods.
1046:             * @param jarPath path to the jar file within the content store
1047:             * @return boolean value indicating success or failure
1048:             */
1049:            private boolean removeJarFile(String jarPath) {
1050:
1051:                // Check to see that the jar file exists, and if so, start
1052:                // removing things.
1053:                File jarFile = new File(jarPath);
1054:                trace("removeJarFile(): " + jarFile);
1055:                if (jarFile != null && jarFile.exists()) {
1056:                    trace("jarFile: " + jarFile + " exists!!! ***");
1057:                    boolean jarFileDelete = false;
1058:                    boolean jarFileParentDirDelete = false;
1059:                    File jarFileParent = null;
1060:                    try {
1061:                        jarFileParent = jarFile.getParentFile();
1062:                        jarFileDelete = jarFile.delete();
1063:                        if (jarFileParent != null) {
1064:                            jarFileParentDirDelete = jarFileParent.delete();
1065:                        }
1066:                    } catch (Exception e) {
1067:                        e.printStackTrace();
1068:                    }
1069:
1070:                    if (!jarFileDelete) {
1071:                        trace(getString("CannotRemoveApplicationJar"));
1072:                    }
1073:                    // Print out a message if we cannot remove the parent directory,
1074:                    // but continue on...
1075:                    if (!jarFileParentDirDelete) {
1076:                        trace(getString("CouldNotRemoveApplicationDir"));
1077:                    }
1078:                    return true;
1079:                } else {
1080:                    trace(getString("ApplicationJarDoesNotExist"));
1081:                }
1082:
1083:                return false;
1084:            }
1085:
1086:            /**
1087:             * Remove application descriptor from content store
1088:             * @param applicationName the application for which the application descriptor should be removed
1089:             * @return boolean value indicating success or failure
1090:             */
1091:            private boolean removeAppDescriptor(JUMPApplication app) {
1092:                String appTitle = app.getTitle();
1093:                String id = Integer.toString(app.getId());
1094:                String uri = REPOSITORY_DESCRIPTORS_DIRNAME + '/' + appTitle
1095:                        + '-' + id + APP_DESCRIPTOR_EXTENSION;
1096:                storeHandle = openStore(true);
1097:                if (storeHandle == null) {
1098:                    return false;
1099:                }
1100:                try {
1101:                    storeHandle.deleteNode(uri);
1102:                } catch (IOException e) {
1103:                    return false;
1104:                }
1105:                closeStore(storeHandle);
1106:                return true;
1107:            }
1108:
1109:            /**
1110:             * Remove an icon file from within the content store
1111:             * @param iconURL URL of icon file within the content store
1112:             * @return boolean value indicating success or failure
1113:             */
1114:            private boolean removeIcon(URL iconURL) {
1115:                String iconFileName = iconURL.getFile();
1116:                trace("Trying to remove icon file: " + iconFileName);
1117:                File iconFile = new File(iconFileName);
1118:                if (iconFile != null && iconFile.exists()) {
1119:                    try {
1120:                        iconFile.delete();
1121:                    } catch (Exception e) {
1122:                        e.printStackTrace();
1123:                        return false;
1124:                    }
1125:                } else {
1126:                    return false;
1127:                }
1128:                return true;
1129:            }
1130:
1131:            /**
1132:             * read from an input stream into a byte buffer[]
1133:             * @param is the input stream where the data is located
1134:             * @param size the number of bytes to read
1135:             * @return byte buffer of read data
1136:             */
1137:            private byte[] copyBuffer(InputStream is, int size) {
1138:                if (is == null) {
1139:                    return null;
1140:                }
1141:
1142:                byte[] buffer = new byte[size];
1143:                try {
1144:
1145:                    // Read data into buffer
1146:                    int rb = 0;
1147:                    int chunk = 0;
1148:                    while ((size - rb) > 0) {
1149:                        chunk = is.read(buffer, rb, size - rb);
1150:                        if (chunk == -1) {
1151:                            break;
1152:                        }
1153:                        rb += chunk;
1154:                    }
1155:                } catch (IOException ex) {
1156:                    ex.printStackTrace();
1157:                    return null;
1158:                }
1159:
1160:                return buffer;
1161:            }
1162:
1163:            /**
1164:             * Obtain the classpath value of the application object
1165:             * @param app application object
1166:             * @return classpath value of the application object
1167:             */
1168:            protected String getAppClasspath(JUMPApplication app) {
1169:                if (app == null) {
1170:                    return null;
1171:                }
1172:                XLETApplication xletApp = (XLETApplication) app;
1173:                return xletApp.getClasspath().getFile();
1174:            }
1175:
1176:            /**
1177:             * Retrieve a String value from the module's resource bundle
1178:             * @param key key value into resource bundle
1179:             * @return value pertaining to the key field in the resource bundle
1180:             */
1181:            private String getString(String key) {
1182:                return InstallerFactoryImpl.getString(key);
1183:            }
1184:
1185:            /**
1186:             * Simple print command that prints messages if verbose is on
1187:             * @param s string to print
1188:             */
1189:            private void trace(String s) {
1190:                if (verbose) {
1191:                    System.out.println(s);
1192:                }
1193:                return;
1194:            }
1195:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.