001: /*
002: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License version
007: * 2 only, as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful, but
010: * WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * General Public License version 2 for more details (a copy is
013: * included at /legal/license.txt).
014: *
015: * You should have received a copy of the GNU General Public License
016: * version 2 along with this work; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
018: * 02110-1301 USA
019: *
020: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
021: * Clara, CA 95054 or visit www.sun.com if you need additional
022: * information or have any questions.
023: */
024:
025: package com.sun.midp.jump.installer;
026:
027: import com.sun.midp.security.SecurityHandler;
028: import com.sun.midp.security.SecurityToken;
029: import com.sun.midp.security.Permissions;
030:
031: import com.sun.midp.midlet.MIDletSuite;
032:
033: import com.sun.midp.midletsuite.MIDletSuiteStorage;
034: import com.sun.midp.midletsuite.MIDletSuiteImpl;
035: import com.sun.midp.midletsuite.MIDletInfo;
036: import com.sun.midp.midletsuite.MIDletSuiteInfo;
037: import com.sun.midp.midletsuite.InstallInfo;
038: import com.sun.midp.midletsuite.SuiteSettings;
039: import com.sun.midp.midletsuite.MIDletSuiteLockedException;
040: import com.sun.midp.midletsuite.MIDletSuiteCorruptedException;
041:
042: import com.sun.midp.io.j2me.storage.RandomAccessStream;
043: import com.sun.midp.io.j2me.storage.File;
044:
045: //import com.sun.midp.content.CHManager;
046:
047: import com.sun.midp.installer.InvalidJadException;
048: import com.sun.midp.installer.ManifestProperties;
049: import com.sun.midp.installer.VerifierImpl;
050: import com.sun.midp.installer.InstallListener;
051: import com.sun.midp.installer.InstallState;
052: import com.sun.midp.installer.JadProperties;
053:
054: /**
055: * Holds the state of an installation, so it can restarted after it has
056: * been stopped.
057: */
058: public class InstallStateImpl implements InstallState, MIDletSuite {
059:
060: /** Location for the downloaded JAD, could be null */
061: public String localJadUrl;
062:
063: /** Location for the downloaded JAR */
064: public String localJarUrl;
065:
066: /** Contains the data obtained during the installation process */
067: public InstallInfo installInfo;
068:
069: /** Contains the data obtained during the installation process */
070: public SuiteSettings suiteSettings;
071:
072: /** ID of the storage where the new midlet suite will be installed. */
073: public int storageId;
074:
075: /** Receives warnings and status. */
076: public InstallListener listener;
077:
078: /** When the install started, in milliseconds. */
079: public long startTime;
080:
081: /** What to do next. */
082: public int nextStep;
083:
084: /** Signals the installation to stop. */
085: public boolean stopInstallation;
086:
087: /**
088: * Signals that installation is at a point where cancel
089: * requests are ignored
090: */
091: public boolean ignoreCancel;
092:
093: /** exception that stopped the installation. */
094: public InvalidJadException exception;
095:
096: /**
097: * Option to force an overwrite of existing components without
098: * any version comparison.
099: */
100: public boolean force;
101:
102: /**
103: * Option to force the RMS data of the suite to be overwritten to
104: * be removed without comparison to the new suite.
105: */
106: public boolean removeRMS;
107:
108: /** Raw JAD. */
109: public byte[] jad;
110:
111: /** character encoding of the JAD. */
112: public String jadEncoding;
113:
114: /** Parsed JAD. */
115: public JadProperties jadProps;
116:
117: /** Parsed manifest. */
118: public ManifestProperties jarProps;
119:
120: /** Cached File object. */
121: public File file;
122:
123: /** User name for authentication. */
124: protected String username;
125:
126: /** Password for authentication. */
127: protected String password;
128:
129: /** User name for proxyAuthentication. */
130: public String proxyUsername;
131:
132: /** Password for proxy authentication. */
133: public String proxyPassword;
134:
135: /** Status to signal the beginning of the data transfer. */
136: public int beginTransferDataStatus;
137:
138: /** Status for the data transfer method to give to the listener. */
139: public int transferStatus;
140:
141: /** Security Handler. */
142: public SecurityHandler securityHandler;
143:
144: /** Holds the unzipped JAR manifest to be saved. */
145: public byte[] manifest;
146:
147: /** Cache of storage object. */
148: public RandomAccessStream storage;
149:
150: /** Cache of MIDlet suite storage object. */
151: public MIDletSuiteStorage midletSuiteStorage;
152:
153: /** The root of all MIDP persistent system data. */
154: public String storageRoot;
155:
156: /** Signals that previous version exists. */
157: public boolean isPreviousVersion;
158:
159: /** Previous MIDlet suite info. */
160: public MIDletSuiteImpl previousSuite;
161:
162: /** Previous MIDlet suite install info. */
163: public InstallInfo previousInstallInfo;
164:
165: /** The ContentHandler installer state. */
166: //public CHManager chmanager;
167: /** Constructor. */
168: public InstallStateImpl() {
169: installInfo = new InstallInfo(UNUSED_SUITE_ID);
170: suiteSettings = new SuiteSettings(UNUSED_SUITE_ID);
171: }
172:
173: /**
174: * Gets the last recoverable exception that stopped the install.
175: * Non-recoverable exceptions are thrown and not saved in the state.
176: *
177: * @return last exception that stopped the install
178: */
179: public InvalidJadException getLastException() {
180: return exception;
181: }
182:
183: /**
184: * Gets the unique ID that the installed suite was stored with.
185: *
186: * @return storage name that can be used to load the suite
187: */
188: public int getID() {
189: return installInfo.id;
190: }
191:
192: /**
193: * Sets the username to be used for HTTP authentication.
194: *
195: * @param theUsername 8 bit username, cannot contain a ":"
196: */
197: public void setUsername(String theUsername) {
198: username = theUsername;
199: }
200:
201: /**
202: * Sets the password to be used for HTTP authentication.
203: *
204: * @param thePassword 8 bit password
205: */
206: public void setPassword(String thePassword) {
207: password = thePassword;
208: }
209:
210: /**
211: * Sets the username to be used for HTTP proxy authentication.
212: *
213: * @param theUsername 8 bit username, cannot contain a ":"
214: */
215: public void setProxyUsername(String theUsername) {
216: proxyUsername = theUsername;
217: }
218:
219: /**
220: * Sets the password to be used for HTTP proxy authentication.
221: *
222: * @param thePassword 8 bit password
223: */
224: public void setProxyPassword(String thePassword) {
225: proxyPassword = thePassword;
226: }
227:
228: /**
229: * Gets a property of the application to be installed.
230: * First from the jaD, then if not found, the JAR manifeSt.
231: *
232: * @param key key of the property
233: *
234: * @return value of the property or null if not found
235: */
236: public String getAppProperty(String key) {
237: String value;
238:
239: if (jadProps != null) {
240: value = jadProps.getProperty(key);
241: if (value != null) {
242: return value;
243: }
244: }
245:
246: if (jarProps != null) {
247: value = jarProps.getProperty(key);
248: if (value != null) {
249: return value;
250: }
251: }
252:
253: return null;
254: }
255:
256: /**
257: * Gets the URL of the JAR.
258: *
259: * @return URL of the JAR
260: */
261: public String getJarUrl() {
262: return installInfo.jarUrl;
263: }
264:
265: /**
266: * Gets the label for the downloaded JAR.
267: *
268: * @return suite name
269: */
270: public String getSuiteName() {
271: return installInfo.suiteName;
272: }
273:
274: /**
275: * Gets the expected size of the JAR.
276: *
277: * @return size of the JAR in K bytes rounded up
278: */
279: public int getJarSize() {
280: return (installInfo.expectedJarSize + 1023) / 1024;
281: }
282:
283: /**
284: * Gets the authorization path of this suite. The path starts with
285: * the most trusted CA that authorized this suite.
286: *
287: * @return array of CA names or null if the suite was not signed
288: */
289: public String[] getAuthPath() {
290: /*
291: * The auth path returned is no a copy because this object is
292: * only available to callers with the AMS permission, which
293: * have permission to build auth paths for new suites.
294: */
295: return installInfo.getAuthPath();
296: }
297:
298: /**
299: * Checks for permission and throw an exception if not allowed.
300: * May block to ask the user a question.
301: *
302: * @param permission ID of the permission to check for,
303: * the ID must be from
304: * {@link com.sun.midp.security.Permissions}
305: * @param resource string to insert into the question, can be null if
306: * no %2 in the question
307: *
308: * @exception SecurityException if the permission is not
309: * allowed by this token
310: * @exception InterruptedException if another thread interrupts the
311: * calling thread while this method is waiting to preempt the
312: * display.
313: */
314: public void checkForPermission(int permission, String resource)
315: throws InterruptedException {
316: checkForPermission(permission, resource, null);
317: }
318:
319: /**
320: * Checks for permission and throw an exception if not allowed.
321: * May block to ask the user a question.
322: *
323: * @param permission ID of the permission to check for,
324: * the ID must be from
325: * {@link com.sun.midp.security.Permissions}
326: * @param resource string to insert into the question, can be null if
327: * no %2 in the question
328: * @param extraValue string to insert into the question,
329: * can be null if no %3 in the question
330: *
331: * @exception SecurityException if the permission is not
332: * allowed by this token
333: * @exception InterruptedException if another thread interrupts the
334: * calling thread while this method is waiting to preempt the
335: * display.
336: */
337: public void checkForPermission(int permission, String resource,
338: String extraValue) throws InterruptedException {
339:
340: securityHandler.checkForPermission(permission, Permissions
341: .getTitle(permission), Permissions
342: .getQuestion(permission), Permissions
343: .getOneshotQuestion(permission), installInfo.suiteName,
344: resource, extraValue, Permissions.getName(permission));
345: }
346:
347: /**
348: * Indicates if the named MIDlet is registered in the suite
349: * with MIDlet-<n> record in the manifest or
350: * application descriptor.
351: * @param midletName class name of the MIDlet to be checked
352: *
353: * @return true if the MIDlet is registered
354: */
355: public boolean isRegistered(String midletName) {
356: String midlet;
357: MIDletInfo midletInfo;
358:
359: for (int i = 1;; i++) {
360: midlet = getAppProperty("MIDlet-" + i);
361: if (midlet == null) {
362: return false; // We went past the last MIDlet
363: }
364:
365: /* Check if the names match. */
366: midletInfo = new MIDletInfo(midlet);
367: if (midletInfo.classname.equals(midletName)) {
368: return true;
369: }
370: }
371: }
372:
373: /**
374: * Counts the number of MIDlets from its properties.
375: * IMPL_NOTE: refactor to avoid duplication with MIDletSuiteImpl.
376: *
377: * @return number of midlet in the suite
378: */
379: public int getNumberOfMIDlets() {
380: int i;
381:
382: for (i = 1; getProperty("MIDlet-" + i) != null; i++)
383: ;
384:
385: return (i - 1);
386: }
387:
388: /**
389: * Returns the suite's name to display to the user.
390: *
391: * @return suite's name that will be displayed to the user
392: */
393: public String getDisplayName() {
394: String displayName = getAppProperty(MIDletSuite.SUITE_NAME_PROP);
395:
396: if (displayName == null) {
397: displayName = String.valueOf(installInfo.id);
398: }
399:
400: return displayName;
401: }
402:
403: /**
404: * Returns the information about the first midlet in the suite.
405: *
406: * @return MIDletInfo structure describing the first midlet
407: * or null if it is not available
408: */
409: public MIDletInfo getMidletInfo() {
410: String midlet;
411:
412: midlet = getAppProperty("MIDlet-1");
413: if (midlet == null) {
414: return null;
415: }
416:
417: return new MIDletInfo(midlet);
418: }
419:
420: /**
421: * Indicates if this suite is trusted.
422: * (not to be confused with a domain named "trusted",
423: * this is used to determine if a trusted symbol should be displayed
424: * to the user and not used for permissions)
425: *
426: * @return true if the suite is trusted false if not
427: */
428: public boolean isTrusted() {
429: return installInfo.trusted;
430: }
431:
432: /**
433: * Check if the suite classes were successfully verified
434: * during the suite installation.
435: *
436: * @return true if the suite classes are verified, false otherwise
437: */
438: public boolean isVerified() {
439: return installInfo.verifyHash != null;
440: }
441:
442: /**
443: * Gets a property of the suite. A property is an attribute from
444: * either the application descriptor or JAR Manifest.
445: *
446: * @param key the name of the property
447: * @return A string with the value of the property.
448: * <code>null</code> is returned if no value
449: * is available for the key.
450: */
451: public String getProperty(String key) {
452: return getAppProperty(key);
453: }
454:
455: /**
456: * Gets push setting for interrupting other MIDlets.
457: * Reuses the Permissions.
458: *
459: * @return push setting for interrupting MIDlets the value
460: * will be permission level from {@link Permissions}
461: */
462: public byte getPushInterruptSetting() {
463: return suiteSettings.getPushInterruptSetting();
464: }
465:
466: /**
467: * Gets push options for this suite.
468: *
469: * @return push options are defined in {@link PushRegistryImpl}
470: */
471: public int getPushOptions() {
472: return suiteSettings.getPushOptions();
473: }
474:
475: /**
476: * Gets list of permissions for this suite.
477: *
478: * @return array of permissions from {@link Permissions}
479: */
480: public byte[] getPermissions() {
481: return suiteSettings.getPermissions();
482: }
483:
484: /**
485: * Replace or add a property to the suite for this run only.
486: *
487: * @param token token with the AMS permission set to allowed
488: * @param key the name of the property
489: * @param value the value of the property
490: *
491: * @exception SecurityException if the caller's token does not have
492: * internal AMS permission
493: */
494: public void setTempProperty(SecurityToken token, String key,
495: String value) {
496: throw new RuntimeException("Not Implemented");
497: }
498:
499: /**
500: * Get the name of a MIDlet.
501: *
502: * @param classname classname of a MIDlet in the suite
503: *
504: * @return name of a MIDlet to show the user
505: */
506: public String getMIDletName(String classname) {
507: throw new RuntimeException("Not Implemented");
508: }
509:
510: /**
511: * Checks to see the suite has the ALLOW level for specific permission.
512: * This is used for by internal APIs that only provide access to
513: * trusted system applications.
514: * <p>
515: * Only trust this method if the object has been obtained from the
516: * MIDletStateHandler of the suite.
517: *
518: * @param permission permission ID from
519: * {@link com.sun.midp.security.Permissions}
520: *
521: * @exception SecurityException if the suite is not
522: * allowed to perform the specified action
523: */
524: public void checkIfPermissionAllowed(int permission) {
525: throw new RuntimeException("Not Implemented");
526: }
527:
528: /**
529: * Gets the status of the specified permission.
530: * If no API on the device defines the specific permission
531: * requested then it must be reported as denied.
532: * If the status of the permission is not known because it might
533: * require a user interaction then it should be reported as unknown.
534: *
535: * @param permission to check if denied, allowed, or unknown
536: * @return 0 if the permission is denied; 1 if the permission is
537: * allowed; -1 if the status is unknown
538: */
539: public int checkPermission(String permission) {
540: throw new RuntimeException("Not Implemented");
541: }
542:
543: /**
544: * Saves any the settings (security or others) that the user may have
545: * changed. Normally called by the scheduler after
546: * the last running MIDlet in the suite is destroyed.
547: * However it could be call during a suspend of the VM so
548: * that persistent settings of the suite can be preserved.
549: */
550: public void saveSettings() {
551: throw new RuntimeException("Not Implemented");
552: }
553:
554: /**
555: * Asks the user want to interrupt the current MIDlet with
556: * a new MIDlet that has received network data.
557: *
558: * @param connection connection to place in the permission question or
559: * null for alarm
560: *
561: * @return true if the use wants interrupt the current MIDlet,
562: * else false
563: */
564: public boolean permissionToInterrupt(String connection) {
565: throw new RuntimeException("Not Implemented");
566: }
567:
568: /**
569: * Determine if the a MIDlet from this suite can be run. Note that
570: * disable suites can still have their settings changed and their
571: * install info displayed.
572: *
573: * @return true if suite is enabled, false otherwise
574: */
575: public boolean isEnabled() {
576: throw new RuntimeException("Not Implemented");
577: }
578:
579: /**
580: * Close the opened MIDletSuite
581: */
582: public void close() {
583: }
584: }
|