Source Code Cross Referenced for CmsConfigurationManager.java in  » Content-Management-System » opencms » org » opencms » configuration » 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 » Content Management System » opencms » org.opencms.configuration 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * File   : $Source: /usr/local/cvs/opencms/src/org/opencms/configuration/CmsConfigurationManager.java,v $
003:         * Date   : $Date: 2008-02-27 12:05:48 $
004:         * Version: $Revision: 1.33 $
005:         *
006:         * This library is part of OpenCms -
007:         * the Open Source Content Management System
008:         *
009:         * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010:         *
011:         * This library is free software; you can redistribute it and/or
012:         * modify it under the terms of the GNU Lesser General Public
013:         * License as published by the Free Software Foundation; either
014:         * version 2.1 of the License, or (at your option) any later version.
015:         *
016:         * This library is distributed in the hope that it will be useful,
017:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
018:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019:         * Lesser General Public License for more details.
020:         *
021:         * For further information about Alkacon Software GmbH, please see the
022:         * company website: http://www.alkacon.com
023:         *
024:         * For further information about OpenCms, please see the
025:         * project website: http://www.opencms.org
026:         * 
027:         * You should have received a copy of the GNU Lesser General Public
028:         * License along with this library; if not, write to the Free Software
029:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
030:         */
031:
032:        package org.opencms.configuration;
033:
034:        import org.opencms.i18n.CmsEncoder;
035:        import org.opencms.main.CmsLog;
036:        import org.opencms.util.CmsFileUtil;
037:        import org.opencms.xml.CmsXmlEntityResolver;
038:        import org.opencms.xml.CmsXmlErrorHandler;
039:
040:        import java.io.File;
041:        import java.io.FileOutputStream;
042:        import java.io.IOException;
043:        import java.io.OutputStream;
044:        import java.net.URL;
045:        import java.text.SimpleDateFormat;
046:        import java.util.ArrayList;
047:        import java.util.Date;
048:        import java.util.Iterator;
049:        import java.util.List;
050:        import java.util.Map;
051:
052:        import org.apache.commons.collections.ExtendedProperties;
053:        import org.apache.commons.digester.Digester;
054:        import org.apache.commons.logging.Log;
055:
056:        import org.dom4j.Document;
057:        import org.dom4j.DocumentHelper;
058:        import org.dom4j.Element;
059:        import org.dom4j.dom.DOMDocumentType;
060:        import org.dom4j.io.OutputFormat;
061:        import org.dom4j.io.XMLWriter;
062:        import org.xml.sax.SAXException;
063:
064:        /**
065:         * Configuration manager for digesting the OpenCms XML configuration.<p>
066:         * 
067:         * Reads the individual configuration class nodes first and creaes new 
068:         * instances of the "base" configuration classes.<p>
069:         * 
070:         * @author Alexander Kandzior 
071:         * 
072:         * @version $Revision: 1.33 $
073:         * 
074:         * @since 6.0.0
075:         */
076:        public class CmsConfigurationManager implements  I_CmsXmlConfiguration {
077:
078:            /** The location of the OpenCms configuration DTD if the default prefix is the system ID. */
079:            public static final String DEFAULT_DTD_LOCATION = "org/opencms/configuration/";
080:
081:            /** The default prefix for the OpenCms configuration DTD. */
082:            public static final String DEFAULT_DTD_PREFIX = "http://www.opencms.org/dtd/6.0/";
083:
084:            /** The name of the default XML file for this configuration. */
085:            public static final String DEFAULT_XML_FILE_NAME = "opencms.xml";
086:
087:            /** The name of the DTD file for this configuration. */
088:            public static final String DTD_FILE_NAME = "opencms-configuration.dtd";
089:
090:            /** The "opencms" root node of the XML configuration. */
091:            public static final String N_ROOT = "opencms";
092:
093:            /** Postfix for original configuration files. */
094:            public static final String POSTFIX_ORI = ".ori";
095:
096:            /** The config node. */
097:            protected static final String N_CONFIG = "config";
098:
099:            /** The configurations node. */
100:            protected static final String N_CONFIGURATION = "configuration";
101:
102:            /** Date format for the backup file time prefix. */
103:            private static final SimpleDateFormat BACKUP_DATE_FORMAT = new SimpleDateFormat(
104:                    "yyyy-MM-dd_HH-mm-ss_");
105:
106:            /** The log object for this class. */
107:            private static final Log LOG = CmsLog
108:                    .getLog(CmsConfigurationManager.class);
109:
110:            /** The number of days to keep old backups for. */
111:            private static final long MAX_BACKUP_DAYS = 15;
112:
113:            /** The folder where to store the backup files of the configuration. */
114:            private File m_backupFolder;
115:
116:            /** The base folder where the configuration files are located. */
117:            private File m_baseFolder;
118:
119:            /** The initialized configuration classes. */
120:            private List m_configurations;
121:
122:            /** The digester for reading the XML configuration. */
123:            private Digester m_digester;
124:
125:            /** The configuration based on <code>opencms.properties</code>. */
126:            private ExtendedProperties m_propertyConfiguration;
127:
128:            /**
129:             * Creates a new OpenCms configuration manager.<p>
130:             * 
131:             * @param baseFolder base folder where XML configurations to load are located
132:             */
133:            public CmsConfigurationManager(String baseFolder) {
134:
135:                m_baseFolder = new File(baseFolder);
136:                if (!m_baseFolder.exists()) {
137:                    if (LOG.isErrorEnabled()) {
138:                        LOG.error(Messages.get().getBundle().key(
139:                                Messages.LOG_INVALID_CONFIG_BASE_FOLDER_1,
140:                                m_baseFolder.getAbsolutePath()));
141:                    }
142:                }
143:                m_backupFolder = new File(m_baseFolder.getAbsolutePath()
144:                        + File.separatorChar + "backup");
145:                if (!m_backupFolder.exists()) {
146:                    if (LOG.isDebugEnabled()) {
147:                        LOG.debug(Messages.get().getBundle().key(
148:                                Messages.LOG_CREATE_CONFIG_BKP_FOLDER_1,
149:                                m_backupFolder.getAbsolutePath()));
150:                    }
151:                    m_backupFolder.mkdirs();
152:                }
153:                if (LOG.isDebugEnabled()) {
154:                    LOG.debug(Messages.get().getBundle().key(
155:                            Messages.LOG_CONFIG_BASE_FOLDER_1,
156:                            m_baseFolder.getAbsolutePath()));
157:                    LOG.debug(Messages.get().getBundle().key(
158:                            Messages.LOG_CONFIG_BKP_FOLDER_1,
159:                            m_backupFolder.getAbsolutePath()));
160:                }
161:                cacheDtdSystemId(this );
162:                m_configurations = new ArrayList();
163:            }
164:
165:            /**
166:             * Adds a configuration object to the configuration manager.<p>
167:             * 
168:             * @param configuration the configuration to add
169:             */
170:            public void addConfiguration(I_CmsXmlConfiguration configuration) {
171:
172:                if (LOG.isDebugEnabled()) {
173:                    LOG.debug(Messages.get().getBundle().key(
174:                            Messages.LOG_ADD_CONFIG_1, configuration));
175:                }
176:                m_configurations.add(configuration);
177:                cacheDtdSystemId(configuration);
178:            }
179:
180:            /**
181:             * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#addConfigurationParameter(java.lang.String, java.lang.String)
182:             */
183:            public void addConfigurationParameter(String paramName,
184:                    String paramValue) {
185:
186:                // noop, this configuration has no additional parameters
187:            }
188:
189:            /**
190:             * @see org.opencms.configuration.I_CmsXmlConfiguration#addXmlDigesterRules(org.apache.commons.digester.Digester)
191:             */
192:            public void addXmlDigesterRules(Digester digester) {
193:
194:                // add rule for <configuration> node        
195:                digester.addObjectCreate("*/" + N_CONFIGURATION + "/"
196:                        + N_CONFIG, I_CmsXmlConfiguration.A_CLASS,
197:                        CmsConfigurationException.class);
198:                digester.addSetNext("*/" + N_CONFIGURATION + "/" + N_CONFIG,
199:                        "addConfiguration");
200:            }
201:
202:            /**
203:             * @see org.opencms.configuration.I_CmsXmlConfiguration#generateXml(org.dom4j.Element)
204:             */
205:            public Element generateXml(Element parent) {
206:
207:                // add the <configuration> node
208:                Element configurationElement = parent
209:                        .addElement(N_CONFIGURATION);
210:                for (int i = 0; i < m_configurations.size(); i++) {
211:                    // append the individual configuration 
212:                    I_CmsXmlConfiguration configuration = (I_CmsXmlConfiguration) m_configurations
213:                            .get(i);
214:                    configurationElement.addElement(N_CONFIG).addAttribute(
215:                            I_CmsXmlConfiguration.A_CLASS,
216:                            configuration.getClass().getName());
217:                }
218:                return parent;
219:            }
220:
221:            /**
222:             * Creates the XML document build from the provided configuration.<p>
223:             * 
224:             * @param configuration the configuration to build the XML for
225:             * @return the XML document build from the provided configuration
226:             */
227:            public Document generateXml(I_CmsXmlConfiguration configuration) {
228:
229:                // create a new document
230:                Document result = DocumentHelper.createDocument();
231:
232:                // set the document type        
233:                DOMDocumentType docType = new DOMDocumentType();
234:                docType.setElementName(N_ROOT);
235:                docType.setSystemID(configuration.getDtdUrlPrefix()
236:                        + configuration.getDtdFilename());
237:                result.setDocType(docType);
238:
239:                Element root = result.addElement(N_ROOT);
240:                // start the XML generation
241:                configuration.generateXml(root);
242:
243:                // return the resulting document
244:                return result;
245:            }
246:
247:            /**
248:             * Returns the backup folder.<p>
249:             *
250:             * @return the backup folder
251:             */
252:            public File getBackupFolder() {
253:
254:                return m_backupFolder;
255:            }
256:
257:            /**
258:             * Returns the properties read from <code>opencms.properties</code>.<p> 
259:             * 
260:             * This is assured to be an instance of {@link org.apache.commons.collections.ExtendedProperties}.<p>
261:             *
262:             * @see #setConfiguration(ExtendedProperties)
263:             * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#getConfiguration()
264:             */
265:            public Map getConfiguration() {
266:
267:                return m_propertyConfiguration;
268:            }
269:
270:            /**
271:             * Returns a specific configuration from the list of initialized configurations.<p>
272:             * 
273:             * @param clazz the configuration class that should be returned
274:             * @return the initialized configuration class instance, or <code>null</code> if this is not found
275:             */
276:            public I_CmsXmlConfiguration getConfiguration(Class clazz) {
277:
278:                for (int i = 0; i < m_configurations.size(); i++) {
279:                    I_CmsXmlConfiguration configuration = (I_CmsXmlConfiguration) m_configurations
280:                            .get(i);
281:                    if (clazz.equals(configuration.getClass())) {
282:                        return configuration;
283:                    }
284:                }
285:                return null;
286:            }
287:
288:            /**
289:             * Returns the list of all initialized configurations.<p>
290:             * 
291:             * @return the list of all initialized configurations
292:             */
293:            public List getConfigurations() {
294:
295:                return m_configurations;
296:            }
297:
298:            /**
299:             * @see org.opencms.configuration.I_CmsXmlConfiguration#getDtdFilename()
300:             */
301:            public String getDtdFilename() {
302:
303:                return DTD_FILE_NAME;
304:            }
305:
306:            /**
307:             * @see org.opencms.configuration.I_CmsXmlConfiguration#getDtdSystemLocation()
308:             */
309:            public String getDtdSystemLocation() {
310:
311:                return DEFAULT_DTD_LOCATION;
312:            }
313:
314:            /**
315:             * @see org.opencms.configuration.I_CmsXmlConfiguration#getDtdUrlPrefix()
316:             */
317:            public String getDtdUrlPrefix() {
318:
319:                return DEFAULT_DTD_PREFIX;
320:            }
321:
322:            /**
323:             * @see org.opencms.configuration.I_CmsXmlConfiguration#getXmlFileName()
324:             */
325:            public String getXmlFileName() {
326:
327:                return DEFAULT_XML_FILE_NAME;
328:            }
329:
330:            /**
331:             * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#initConfiguration()
332:             */
333:            public void initConfiguration() {
334:
335:                // does not need to be initialized
336:                if (LOG.isDebugEnabled()) {
337:                    LOG.debug(Messages.get().getBundle().key(
338:                            Messages.LOG_INIT_CONFIGURATION_1, this ));
339:                }
340:            }
341:
342:            /**
343:             * Loads the OpenCms configuration from the given XML file.<p>
344:             * 
345:             * @throws SAXException in case of XML parse errors
346:             * @throws IOException in case of file IO errors
347:             */
348:            public void loadXmlConfiguration() throws SAXException, IOException {
349:
350:                URL baseUrl = m_baseFolder.toURI().toURL();
351:                if (LOG.isDebugEnabled()) {
352:                    LOG.debug(Messages.get().getBundle().key(
353:                            Messages.LOG_BASE_URL_1, baseUrl));
354:                }
355:
356:                // first load the base configuration
357:                loadXmlConfiguration(baseUrl, this );
358:
359:                // now iterate all sub-configrations
360:                Iterator i = m_configurations.iterator();
361:                while (i.hasNext()) {
362:                    I_CmsXmlConfiguration config = (I_CmsXmlConfiguration) i
363:                            .next();
364:                    loadXmlConfiguration(baseUrl, config);
365:                }
366:
367:                // remove the old backups
368:                removeOldBackups(MAX_BACKUP_DAYS);
369:            }
370:
371:            /**
372:             * Sets the configuration read from the <code>opencms.properties</code>.<p>
373:             * 
374:             * @param propertyConfiguration the configuration read from the <code>opencms.properties</code>
375:             * 
376:             * @see #getConfiguration()
377:             */
378:            public void setConfiguration(
379:                    ExtendedProperties propertyConfiguration) {
380:
381:                m_propertyConfiguration = propertyConfiguration;
382:            }
383:
384:            /**
385:             * Writes the XML configuration for the provided configuration instance.<p>
386:             * 
387:             * @param clazz the configuration class to write the XML for
388:             * @throws IOException in case of I/O errors while writing
389:             * @throws CmsConfigurationException if the given class is not a valid configuration class
390:             */
391:            public void writeConfiguration(Class clazz) throws IOException,
392:                    CmsConfigurationException {
393:
394:                I_CmsXmlConfiguration configuration = getConfiguration(clazz);
395:                if (configuration == null) {
396:                    throw new CmsConfigurationException(Messages.get()
397:                            .container(
398:                                    Messages.ERR_CONFIG_WITH_UNKNOWN_CLASS_1,
399:                                    clazz.getName()));
400:                }
401:
402:                // generate the file URL for the XML input
403:                File file = new File(m_baseFolder, configuration
404:                        .getXmlFileName());
405:                if (LOG.isDebugEnabled()) {
406:                    LOG.debug(Messages.get().getBundle().key(
407:                            Messages.LOG_WRITE_CONFIG_XMLFILE_1,
408:                            file.getAbsolutePath()));
409:                }
410:
411:                // generate the XML document 
412:                Document config = generateXml(configuration);
413:
414:                // output the document
415:                XMLWriter writer = null;
416:                OutputFormat format = OutputFormat.createPrettyPrint();
417:                format.setIndentSize(4);
418:                format.setTrimText(false);
419:                format.setEncoding(CmsEncoder.ENCODING_UTF_8);
420:
421:                try {
422:                    OutputStream out = new FileOutputStream(file);
423:                    writer = new XMLWriter(out, format);
424:                    writer.write(config);
425:                    writer.flush();
426:                } finally {
427:                    if (writer != null) {
428:                        writer.close();
429:                    }
430:                }
431:
432:                if (LOG.isInfoEnabled()) {
433:                    LOG.info(Messages.get().getBundle().key(
434:                            Messages.LOG_WRITE_CONFIG_SUCCESS_2,
435:                            file.getAbsolutePath(),
436:                            configuration.getClass().getName()));
437:                }
438:            }
439:
440:            /**
441:             * Creates a backup of the given XML configurations input file.<p>
442:             * 
443:             * @param configuration the configuration for which the input file should be backed up
444:             */
445:            private void backupXmlConfiguration(
446:                    I_CmsXmlConfiguration configuration) {
447:
448:                String fromName = m_baseFolder.getAbsolutePath()
449:                        + File.separatorChar + configuration.getXmlFileName();
450:                String toDatePrefix = BACKUP_DATE_FORMAT.format(new Date());
451:                String toName = m_backupFolder.getAbsolutePath()
452:                        + File.separatorChar + toDatePrefix
453:                        + configuration.getXmlFileName();
454:
455:                if (LOG.isDebugEnabled()) {
456:                    LOG
457:                            .debug(Messages.get().getBundle().key(
458:                                    Messages.LOG_CREATE_CONFIG_BKP_2, fromName,
459:                                    toName));
460:                }
461:
462:                try {
463:                    CmsFileUtil.copy(fromName, toName);
464:                } catch (IOException e) {
465:                    LOG.error(Messages.get().getBundle().key(
466:                            Messages.LOG_CREATE_CONFIG_BKP_FAILURE_1, toName),
467:                            e);
468:                }
469:            }
470:
471:            /**
472:             * Adds a new DTD system id prefix mapping for internal resolution of external URLs.<p>
473:             * 
474:             * @param configuration the configuration to add the mapping from
475:             */
476:            private void cacheDtdSystemId(I_CmsXmlConfiguration configuration) {
477:
478:                if (configuration.getDtdSystemLocation() != null) {
479:                    try {
480:                        String file = CmsFileUtil.readFile(configuration
481:                                .getDtdSystemLocation()
482:                                + configuration.getDtdFilename(),
483:                                CmsEncoder.ENCODING_UTF_8);
484:                        CmsXmlEntityResolver.cacheSystemId(configuration
485:                                .getDtdUrlPrefix()
486:                                + configuration.getDtdFilename(), file
487:                                .getBytes(CmsEncoder.ENCODING_UTF_8));
488:                        if (LOG.isDebugEnabled()) {
489:                            LOG.debug(Messages.get().getBundle().key(
490:                                    Messages.LOG_CACHE_DTD_SYSTEM_ID_1,
491:                                    configuration.getDtdUrlPrefix()
492:                                            + configuration.getDtdFilename()
493:                                            + " --> "
494:                                            + configuration
495:                                                    .getDtdSystemLocation()
496:                                            + configuration.getDtdFilename()));
497:                        }
498:                    } catch (IOException e) {
499:                        LOG.error(Messages.get().getBundle().key(
500:                                Messages.LOG_CACHE_DTD_SYSTEM_ID_FAILURE_1,
501:                                configuration.getDtdSystemLocation()
502:                                        + configuration.getDtdFilename()), e);
503:                    }
504:                }
505:            }
506:
507:            /**
508:             * Loads the OpenCms configuration from the given XML URL.<p>
509:             * 
510:             * @param url the base URL of the XML configuration to load
511:             * @param configuration the configuration to load
512:             * @throws SAXException in case of XML parse errors
513:             * @throws IOException in case of file IO errors
514:             */
515:            private void loadXmlConfiguration(URL url,
516:                    I_CmsXmlConfiguration configuration) throws SAXException,
517:                    IOException {
518:
519:                // generate the file URL for the XML input
520:                URL fileUrl = new URL(url, configuration.getXmlFileName());
521:                if (LOG.isDebugEnabled()) {
522:                    LOG.debug(Messages.get().getBundle().key(
523:                            Messages.LOG_LOAD_CONFIG_XMLFILE_1, fileUrl));
524:                }
525:
526:                // create a backup of the configuration
527:                backupXmlConfiguration(configuration);
528:
529:                // instantiate Digester and enable XML validation
530:                m_digester = new Digester();
531:                m_digester.setUseContextClassLoader(true);
532:                m_digester.setValidating(true);
533:                m_digester.setEntityResolver(new CmsXmlEntityResolver(null));
534:                m_digester.setRuleNamespaceURI(null);
535:                m_digester.setErrorHandler(new CmsXmlErrorHandler(fileUrl
536:                        .getFile()));
537:
538:                // add this class to the Digester
539:                m_digester.push(configuration);
540:
541:                configuration.addXmlDigesterRules(m_digester);
542:
543:                // start the parsing process        
544:                m_digester.parse(fileUrl.openStream());
545:            }
546:
547:            /**
548:             * Removes all backups that are older then the given number of days.<p>
549:             * 
550:             * @param daysToKeep the days to keep the backups for
551:             */
552:            private void removeOldBackups(long daysToKeep) {
553:
554:                long maxAge = (System.currentTimeMillis() - (daysToKeep * 24 * 60 * 60 * 1000));
555:                File[] files = m_backupFolder.listFiles();
556:                for (int i = 0; i < files.length; i++) {
557:                    File file = files[i];
558:                    long lastMod = file.lastModified();
559:                    if ((lastMod < maxAge)
560:                            & (!file.getAbsolutePath().endsWith(
561:                                    CmsConfigurationManager.POSTFIX_ORI))) {
562:                        file.delete();
563:                        if (LOG.isDebugEnabled()) {
564:                            LOG.debug(Messages.get().getBundle().key(
565:                                    Messages.LOG_REMOVE_CONFIG_FILE_1,
566:                                    file.getAbsolutePath()));
567:                        }
568:                    }
569:                }
570:            }
571:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.