Source Code Cross Referenced for OtaNotifier.java in  » 6.0-JDK-Modules » j2me » com » sun » midp » 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.midp.installer 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *
003:         *
004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006:         * 
007:         * This program is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU General Public License version
009:         * 2 only, as published by the Free Software Foundation.
010:         * 
011:         * This program is distributed in the hope that it will be useful, but
012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014:         * General Public License version 2 for more details (a copy is
015:         * included at /legal/license.txt).
016:         * 
017:         * You should have received a copy of the GNU General Public License
018:         * version 2 along with this work; if not, write to the Free Software
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA
021:         * 
022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023:         * Clara, CA 95054 or visit www.sun.com if you need additional
024:         * information or have any questions.
025:         */
026:
027:        package com.sun.midp.installer;
028:
029:        import java.io.IOException;
030:        import java.io.OutputStream;
031:
032:        import javax.microedition.io.Connector;
033:        import javax.microedition.io.HttpConnection;
034:
035:        import com.sun.midp.configurator.Constants;
036:
037:        import com.sun.midp.io.Base64;
038:
039:        import com.sun.midp.io.j2me.http.Protocol;
040:
041:        import com.sun.midp.midlet.MIDletSuite;
042:
043:        import com.sun.midp.midlet.MIDletStateHandler;
044:
045:        import com.sun.midp.midletsuite.MIDletSuiteStorage;
046:
047:        import com.sun.midp.security.Permissions;
048:        import com.sun.midp.security.SecurityToken;
049:
050:        /**
051:         * This class handles sending installation and deletion notifications as
052:         * specified by the OTA section of the MIDP 2.0 specification.
053:         * The delete notifications are only sent when an install notification is
054:         * sent. The installer will call this class to send the initial install
055:         * notification, if the notification fails and is a success notification,
056:         * the notification will be queued, so that the next time a MIDlet from the
057:         * suite is run, that suite's notification will be retried. The MIDlet
058:         * state handler will call this class to process install notification retries.
059:         */
060:        public final class OtaNotifier {
061:            /** Retry delay. */
062:            static final int RETRY_DELAY = 3000; // 3 seconds
063:
064:            /** MIDlet property for the install notify URL. */
065:            public static final String NOTIFY_PROP = "MIDlet-Install-Notify";
066:
067:            /** Success message for the suite provider. */
068:            public static final String SUCCESS_MSG = "900 Success";
069:
070:            /** Error message for the suite provider. */
071:            public static final String INSUFFICIENT_MEM_MSG = "901 Insufficient Memory";
072:
073:            /** Error message for the suite provider. */
074:            public static final String USER_CANCELLED_MSG = "902 User Cancelled";
075:
076:            /** Error message for the suite provider. */
077:            public static final String JAR_SIZE_MISMATCH_MSG = "904 JAR size mismatch";
078:
079:            /** Error message for the suite provider. */
080:            public static final String ATTRIBUTE_MISMATCH_MSG = "905 Attribute Mismatch";
081:
082:            /** Error message for the suite provider. */
083:            public static final String INVALID_JAD_MSG = "906 Invalid Descriptor";
084:
085:            /** Error message for the suite provider. */
086:            public static final String INVALID_JAR_MSG = "907 Invalid JAR";
087:
088:            /** Error message for the suite provider. */
089:            public static final String INCOMPATIBLE_MSG = "908 Incompatible Configuration or Profile";
090:
091:            /** Error message for authentication failure. */
092:            public static final String AUTHENTICATION_FAILURE_MSG = "909 Application authentication failure";
093:
094:            /** Error message for authorization failure. */
095:            public static final String AUTHORIZATION_FAILURE_MSG = "910 Application authorization failure";
096:
097:            /** Error message for push registration failure. */
098:            public static final String PUSH_REG_FAILURE_MSG = "911 Push registration failure";
099:
100:            /** Error message for push registration failure. */
101:            public static final String DELETE_NOTIFICATION_MSG = "912 Deletion Notification";
102:
103:            /** Message to send when a content handler install fails. */
104:            public static final String CONTENT_HANDLER_CONFLICT = "938 Content handler conflicts with other handlers";
105:
106:            /** Message to send when a content handler install fails. */
107:            public static final String INVALID_CONTENT_HANDLER = "939 Content handler install failed";
108:
109:            /**
110:             * Posts a status message back to the provider's URL in JAD.
111:             * This method will also retry ALL pending delete notifications.
112:             *
113:             * @param message status message to post
114:             * @param suite MIDlet suite object
115:             * @param proxyUsername if not null, it will be put in the post
116:             * @param proxyPassword if not null, it will be put in the post
117:             */
118:            public static void postInstallMsgBackToProvider(String message,
119:                    MIDletSuite suite, String proxyUsername,
120:                    String proxyPassword) {
121:                String url;
122:                MIDletSuite callingMidletSuite = MIDletStateHandler
123:                        .getMidletStateHandler().getMIDletSuite();
124:
125:                if (callingMidletSuite == null) {
126:                    throw new IllegalStateException(
127:                            "This method can't be called "
128:                                    + "before a suite is started.");
129:                }
130:
131:                callingMidletSuite.checkIfPermissionAllowed(Permissions.AMS);
132:
133:                // Now, send out install notifications
134:                url = suite.getProperty(NOTIFY_PROP);
135:                try {
136:                    postMsgBackToProvider(message, url, proxyUsername,
137:                            proxyPassword);
138:                } catch (Throwable t) {
139:                    if (message == SUCCESS_MSG) {
140:                        // Only queue successful install notifications for retry
141:                        addInstallNotification(suite.getID(), url);
142:                    }
143:                }
144:            }
145:
146:            /**
147:             * Retry the pending install status message for this suite only.
148:             * This method will also retry ALL pending delete notifications,
149:             * if the install notification was retried.
150:             *
151:             * @param token security token of the caller
152:             * @param suite MIDlet suite object
153:             */
154:            public static void retryInstallNotification(SecurityToken token,
155:                    MIDletSuite suite) {
156:                /*
157:                 * Delay any processing so that startup time is not effected.
158:                 */
159:                new Thread(new InstallRetryHandler(token, suite)).start();
160:            }
161:
162:            /**
163:             * Retry the pending install status message for this suite only.
164:             * This method will also retry ALL pending delete notifications,
165:             * if the install notification was retried.
166:             *
167:             * @param token security token of the caller
168:             * @param suite MIDlet suite object
169:             */
170:            static void retryInstallNotificationInternal(SecurityToken token,
171:                    MIDletSuite suite) {
172:                PendingNotification notification = new PendingNotification();
173:
174:                token.checkIfPermissionAllowed(Permissions.AMS);
175:
176:                // Now, send out install notifications
177:                if (suite.getProperty(NOTIFY_PROP) == null) {
178:                    return;
179:                }
180:
181:                if (!getInstallNotificationForRetry(suite.getID(), notification)) {
182:                    return;
183:                }
184:
185:                try {
186:                    Protocol httpConnection = new Protocol();
187:
188:                    httpConnection.openPrim(token, notification.url);
189:                    postMsgBackToProvider(SUCCESS_MSG, httpConnection, null,
190:                            null);
191:                    removeInstallNotification(notification.suiteId);
192:                } catch (Throwable t) {
193:                    if (notification.retries >= Constants.MAX_INSTALL_DELETE_NOTIFICATION_RETRIES) {
194:                        removeInstallNotification(notification.suiteId);
195:                    }
196:                }
197:
198:                try {
199:                    // Send out delete notifications that have been queued, first
200:                    postQueuedDeleteMsgsBackToProvider(null, null);
201:                } catch (Throwable t) {
202:                    // ignore
203:                }
204:            }
205:
206:            /**
207:             * Posts all queued delete notification messages
208:             *
209:             * @param proxyUsername if not null, it will be put in the post
210:             * @param proxyPassword if not null, it will be put in the post
211:             */
212:            public static void postQueuedDeleteMsgsBackToProvider(
213:                    String proxyUsername, String proxyPassword) {
214:                PendingNotification[] deleteNotifyList;
215:
216:                deleteNotifyList = getDeleteNotifications();
217:
218:                for (int i = 0; i < deleteNotifyList.length; i++) {
219:                    try {
220:                        postMsgBackToProvider(DELETE_NOTIFICATION_MSG,
221:                                deleteNotifyList[i].url, proxyUsername,
222:                                proxyPassword);
223:                        removeDeleteNotification(deleteNotifyList[i].suiteId);
224:                    } catch (Throwable t) {
225:                        if (deleteNotifyList[i].retries >= Constants.MAX_INSTALL_DELETE_NOTIFICATION_RETRIES) {
226:                            removeDeleteNotification(deleteNotifyList[i].suiteId);
227:                        }
228:                    }
229:                }
230:            }
231:
232:            /**
233:             * Posts a status message back to the provider's URL in JAD.
234:             *
235:             * @param message status message to post
236:             * @param url target http url for the status message
237:             * @param proxyUsername if not null, it will be put in the post
238:             * @param proxyPassword if not null, it will be put in the post
239:             *
240:             * @exception IOException is thrown if any error prevents the
241:             *            notification from being successful
242:             */
243:            private static void postMsgBackToProvider(String message,
244:                    String url, String proxyUsername, String proxyPassword)
245:                    throws IOException {
246:                HttpConnection transaction;
247:
248:                if (url == null) {
249:                    return;
250:                }
251:
252:                transaction = (HttpConnection) Connector.open(url,
253:                        Connector.WRITE);
254:
255:                postMsgBackToProvider(message, transaction, proxyUsername,
256:                        proxyPassword);
257:            }
258:
259:            /**
260:             * Posts a status message back to the provider's URL in JAD.
261:             *
262:             * @param message status message to post
263:             * @param transaction http connection to use for posting the status message
264:             * @param proxyUsername if not null, it will be put in the post
265:             * @param proxyPassword if not null, it will be put in the post
266:             *
267:             * @exception IOException is thrown if any error prevents the
268:             *            notification from being successful
269:             */
270:            private static void postMsgBackToProvider(String message,
271:                    HttpConnection transaction, String proxyUsername,
272:                    String proxyPassword) throws IOException {
273:                OutputStream out;
274:
275:                try {
276:                    transaction.setRequestMethod(HttpConnection.POST);
277:
278:                    if (proxyUsername != null && proxyPassword != null) {
279:                        transaction.setRequestProperty("Proxy-Authorization",
280:                                formatAuthCredentials(proxyUsername,
281:                                        proxyPassword));
282:                    }
283:
284:                    out = transaction.openOutputStream();
285:
286:                    try {
287:                        int responseCode;
288:
289:                        out.write(message.getBytes());
290:                        responseCode = transaction.getResponseCode();
291:                        if (responseCode != HttpConnection.HTTP_OK) {
292:                            throw new IOException("Failed to notify "
293:                                    + transaction.getURL()
294:                                    + " HTTP response code: " + responseCode);
295:                        }
296:                    } finally {
297:                        out.close();
298:                    }
299:                } finally {
300:                    transaction.close();
301:                }
302:            }
303:
304:            /**
305:             * Formats the username and password for HTTP basic authentication
306:             * according RFC 2617.
307:             *
308:             * @param username for HTTP authentication
309:             * @param password for HTTP authentication
310:             *
311:             * @return properly formated basic authentication credential
312:             */
313:            private static String formatAuthCredentials(String username,
314:                    String password) {
315:                byte[] data = new byte[username.length() + password.length()
316:                        + 1];
317:                int j = 0;
318:
319:                for (int i = 0; i < username.length(); i++, j++) {
320:                    data[j] = (byte) username.charAt(i);
321:                }
322:
323:                data[j] = (byte) ':';
324:                j++;
325:
326:                for (int i = 0; i < password.length(); i++, j++) {
327:                    data[j] = (byte) password.charAt(i);
328:                }
329:
330:                return "Basic " + Base64.encode(data, 0, data.length);
331:            }
332:
333:            /**
334:             * Retrieves the queued delete notification list. Each element
335:             * in the array is a URL to send a delete notification to.
336:             *
337:             * @return the delete notification list
338:             */
339:            private static synchronized PendingNotification[] getDeleteNotifications() {
340:                PendingNotification[] array = new PendingNotification[getNumberOfDeleteNotifications()];
341:
342:                if (array.length > 0) {
343:                    for (int i = 0; i < array.length; i++) {
344:                        array[i] = new PendingNotification();
345:                    }
346:
347:                    fillDeleteNotificationListForRetry(array);
348:                }
349:
350:                return array;
351:            }
352:
353:            /**
354:             * Retrieves the number of URLs queued delete in the notification list.
355:             *
356:             * @return the number of URLs in the delete notification list
357:             */
358:            private static native int getNumberOfDeleteNotifications();
359:
360:            /**
361:             * Retrieves the queued delete notification list from storage and
362:             * increments the retry count of every member of the list.
363:             *
364:             * @param list empty delete notification list to fill
365:             */
366:            private static native void fillDeleteNotificationListForRetry(
367:                    PendingNotification[] list);
368:
369:            /**
370:             * Removes the element from the delete notification list.
371:             *
372:             * @param suiteId suite ID of the notification
373:             */
374:            private static native void removeDeleteNotification(int suiteId);
375:
376:            /**
377:             * Adds an element to the install notification list.
378:             *
379:             * @param suiteId suite the notification belongs to
380:             * @param url url to send the notification to
381:             */
382:            private static native void addInstallNotification(int suiteId,
383:                    String url);
384:
385:            /**
386:             * Retrieves the URL of suite's install notification from storage and
387:             * increments the retry count of element.
388:             *
389:             * @param suiteId suite ID of the notification
390:             * @param dest where to put the notification
391:             *
392:             * @return true if the notification is found
393:             */
394:            private static native boolean getInstallNotificationForRetry(
395:                    int suiteId, PendingNotification dest);
396:
397:            /**
398:             * Removes the element from the install notification list.
399:             *
400:             * @param suiteId suite ID of the notification
401:             */
402:            private static native void removeInstallNotification(int suiteId);
403:        }
404:
405:        /** Executes install reties in the background. */
406:        final class InstallRetryHandler implements  Runnable {
407:            /** Security token of the caller. */
408:            private SecurityToken token;
409:
410:            /** MIDlet suite to retry. */
411:            private MIDletSuite suite;
412:
413:            /**
414:             * Construct a InstallRetryHandler.
415:             *
416:             * @param theToken security token of the caller
417:             * @param theSuite MIDlet suite object
418:             */
419:            InstallRetryHandler(SecurityToken theToken, MIDletSuite theSuite) {
420:                token = theToken;
421:                suite = theSuite;
422:            }
423:
424:            /** Retries after a short delay. */
425:            public void run() {
426:                try {
427:                    Thread.sleep(OtaNotifier.RETRY_DELAY);
428:                } catch (InterruptedException ie) {
429:                    // ignore
430:                }
431:
432:                OtaNotifier.retryInstallNotificationInternal(token, suite);
433:            }
434:        }
435:
436:        /** Pending install or delete notification */
437:        final class PendingNotification {
438:            /** Number of times the record has been retried. */
439:            int retries;
440:
441:            /** Suite this notification is for. */
442:            int suiteId;
443:
444:            /** URL to post the notification to. */
445:            String url;
446:
447:            /**
448:             * Returns a debug string.
449:             *
450:             * @return value of each field in a string
451:             */
452:            public String toString() {
453:                return "PendingNotification(suite ID = " + suiteId
454:                        + ", retries = " + retries + ", URL = " + url + ")";
455:            }
456:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.