Source Code Cross Referenced for APDUManager.java in  » 6.0-JDK-Modules » j2me » com » sun » io » j2me » apdu » 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.io.j2me.apdu 
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.io.j2me.apdu;
028:
029:        import javax.microedition.io.*;
030:        import com.sun.j2me.main.Configuration;
031:
032:        import java.io.*;
033:
034:        /**
035:         * This class provides an interface to the low level APDU protocol 
036:         * details as described below:
037:         * 
038:         * 1. Manage Card power up/reset. 
039:         * 2. APDU scheduler-Can assign priorities to APDUs to synchronize card 
040:         * access. Synchronization is required between APDUs being sent by native 
041:         * telecom software and APDUs sent by J2ME application. The reference 
042:         * implementation will only have APDUs sent by the J2ME application which 
043:         * would all have the same priority.  
044:         * 3. APDU Dispatcher-Support APDU exchange with the card. It has transaction 
045:         * capabilities to receive the APDUs from applications on the consumer device 
046:         * and return the responses to the corresponding application. 
047:         * 4. J2ME applications are oblivious of the logical channel information. 
048:         * Getting the logical channel for communicating with the smart card 
049:         * application is the responsibility of the APDUManager which sends 
050:         * appropriate APDUs to the card to get the logical channels 
051:         * assigned for a new connection or close channels when the connection is 
052:         * closed.
053:         */
054:        public class APDUManager {
055:
056:            /** SAT selection APDU for testing purposes. */
057:            private static final String SAT_APDU_PROP = "com.sun.io.j2me.apdu.satselectapdu";
058:
059:            /** Contains references to all supported slots. */
060:            static Slot[] slots;
061:
062:            /**
063:             * Creates SAT connection.
064:             *
065:             * @param slot Slot number
066:             * @return new connection handle
067:             * @exception IOException when SIM is not present or
068:             * connection cannot be established with the card.
069:             */
070:            static Handle openSATConnection(int slot) throws IOException {
071:
072:                Handle h = null;
073:
074:                checkSlotNumber(slot);
075:                Slot cardSlot = slots[slot];
076:
077:                String satAPDU = Configuration.getProperty(SAT_APDU_PROP);
078:                if (satAPDU != null) {
079:                    byte[] apdu = new byte[24];
080:                    boolean ok;
081:                    try {
082:                        int len = parseDottedBytes(satAPDU, apdu, 0);
083:                        ok = len >= 10 && len <= 22; // 5 bytes hdr + AID + Le
084:                        int Lc = (apdu[4] & 0xFF);
085:                        if (ok
086:                                && (len < Lc + 5 || len > Lc + 5 + 1
087:                                        || apdu[0] != (byte) 0x00
088:                                        || apdu[1] != (byte) 0xA4 || apdu[2] != (byte) 0x04)) {
089:                            ok = false;
090:                        }
091:                        if (ok && len == Lc + 5) {
092:                            apdu[len] = 0x7F;
093:                        }
094:                    } catch (NullPointerException npe) {
095:                        ok = false;
096:                    } catch (IndexOutOfBoundsException iobe) {
097:                        ok = false;
098:                    } catch (IllegalArgumentException iae) {
099:                        ok = false;
100:                    }
101:
102:                    if (ok) {
103:                        h = selectApplication(true, apdu, slot);
104:                    }
105:                }
106:                if (h == null) {
107:                    if (!isAlive(cardSlot)) {
108:                        throw new ConnectionNotFoundException("SIM not found");
109:                    }
110:                    h = new Handle(slot, 0);
111:                }
112:                return h;
113:            }
114:
115:            /**
116:             * Opens a connection to a smart card for reading of ACL.
117:             * This method is called from <code>reset</code>
118:             * method, so it does not need <code>synchronized</code>
119:             * statement.
120:             *
121:             * @param apdu The APDU that will be used for opening
122:             * @param slot Slot number
123:             * @return new connection handle
124:             * @exception IOException when a card is not present or
125:             * connection cannot be established with the card.
126:             */
127:            public static Handle openACLConnection(byte[] apdu, int slot)
128:                    throws IOException {
129:
130:                checkSlotNumber(slot);
131:                return selectApplication(true, apdu, slot);
132:            }
133:
134:            /**
135:             * Initializes ACL for the slot (if needed). This method is invoked
136:             * when an establishment of new connection is being performed. 
137:             * @param slot The slot number
138:             */
139:            public static void initACL(int slot) {
140:
141:                try {
142:                    checkSlotNumber(slot);
143:                    Slot cardSlot = slots[slot];
144:                    if (!cardSlot.powered) {
145:                        reset(cardSlot); // here a reading of ACL is being performed
146:                    }
147:                } catch (IOException e) {
148:                } // ignored
149:            }
150:
151:            /**
152:             * Verifies that slot number is correct. Invokes init method
153:             * if necessary.
154:             * @param slot the slot number
155:             * @throws ConnectionNotFoundException if slot number is wrong
156:             */
157:            public static void checkSlotNumber(int slot)
158:                    throws ConnectionNotFoundException {
159:
160:                try {
161:                    init();
162:                } catch (IOException e) {
163:                    throw new ConnectionNotFoundException(
164:                            "Invalid configuration: " + e);
165:                }
166:                if (slot < 0 || slot >= getSlotCount()) {
167:                    throw new ConnectionNotFoundException(
168:                            "Invalid slot identifier: " + slot);
169:                }
170:            }
171:
172:            /**
173:             * Checks if this slot is SAT slot.
174:             * @param slot the slot number
175:             * @return SAT check result
176:             * @throws IOException If an error occured.
177:             */
178:            public static boolean isSatSlot(int slot) throws IOException {
179:                checkSlotNumber(slot);
180:                return isSAT(slot);
181:            }
182:
183:            /**
184:             * This method returns the ATR received from the card.
185:             * @param slot the slot number
186:             * @return ATR information received from the card at startup or
187:             * reset. In case of I/O troubles returns null.
188:             */
189:            public static byte[] getATR(int slot) {
190:                byte[] result = null;
191:                Slot cardSlot = slots[slot];
192:
193:                if (isAlive(cardSlot) && cardSlot.atr != null) {
194:                    int len = cardSlot.atr.length;
195:                    result = new byte[len];
196:                    System.arraycopy(cardSlot.atr, 0, result, 0, len);
197:                }
198:                return result;
199:            }
200:
201:            /**
202:             * Returns the number of slots.
203:             * @return the number of slots. If error occured it returns 0.
204:             */
205:            public static int getSlotCount() {
206:                try {
207:                    init();
208:                } catch (IOException e) {
209:                    return 0;
210:                }
211:                return slots.length;
212:            }
213:
214:            /**
215:             * Checks if the the connection is still live or not. It sends special
216:             * <code>isAliveAPDU</code> to the card and checks if an error occured.
217:             *
218:             * @param slot The slot object.
219:             * @return <code>true</code> if the connection is alive, <false> otherwise
220:             */
221:            private static boolean isAlive(Slot slot) {
222:                int tries = 2;
223:                do {
224:                    if (!slot.powered) {
225:                        try {
226:                            clean(slot);
227:                            reset(slot);
228:                        } catch (IOException e) {
229:                        } // ignored
230:                    }
231:                    try {
232:                        exchangeAPDU(slot, slot.isAliveAPDU);
233:                        return true;
234:                    } catch (IOException e) {
235:                    } // ignored
236:                } while (--tries > 0);
237:                return false;
238:            }
239:
240:            /**
241:             * Cleans the slot object before a reset.
242:             *
243:             * @param slot The slot object.
244:             */
245:            private static void clean(Slot slot) {
246:                slot.basicChannelInUse = false;
247:                slot.SIMPresent = false;
248:                slot.FCI = null;
249:            }
250:
251:            /**
252:             * This method is used to close connection with the card. If the
253:             * channel number passed to this method is for basic channel then
254:             * the basic channel is marked as available and nothing is
255:             * communicated with the card.
256:             * If the channel is not the basic channel, a request to close the
257:             * channel is sent to the card.
258:             * @param slot the slot object
259:             * @param channel channel number
260:             * @exception IOException if a communication error happens
261:             */
262:            private static void closeChannel(Slot slot, int channel)
263:                    throws IOException {
264:
265:                if (channel == 0) {
266:                    slot.basicChannelInUse = false;
267:                    return;
268:                }
269:
270:                try {
271:                    slot.closeChannelAPDU[3] = (byte) channel;
272:                    exchangeAPDU(slot, slot.closeChannelAPDU);
273:                } catch (IOException ioException) {
274:                    throw new IOException("Error closing connection: "
275:                            + ioException);
276:                }
277:            }
278:
279:            /**
280:             * The public method which should be called when application
281:             * selection is required. Calls an internal method.
282:             *
283:             * @param selectAPDU byte encoded selection APDU
284:             * @param slot slot number
285:             * @return new connection handle
286:             * @exception IOException when selection is not successful
287:             */
288:            public static Handle selectApplication(byte[] selectAPDU, int slot)
289:                    throws IOException {
290:                checkSlotNumber(slot);
291:                return selectApplication(false, selectAPDU, slot);
292:            }
293:
294:            /**
295:             * This method is called when there is a connection creation is in 
296:             * progress
297:             * and specifically card application selection is required. If the card 
298:             * application selection is successful
299:             * this method gets the channel information from the CAD which it returns
300:             * to the APDUConnection object.
301:             *
302:             * @param forSAT is this selection is making for SAT?
303:             * @param selectAPDU byte encoded selection APDU
304:             * @param slot slot number
305:             * @return new connection handle
306:             * @exception IOException when selection is not successful
307:             */
308:            private static Handle selectApplication(boolean forSAT,
309:                    byte[] selectAPDU, int slot) throws IOException {
310:
311:                int channel;
312:
313:                Slot cardSlot = slots[slot]; // we have checked slot number earlier
314:
315:                // Test if 'POWER UP' is needed or a card was changed
316:                if (!isAlive(cardSlot)) {
317:                    throw new ConnectionNotFoundException("SmartCard not found");
318:                }
319:
320:                if (!forSAT
321:                        && (cardSlot.basicChannelInUse || cardSlot.SIMPresent)) {
322:                    // get another channel for communication.
323:                    byte[] response = exchangeAPDU(cardSlot,
324:                            cardSlot.getChannelAPDU);
325:                    if (response.length == 2) {
326:                        // just got back the status word
327:                        throw new IOException("No logical channel available");
328:                    }
329:                    // new channel number is in the first byte of response
330:                    channel = response[0];
331:                } else {
332:                    cardSlot.basicChannelInUse = true;
333:                    channel = 0;
334:                }
335:
336:                selectAPDU[0] = (byte) ((selectAPDU[0] & 0xFC) | channel);
337:
338:                byte[] result = exchangeAPDU(cardSlot, selectAPDU);
339:
340:                int sw1 = result[result.length - 2] & 0xFF;
341:                int sw2 = result[result.length - 1] & 0xFF;
342:                if ((sw1 << 8) + sw2 != 0x9000) {
343:                    closeChannel(cardSlot, channel);
344:                    throw new ConnectionNotFoundException(
345:                            "Card application selection failed");
346:                }
347:                cardSlot.FCI = result;
348:                return new Handle(slot, channel);
349:            }
350:
351:            /**
352:             * This method reads the configuration file for number of slots
353:             * and their parameters and performs necessary initialization.
354:             * @exception IOException if there are any config problem
355:             */
356:            synchronized private static void init() throws IOException {
357:
358:                if (slots != null) {
359:                    return;
360:                }
361:                int slotCount = init0();
362:
363:                slots = new Slot[slotCount];
364:                for (int i = 0; i < slotCount; i++) {
365:                    slots[i] = new Slot(i);
366:                }
367:            }
368:
369:            /**
370:             * This public method takes in the command APDU in the form of 
371:             * a byte array and calls the native exchangeAPDU0 method 
372:             * to send the APDU to the card. If there are no errors, this method
373:             * gets the response APDU data from the card and returns that.
374:             * @param h connection handle
375:             * @param apduData APDU data in byte array form
376:             * @return response APDU data in byte array form
377:             * @exception IOException if there are any IO problems
378:             */
379:            public static byte[] exchangeAPDU(Handle h, byte[] apduData)
380:                    throws IOException {
381:                byte[] retData;
382:
383:                Slot slot = h.cardSlot;
384:                try {
385:                    synchronized (slot) {
386:                        byte[] respBuffer = slot.respBuffer;
387:                        int respLen = exchangeAPDU0(h, null, apduData,
388:                                respBuffer);
389:                        retData = new byte[respLen];
390:                        System.arraycopy(respBuffer, 0, retData, 0, respLen);
391:                    }
392:                    return retData;
393:                } catch (IOException e) {
394:                    if (!slot.powered) {
395:                        // power up the slot after removal/insertion
396:                        isAlive(slot);
397:                    }
398:                    throw e;
399:                }
400:            }
401:
402:            /**
403:             * This internal method takes in the command APDU in the form of 
404:             * a byte array and calls the native exchangeAPDU0 method 
405:             * to send the APDU to the card. If there are no errors, this method
406:             * gets the response APDU data from the card and returns that.
407:             * @param slot the slot object
408:             * @param apduData APDU data in byte array form
409:             * @return response APDU data in byte array form
410:             * @exception IOException if there are any IO problems
411:             */
412:            private static byte[] exchangeAPDU(Slot slot, byte[] apduData)
413:                    throws IOException {
414:                byte[] retData;
415:                synchronized (slot) {
416:                    byte[] respBuffer = slot.respBuffer;
417:                    int respLen = exchangeAPDU0(null, slot, apduData,
418:                            respBuffer);
419:                    retData = new byte[respLen];
420:                    System.arraycopy(respBuffer, 0, retData, 0, respLen);
421:                }
422:                return retData;
423:            }
424:
425:            /**
426:             * Performs reset of device.
427:             * Saves ATR into provided slot object. After the reset invokes 
428:             * an ACL loading for this slot.
429:             *
430:             * @param cardSlot the slot object to be reset
431:             * @throws IOException If a reset failed.
432:             */
433:            private static void reset(Slot cardSlot) throws IOException {
434:                synchronized (cardSlot) {
435:                    byte[] atr = reset0(cardSlot);
436:                    cardSlot.atr = atr;
437:                    // after reset we must reload access control file
438:                    com.sun.satsa.acl.AccessControlManager.init(cardSlot.slot);
439:                    cardSlot.SIMPresent = isSatSlot(cardSlot.slot);
440:                }
441:            }
442:
443:            /**
444:             * Closes the connection.
445:             * @param h connection handle
446:             * @exception IOException if there are any IO problems
447:             */
448:            public static void closeConnection(Handle h) throws IOException {
449:                Slot cardSlot = h.cardSlot;
450:                synchronized (cardSlot) {
451:                    h.opened = false;
452:                    if (h.cardSessionId != cardSlot.cardSessionId) {
453:                        throw new IOException();
454:                    }
455:                    closeChannel(cardSlot, h.channel);
456:                }
457:            }
458:
459:            /**
460:             * Parses string that contains hexadecimal byte values separated by
461:             * dots. May throw runtime exceptions.
462:             * @param src source string
463:             * @param dest destination array
464:             * @param offset target offset
465:             * @return number of bytes parsed
466:             */
467:            public static int parseDottedBytes(String src, byte[] dest,
468:                    int offset) {
469:
470:                int i = 0;
471:                int len = 0;
472:                int j;
473:
474:                while (i != src.length() + 1) {
475:
476:                    if ((j = src.indexOf('.', i)) == -1) {
477:                        j = src.length();
478:                    }
479:
480:                    int l = Integer.parseInt(src.substring(i, j), 16);
481:                    if (l != (l & 0xff)) {
482:                        throw new IllegalArgumentException();
483:                    }
484:                    dest[offset + len++] = (byte) l;
485:                    i = j + 1;
486:                }
487:                return len;
488:            }
489:
490:            /**
491:             * Performs data transfer to the device. This method must be called within
492:             * <code>synchronize</code> block with the Slot object.
493:             *
494:             * @param h Connection handle. Can be null for internal purposes
495:             * @param slot Slot object. Unused when <code>h</code> is not null. 
496:             * Must be provided if <code>h</code> is <code>null</code>.
497:             * @param request Buffer with request data
498:             * @param response Buffer for response data
499:             * @return Length of response data
500:             * @exception NullPointerException if any needed parameter is null
501:             * @exception IllegalArgumentException if request does not contain proper 
502:             * APDU
503:             * @exception InterruptedIOException if the connection handle is suddenly 
504:             * closed
505:             * in the middle of exchange or the card was removed and inserted again
506:             * @exception IOException if any I/O troubles occured
507:             */
508:            private static native int exchangeAPDU0(Handle h, Slot slot,
509:                    byte[] request, byte[] response) throws IOException;
510:
511:            /**
512:             * Performs reset of the card in the slot. This method must be called within
513:             * <code>synchronize</code> block with the Slot object.
514:             *
515:             * @param slot Slot object
516:             * @return byte array with ATR
517:             * @exception NullPointerException if parameter is null
518:             * @exception IOException if any i/o troubles occured
519:             */
520:            private static native byte[] reset0(Slot slot) throws IOException;
521:
522:            /**
523:             * Initializes the device.
524:             *
525:             * @return number of supported slots 
526:             * @exception CardDeviceException If configuration failed.
527:             * @exception IOException in case of I/O problems.
528:             */
529:            private static native int init0() throws IOException;
530:
531:            /**
532:             * Checks if this slot is SAT slot. This method is invoked once after 
533:             * a reset of the card.
534:             * @param slot Slot number
535:             * @return <code>true</code> if the slot is dedicated for SAT,
536:             *         <code>false</code> if not
537:             * @exception IOException in case of error
538:             */
539:            private static native boolean isSAT(int slot);
540:
541:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.