KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sync4j > server > notification > NotificationEngineImpl


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

18 package sync4j.server.notification;
19
20 import java.security.GeneralSecurityException JavaDoc;
21 import java.util.logging.Level JavaDoc;
22 import java.util.logging.Logger JavaDoc;
23
24 import sync4j.framework.config.Configuration;
25 import sync4j.framework.core.bootstrap.BootStrap;
26 import sync4j.framework.core.dm.ddf.SyncMLDM;
27 import sync4j.framework.logging.Sync4jLogger;
28 import sync4j.framework.logging.Sync4jLoggerName;
29 import sync4j.framework.notification.*;
30 import sync4j.framework.tools.DbgTools;
31 import sync4j.framework.tools.SecurityTools;
32 import sync4j.framework.tools.beans.BeanFactory;
33
34 import org.apache.commons.lang.StringUtils;
35
36 /**
37  * Concrete implementation of a <code>NotificationEngine</code>
38  * @author Stefano Nichele @ Funambol
39  *
40  * @version $Id: NotificationEngineImpl.java,v 1.1 2005/05/16 17:32:56 nichele Exp $
41  */

42 public class NotificationEngineImpl extends AbstractNotificationEngine {
43
44     // --------------------------------------------------------------- Constants
45

46     private static final float SYNCML_DM_PROTOCOL_VERSION = 1.1f;
47
48     public static final String JavaDoc NOTIFICATION_SENDER_BEAN =
49         "sync4j/server/engine/dm/NotificationSender.xml";
50
51     public static final String JavaDoc BOOTSTRAP_SENDER_BEAN =
52         "sync4j/server/engine/dm/BootstrapSender.xml";
53
54
55     // -------------------------------------------------------------- Properties
56

57     // ------------------------------------------------------------ Private Data
58

59     private static final Logger JavaDoc log = Sync4jLogger.getLogger(Sync4jLoggerName.SERVER_DM_NOTIFICATION);
60
61     private Configuration config = null;
62
63
64     // ------------------------------------------------------------- Constructor
65

66     public NotificationEngineImpl(Configuration config) {
67         super(config);
68         this.config = config;
69     }
70
71     // ---------------------------------------------------------- Public Methods
72

73     /**
74      * Send a notification message.
75      * @param messageType the type of the message. See {@link NotificationConstants} for details.
76      * @param transportType the transport type used to send the message. See {@link NotificationConstants} for details.
77      * @param sessionId the session id
78      * @param phoneNumber the phone number of the target device
79      * @param info application specific info
80      * @param serverId the server identifier (necessary to calculate the digest of the message)
81      * @param serverPassword the server password (necessary to calculate the digest of the message)
82      * @param serverNonce the server nonce (necessary to calculate the digest of the message)
83      * @throws NotificationException if a error occurs
84      */

85     public void sendNotificationMessage( int messageType ,
86                                          int transportType ,
87                                          int sessionId ,
88                                          String JavaDoc phoneNumber ,
89                                          String JavaDoc info ,
90                                          String JavaDoc serverId ,
91                                          String JavaDoc serverPassword,
92                                          byte[] serverNonce
93                                        ) throws NotificationException {
94
95         if (log.isLoggable(Level.INFO)) {
96             log.info("sendNotificationMessage with: "+
97                      "\n- messageType: " + messageType +
98                      "\n- transportType: " + transportType +
99                      "\n- sessionId: " + sessionId +
100                      "\n- phoneNumber: " + phoneNumber +
101                      "\n- info: " + info +
102                      "\n- serverId: " + serverId +
103                      "\n- serverPassword: " + serverPassword +
104                      "\n- serverNonde: " + serverNonce
105                      );
106         }
107
108         NotificationMessageBuilder messageBuilder = null;
109         Sender messageSender = null;
110
111         messageBuilder = getNotificationMessageBuilder(messageType);
112
113         messageSender = getSender(transportType, messageType);
114
115         if (log.isLoggable(Level.FINE)) {
116             log.fine("NotificationMessageBuilder: " + messageBuilder);
117             log.fine("Sender: " + messageSender );
118         }
119
120
121         // build message to send
122
byte[] message = messageBuilder.buildMessage(sessionId, phoneNumber, serverId, serverPassword, serverNonce, SYNCML_DM_PROTOCOL_VERSION);
123
124
125         if (log.isLoggable(Level.FINE)) {
126             log.fine("Notification message to send: " + DbgTools.bytesToHex(message));
127         }
128
129         // send message
130
messageSender.sendMessage(messageType, phoneNumber, message, info);
131
132         if (log.isLoggable(Level.INFO)) {
133             log.info("Notification message to " + phoneNumber + " sent");
134         }
135
136     }
137
138     /**
139      * Sends more notification messages.
140      * @param messageType the type of the message. See {@link NotificationConstants} for details.
141      * @param transportType the transport type used to send the message. See {@link NotificationConstants} for details.
142      * @param sessionIds the session identifiers
143      * @param phoneNumbers the phone numbers list of the target devices
144      * @param info application specific info
145      * @param serverId the server identifier (necessary to calculate the digest of the message)
146      * @param serverPassword the server passwords list (necessary to calculate the digest of the message)
147      * @param serverNonce the server nonces list (necessary to calculate the digest of the message)
148      * @throws NotificationException if a error occurs
149      */

150     public void sendNotificationMessages(int messageType,
151                                          int transportType,
152                                          int[] sessionIds,
153                                          String JavaDoc[] phoneNumbers,
154                                          String JavaDoc info,
155                                          String JavaDoc serverId,
156                                          String JavaDoc[] serverPasswords,
157                                          byte[][] serverNonces) throws NotificationException {
158
159         if (log.isLoggable(Level.INFO)) {
160             log.info("sendNotificationMessages with: "+
161                      "\n- messageType: " + messageType +
162                      "\n- transportType: " + transportType +
163                      "\n- info: " + info +
164                      "\n- serverId: " + serverId );
165         }
166
167         NotificationMessageBuilder messageBuilder = null;
168         Sender messageSender = null;
169
170         messageBuilder = getNotificationMessageBuilder(messageType);
171         messageSender = getSender(transportType, messageType);
172
173         if (log.isLoggable(Level.FINE)) {
174             log.fine("NotificationMessageBuilder: " + messageBuilder);
175             log.fine("Sender: " + messageSender );
176         }
177
178         int numDevices = phoneNumbers.length;
179         byte[][] messages = new byte[numDevices][];
180         for (int i=0; i<numDevices; i++) {
181
182             // build message to send
183
messages[i] = messageBuilder.buildMessage(sessionIds[i], phoneNumbers[i], serverId,
184                 serverPasswords[i], serverNonces[i], SYNCML_DM_PROTOCOL_VERSION);
185
186             if (log.isLoggable(Level.FINE)) {
187                 log.fine("Notification message to send to " + phoneNumbers[i] + ": " +
188                          DbgTools.bytesToHex(messages[i]));
189             }
190         }
191
192         // send message
193
messageSender.sendMessages(messageType, phoneNumbers, messages, info);
194
195         if (log.isLoggable(Level.INFO)) {
196             log.info("Notification message sent to " + phoneNumbers.length + " devices");
197         }
198
199     }
200
201
202
203     /**
204      * Sends a bootstrap message.
205      * @param messageType the type of the message. See {@link NotificationConstants} for details.
206      * @param transportType the transport type used to send the message. See {@link NotificationConstants} for details.
207      * @param serverUri the server uri
208      * @param deviceUri the device uri
209      * @param phoneNumber the phone number of the target device
210      * @param syncMLDM the message to send
211      * @param info application specific info
212      * @throws NotificationException
213      */

214     public void sendBootstrapMessage(int messageType,
215                                      int transportType,
216                                      String JavaDoc serverUri,
217                                      String JavaDoc deviceUri,
218                                      String JavaDoc phoneNumber,
219                                      SyncMLDM syncMLDM,
220                                      String JavaDoc info) throws NotificationException {
221
222         if (log.isLoggable(Level.INFO)) {
223             log.info("sendBootstrapMessage with messageType: " + messageType +
224                      ", transportType: " + transportType + ", serverUri: " + serverUri +
225                      ", deviceUri: " + deviceUri +
226                      ", phoneNumber: " + phoneNumber);
227         }
228
229         // verify syncMLDM. Each bootstrap message MUST only contain one dm account
230
//if (syncMLDM.getDmAcc().getDMAccounts().size() != 1) {
231
// throw new NotificationException("Bootstrap message MUST only contain one dm account");
232
//}
233

234         BootstrapMessageBuilder messageBuilder = null;
235         Sender messageSender = null;
236
237         messageBuilder = getBootstrapMessageBuilder(messageType);
238
239         messageSender = getSender(transportType, messageType);
240
241         if (log.isLoggable(Level.FINE)) {
242             log.fine("BootstrapMessageBuilder: " + messageBuilder);
243             log.fine("Sender: " + messageSender);
244         }
245
246         // build message
247
byte[] message = messageBuilder.buildMessage(serverUri, deviceUri, phoneNumber, syncMLDM);
248
249         if (log.isLoggable(Level.INFO)) {
250             log.info("Bootstrap message to send: " + message + " (length: " + message.length + ")");
251         }
252
253         // send message
254
messageSender.sendMessage(messageType, phoneNumber, message, info);
255
256         if (log.isLoggable(Level.INFO)) {
257             log.info("Bootstrap message to " + phoneNumber + " sent");
258         }
259     }
260
261
262     /**
263      * Sends bootstrap messages. If in a bootstrap object the digest is null and
264      * the imsi isn't null, the digest is computed using HMAC
265      * @param messageType the type of the message. See {@link NotificationConstants} for details.
266      * @param transportType the transport type used to send the message. See {@link NotificationConstants} for details.
267      * @param bootstrap the bootstrap list
268      * @param serverUri the server uri list
269      * @param syncMLDM the message list to send
270      * @param info application specific info
271      * @throws NotificationException
272      */

273     public void sendBootstrapMessages(int messageType,
274                                       int transportType,
275                                       BootStrap[] bootstrap,
276                                       String JavaDoc serverUri,
277                                       SyncMLDM[] syncMLDM,
278                                       String JavaDoc info) throws NotificationException {
279
280         if (log.isLoggable(Level.INFO)) {
281             log.info("sendBootstrapMessage with messageType: " + messageType +
282                      ", transportType: " + transportType + " to " + bootstrap.length + " devices");
283         }
284
285         int numDevices = bootstrap.length;
286
287         Sender messageSender = getSender(transportType, messageType);
288
289         byte[][] messages = new byte[numDevices][];
290         String JavaDoc[] macs = new String JavaDoc[numDevices];
291         int[] authMethods = new int[numDevices];
292         String JavaDoc[] phoneNumbers = new String JavaDoc[numDevices];
293
294         BootstrapMessageBuilder messageBuilder = null;
295         String JavaDoc imsi = null;
296         String JavaDoc userPin = null;
297
298         for (int i=0; i<numDevices; i++) {
299             verifyBootStrap(bootstrap[i]);
300
301             phoneNumbers[i] = bootstrap[i].getMsisdn();
302
303             // verify syncMLDM. Each bootstrap message MUST only contain one dm account
304
//if (syncMLDM[i].getDmAcc().getDMAccounts().size() != 1) {
305
// throw new NotificationException(
306
// "Bootstrap message MUST only contain one dm account");
307
//}
308

309             messageBuilder = getBootstrapMessageBuilder(messageType);
310
311             if (log.isLoggable(Level.FINEST)) {
312                 log.finest("BootstrapMessageBuilder: " + messageBuilder);
313             }
314
315             // build message
316
messages[i] = messageBuilder.buildMessage(serverUri,
317                                                       bootstrap[i].getDeviceId(),
318                                                       bootstrap[i].getMsisdn(),
319                                                       syncMLDM[i]);
320
321             authMethods[i] = bootstrap[i].getAuthMethod();
322
323             macs[i] = bootstrap[i].getDigest();
324             if (macs[i] == null) {
325
326                 imsi = bootstrap[i].getImsi();
327                 userPin = bootstrap[i].getUserPin();
328
329                 if (authMethods[i] == NotificationConstants.AUTH_METHOD_NETWPIN) {
330
331                     if (bootstrap[i].isImsiInSemiOctet()) {
332                         if (log.isLoggable(Level.FINEST)) {
333                             log.finest("Compute mac using imsi in semi-octect");
334                         }
335
336                         macs[i] = computeMac(getKeyFromIMSI(imsi), messages[i]);
337                     } else {
338                         if (log.isLoggable(Level.FINEST)) {
339                             log.finest("Compute mac using imsi in textplain");
340                         }
341
342                         macs[i] = computeMac(imsi.getBytes(), messages[i]);
343                     }
344                 } else if (authMethods[i] == NotificationConstants.AUTH_METHOD_USERPIN) {
345
346                     byte[] key = null;
347                     //
348
// If userpin is null, I use the imsi also isn't properly correct
349
//
350
if (userPin == null) {
351
352                         if (log.isLoggable(Level.FINEST)) {
353                             log.finest("Try using USERPIN but userPin is null. Uses imsi to calculate the MAC ");
354                         }
355
356                         if (imsi == null) {
357                             if (log.isLoggable(Level.FINEST)) {
358                                 log.finest("Try using USERPIN but userPin and imsi are null");
359                             }
360                             throw new NotificationException(
361                                 "Userpin or imsi must be not null using USERPIN authentication method");
362                         }
363
364                         if (bootstrap[i].isImsiInSemiOctet()) {
365
366                             if (log.isLoggable(Level.FINEST)) {
367                                 log.finest("Compute mac using imsi in semi-octect");
368                             }
369
370                             key = getKeyFromIMSI(imsi);
371                         } else {
372                             if (log.isLoggable(Level.FINEST)) {
373                                 log.finest("Compute mac using imsi in textplain");
374                             }
375
376                             key = imsi.getBytes();
377                         }
378                     } else {
379                         if (log.isLoggable(Level.FINEST)) {
380                             log.finest("Compute mac using user pin");
381                         }
382                         key = userPin.getBytes();
383                     }
384
385                     macs[i] = computeMac(key, messages[i]);
386                 } else if (authMethods[i] == NotificationConstants.AUTH_METHOD_USERNETWPIN) {
387                     byte[] imsiKey = null;
388                     if (bootstrap[i].isImsiInSemiOctet()) {
389                         if (log.isLoggable(Level.FINEST)) {
390                             log.finest("Compute mac using imsi (in semi-octect) and user pin");
391                         }
392
393                         imsiKey = getKeyFromIMSI(imsi);
394                     } else {
395                         if (log.isLoggable(Level.FINEST)) {
396                             log.finest("Compute mac using imsi (in text-plain) and user pin");
397                         }
398                         imsiKey = imsi.getBytes();
399                     }
400                     // Append imsiKey with the user pin
401
int imsiKeyLength = imsiKey.length;
402                     byte[] userPinKey = userPin.getBytes();
403                     int userPinKeyLength = userPinKey.length;
404                     byte[] key = new byte[imsiKeyLength + userPinKeyLength];
405                     System.arraycopy(imsiKey, 0, key, 0, imsiKeyLength);
406                     System.arraycopy(userPinKey, 0, key, imsiKeyLength, userPinKeyLength);
407                     macs[i] = computeMac(key, messages[i]);
408                 }
409
410             }
411
412
413
414             if (log.isLoggable(Level.FINEST)) {
415                 log.finest("Bootstrap message to send: " + messages[i] + " (length: " + messages[i].length +
416                          ")");
417             }
418         }
419
420         // send message
421
messageSender.sendMessages(messageType, CONTENT_TYPE_BOOTSTRAP, macs, authMethods, phoneNumbers, messages, info);
422    }
423
424    /**
425     * Sends more bootstrap message.
426     * @param messageType the type of the message. See {@link NotificationConstants} for details.
427     * @param transportType the transport type used to send the message. See {@link NotificationConstants} for details.
428     * @param phoneNumbers the phone numbers
429     * @param macs the macs of the messages
430     * @param authMethods the authetication methods
431     * @param messages the messages
432     * @param info application specific info
433     * @throws NotificationException if a error occurs
434     */

435    public void sendBootstrapMessages(int messageType,
436                                      int transportType,
437                                      String JavaDoc[] phoneNumbers,
438                                      String JavaDoc[] macs,
439                                      int[] authMethods,
440                                      byte[][] messages,
441                                      String JavaDoc info) throws NotificationException {
442
443        Sender messageSender = null;
444
445        messageSender = getSender(transportType, messageType);
446
447        if (log.isLoggable(Level.FINE)) {
448            log.fine("Sender: " + messageSender);
449        }
450
451        // send message
452
messageSender.sendMessages(messageType, CONTENT_TYPE_BOOTSTRAP, macs, authMethods, phoneNumbers, messages, info);
453     }
454
455    /**
456     * Preprare bootstrap message
457     * @param messageType the type of the message. See {@link NotificationConstants} for details.
458     * @param bootstrap the bootstrap list
459     * @param serverUri the server uri list
460     * @param syncMLDM the message list to send
461     * @param info application specific info
462     */

463    public BootStrap[] prepareBootstrap(int messageType,
464                                        BootStrap[] bootstrap,
465                                        String JavaDoc serverUri,
466                                        SyncMLDM[] syncMLDM,
467                                        String JavaDoc info) throws NotificationException {
468
469        if (log.isLoggable(Level.INFO)) {
470            log.info("prepareBootstrap with messageType: " + messageType +
471                     " for " + bootstrap.length + " devices");
472        }
473
474        int numDevices = bootstrap.length;
475
476        byte[][] messages = new byte[numDevices][];
477        String JavaDoc[] digests = new String JavaDoc[numDevices];
478        String JavaDoc[] phoneNumbers = new String JavaDoc[numDevices];
479
480        BootstrapMessageBuilder messageBuilder = null;
481
482        for (int i=0; i<numDevices; i++) {
483
484            digests[i] = bootstrap[i].getDigest();
485            phoneNumbers[i] = bootstrap[i].getMsisdn();
486
487            // verify syncMLDM. Each bootstrap message MUST only contain one dm account
488
//if (syncMLDM[i].getDmAcc().getDMAccounts().size() != 1) {
489
// throw new NotificationException(
490
// "Bootstrap message must contain only one dm account");
491
//}
492

493            messageBuilder = getBootstrapMessageBuilder(messageType);
494
495            if (log.isLoggable(Level.FINEST)) {
496                log.finest("BootstrapMessageBuilder: " + messageBuilder);
497            }
498
499            // build message
500
messages[i] = messageBuilder.buildMessage(serverUri,
501                                                      bootstrap[i].getDeviceId(),
502                                                      bootstrap[i].getMsisdn(),
503                                                      syncMLDM[i]);
504
505            bootstrap[i].setBootstrapMessage(messages[i]);
506            if (log.isLoggable(Level.FINEST)) {
507                log.finest(bootstrap[i].toString());
508            }
509        }
510
511        return bootstrap;
512    }
513
514
515
516     // --------------------------------------------------------- Private Methods
517
/**
518      * Returns the bootstrap message builder for the given messageType
519      * @param messageType
520      * @throws NotificationException
521      * @return BootstrapMessageBuilder
522      */

523     private BootstrapMessageBuilder getBootstrapMessageBuilder(int messageType) throws
524         NotificationException {
525         BootstrapMessageBuilder messageBuilder = null;
526
527         switch (messageType) {
528             case NotificationConstants.MESSAGE_TYPE_BOOTSTRAP_PLAIN:
529                 messageBuilder = new PlainBootstrapMessageBuilder();
530                 break;
531             case NotificationConstants.MESSAGE_TYPE_BOOTSTRAP_WAP:
532                 messageBuilder = new WAPBootstrapMessageBuilder();
533                 break;
534
535             default:
536                 throw new NotificationException("Message type not supported");
537         }
538
539         return messageBuilder;
540     }
541
542     /**
543      * Returns the sender for the given transportType and messageType.
544      * ATTENTION: in this implementation read the sender as bean independently from the transportType value.
545      *
546      * @param transportType int
547      * @throws NotificationException
548      * @return Sender
549      */

550     private Sender getSender(int transportType, int messageType) throws NotificationException {
551         Sender messageSender = null;
552
553         // read the sender object from the config path
554
ClassLoader JavaDoc classLoader = config.getClassLoader();
555
556         try {
557             if (messageType == NotificationConstants.MESSAGE_TYPE_BOOTSTRAP_PLAIN ||
558                 messageType == NotificationConstants.MESSAGE_TYPE_BOOTSTRAP_WAP) {
559
560                 messageSender = (Sender)BeanFactory.getBeanInstance(classLoader, BOOTSTRAP_SENDER_BEAN);
561
562             } else if (messageType == NotificationConstants.MESSAGE_TYPE_NOTIFICATION_GENERIC) {
563
564                 messageSender = (Sender)BeanFactory.getBeanInstance(classLoader, NOTIFICATION_SENDER_BEAN);
565
566             } else {
567                 messageSender = new SimpleSender();
568             }
569
570         } catch (Exception JavaDoc ex) {
571             log.throwing(getClass().getName(), "getSender", ex);
572             throw new NotificationException("Error reading the sender", ex);
573         }
574
575         return messageSender;
576     }
577
578     /**
579      * Returns the notification message builder for the given messageType
580      * @param messageType int
581      * @throws NotificationException
582      * @return NotificationMessageBuilder
583      */

584     private NotificationMessageBuilder getNotificationMessageBuilder(int messageType) throws
585         NotificationException {
586
587         NotificationMessageBuilder messageBuilder = null;
588
589         // get NotificationMessageBuilder
590
switch (messageType) {
591             case NotificationConstants.MESSAGE_TYPE_NOTIFICATION_GENERIC:
592                 messageBuilder = new GenericNotificationMessageBuilder();
593                 break;
594             default:
595                 throw new NotificationException("Message type not supported");
596         }
597
598         return messageBuilder;
599     }
600
601     /**
602      * Compute the mac of the message using the given key.
603      *
604      * @param key the key to use
605      * @param message the message
606      * @throws NotificationException if a error occurs
607      * @return the mac of the message
608      */

609     private String JavaDoc computeMac(byte[] key, byte[] message) throws NotificationException {
610
611         byte[] bMac = null;
612
613         try {
614             bMac = SecurityTools.computeHmacSha1(key, message);
615         } catch (GeneralSecurityException JavaDoc e) {
616             throw new NotificationException("Error computing the mac", e);
617         }
618
619         String JavaDoc mac = bytesToHex(bMac);
620
621         if (log.isLoggable(Level.FINEST)) {
622             log.finest("Mac: " + mac);
623         }
624         return mac;
625     }
626
627     /**
628      * Returns hex String representation of given byte[]
629      * @param b byte[]
630      * @return the hex representation of the byte[]
631      */

632     private static String JavaDoc bytesToHex(byte[] b) {
633         StringBuffer JavaDoc buf = new StringBuffer JavaDoc("");
634         for (int i = 0; i < b.length; i++) {
635             buf.append(byteToHex(b[i]));
636         }
637         return buf.toString();
638     }
639
640     /**
641      * Returns hex String representation of given byte
642      * @param b byte
643      * @return the hex representation of the byte
644      */

645     private static String JavaDoc byteToHex(byte b) {
646         // Returns hex String representation of byte b
647
char hexDigit[] = {
648                           '0', '1', '2', '3', '4', '5', '6', '7',
649                           '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
650         };
651         char[] array = {hexDigit[ (b >> 4) & 0x0f], hexDigit[b & 0x0f]};
652         return new String JavaDoc(array);
653     }
654
655     /**
656      * Computes the bytes array to use as key in the mac calculation
657      * based on imsi. The IMSI MUST be on semi-octet representation as defined
658      * in Digital cellular Telecommunications system (Phase 2+); Specification of the Subscriber
659      * Identity Module - Mobile Equipment (SIM - ME) interface
660      * (GSM 11.11 version 7.2.0 Release 1998)
661      *
662      * @param imsi String
663      * @return byte[]
664      */

665     private static byte[] getKeyFromIMSI(String JavaDoc imsi) throws NotificationException {
666
667         imsi = imsi.trim();
668
669         if (log.isLoggable(Level.FINEST)) {
670             log.finest("IMSI: " + imsi);
671         }
672
673         if ( (imsi.length() % 2) == 1 ) {
674             imsi = "9" + imsi;
675         } else {
676             imsi = "1" + imsi;
677             imsi = imsi + "F";
678
679         }
680
681         if (log.isLoggable(Level.FINEST)) {
682             log.finest("IMSI updated: " + imsi);
683         }
684
685         int numDigit = imsi.length();
686         String JavaDoc temp = null;
687         char c1 = 0;
688         char c2 = 0;
689         byte b = 0;
690         byte[] key = new byte[numDigit / 2]; // always even
691
int t = 0;
692         for (int i = 0; i < numDigit; i++) {
693             c1 = imsi.charAt(i);
694             c2 = imsi.charAt(++i);
695             temp = "" + c2 + c1;
696             try {
697                 key[t] = (byte) (Integer.parseInt(temp, 16));
698             } catch (NumberFormatException JavaDoc ex) {
699                 throw new NotificationException("IMSI isn't valid (only numbers are permitted)");
700             }
701             t++;
702         }
703         if (log.isLoggable(Level.FINEST)) {
704             log.finest("Key from imsi: " + bytesToHex(key));
705         }
706
707         return key;
708     }
709
710
711     /**
712      * Verify if the given bootstrap is correct (from the semantic point of view)
713      * @param bootstrap BootStrap
714      * @throws NotificationException if the bootstrap is not correct
715      */

716     private void verifyBootStrap(BootStrap bootstrap) throws NotificationException {
717
718         if (bootstrap == null) {
719             throw new NotificationException(
720                 "Unable to send the bootstrap (is null)");
721         }
722
723         String JavaDoc imsi = bootstrap.getImsi();
724         String JavaDoc userPin = bootstrap.getUserPin();
725         int authMethod = bootstrap.getAuthMethod();
726         String JavaDoc digest = bootstrap.getDigest();
727
728         if (StringUtils.isNotEmpty(digest)) {
729             return;
730         }
731
732         if (authMethod == NotificationConstants.AUTH_METHOD_NETWPIN) {
733             if (StringUtils.isEmpty(imsi)) {
734                 throw new NotificationException(
735                     "Imsi can't be null using NETWPIN authentication method");
736             }
737         } else if (authMethod == NotificationConstants.AUTH_METHOD_USERPIN) {
738             if (StringUtils.isEmpty(userPin) && StringUtils.isEmpty(imsi)) {
739                 throw new NotificationException(
740                     "Userpin or imsi must be not null using USERPIN authentication method");
741             }
742         } else if (authMethod == NotificationConstants.AUTH_METHOD_USERNETWPIN) {
743             if (StringUtils.isEmpty(imsi)) {
744                 throw new NotificationException(
745                     "Imsi can't be null using USERNETWPIN authentication method");
746             }
747
748             if (StringUtils.isEmpty(userPin)) {
749                 throw new NotificationException(
750                     "Userpin can't be null using USERNETWPIN authentication method");
751             }
752         }
753     }
754
755 }
Popular Tags