Source Code Cross Referenced for LogManager.java in  » Workflow-Engines » pegasus-2.1.0 » org » griphyn » cPlanner » common » 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 » Workflow Engines » pegasus 2.1.0 » org.griphyn.cPlanner.common 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * This file or a portion of this file is licensed under the terms of
003:         * the Globus Toolkit Public License, found in file GTPL, or at
004:         * http://www.globus.org/toolkit/download/license.html. This notice must
005:         * appear in redistributions of this file, with or without modification.
006:         *
007:         * Redistributions of this Software, with or without modification, must
008:         * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
009:         * some other similar material which is provided with the Software (if
010:         * any).
011:         *
012:         * Copyright 1999-2004 University of Chicago and The University of
013:         * Southern California. All rights reserved.
014:         */
015:        package org.griphyn.cPlanner.common;
016:
017:        import org.griphyn.common.util.Currently;
018:
019:        import org.apache.log4j.Level;
020:
021:        import java.io.OutputStream;
022:        import java.io.PrintWriter;
023:        import java.io.File;
024:        import java.io.FileOutputStream;
025:        import java.io.IOException;
026:        import java.io.Writer;
027:
028:        import java.util.Stack;
029:
030:        /**
031:         * The logging class that to log messages at different levels.
032:         * Currently the following levels are supported.<p>
033:         *
034:         * Eventually, each of the level can have a different writer stream underneath.
035:         *
036:         * <p>
037:         * The messages can be logged at various levels. The various levels of logging
038:         * with increasing levels of verbosity are displayed in the following table.
039:         *
040:         * <p>
041:         * <table border="1">
042:         * <tr align="left"><th>Logging Level</th><th>Description</th></tr>
043:         * <tr align="left"><th>FATAL</th>
044:         *  <td>all fatal error messages are logged in this level.</td>
045:         * </tr>
046:         * <tr align="left"><th>ERROR</th>
047:         *  <td>all non fatal error messages are logged in this level.</td>
048:         * </tr>
049:         * <tr align="left"><th>WARNING</th>
050:         *  <td>all warning messages are logged in this level.</td>
051:         * </tr>
052:         * <tr align="left"><th>INFO</th>
053:         *  <td>all information logging messages are logged in this level.</td>
054:         * </tr>
055:         * <tr align="left"><th>CONFIG</th>
056:         *  <td>all configuration messages are logged in this level.</td>
057:         * </tr>
058:         * <tr align="left"><th>DEBUG</th>
059:         *  <td>all debug messages are logged in this level.</td>
060:         * </tr>
061:         * </table>
062:
063:         *
064:         * @author Karan Vahi
065:         * @author Gaurang Mehta
066:         * @version $Revision: 158 $
067:         */
068:        public class LogManager {
069:
070:            //level  constants that loosely match Log4J and are used
071:            //to generate the appropriate mask values.
072:
073:            /**
074:             * The level value, to indicate a FATAL error message.
075:             */
076:            public static final int FATAL_MESSAGE_LEVEL = 0;
077:
078:            /**
079:             * The level value, to indicate an ERROR message.
080:             */
081:            public static final int ERROR_MESSAGE_LEVEL = 1;
082:
083:            /**
084:             * The level value, to indicate a WARNING error message.
085:             */
086:            public static final int WARNING_MESSAGE_LEVEL = 2;
087:
088:            /**
089:             * The level value, to indicate a INFO message.
090:             */
091:            public static final int INFO_MESSAGE_LEVEL = 3;
092:
093:            /**
094:             * The level value, to indicate a CONFIG message.
095:             */
096:            public static final int CONFIG_MESSAGE_LEVEL = 4;
097:
098:            /**
099:             * The level value, to indicate a DEBUG message.
100:             */
101:            public static final int DEBUG_MESSAGE_LEVEL = 5;
102:
103:            /**
104:             * The type value to indicate a FATAL error message.
105:             */
106:            private static final int FATAL_MESSAGE_TYPE = 0x1;
107:
108:            /**
109:             * The type value to indicate an ERROR message.
110:             */
111:            private static final int ERROR_MESSAGE_TYPE = 0x2;
112:
113:            /**
114:             * The type value to indicate a WARNING message.
115:             */
116:            private static final int WARNING_MESSAGE_TYPE = 0x4;
117:
118:            /**
119:             * The type value to indicate an INFORMATIVE message.
120:             */
121:            private static final int INFO_MESSAGE_TYPE = 0x8;
122:
123:            /**
124:             * The type value to indicate a CONFIG message.
125:             */
126:            private static final int CONFIG_MESSAGE_TYPE = 0x10;
127:
128:            /**
129:             * The type value to indicate a DEBUG message.
130:             */
131:            private static final int DEBUG_MESSAGE_TYPE = 0x20;
132:
133:            /**
134:             * Ensures only one object is created always. Implements the Singleton.
135:             */
136:            private static LogManager logger;
137:
138:            /**
139:             * The debug level. Higher the level the more the detail is logged. At present
140:             * can be 0 or 1. This is set according to the option given by the user, whether
141:             * verbose or not.
142:             */
143:            private int mDebugLevel;
144:
145:            /**
146:             * The stream to which one writes. It is System.out by default for the
147:             * current release. One can set it using setOutputWriter.
148:             *
149:             * @see #setOutputWriter
150:             */
151:            private PrintWriter mWriter;
152:
153:            /**
154:             * The stream to which all the error messages are logged.By default it is
155:             * System.err
156:             */
157:            private PrintWriter mErrWriter;
158:
159:            /**
160:             * The mask that needs to be deployed to determine what messages are to be
161:             * logged.
162:             */
163:            private int mMask;
164:
165:            /**
166:             * This is used to format the time stamp.
167:             */
168:            private static Currently mFormatter;
169:
170:            /**
171:             * The constructor.
172:             */
173:            private LogManager() {
174:                mDebugLevel = 0;
175:                mWriter = new PrintWriter(System.out, true);
176:                mErrWriter = new PrintWriter(System.err, true);
177:                LogManager.mFormatter = new Currently(
178:                        "yyyy.MM.dd HH:mm:ss.SSS zzz: ");
179:                //by default we are logging only INFO
180:                //and all message less than WARN
181:                mMask = generateMask(WARNING_MESSAGE_LEVEL, true);
182:            }
183:
184:            /**
185:             * To get a reference to the the object.
186:             *
187:             * @return a singleton access to the object.
188:             */
189:            public static LogManager getInstance() {
190:                if (logger == null) {
191:                    logger = new LogManager();
192:                }
193:                return logger;
194:            }
195:
196:            /**
197:             * Checks the destination location for existence, if it can
198:             * be created, if it is writable etc.
199:             *
200:             * @param file is the file to write out to.
201:             *
202:             * @throws IOException in case of error while writing out files.
203:             */
204:            private static void sanityCheckOnFile(File file) throws IOException {
205:                if (file.exists()) {
206:                    // location exists
207:                    if (file.isFile()) {
208:                        // ok, is a file
209:                        if (file.canWrite()) {
210:                            // can write, all is well
211:                            return;
212:                        } else {
213:                            // all is there, but I cannot write to file
214:                            throw new IOException(
215:                                    "Cannot write to existing file "
216:                                            + file.getAbsolutePath());
217:                        }
218:                    } else {
219:                        // exists but not a file
220:                        throw new IOException("File " + file.getAbsolutePath()
221:                                + " already " + "exists, but is not a file.");
222:                    }
223:                } else {
224:                    // check to see if you can write to the parent directory
225:                    //could have tried to do just a make dir on parent directory.
226:                    sanityCheckOnDirectory(file.getParentFile());
227:                }
228:            }
229:
230:            /**
231:             * Checks the destination location for existence, if it can
232:             * be created, if it is writable etc.
233:             *
234:             * @param dir is the new base directory to optionally create.
235:             *
236:             * @throws IOException in case of error while writing out files.
237:             */
238:            private static void sanityCheckOnDirectory(File dir)
239:                    throws IOException {
240:                if (dir.exists()) {
241:                    // location exists
242:                    if (dir.isDirectory()) {
243:                        // ok, isa directory
244:                        if (dir.canWrite()) {
245:                            // can write, all is well
246:                            return;
247:                        } else {
248:                            // all is there, but I cannot write to dir
249:                            throw new IOException(
250:                                    "Cannot write to existing directory "
251:                                            + dir.getPath());
252:                        }
253:                    } else {
254:                        // exists but not a directory
255:                        throw new IOException("Destination " + dir.getPath()
256:                                + " already "
257:                                + "exists, but is not a directory.");
258:                    }
259:                } else {
260:                    // does not exist, try to make it
261:                    if (!dir.mkdirs()) {
262:                        throw new IOException(
263:                                "Unable to create directory destination "
264:                                        + dir.getPath());
265:                    }
266:                }
267:            }
268:
269:            /**
270:             * Sets the debug level. All those messages are logged which have a
271:             * level less than equal to the debug level.
272:             *
273:             * @param level   the level to which the debug level needs to be set to.
274:             */
275:            public void setLevel(Level level) {
276:                int value = level.toInt();
277:                switch (value) {
278:                case Level.DEBUG_INT:
279:                    value = this .DEBUG_MESSAGE_LEVEL;
280:                    break;
281:
282:                case Level.INFO_INT:
283:                    value = this .INFO_MESSAGE_LEVEL;
284:                    break;
285:
286:                case Level.WARN_INT:
287:                    value = this .WARNING_MESSAGE_LEVEL;
288:                    break;
289:
290:                case Level.ERROR_INT:
291:                    value = this .ERROR_MESSAGE_LEVEL;
292:                    break;
293:
294:                default:
295:                    value = this .FATAL_MESSAGE_LEVEL;
296:                    break;
297:                }
298:                setLevel(value, false);
299:            }
300:
301:            /**
302:             * Sets the debug level. All those messages are logged which have a
303:             * level less than equal to the debug level. In addition the info messages
304:             * are always logged.
305:             *
306:             * @param level   the level to which the debug level needs to be set to.
307:             */
308:            public void setLevel(int level) {
309:                setLevel(level, true);
310:            }
311:
312:            /**
313:             * Sets the debug level. All those messages are logged which have a
314:             * level less than equal to the debug level. In case the boolean info
315:             * is set, all the info messages are also logged.
316:             *
317:             * @param level the level to which the debug level needs to be set to.
318:             * @param info  boolean denoting whether the INFO messages need to be
319:             *              logged or not.
320:             */
321:            public void setLevel(int level, boolean info) {
322:                mDebugLevel = level;
323:                mMask = generateMask(level, info);
324:            }
325:
326:            /**
327:             * Returns the debug level.
328:             *
329:             * @return  the level to which the debug level has been set to.
330:             */
331:            public int getLevel() {
332:                return mDebugLevel;
333:            }
334:
335:            /**
336:             * Sets both the output writer and the error writer to the same
337:             * underlying writer.
338:             *
339:             * @param out is the name of a file to append to. Special names are
340:             * <code>stdout</code> and <code>stderr</code>, which map to the
341:             * system's respective streams.
342:             *
343:             * @see #setWriters(OutputStream)
344:             */
345:            public void setWriters(String out) {
346:                try {
347:                    mWriter = (PrintWriter) getWriter(out);
348:                    mErrWriter = mWriter;
349:                } catch (IOException e) {
350:                    //log on the existing streams !!!
351:                    log("Unable to set streams for logging ", e,
352:                            this .WARNING_MESSAGE_LEVEL);
353:                }
354:
355:            }
356:
357:            /**
358:             * Sets both the output writer and the error writer to the same
359:             * underlying writer.
360:             *
361:             * Note: The previous stream is not closed automatically.
362:             *
363:             * @param err  the stream to which error messages are to be logged.
364:             */
365:            public void setWriters(OutputStream err) {
366:                mWriter = new PrintWriter(err, true);
367:                mErrWriter = mWriter;
368:            }
369:
370:            /**
371:             * Sets the writer associated with the class to the one specified for all
372:             * type of messages other than error messages.
373:             *
374:             * @param out is the name of a file to append to. Special names are
375:             * <code>stdout</code> and <code>stderr</code>, which map to the
376:             * system's respective streams.
377:             *
378:             * @see #setOutputWriter(OutputStream)
379:             */
380:            public void setOutputWriter(String out) {
381:                try {
382:                    mWriter = (PrintWriter) getWriter(out);
383:                } catch (IOException e) {
384:                    //log on the existing streams !!!
385:                    log("Unable to set streams for logging ", e,
386:                            this .WARNING_MESSAGE_LEVEL);
387:                }
388:            }
389:
390:            /**
391:             * Sets the writer associated with the class to the one specified for all
392:             * type of messages other than error messages.
393:             * By default it is System.out.
394:             *
395:             * @param out  the stream to which the messages are logged.
396:             *
397:             * @see #setErrorWriter(OutputStream)
398:             */
399:            public void setOutputWriter(OutputStream out) {
400:                mWriter = new PrintWriter(out, true);
401:            }
402:
403:            /**
404:             * Certains levels like FATAL, ERROR and WARN can be set to log to a
405:             * different stream, than the default stream used for writing other messages.
406:             * By default, these messages are logged to stderr.
407:             * Note: The previous stream is not closed automatically.
408:             *
409:             * @param out is the name of a file to append to. Special names are
410:             * <code>stdout</code> and <code>stderr</code>, which map to the
411:             * system's respective streams.
412:             *
413:             * @see #setErrorWriter(OutputStream)
414:             */
415:            public void setErrorWriter(String out) {
416:                try {
417:                    mErrWriter = (PrintWriter) getWriter(out);
418:                } catch (IOException e) {
419:                    //log on the existing streams !!!
420:                    log("Unable to set streams for logging ", e,
421:                            this .WARNING_MESSAGE_LEVEL);
422:                }
423:
424:            }
425:
426:            /**
427:             * Certains levels like FATAL, ERROR and WARN can be set to log to a
428:             * different stream, than the default stream used for writing other messages.
429:             * By default, these messages are logged to stderr.
430:             * Note: The previous stream is not closed automatically.
431:             *
432:             * @param err  the stream to which error messages are to be logged.
433:             */
434:            public void setErrorWriter(OutputStream err) {
435:                mErrWriter = new PrintWriter(err, true);
436:            }
437:
438:            /**
439:             * Logs the exception on the appropriate queue if the level of the message
440:             * is less than or equal to the level set for the Logger. For INFO level
441:             * message, the boolean indicating that a completion message is to follow
442:             * is set to true always.
443:             *
444:             * @param message  the message to be logged.
445:             * @param e        the exception to be logged
446:             * @param level    the level on which the message has to be logged.
447:             *
448:             * @see #setLevel(int)
449:             * @see #log(String,int)
450:             */
451:            public void log(String message, Exception e, int level) {
452:                StringBuffer msg = new StringBuffer();
453:                msg.append(message).append(" ").append(e.getClass()).append(
454:                        ": ").append(e.getMessage());
455:                log(msg.toString(), level);
456:            }
457:
458:            /**
459:             * Logs the message on the appropriate queue if the level of the message
460:             * is less than or equal to the level set for the Logger. For INFO level
461:             * message, the boolean indicating that a completion message is to follow
462:             * is set to true always.
463:             *
464:             * @param message  the message to be logged.
465:             * @param level    the level on which the message has to be logged.
466:             *
467:             * @see #setLevel(int)
468:             * @see #log(String,int,boolean)
469:             */
470:            public void log(String message, int level) {
471:                log(message, level, (level == this .INFO_MESSAGE_LEVEL) ? true
472:                        : false);
473:            }
474:
475:            /**
476:             * Logs the message on the appropriate queue if the level of the message
477:             * is less than or equal to the level set for the Logger.
478:             *
479:             * @param message  the message to be logged.
480:             * @param level    the level on which the message has to be logged.
481:             * @param comp     boolean indicating whether a completion message
482:             *                 follows or not.
483:             *
484:             * @see #setLevel(int)
485:             */
486:            private void log(String message, int level, boolean comp) {
487:                int type = (int) Math.pow(2, level);
488:                if ((type & mMask) != 0x0) {
489:                    //we need to log the message
490:                    //get hold of the writer to be used to logging the message.
491:                    PrintWriter writer = getWriter(level);
492:                    writer.print(LogManager.mFormatter.now());
493:                    String prefix = getPrefix(type);
494:                    message = prefix + " " + message;
495:                    /*
496:                     *uncomment if we want commpetion message for INFO
497:                     *on same line
498:                    if(comp){
499:                        if((mMask & INFO_MESSAGE_TYPE) == INFO_MESSAGE_TYPE){
500:                            //we need to just print the message
501:                            writer.print(message);
502:                        }
503:                        else{
504:                            //write out on a new line and
505:                            //push the message to the stack
506:                            writer.println(message);
507:                    //                     mMsgStack.push(message);
508:                        }
509:                    }
510:                    else{
511:                        writer.println(message);
512:                    }
513:                     */
514:                    writer.println(message);
515:                    writer.flush();
516:                }
517:            }
518:
519:            /**
520:             * Gets the timestamp nicely formatted. It generates the date-timestamp
521:             * in extended ISO 8601 format. It generates the timestamp using
522:             * the local timezone not the UTC. An example of the date-timestamp
523:             * generated would be 2003-06-06T14:31:27-07:00 where -07:00 denotes the timezone
524:             * offset of the local timezone from UTC.
525:             *
526:             * @return the formattted timestamp;
527:             */
528:            public String getTimeStamp() {
529:                String st = LogManager.mFormatter.now();
530:
531:                st = Currently.iso8601(false);
532:
533:                return st;
534:            }
535:
536:            /**
537:             * Logs the completion message on the basis of the debug level.
538:             *
539:             * @param message the message to be logged.
540:             * @param level  the debug level of the start message for whose completion
541:             *                    you want.
542:             */
543:            public void logCompletion(String message, int level) {
544:                int type = (int) Math.pow(2, level);
545:                if ((type & mMask) != 0x0) {
546:                    PrintWriter writer = getWriter(level);
547:                    /*uncomment if we want commpetion message for INFO
548:                      on same line
549:                    if ( (mMask & INFO_MESSAGE_TYPE) == INFO_MESSAGE_TYPE) {
550:                        writer.println(" (completed)");
551:                    }
552:                    else {
553:                        writer.print(LogManager.mFormatter.now());
554:                        writer.println(message + " (completed)");
555:                    }
556:                     */
557:                    String prefix = getPrefix(type);
558:                    message = prefix + " " + message;
559:                    writer.print(LogManager.mFormatter.now());
560:                    writer.println(message + " (completed)");
561:                }
562:            }
563:
564:            /**
565:             * Generates the appropriate mask value, corresponding to the level
566:             * passed.
567:             *
568:             * @param level the level to which the debug level needs to be set to.
569:             * @param info  boolean denoting whether the INFO messages need to be
570:             *              logged or not.
571:             *
572:             * @return mask corresponding to the debug level passed.
573:             */
574:            private int generateMask(int level, boolean info) {
575:
576:                //construct the appropriate mask
577:                int mask = 0x0;
578:                for (int i = 0; i <= level; i++) {
579:                    mask |= (int) Math.pow(2, i);
580:                }
581:                if (info) {
582:                    mask |= INFO_MESSAGE_TYPE;
583:                }
584:                return mask;
585:            }
586:
587:            /**
588:             * Returns the prefix that needs to be logged corresponding to a particular
589:             * message type, when a message is being logged.
590:             * Should be returning an enumerated data type.
591:             *
592:             * @param type   the type for which prefix is required.
593:             *
594:             * @return the message type
595:             */
596:            private String getPrefix(int type) {
597:                String result = null;
598:                switch (type) {
599:                case FATAL_MESSAGE_TYPE:
600:                    result = "[FATAL ERROR]";
601:                    break;
602:
603:                case ERROR_MESSAGE_TYPE:
604:                    result = "[ERROR]";
605:                    break;
606:
607:                case WARNING_MESSAGE_TYPE:
608:                    result = "[WARNING]";
609:                    break;
610:
611:                case INFO_MESSAGE_TYPE:
612:                    result = "[INFO]";
613:                    break;
614:
615:                case CONFIG_MESSAGE_TYPE:
616:                    result = "[CONFIG]";
617:                    break;
618:
619:                case DEBUG_MESSAGE_TYPE:
620:                    result = "[DEBUG]";
621:                    break;
622:
623:                default:
624:                    result = "[UNKNOWN]";
625:                }
626:                return result;
627:            }
628:
629:            /**
630:             * Sets an internal writer to point to a particular stream.
631:             *
632:             * @param out is the name of a file to append to. Special names are
633:             * <code>stdout</code> and <code>stderr</code>, which map to the
634:             * system's respective streams.
635:             *
636:             * @return the corresponding writer.
637:             *
638:             * @throws IOException in case of being unable to open a stream.
639:             */
640:            private Writer getWriter(String out) throws IOException {
641:                //check if value refers to any of the predefined streams
642:                OutputStream stream;
643:                if (out.equalsIgnoreCase("stdout")) {
644:                    stream = System.out;
645:                } else if (out.equalsIgnoreCase("stderr")) {
646:                    stream = System.err;
647:                } else {
648:                    //try to create an output stream to file specified
649:                    File f = new File(out);
650:
651:                    //do some sanity checks on file
652:                    sanityCheckOnFile(f);
653:                    stream = new FileOutputStream(f);
654:                }
655:                return new PrintWriter(stream);
656:            }
657:
658:            /**
659:             * Returns a PrintWriter stream on which to log the message. Later on
660:             * this, function would return the appropriate LOG4J queue on which
661:             * the message needs to be logged.
662:             *
663:             * @param level  the level
664:             *
665:             * @return PrintWriter for logging the message.
666:             */
667:            private PrintWriter getWriter(int level) {
668:                return (level >= FATAL_MESSAGE_LEVEL && level <= WARNING_MESSAGE_LEVEL) ? mErrWriter
669:                        : mWriter;
670:            }
671:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.