Source Code Cross Referenced for ImRModel.java in  » Collaboration » JacORB » org » jacorb » imr » util » 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 » Collaboration » JacORB » org.jacorb.imr.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *        JacORB - a free Java ORB
003:         *
004:         *   Copyright (C) 1999-2004 Gerald Brose
005:         *
006:         *   This library is free software; you can redistribute it and/or
007:         *   modify it under the terms of the GNU Library General Public
008:         *   License as published by the Free Software Foundation; either
009:         *   version 2 of the License, or (at your option) any later version.
010:         *
011:         *   This library is distributed in the hope that it will be useful,
012:         *   but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014:         *   Library General Public License for more details.
015:         *
016:         *   You should have received a copy of the GNU Library General Public
017:         *   License along with this library; if not, write to the Free
018:         *   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
019:         *
020:         */
021:        package org.jacorb.imr.util;
022:
023:        import org.apache.avalon.framework.logger.Logger;
024:
025:        import org.jacorb.imr.*;
026:        import org.jacorb.imr.AdminPackage.*;
027:
028:        import java.util.*;
029:
030:        import javax.swing.tree.*;
031:        import javax.swing.*;
032:        import javax.swing.table.*;
033:
034:        /**
035:         * This class provides the GUIs functionality
036:         * communicating with the repository.
037:         *
038:         * @author Nicolas Noffke
039:         *
040:         * $Id: ImRModel.java,v 1.12 2006/06/14 11:54:40 alphonse.bendt Exp $
041:         */
042:
043:        public class ImRModel {
044:            private Admin m_admin;
045:            private org.jacorb.orb.ORB m_orb;
046:
047:            private org.jacorb.config.Configuration configuration = null;
048:
049:            /** the specific logger for this component */
050:            private Logger logger = null;
051:
052:            private ServerInfo[] m_servers;
053:            private ImRInfo m_imr_info;
054:
055:            private DefaultMutableTreeNode m_top_node;
056:            private JTree m_tree;
057:            private DefaultTreeModel m_tree_model;
058:
059:            private ImRPOATableModel m_poa_model;
060:            private ImRServerTableModel m_server_model;
061:
062:            private Hashtable m_server_names;
063:
064:            private JComboBox m_host_selector;
065:            private DefaultComboBoxModel m_host_selector_model;
066:            private Hashtable m_host_names;
067:
068:            private RefreshThread m_refresh_thread;
069:            protected int m_current_refresh_interval = 20000;
070:            protected boolean m_refresh_disabled = false;
071:
072:            private Vector m_server_nodes;
073:            private Vector m_poa_nodes; //contains other Vectors
074:
075:            /**
076:             * The constructor. Connects to default repository and fetches the servers.
077:             */
078:
079:            public ImRModel() {
080:                m_orb = (org.jacorb.orb.ORB) org.omg.CORBA.ORB.init(
081:                        new String[0], null);
082:                configuration = m_orb.getConfiguration();
083:                logger = configuration.getNamedLogger("jacorb.imr.model");
084:
085:                try {
086:                    m_admin = AdminHelper
087:                            .narrow(m_orb
088:                                    .resolve_initial_references("ImplementationRepository"));
089:                } catch (org.omg.CORBA.ORBPackage.InvalidName in) {
090:                    if (logger.isWarnEnabled())
091:                        logger.warn("Could not contact Impl. Repository!");
092:                    return;
093:                }
094:
095:                fetchImRInfo();
096:
097:                m_top_node = new DefaultMutableTreeNode(m_imr_info);
098:                m_tree_model = new DefaultTreeModel(m_top_node, false);
099:                m_tree = new JTree(m_tree_model);
100:
101:                m_server_model = new ImRServerTableModel(this );
102:                m_poa_model = new ImRPOATableModel();
103:
104:                m_server_names = new Hashtable();
105:
106:                m_server_nodes = new Vector();
107:                m_poa_nodes = new Vector();
108:
109:                m_host_names = new Hashtable();
110:                m_host_selector_model = new DefaultComboBoxModel();
111:                m_host_selector = new JComboBox(m_host_selector_model);
112:                m_host_selector.setEditable(true);
113:
114:                fetchServers();
115:                m_tree.expandRow(0);
116:
117:                m_refresh_thread = new RefreshThread(m_current_refresh_interval);
118:            }
119:
120:            /**
121:             * Connect the manager to a remote repository.
122:             *
123:             * @param ior_url an url pointing to the IOR file of a remote repository.
124:             */
125:            public void connectTo(String ior_url) {
126:                try {
127:                    m_admin = AdminHelper
128:                            .narrow(m_orb
129:                                    .resolve_initial_references("ImplementationRepository"));
130:                } catch (org.omg.CORBA.ORBPackage.InvalidName in) {
131:                    if (logger.isWarnEnabled())
132:                        logger.warn("Could not contact Impl. Repository!");
133:                    return;
134:                }
135:
136:                fetchImRInfo();
137:
138:                m_top_node.setUserObject(m_imr_info);
139:
140:                fetchServers();
141:
142:                setRefreshInterval(m_current_refresh_interval);
143:            }
144:
145:            /**
146:             * Get a JComboBox containing all known hostnames.
147:             *
148:             * @return a JComboBox.
149:             */
150:            public JComboBox getHostSelector() {
151:                return m_host_selector;
152:            }
153:
154:            /**
155:             * Get the table model for the POA table.
156:             */
157:            public TableModel getPOATableModel() {
158:                return m_poa_model;
159:            }
160:
161:            /**
162:             * Get the table model for the server table.
163:             */
164:            public TableModel getServerTableModel() {
165:                return m_server_model;
166:            }
167:
168:            /**
169:             * Set the POA table model to the specific server, i.e.
170:             * the POA table displays this servers poas.
171:             *
172:             * @param server the servers name to build the table for.
173:             */
174:            public void poaTableForServer(ServerInfo server) {
175:                m_poa_model.setPOAs(server.poas);
176:            }
177:
178:            /**
179:             * Fetch all servers from the repository. Rebuild Tree and HostSelector.
180:             */
181:            public void fetchServers() {
182:                m_servers = m_admin.list_servers();
183:
184:                m_server_model.setServers(m_servers);
185:
186:                m_server_names.clear();
187:                for (int _i = 0; _i < m_servers.length; _i++)
188:                    m_server_names.put(m_servers[_i].name, new Integer(_i));
189:
190:                String _server = m_poa_model.getServerName();
191:                if (_server != null)
192:                    m_poa_model
193:                            .setPOAs(m_servers[indexForServerName(_server)].poas);
194:
195:                buildTree();
196:                buildHostSelectorModel();
197:            }
198:
199:            /**
200:             * Remove a server from the repository.
201:             *
202:             * @param name the servers name.
203:             */
204:            public void removeServer(String name) {
205:                removeServer(indexForServerName(name));
206:            }
207:
208:            /**
209:             * Remove a server from the repository.
210:             *
211:             * @param server_row the servers row in the table.
212:             */
213:            public void removeServer(int server_row) {
214:                try {
215:                    m_admin.unregister_server(m_servers[server_row].name);
216:                } catch (Exception _e) {
217:                    handleException(_e);
218:                }
219:
220:                fetchServers();
221:            }
222:
223:            /**
224:             * Hold a server.
225:             *
226:             * @param name the servers name.
227:             */
228:            public void holdServer(String name) {
229:                holdServer(indexForServerName(name));
230:            }
231:
232:            /**
233:             * Hold a server.
234:             *
235:             * @param server_row the servers row in the table.
236:             */
237:            public void holdServer(int server_row) {
238:                try {
239:                    m_admin.hold_server(m_servers[server_row].name);
240:                } catch (Exception _e) {
241:                    handleException(_e);
242:                }
243:
244:                refreshServer(server_row);
245:            }
246:
247:            /**
248:             * Release a server.
249:             *
250:             * @param name the servers name.
251:             */
252:            public void releaseServer(String name) {
253:                releaseServer(indexForServerName(name));
254:            }
255:
256:            /**
257:             * Release a server.
258:             *
259:             * @param server_row the servers row in the table.
260:             */
261:            public void releaseServer(int server_row) {
262:                try {
263:                    m_admin.release_server(m_servers[server_row].name);
264:                } catch (Exception _e) {
265:                    handleException(_e);
266:                }
267:
268:                refreshServer(server_row);
269:            }
270:
271:            /**
272:             * Refresh a server.
273:             *
274:             * @param name the servers name.
275:             */
276:            public void refreshServer(String name) {
277:                refreshServer(indexForServerName(name));
278:            }
279:
280:            /**
281:             * Refresh a server.
282:             *
283:             * @param index the servers row in the table.
284:             */
285:            public void refreshServer(int index) {
286:                try {
287:                    ServerInfo _server = m_admin
288:                            .get_server_info(m_servers[index].name);
289:
290:                    m_servers[index] = _server;
291:
292:                    buildServerNode(index);
293:
294:                    m_server_model.serverRefreshed(index);
295:
296:                    if (m_host_names.put(m_servers[index].host,
297:                            m_servers[index].host) == null)
298:                        m_host_selector_model.addElement(m_servers[index].host);
299:
300:                    if (_server.name.equals(m_poa_model.getServerName()))
301:                        m_poa_model.setPOAs(_server.poas);
302:
303:                } catch (Exception _e) {
304:                    handleException(_e);
305:                }
306:            }
307:
308:            /**
309:             * Set a server down.
310:             *
311:             * @param name the servers name.
312:             */
313:            public void setServerDown(String name) {
314:                setServerDown(indexForServerName(name));
315:            }
316:
317:            /**
318:             * Set a server down.
319:             *
320:             * @param server_row the servers row in the table.
321:             */
322:            public void setServerDown(int server_row) {
323:                Registration _reg = RegistrationHelper.narrow(m_admin);
324:
325:                try {
326:                    _reg.set_server_down(m_servers[server_row].name);
327:                } catch (Exception _e) {
328:                    handleException(_e);
329:                }
330:
331:                refreshServer(m_servers[server_row].name);
332:            }
333:
334:            /**
335:             * Add a server to the repository.
336:             *
337:             * @param name the servers name.
338:             * @param command the servers startup command. Leave empty (not null)
339:             * if automatic startup is not desired.
340:             * @param host the host the server is running on.
341:             */
342:            public void addServer(String name, String command, String host) {
343:                try {
344:                    m_admin.register_server(name, command, host);
345:                } catch (Exception _e) {
346:                    handleException(_e);
347:                }
348:
349:                fetchServers();
350:            }
351:
352:            /**
353:             * Get the tree representation of the server structure.
354:             *
355:             * @return a JTree.
356:             */
357:            public JTree getTree() {
358:                return m_tree;
359:            }
360:
361:            /**
362:             * Shut the repository down.
363:             *
364:             * @param wait true, if ORB should wait for still open connections to be
365:             * closed by clients.
366:             */
367:            public void imrShutdown(boolean wait) {
368:                disableRefresh();
369:
370:                try {
371:                    m_admin.shutdown(wait);
372:
373:                    m_top_node.removeAllChildren();
374:                    m_servers = null;
375:                } catch (Exception _e) {
376:                    handleException(_e);
377:                }
378:            }
379:
380:            /**
381:             * Make a backup of the server table.
382:             */
383:            public void saveTable() {
384:                try {
385:                    m_admin.save_server_table();
386:                } catch (Exception _e) {
387:                    handleException(_e);
388:                }
389:            }
390:
391:            /**
392:             * Get the row number of a POA in the POA table.
393:             *
394:             * @param server the server node the POA belongs to.
395:             * @param poa the poas poa node.
396:             */
397:            public int getRow(ServerInfo server, POAInfo poa) {
398:                for (int _i = 0; _i < server.poas.length; _i++) {
399:                    if (server.poas[_i] == poa)
400:                        return _i;
401:                }
402:
403:                return -1;
404:            }
405:
406:            /**
407:             * Set the interval by which the internal data is refreshed.
408:             *
409:             * @param interval refresh interval in ms.
410:             */
411:            public void setRefreshInterval(int interval) {
412:                m_current_refresh_interval = interval;
413:                m_refresh_disabled = false;
414:                m_refresh_thread.setInterval(interval);
415:            }
416:
417:            /**
418:             * Disable the automatic refresh.
419:             */
420:            public void disableRefresh() {
421:                m_refresh_disabled = true;
422:                m_refresh_thread.setInterval(0);
423:            }
424:
425:            /**
426:             * Update a server in the repository by changes the user made in the server
427:             * table of the GUI.
428:             *
429:             * @param server_row the row of the server in the table.
430:             * @param field_name the columns name.
431:             * @param new_value the cells new value.
432:             */
433:            protected void updateServer(int server_row, String field_name,
434:                    Object new_value) {
435:                String _host = m_servers[server_row].host;
436:                String _cmd = m_servers[server_row].command;
437:
438:                if (new_value instanceof  String) {
439:                    if (field_name.equals("Host")) {
440:                        _host = (String) new_value;
441:                        if (m_host_names.put(new_value, new_value) == null)
442:                            m_host_selector_model.addElement(new_value);
443:                    } else if (field_name.equals("Command"))
444:                        _cmd = (String) new_value;
445:
446:                    try {
447:                        m_admin.edit_server(m_servers[server_row].name, _cmd,
448:                                _host);
449:                    } catch (Exception _e) {
450:                        handleException(_e);
451:                    }
452:                } else if (new_value instanceof  Boolean) {
453:                    if (field_name.equals("active")) {
454:                        if (!((Boolean) new_value).booleanValue())
455:                            setServerDown(m_servers[server_row].name);
456:                    } else if (field_name.equals("holding")) {
457:                        try {
458:                            if (((Boolean) new_value).booleanValue())
459:                                m_admin.hold_server(m_servers[server_row].name);
460:                            else
461:                                m_admin
462:                                        .release_server(m_servers[server_row].name);
463:
464:                        } catch (Exception _e) {
465:                            handleException(_e);
466:                        }
467:                    }
468:                }
469:
470:                refreshServer(m_servers[server_row].name);
471:            }
472:
473:            /**
474:             * Bring up error message Dialog.
475:             *
476:             * @param e the exception that has been thrown.
477:             */
478:
479:            private void handleException(Exception e) {
480:                if (e instanceof  org.omg.CORBA.UserException) {
481:                    String _msg = e.toString();
482:                    if (e instanceof  IllegalServerName)
483:                        _msg = "The specified server name is not allowed";
484:                    else if (e instanceof  DuplicateServerName)
485:                        _msg = "A server with name "
486:                                + ((DuplicateServerName) e).name
487:                                + " has already been registered with the repository";
488:                    else if (e instanceof  FileOpFailed)
489:                        _msg = "The backup operation failed";
490:
491:                    JOptionPane.showMessageDialog(new JFrame(), _msg,
492:                            "An error occurred", JOptionPane.ERROR_MESSAGE);
493:                } else {
494:                    logger.warn("Exception: ", e);
495:                }
496:            }
497:
498:            /**
499:             * Fill the model of the combo box with host names.
500:             * After fetching hosts from the repository, they are "pinged" in order to
501:             * see if they are still up.
502:             */
503:
504:            private void buildHostSelectorModel() {
505:                HostInfo[] _hosts = m_admin.list_hosts();
506:
507:                for (int _i = 0; _i < _hosts.length; _i++) {
508:                    try {
509:                        ServerStartupDaemon _ssd = ServerStartupDaemonHelper
510:                                .narrow(m_orb
511:                                        .string_to_object(_hosts[_i].ior_string));
512:                        _ssd.get_system_load();
513:                        _ssd._release();
514:
515:                        // ssd is up and seems to work
516:                        if (m_host_names.put(_hosts[_i].name, _hosts[_i].name) == null)
517:                            m_host_selector_model.addElement(_hosts[_i].name);
518:                    } catch (Exception _e) {
519:                        //ignore
520:                    }
521:                }
522:
523:                for (int _i = 0; _i < m_servers.length; _i++)
524:                    if (m_host_names
525:                            .put(m_servers[_i].host, m_servers[_i].host) == null)
526:                        m_host_selector_model.addElement(m_servers[_i].host);
527:            }
528:
529:            /**
530:             * Get a servers row by its name.
531:             *
532:             * @param name the servers name.
533:             * @return the servers row
534:             */
535:            private int indexForServerName(String name) {
536:                return ((Integer) m_server_names.get(name)).intValue();
537:            }
538:
539:            /**
540:             * Get the ImRInfo struct from the repository.
541:             */
542:            private void fetchImRInfo() {
543:                Registration _reg = RegistrationHelper.narrow(m_admin);
544:
545:                m_imr_info = _reg.get_imr_info();
546:            }
547:
548:            /**
549:             * Build a tree node for a server, with all its
550:             * dependend POAs.
551:             *
552:             * @param index the servers ServerInfo struct.
553:             */
554:            private void buildServerNode(int index) {
555:                DefaultMutableTreeNode _server_node;
556:                POAInfo[] _poa_array = m_servers[index].poas;
557:                Vector _poas;
558:                if (index < m_server_nodes.size()) {
559:                    // a server node for that index exists
560:                    _server_node = (DefaultMutableTreeNode) m_server_nodes
561:                            .elementAt(index);
562:                    _poas = (Vector) m_poa_nodes.elementAt(index);
563:
564:                } else {
565:                    // a new server node has to be created
566:                    _server_node = new DefaultMutableTreeNode(m_servers[index]);
567:                    m_server_nodes.addElement(_server_node);
568:                    m_tree_model
569:                            .insertNodeInto(_server_node, m_top_node, index);
570:                    m_tree.scrollPathToVisible(new TreePath(_server_node
571:                            .getPath()));
572:
573:                    _poas = new Vector();
574:                    m_poa_nodes.addElement(_poas);
575:                }
576:
577:                int _i;
578:                //update existing nodes
579:                for (_i = 0; _i < _poas.size(); _i++) {
580:                    if (_i < _poa_array.length) {
581:                        DefaultMutableTreeNode _poa = (DefaultMutableTreeNode) _poas
582:                                .elementAt(_i);
583:                        _poa.setUserObject(_poa_array[_i]);
584:                    } else
585:                        break;
586:                }
587:                if (_i >= _poa_array.length) {
588:                    //remove surplus nodes
589:                    for (int _j = _poas.size() - 1; _j >= _i; _j--) {
590:                        DefaultMutableTreeNode _poa = (DefaultMutableTreeNode) _poas
591:                                .elementAt(_j);
592:                        _poas.removeElementAt(_j);
593:                        m_tree_model.removeNodeFromParent(_poa);
594:                    }
595:                } else {
596:                    // build new nodes
597:                    for (int _j = _i; _j < _poa_array.length; _j++) {
598:                        DefaultMutableTreeNode _poa = new DefaultMutableTreeNode(
599:                                _poa_array[_j]);
600:                        _poas.addElement(_poa);
601:                        m_tree_model.insertNodeInto(_poa, _server_node, _j);
602:                    }
603:                }
604:            }
605:
606:            /**
607:             * Remove a server node from the tree.
608:             *
609:             * @param index the servers index in the table.
610:             */
611:            private void removeServerNode(int index) {
612:                DefaultMutableTreeNode _server_node = (DefaultMutableTreeNode) m_server_nodes
613:                        .elementAt(index);
614:                Vector _poas = (Vector) m_poa_nodes.elementAt(index);
615:
616:                for (int _j = _poas.size() - 1; _j >= 0; _j--) {
617:                    DefaultMutableTreeNode _poa = (DefaultMutableTreeNode) _poas
618:                            .elementAt(_j);
619:                    _poas.removeElementAt(_j);
620:                    m_tree_model.removeNodeFromParent(_poa);
621:                }
622:
623:                m_server_nodes.removeElementAt(index);
624:                m_tree_model.removeNodeFromParent(_server_node);
625:            }
626:
627:            /**
628:             * Build the tree by building all its server nodes. The
629:             * root node stays always the same.
630:             */
631:            private void buildTree() {
632:                int _i;
633:                // update exisiting nodes
634:                for (_i = 0; _i < m_server_nodes.size(); _i++) {
635:                    if (_i < m_servers.length) {
636:                        DefaultMutableTreeNode _server = (DefaultMutableTreeNode) m_server_nodes
637:                                .elementAt(_i);
638:                        _server.setUserObject(m_servers[_i]);
639:                        buildServerNode(_i);
640:                    } else
641:                        break;
642:                }
643:
644:                if (_i >= m_servers.length) {
645:                    //remove surplus nodes
646:                    for (int _j = m_server_nodes.size() - 1; _j >= _i; _j--)
647:                        removeServerNode(_j);
648:                } else {
649:                    //add new nodes
650:                    for (int _j = _i; _j < m_servers.length; _j++)
651:                        buildServerNode(_j);
652:                }
653:            }
654:
655:            private class RefreshThread extends Thread {
656:                private long m_interval;
657:
658:                public RefreshThread(long interval) {
659:                    m_interval = interval;
660:
661:                    start();
662:                }
663:
664:                public synchronized void run() {
665:                    while (true) {
666:                        while (m_interval <= 0) {
667:                            try {
668:                                this .wait();
669:                            } catch (Exception _e) {
670:                                handleException(_e);
671:                            }
672:                        }
673:                        try {
674:                            fetchServers();
675:                        } catch (Exception _e) {
676:                            handleException(_e);
677:                        }
678:
679:                        try {
680:                            this .wait(m_interval);
681:                        } catch (Exception _e) {
682:                            handleException(_e);
683:                        }
684:                    }
685:                }
686:
687:                public synchronized void setInterval(long interval) {
688:                    m_interval = interval;
689:
690:                    this .notifyAll();
691:                }
692:            }
693:        } // ImRModel
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.