Source Code Cross Referenced for CldcTransactionStoreImpl.java in  » 6.0-JDK-Modules » j2me » com » sun » j2me » payment » 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.j2me.payment 
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.j2me.payment;
028:
029:        import java.io.*;
030:        import java.util.Hashtable;
031:        import java.util.Random;
032:        import java.util.Vector;
033:        import javax.microedition.io.Connector;
034:
035:        import com.sun.midp.io.j2me.storage.*;
036:
037:        import javax.microedition.payment.TransactionRecord;
038:
039:        import com.sun.j2me.payment.PaymentInfo;
040:        import com.sun.j2me.payment.ProviderInfo;
041:        import com.sun.j2me.payment.Transaction;
042:        import com.sun.j2me.payment.TransactionStore;
043:
044:        import com.sun.midp.midletsuite.*;
045:        import com.sun.midp.security.*;
046:        import javax.microedition.rms.*;
047:
048:        /**
049:         * This class implements the transaction store. It uses RMS
050:         * to store the transaction records.
051:         *
052:         */
053:        public final class CldcTransactionStoreImpl implements  TransactionStore {
054:
055:            /**
056:             * This class has a different security domain than the MIDlet suite.
057:             * The token is initialized with a value handed to class constructor.
058:             */
059:            private static SecurityToken securityToken;
060:
061:            /** The list of Transaction Records with reserved and missed status */
062:            private Vector inProcessRecords = new Vector();
063:
064:            /**
065:             * The reference to the property containing maximum number of passed
066:             * transactions
067:             */
068:            private static final String TRANSACTIONS_LIMIT_PROPERTY = "payment.transactions.limit";
069:            /** The maximum number of passed transactions */
070:            private static final int DEFAULT_TRANSACTIONS_LIMIT = 16;
071:
072:            /** The maximum number of missed transactions per application. */
073:            static final int MISSED_TRANSACTIONS_LIMIT = 4;
074:            /** The maximum total number of past transactions. */
075:            static final int PASSED_TRANSACTIONS_LIMIT;
076:
077:            /** The RMS record ID of the NextTransactionID counter */
078:            private static final int NEXT_TRANSACTION_RECORD_ID = 1;
079:            /** The RMS record ID of the NextApplicationD counter */
080:            private static final int NEXT_APPLICATION_RECORD_ID = 2;
081:
082:            /** The number of bytes in the int */
083:            private static final int SIZE_OF_INT = 4;
084:
085:            /** lock used to synchronize this Transaction Store */
086:            Object tsLock;
087:
088:            static {
089:                // get the passed transactions limit from the system
090:                int limit = DEFAULT_TRANSACTIONS_LIMIT;
091:                String limitStr = System
092:                        .getProperty(TRANSACTIONS_LIMIT_PROPERTY);
093:                if (limitStr != null) {
094:                    try {
095:                        int value = Integer.parseInt(limitStr);
096:                        if (value >= 0) {
097:                            limit = value;
098:                        }
099:                    } catch (NumberFormatException e) {
100:                    }
101:                }
102:
103:                PASSED_TRANSACTIONS_LIMIT = limit;
104:            }
105:
106:            /**
107:             * Creates a new instance of <code>CldcTransactionStoreImpl</code>. It needs
108:             * a security token to perform file system manipulations.
109:             *
110:             * @param securityToken the security token
111:             * @throws IOException indicates a storage failure
112:             */
113:            public CldcTransactionStoreImpl(SecurityToken securityToken)
114:                    throws IOException {
115:                this .securityToken = securityToken;
116:                tsLock = new Object();
117:                initStore();
118:            }
119:
120:            /**
121:             * Adds the given transaction to the store. It returns a new transaction
122:             * record for the transaction. This transaction record must have its
123:             * <code>wasMissed</code> flag cleared.
124:             *
125:             * @param transaction the transaction
126:             * @return the new transaction record
127:             * @throws IOException indicates a storage failure
128:             */
129:            public TransactionRecord addTransaction(Transaction transaction)
130:                    throws IOException {
131:                int transactionID = transaction.getTransactionID();
132:                CldcTransactionRecordImpl record = findReservedRecord(transactionID);
133:                if (record == null) {
134:                    throw new IllegalStateException(
135:                            "The transaction record hasn't " + "been reserved");
136:                }
137:
138:                record.setStatus(CldcTransactionRecordImpl.MISSED);
139:                record.update(transaction);
140:
141:                if (!record.isFake()) {
142:
143:                    try {
144:                        TransactionStorageImpl store = new TransactionStorageImpl(
145:                                securityToken, false);
146:                        try {
147:                            writeTransactionRecord(record, store, record
148:                                    .getRecordID());
149:                        } finally {
150:                            store.closeStore();
151:                        }
152:                    } catch (RecordStoreException ex) {
153:                        throw new IOException("Storage Failure: "
154:                                + ex.getMessage());
155:                    }
156:                }
157:
158:                // store the transaction record as missed but return it as not missed
159:                return record.createDuplicateRecord();
160:            }
161:
162:            /**
163:             * It returns <code>true</code> if the <code>setDelivered</code> method
164:             * was called for the given transaction ID.
165:             *
166:             * @param transactionID the transaction ID
167:             * @return true if transaction with Transaction ID were delivered to user
168:             * @throws IOException indicates a storage failure
169:             */
170:            public boolean wasDelivered(int transactionID) throws IOException {
171:                CldcTransactionRecordImpl transactionRecord = findMissedRecord(transactionID);
172:                return transactionRecord == null;
173:            }
174:
175:            /**
176:             * This method is called after the application is successfully notified
177:             * about the transaction with the given transaction ID.
178:             *
179:             * @param transactionID the transaction ID
180:             * @throws IOException indicates a storage failure
181:             */
182:            public void setDelivered(int transactionID) throws IOException {
183:                CldcTransactionRecordImpl transactionRecord = null;
184:
185:                synchronized (tsLock) {
186:                    transactionRecord = findMissedRecord(transactionID);
187:                    if (transactionRecord == null) {
188:                        throw new IllegalArgumentException(
189:                                "Not a stored transaction");
190:                    }
191:
192:                    inProcessRecords.removeElement(transactionRecord);
193:                }
194:
195:                if (!transactionRecord.isFake()) {
196:                    transactionRecord
197:                            .setStatus(CldcTransactionRecordImpl.PASSED);
198:
199:                    try {
200:                        TransactionStorageImpl store = new TransactionStorageImpl(
201:                                securityToken, false);
202:                        try {
203:                            if (transactionRecord.getRecordID() > 0) {
204:                                writeTransactionRecord(transactionRecord,
205:                                        store, transactionRecord.getRecordID());
206:                            }
207:                            // limit the passed transactions count
208:                            limitPassedRecords(store);
209:                        } finally {
210:                            store.closeStore();
211:                        }
212:                    } catch (RecordStoreException ex) {
213:                        throw new IOException("Storage Failure "
214:                                + ex.getMessage());
215:                    }
216:                }
217:            }
218:
219:            /**
220:             * Returns an identification number, which can be used as
221:             * <code>applicationID</code> in the other methods. During installation
222:             * each payment supporting <code>MIDletSuite</code> should get such number
223:             * and have it stored. From that point this number will identify that
224:             * <code>MIDletSuite</code> to the transaction store.
225:             *
226:             * @return the payment application id
227:             * @throws IOException indicates a storage failure
228:             */
229:            public int getNextApplicationID() throws IOException {
230:                int nextApplicationID = 0;
231:                try {
232:                    TransactionStorageImpl store = new TransactionStorageImpl(
233:                            securityToken, false);
234:                    try {
235:                        nextApplicationID = getIntFromByteArray(store
236:                                .getRecord(NEXT_APPLICATION_RECORD_ID));
237:                        nextApplicationID++;
238:                        if (nextApplicationID <= 0) {
239:                            nextApplicationID = 1;
240:                        }
241:                        store.setRecord(NEXT_APPLICATION_RECORD_ID,
242:                                getByteArrayFromInt(nextApplicationID));
243:                    } finally {
244:                        store.closeStore();
245:                    }
246:                } catch (RecordStoreException ex) {
247:                    throw new IOException("Storage Failure");
248:                }
249:                return nextApplicationID;
250:            }
251:
252:            /**
253:             * Returns an array of the missed transaction records for the given
254:             * application ID. The transaction records are returned in the order in
255:             * which they have been added to the store. Each transaction record must
256:             * have its <code>wasMissed</code> flag set.
257:             *
258:             * @param applicationID the application ID
259:             * @return the array of the missed transaction records
260:             * @throws IOException indicates a storage failure
261:             */
262:            public TransactionRecord[] getMissedTransactions(int applicationID)
263:                    throws IOException {
264:                return getMissedTransactions(applicationID, false);
265:            }
266:
267:            /**
268:             * Returns a Vector of passed or missed transaction records for the given
269:             * application ID. 
270:             *
271:             * @param applicationID the application ID
272:             * @param wasMissed true if missed transactions are required
273:             *
274:             * @return the Vector of transaction records
275:             * @throws IOException indicates a storage failure
276:             */
277:            private Vector getTransactions(int applicationID, boolean wasMissed)
278:                    throws IOException {
279:                Vector records = new Vector();
280:
281:                /* Get none-fake elements */
282:                try {
283:                    TransactionStorageImpl store = new TransactionStorageImpl(
284:                            securityToken, false);
285:                    try {
286:                        /* read passed transactions */
287:                        int[] recordIDs = store.getRecordIDs();
288:                        CldcTransactionRecordImpl r;
289:                        for (int i = 0; i < recordIDs.length; i++) {
290:                            int recId = recordIDs[i];
291:                            r = readTransactionRecord(store, recId);
292:                            if (null != r
293:                                    && (r.getApplicationID() == applicationID)
294:                                    && (r.wasMissed() == wasMissed)) {
295:                                r.add2list(records);
296:                            }
297:                        }
298:                    } finally {
299:                        store.closeStore();
300:                    }
301:                } catch (RecordStoreException ex) {
302:                    throw new IOException("Storage Failure: " + ex.getMessage());
303:                }
304:
305:                return records;
306:            }
307:
308:            /**
309:             * Returns an array of the past transaction records for the given
310:             * application ID. The transaction record are returned in the reverse order
311:             * as they have been added to the store (most recent first). Each
312:             * transaction record must have its <code>wasMissed</code> flag cleared.
313:             *
314:             * @param applicationID the application ID
315:             * @return the array of the passed transaction records
316:             * @throws IOException indicates a storage failure
317:             */
318:            public TransactionRecord[] getPassedTransactions(int applicationID)
319:                    throws IOException {
320:
321:                Vector passedRecords = getTransactions(applicationID, false);
322:
323:                int count = passedRecords.size();
324:
325:                if (count == 0) {
326:                    return null;
327:                }
328:
329:                CldcTransactionRecordImpl[] appRecords = new CldcTransactionRecordImpl[count];
330:                /* sort passedRecords and store in appRecords (reverse mode) */
331:                for (int i = 0, j = (count - 1); i < count; i++, j--) {
332:                    appRecords[j] = (CldcTransactionRecordImpl) passedRecords
333:                            .elementAt(i);
334:                }
335:                passedRecords.removeAllElements();
336:
337:                return appRecords;
338:            }
339:
340:            /**
341:             * Reserves space for the given transaction in the store. It should be
342:             * called before any call to the <code>addTransaction</code> method to
343:             * ensure that the <code>addTransaction</code> method won't fail later
344:             * (when it is inappropriate) due to full store. This method can apply some
345:             * store policies, like enforcing a maximum number of missed transactions
346:             * per <code>MIDletSuite</code>.
347:             * <p>
348:             * The <code>applicationID</code> identifies the application (MIDlet suite)
349:             * to the transaction store. MIDlet suites which are run directly can use
350:             * negative application IDs to avoid permanent storing of created
351:             * transaction records.
352:             *
353:             * @param applicationID the application id
354:             * @param transaction the transaction
355:             * @return an unique ID created for the transaction
356:             * @throws IOException indicates that the store is full or won't accept any
357:             *      further transaction records from that application
358:             */
359:            public int reserve(int applicationID, Transaction transaction)
360:                    throws IOException {
361:
362:                /* assign transactionID */
363:                int transactionID;
364:                try {
365:                    TransactionStorageImpl store = new TransactionStorageImpl(
366:                            securityToken, false);
367:                    try {
368:
369:                        int count = 0;
370:                        /* count missed and reserved transactions */
371:                        CldcTransactionRecordImpl r;
372:                        for (int i = 0; i < inProcessRecords.size(); i++) {
373:                            r = (CldcTransactionRecordImpl) inProcessRecords
374:                                    .elementAt(i);
375:                            if (r.wasMissed()
376:                                    && (r.getApplicationID() == applicationID)) {
377:                                count++;
378:                            }
379:                        }
380:
381:                        /* check the limit */
382:                        if (count >= MISSED_TRANSACTIONS_LIMIT) {
383:                            throw new IOException("No more space for records");
384:                        }
385:
386:                        String applicationName = transaction
387:                                .getTransactionModule()
388:                                .getMIDlet()
389:                                .getAppProperty(MIDletSuiteImpl.SUITE_NAME_PROP);
390:
391:                        /* assign transactionID */
392:                        int nextTransactionID = getIntFromByteArray(store
393:                                .getRecord(NEXT_TRANSACTION_RECORD_ID));
394:                        transactionID = nextTransactionID++;
395:                        if (nextTransactionID <= 0) {
396:                            nextTransactionID = 1;
397:                        }
398:                        transaction.setTransactionID(transactionID);
399:
400:                        /* don't reserve space if applicationID < 0 */
401:                        if (applicationID > 0) {
402:                            /* create reserved transaction */
403:                            CldcTransactionRecordImpl newTransactionRecord = new CldcTransactionRecordImpl(
404:                                    applicationID, applicationName,
405:                                    transaction, System.currentTimeMillis(),
406:                                    false);
407:
408:                            store.setRecord(NEXT_TRANSACTION_RECORD_ID,
409:                                    getByteArrayFromInt(nextTransactionID));
410:
411:                            writeTransactionRecord(newTransactionRecord, store,
412:                                    0);
413:
414:                            inProcessRecords.addElement(newTransactionRecord);
415:                        } else {
416:                            /* create reserved fake transaction */
417:                            CldcTransactionRecordImpl newTransactionRecord = new CldcTransactionRecordImpl(
418:                                    applicationID, applicationName,
419:                                    transaction, System.currentTimeMillis(),
420:                                    true);
421:                            inProcessRecords.addElement(newTransactionRecord);
422:                        }
423:                    } finally {
424:                        store.closeStore();
425:                    }
426:                } catch (RecordStoreException ex) {
427:                    throw new IOException("Storage Failure: " + ex.getMessage());
428:                }
429:                return transactionID;
430:            }
431:
432:            /**
433:             * Returns the size which is used in the store by the application of the
434:             * given application ID. This size doesn't include the size of the passed
435:             * transactions (it includes only the part of the store which is
436:             * removed/uninstalled by the <code>removeApplicationRecords</code> method).
437:             *
438:             * @param applicationID the application ID
439:             * @return the size used by the application
440:             * @throws IOException indicates a storage failure
441:             */
442:            public int getSizeUsedByApplication(int applicationID)
443:                    throws IOException {
444:
445:                int size = 0;
446:                try {
447:                    TransactionStorageImpl store = new TransactionStorageImpl(
448:                            securityToken, false);
449:                    try {
450:                        /* read missed transactions */
451:                        int[] recordIDs = store.getRecordIDs();
452:                        CldcTransactionRecordImpl r;
453:                        for (int i = 0; i < recordIDs.length; i++) {
454:                            int recId = recordIDs[i];
455:                            r = readTransactionRecord(store, recId);
456:                            if (null != r
457:                                    && (r.getApplicationID() == applicationID)
458:                                    && r.wasMissed()) {
459:                                size += store.getRecordSize(recId);
460:                            }
461:                        }
462:                    } finally {
463:                        store.closeStore();
464:                    }
465:                }
466:
467:                catch (RecordStoreException ex) {
468:                    throw new IOException("Storage Failure: " + ex.getMessage());
469:                }
470:
471:                return size;
472:            }
473:
474:            /**
475:             * Removes the missed records used by the application of the given
476:             * application ID. This is to be used, when the MIDlet suite is uninstalled.
477:             *
478:             * @param applicationID the application ID
479:             * @throws IOException indicates a storage failure
480:             */
481:            public void removeApplicationRecords(int applicationID)
482:                    throws IOException {
483:                try {
484:                    TransactionStorageImpl store = new TransactionStorageImpl(
485:                            securityToken, false);
486:                    try {
487:                        /* read missed and passed transactions */
488:                        int[] recordIDs = store.getRecordIDs();
489:                        CldcTransactionRecordImpl r;
490:                        for (int i = 0; i < recordIDs.length; i++) {
491:                            int recId = recordIDs[i];
492:                            r = readTransactionRecord(store, recId);
493:                            if (null != r
494:                                    && (r.getApplicationID() == applicationID)
495:                                    && r.wasMissed()) {
496:                                store.deleteRecord(recId);
497:                            }
498:                        }
499:                    } finally {
500:                        store.closeStore();
501:                    }
502:                } catch (RecordStoreException ex) {
503:                    throw new IOException("Storage Failure: " + ex.getMessage());
504:                }
505:
506:                synchronized (tsLock) {
507:                    /* count missed and reserved transactions */
508:                    CldcTransactionRecordImpl r;
509:                    for (int i = (inProcessRecords.size() - 1); i >= 0; i--) {
510:                        r = (CldcTransactionRecordImpl) inProcessRecords
511:                                .elementAt(i);
512:                        if (r.wasMissed()
513:                                && (r.getApplicationID() == applicationID)) {
514:                            inProcessRecords.removeElementAt(i);
515:                        }
516:                    }
517:                }
518:            }
519:
520:            /**
521:             * Removes all transaction records from the store. This is a helper method
522:             * which is used in test suites to get clean state before test execution.
523:             *
524:             * @throws IOException indicates a storage failure
525:             */
526:            public void cleanUp() throws IOException {
527:                try {
528:                    TransactionStorageImpl.deleteStore(securityToken);
529:                } catch (RecordStoreException ex) {
530:                    // Nothing to do
531:                }
532:
533:                initStore();
534:            }
535:
536:            /**
537:             * Returns an array of the missed transaction records for the given
538:             * application ID. The transaction records are returned in the order in
539:             * which they have been added to the store. Each transaction record must
540:             * have its <code>wasMissed</code> flag set.
541:             *
542:             * @param applicationID the application ID
543:             * @param fakeOnly if true returns only fake transactions for given
544:             * applicationID
545:             * @return the array of the missed transaction records
546:             * @throws IOException indicates a storage failure
547:             */
548:            TransactionRecord[] getMissedTransactions(int applicationID,
549:                    boolean fakeOnly) throws IOException {
550:                Vector missedRecords = new Vector();
551:                if (!fakeOnly) {
552:                    missedRecords = getTransactions(applicationID, true);
553:                }
554:
555:                synchronized (tsLock) {
556:                    /* Get FakeOnly elements */
557:                    for (int i = 0; i < inProcessRecords.size(); ++i) {
558:                        CldcTransactionRecordImpl record = (CldcTransactionRecordImpl) inProcessRecords
559:                                .elementAt(i);
560:                        if ((record.getApplicationID() == applicationID)
561:                                && record.wasMissed() && record.isFake()) {
562:                            record.add2list(missedRecords);
563:                        }
564:                    }
565:                }
566:
567:                int count = missedRecords.size();
568:
569:                if (count == 0) {
570:                    return null;
571:                }
572:
573:                CldcTransactionRecordImpl[] appRecords = new CldcTransactionRecordImpl[count];
574:
575:                missedRecords.copyInto(appRecords);
576:
577:                return appRecords;
578:            }
579:
580:            // === DEBUG MODE ===
581:            /**
582:             * Generates Fake records for Debug mode
583:             *
584:             * @param applicationID the application ID
585:             * @param applicationName the application Name
586:             * @param paymentInfo properties of the payment module
587:             * @param featurePrefix prefix of the feature
588:             * @param validProviders array of Provider IDs
589:             * @param count number of fake transactions to add
590:             * @throws IOException indicates a storage failure
591:             */
592:            void generateFakeRecords(int applicationID, String applicationName,
593:                    PaymentInfo paymentInfo, String featurePrefix,
594:                    int[] validProviders, int count) throws IOException {
595:                // count > 0
596:
597:                // reserve transaction IDs
598:                int transactionID;
599:
600:                try {
601:                    TransactionStorageImpl store = new TransactionStorageImpl(
602:                            securityToken, false);
603:                    try {
604:                        /* assign transactionID */
605:                        int nextTransactionID = getIntFromByteArray(store
606:                                .getRecord(NEXT_TRANSACTION_RECORD_ID));
607:                        transactionID = nextTransactionID;
608:                        nextTransactionID += count;
609:                        if (nextTransactionID <= 0) {
610:                            nextTransactionID = count;
611:                        }
612:
613:                        store.setRecord(NEXT_TRANSACTION_RECORD_ID,
614:                                getByteArrayFromInt(nextTransactionID));
615:                    } finally {
616:                        store.closeStore();
617:                    }
618:                } catch (RecordStoreException ex) {
619:                    throw new IOException("Storage Failure: " + ex.getMessage());
620:                }
621:
622:                Random random = new Random();
623:
624:                long timestamp = System.currentTimeMillis() - 3600000;
625:                int deltaTime = 3600000 / count;
626:                int numFeatures = paymentInfo.getNumFeatures();
627:
628:                for (int i = 0; i < count; ++i) {
629:                    int state = random.nextInt(3);
630:                    int featureID = (i + (count >>> 1)) * (numFeatures - 1)
631:                            / count;
632:                    double price;
633:                    String currency;
634:
635:                    if (state != TransactionRecord.TRANSACTION_REJECTED) {
636:                        int priceTag = paymentInfo
637:                                .getPriceTagForFeature(featureID);
638:                        int providerID = validProviders[random
639:                                .nextInt(validProviders.length)];
640:                        ProviderInfo providerInfo = paymentInfo
641:                                .getProvider(providerID);
642:
643:                        price = providerInfo.getPrice(priceTag);
644:                        currency = providerInfo.getCurrency();
645:                    } else {
646:                        price = 0;
647:                        currency = "";
648:                    }
649:
650:                    inProcessRecords.addElement(CldcTransactionRecordImpl
651:                            .createFakeRecord(transactionID++, applicationID,
652:                                    applicationName, featureID, featurePrefix
653:                                            + featureID, price, currency,
654:                                    state, timestamp));
655:
656:                    if (transactionID <= 0) {
657:                        transactionID = 1;
658:                    }
659:
660:                    timestamp += deltaTime;
661:                }
662:            }
663:
664:            // === DEBUG MODE ===
665:
666:            /**
667:             * Finds Transaction Record with given Transaction ID and status
668:             *
669:             * @param transactionID the transaction ID
670:             * @param status the status of transaction
671:             * @return the transaction record if found or null
672:             * @throws IOException indicates a storage failure
673:             */
674:            private CldcTransactionRecordImpl findRecord(int transactionID,
675:                    int status) throws IOException {
676:
677:                CldcTransactionRecordImpl r = null;
678:                CldcTransactionRecordImpl record = null;
679:
680:                synchronized (tsLock) {
681:                    int count = inProcessRecords.size();
682:                    /* Try to find in the vector */
683:                    for (int i = 0; i < count; ++i) {
684:                        r = (CldcTransactionRecordImpl) inProcessRecords
685:                                .elementAt(i);
686:                        if (r.getTransactionID() == transactionID) {
687:                            return r;
688:                        }
689:                    }
690:                }
691:                /* Get none-fake elements */
692:                try {
693:                    TransactionStorageImpl store = new TransactionStorageImpl(
694:                            securityToken, false);
695:                    try {
696:                        /* fiind reserved transaction */
697:                        int[] recordIDs = store.getRecordIDs();
698:                        for (int i = 0; i < recordIDs.length; i++) {
699:                            int recId = recordIDs[i];
700:                            r = readTransactionRecord(store, recId);
701:                            if (null != r
702:                                    && (r.getTransactionID() == transactionID)
703:                                    && (r.getStatus() == status)) {
704:                                r.setRecordID(recId);
705:                                record = r;
706:                                break;
707:                            }
708:                        }
709:                    } finally {
710:                        store.closeStore();
711:                    }
712:                } catch (RecordStoreException ex) {
713:                    throw new IOException("Storage Failure: " + ex.getMessage());
714:                } catch (IOException ex) {
715:                    throw new IOException("Storage Failure: " + ex.getMessage());
716:                }
717:
718:                return record;
719:            }
720:
721:            /**
722:             * Finds missed Transaction Record with the given Transaction ID
723:             *
724:             * @param transactionID the transaction ID
725:             * @return the transaction record if found or null
726:             * @throws IOException indicates a storage failure
727:             */
728:            private CldcTransactionRecordImpl findMissedRecord(int transactionID)
729:                    throws IOException {
730:                return findRecord(transactionID,
731:                        CldcTransactionRecordImpl.MISSED);
732:            }
733:
734:            /**
735:             * Finds reserved Transaction Record with the given Transaction ID
736:             *
737:             * @param transactionID the transaction ID
738:             * @return the transaction record if found or null
739:             * @throws IOException indicates a storage failure
740:             */
741:            private CldcTransactionRecordImpl findReservedRecord(
742:                    int transactionID) throws IOException {
743:                return findRecord(transactionID,
744:                        CldcTransactionRecordImpl.RESERVED);
745:            }
746:
747:            /**
748:             * retrives Int from the ByteArray
749:             *
750:             * @param data the array of bytes
751:             * @return integer value converted from byte array or -1
752:             */
753:            static int getIntFromByteArray(byte[] data) {
754:                if (data.length == SIZE_OF_INT) {
755:                    return (((int) (data[0]) << 24) | ((int) (data[1]) << 16)
756:                            | ((int) (data[2]) << 8) | (int) (data[3]));
757:                }
758:                return -1;
759:            }
760:
761:            /**
762:             * puts integer into the ByteArray
763:             *
764:             * @param v the integer value
765:             * @return byte array containing the integer value
766:             */
767:            static byte[] getByteArrayFromInt(int v) {
768:                byte[] data = new byte[SIZE_OF_INT];
769:
770:                data[0] = (byte) ((byte) ((v) >> 24) & 0xFF);
771:                data[1] = (byte) ((byte) ((v) >> 16) & 0xFF);
772:                data[2] = (byte) ((byte) ((v) >> 8) & 0xFF);
773:                data[3] = (byte) ((byte) (v) & 0xFF);
774:
775:                return data;
776:            }
777:
778:            /**
779:             * Initializes the store. It's used when the transaction store file doesn't
780:             * exists.
781:             *
782:             * @throws IOException indicates a storage failure
783:             */
784:            private void initStore() throws IOException {
785:                int nextTransactionID = 1;
786:                int nextApplicationID = 1;
787:
788:                try {
789:                    TransactionStorageImpl store = new TransactionStorageImpl(
790:                            securityToken, true);
791:                    try {
792:                        if (store.getNumRecords() == 0) {
793:                            /* Record ID = NEXT_TRANSACTION_RECORD_ID */
794:                            store
795:                                    .addRecord(getByteArrayFromInt(nextTransactionID));
796:                            /* Record ID = NEXT_APPLICATION_RECORD_ID */
797:                            store
798:                                    .addRecord(getByteArrayFromInt(nextApplicationID));
799:                        }
800:                    } catch (RecordStoreException ex) {
801:                        throw new IOException(
802:                                "Error initializing Transaction Store: "
803:                                        + ex.getMessage());
804:                    } finally {
805:                        store.closeStore();
806:                    }
807:                } catch (RecordStoreFullException ex) {
808:                    throw new IOException(
809:                            "Error initializing Transaction Store: "
810:                                    + ex.getMessage());
811:                } catch (RecordStoreException ex) {
812:                    /* Nothing to do. The store is creating by another isolate */
813:                }
814:            }
815:
816:            /**
817:             * Limits the count of the passed transaction records in the given
818:             * vector to the given value.
819:             *
820:             * @param st TransactionStorageImpl reference
821:             *
822:             * @throws RecordStoreException indicates a storage failure
823:             * @throws IOException indicates a storage failure
824:             */
825:            private void limitPassedRecords(TransactionStorageImpl st)
826:                    throws RecordStoreException, IOException {
827:                Vector passedRecords = new Vector();
828:                CldcTransactionRecordImpl r;
829:                /* read passed transactions */
830:                int[] recordIDs = st.getRecordIDs();
831:                for (int i = 0; i < recordIDs.length; i++) {
832:                    int recId = recordIDs[i];
833:                    r = readTransactionRecord(st, recId);
834:                    if (null != r && !r.wasMissed()) {
835:                        r.add2list(passedRecords);
836:                    }
837:                }
838:
839:                while (passedRecords.size() > PASSED_TRANSACTIONS_LIMIT) {
840:                    r = (CldcTransactionRecordImpl) passedRecords.elementAt(0);
841:                    st.deleteRecord(r.getRecordID());
842:                    passedRecords.removeElementAt(0);
843:                }
844:            }
845:
846:            /**
847:             * Remove missed transaction for give application.
848:             *
849:             * @param appID application payment id
850:             * @throws IOException if there is an error accessing storage
851:             */
852:            protected void removeMissedTransaction(int appID)
853:                    throws IOException {
854:                CldcTransactionRecordImpl[] recs = (CldcTransactionRecordImpl[]) getMissedTransactions(appID);
855:                if (null == recs) {
856:                    return;
857:                }
858:                try {
859:                    TransactionStorageImpl store = new TransactionStorageImpl(
860:                            securityToken, false);
861:                    try {
862:                        for (int i = 0; i < recs.length; i++) {
863:                            store.deleteRecord(recs[i].getRecordID());
864:                        }
865:                    } finally {
866:                        store.closeStore();
867:                    }
868:                } catch (RecordStoreException ex) {
869:                    throw new IOException("Storage Failure: " + ex.getMessage());
870:                }
871:            }
872:
873:            /**
874:             * This service function reads and returns TransactionRecord from store.
875:             *
876:             * @param st TransactionStorageImpl reference
877:             * @param recId ID of the record to be read
878:             * @return CldcTransactionRecordImpl if recId points to proper record,
879:             *  otherwise null
880:             * @throws IOException  if an I/O error occurs
881:             * @throws RecordStoreException if a general record store exception occurs
882:             */
883:            private CldcTransactionRecordImpl readTransactionRecord(
884:                    TransactionStorageImpl st, int recId) throws IOException,
885:                    RecordStoreException {
886:                byte[] nextRec = st.getRecord(recId);
887:                CldcTransactionRecordImpl r = null;
888:                if (nextRec.length > SIZE_OF_INT) {
889:                    ByteArrayInputStream bis = new ByteArrayInputStream(nextRec);
890:                    DataInputStream is = new DataInputStream(bis);
891:                    r = CldcTransactionRecordImpl.read(is);
892:                    r.setRecordID(recId);
893:                }
894:                return r;
895:            }
896:
897:            /**
898:             * This service function writes TransactionRecord into store.
899:             *
900:             * @param record CldcTransactionRecordImpl reference
901:             * @param st TransactionStorageImpl reference
902:             * @param recId ID of the record to be replaced or 0
903:             *
904:             * @throws IOException  if an I/O error occurs
905:             * @throws RecordStoreException if a general record store exception occurs
906:             */
907:            private void writeTransactionRecord(
908:                    CldcTransactionRecordImpl record,
909:                    TransactionStorageImpl st, int recId) throws IOException,
910:                    RecordStoreException {
911:
912:                /* formate transaction inside ByteArray */
913:                ByteArrayOutputStream bos = new ByteArrayOutputStream();
914:                DataOutputStream os = new DataOutputStream(bos);
915:                record.write(os);
916:                byte[] data = bos.toByteArray();
917:
918:                if (recId == 0) {
919:                    recId = st.addRecord(data);
920:                    record.setRecordID(recId);
921:                } else {
922:                    st.setRecord(recId, data);
923:                }
924:            }
925:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.