Source Code Cross Referenced for ChatComponent.java in  » IDE-Netbeans » collab » org » netbeans » modules » collab » channel » chat » 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 » IDE Netbeans » collab » org.netbeans.modules.collab.channel.chat 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:        package org.netbeans.modules.collab.channel.chat;
0042:
0043:        import com.sun.collablet.CollabException;
0044:        import com.sun.collablet.CollabManager;
0045:        import com.sun.collablet.CollabMessage;
0046:        import com.sun.collablet.CollabPrincipal;
0047:        import com.sun.collablet.ContentTypes;
0048:        import com.sun.collablet.Conversation;
0049:        import com.sun.collablet.ConversationPrivilege;
0050:        import com.sun.collablet.UserInterface;
0051:        import com.sun.collablet.chat.ChatCollablet;
0052:        import java.awt.GridBagConstraints;
0053:        import java.awt.GridBagLayout;
0054:        import org.openide.ErrorManager;
0055:
0056:        import org.openide.awt.*;
0057:        import org.openide.util.*;
0058:        import org.openide.windows.*;
0059:
0060:        import java.awt.BorderLayout;
0061:        import java.awt.Color;
0062:        import java.awt.Dimension;
0063:        import java.awt.Font;
0064:        import java.awt.FontMetrics;
0065:        import java.awt.Graphics;
0066:        import java.awt.GridLayout;
0067:        import java.awt.Image;
0068:        import java.awt.Rectangle;
0069:        import java.awt.Shape;
0070:        import java.awt.datatransfer.*;
0071:        import java.awt.event.*;
0072:
0073:        import java.beans.*;
0074:
0075:        import java.io.*;
0076:
0077:        import java.lang.reflect.*;
0078:
0079:        import java.net.URL;
0080:
0081:        import java.text.*;
0082:
0083:        import java.util.*;
0084:
0085:        import javax.swing.*;
0086:        import javax.swing.SwingUtilities;
0087:        import javax.swing.border.*;
0088:        import javax.swing.event.*;
0089:        import javax.swing.plaf.basic.BasicMenuItemUI;
0090:        import javax.swing.text.*;
0091:        import javax.swing.text.html.*;
0092:
0093:        import org.netbeans.modules.collab.*;
0094:        import org.netbeans.modules.collab.channel.chat.messagetype.CollabContentType;
0095:        import org.netbeans.modules.collab.core.Debug;
0096:
0097:        /**
0098:         *
0099:         *
0100:         * @author Todd Fast, todd.fast@sun.com
0101:         */
0102:        public class ChatComponent extends JPanel implements  HyperlinkListener {
0103:            ////////////////////////////////////////////////////////////////////////////
0104:            // Class variables
0105:            ////////////////////////////////////////////////////////////////////////////
0106:            private static final long serialVersionUID = 1L;
0107:            private static final String END_ELEMENT_ID = "END";
0108:            private static final String MESSAGE_TEMPLATE_ELEMENT_ID = "MESSAGE_TEMPLATE";
0109:            private static final String SYSTEM_MESSAGE_TEMPLATE_ELEMENT_ID = "SYSTEM_MESSAGE_TEMPLATE";
0110:            private static final String CHAT_MESSAGE_TEMPLATE_ELEMENT_ID = "CHAT_MESSAGE_TEMPLATE";
0111:            private static final String CHAT_TEMPLATE_RESOURCE = "/org/netbeans/modules/collab/channel/chat/chat_template.html";
0112:            private static String[][] smiles = new String[][] {
0113:                    { ":-)", "emo_smiley16.png" },
0114:                    { ":)", "emo_smiley16.png" }, { ":-(", "emo_sad16.png" },
0115:                    { ":(", "emo_sad16.png" }, { ";-)", "emo_wink16.png" },
0116:                    { ";)", "emo_wink16.png" },
0117:                    { ":=)", "emo_laughing16.png" },
0118:                    { "8-)", "emo_cool16.png" }, { ":-D", "emo_grin16.png" } };
0119:
0120:            // NOTE: These constants must be kept in sync with the values in the
0121:            // HTML template file!
0122:            private static final String TOKEN_SENDER_CLASS = "__SENDER_CLASS__";
0123:            private static final String TOKEN_SENDER = "__SENDER__";
0124:            private static final String TOKEN_MESSAGE_CLASS = "__MESSAGE_CLASS__";
0125:            private static final String TOKEN_MESSAGE = "__MESSAGE__";
0126:            private static final String TOKEN_MESSAGE_TEXT = "__MESSAGE_TEXT__";
0127:            private static final String TOKEN_TIMESTAMP = "__TIMESTAMP__";
0128:            private static final String TOKEN_CONTENT_TYPE = "__CONTENT_TYPE__";
0129:            private static final String MESSAGE_CLASS_CHAT = "message-chat";
0130:            private static final String MESSAGE_CLASS_TEXT = "message-text";
0131:            private static final String MESSAGE_CLASS_HTML = "message-html";
0132:            private static final String MESSAGE_CLASS_SYSTEM = "message-system";
0133:            private static final String MESSAGE_CLASS_OTHER = "message-other";
0134:            private static final String MESSAGE_CLASS_XML = "message-xml";
0135:            private static final String MESSAGE_CLASS_JAVA = "message-java";
0136:            private static final String DEFAULT_SENDER_CLASS = "sender-default";
0137:            private static final int MAX_SENDER_CLASSES = 9;
0138:            private static final String TOKEN_BASE_FONT_SIZE = "@BASE_FONT_SIZE@";
0139:            private static final String TOKEN_SMALL_FONT_SIZE = "@SMALL_FONT_SIZE@";
0140:
0141:            ////////////////////////////////////////////////////////////////////////////
0142:            // Instance variables
0143:            ////////////////////////////////////////////////////////////////////////////
0144:            private ChatCollablet channel;
0145:            private JEditorPane transcriptPane;
0146:            private ChatInputPane inputPane;
0147:            private JButton sendButton;
0148:            private JLabel typingMessageLabel;
0149:            private String inputContentType = ContentTypes.UNKNOWN_TEXT;
0150:            private String previouslySelectedContentType;
0151:            private Element endElement;
0152:            private String messageTemplate;
0153:            private String chatMessageTemplate;
0154:            private String systemMessageTemplate;
0155:            private Map senderStyles = new HashMap();
0156:            private Map contentTypeToButton = new HashMap();
0157:            private int lastSenderStyleIndex;
0158:            private ConversationChangeListener conversationListener;
0159:            private javax.swing.Timer typingTimer = null;
0160:            private int TYPE_TIMER_INTERVAL = 2000;
0161:            private Set typingParticipants = Collections
0162:                    .synchronizedSet(new HashSet());
0163:            private JPopupMenu popupMenu;
0164:            private JPopupMenu newMenu;
0165:            private JButton smileyButton;
0166:            private JToggleButton chatFocusButton;
0167:
0168:            /**
0169:             *
0170:             *
0171:             */
0172:            public ChatComponent(ChatCollablet channel) {
0173:                super ();
0174:                this .channel = channel;
0175:
0176:                initialize();
0177:                initTypingTimer();
0178:
0179:                // Listen to conversation changes
0180:                conversationListener = new ConversationChangeListener();
0181:                channel.addPropertyChangeListener(conversationListener);
0182:                channel.getConversation().addPropertyChangeListener(
0183:                        conversationListener);
0184:
0185:                // To update Find, Copy, etc. actions, add to constructor:
0186:                //		ActionMap map = getActionMap();
0187:                //		Action findBinding = new MyFindAction(this);
0188:                //		map.put(((CallbackSystemAction)SystemAction.get(
0189:                //			FindAction.class)).getActionMapKey(), findBinding);
0190:                // Ensure that the first sender style is reserved for us
0191:                lastSenderStyleIndex++;
0192:                allocateNewSenderStyleClass(channel.getConversation()
0193:                        .getCollabSession().getUserPrincipal().getDisplayName());
0194:
0195:                if (chatFocusButton != null) {
0196:                    chatFocusButton.setSelected(true);
0197:                }
0198:
0199:                setHelpCtx();
0200:            }
0201:
0202:            /**
0203:             *set help ctx map id for context sensitive help
0204:             *
0205:             */
0206:            private void setHelpCtx() {
0207:                HelpCtx.setHelpIDString(this , "collab_chat_overview"); //NOI18n
0208:            }
0209:
0210:            /**
0211:             *
0212:             *
0213:             */
0214:            private void initialize() {
0215:                // Set our layout--if we don't do this, nothing will appear in
0216:                // the component
0217:                setLayout(new BorderLayout());
0218:
0219:                JSplitPane splitPanel = new JSplitPane(
0220:                        JSplitPane.VERTICAL_SPLIT, true);
0221:                splitPanel.setResizeWeight(0.85f);
0222:                splitPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
0223:
0224:                // We must set the editor kit explicitly in order to keep NetBeans
0225:                // from installing its own document type
0226:                transcriptPane = new JEditorPane();
0227:                transcriptPane.setEditable(false);
0228:
0229:                // Install our own editor kit in order to ensure rendering of the
0230:                // message template element is no-op'd
0231:                transcriptPane.setEditorKit(new HTMLEditorKit() {
0232:                    public ViewFactory getViewFactory() {
0233:                        return new ChatHTMLFactory();
0234:                    }
0235:                });
0236:
0237:                createPopupMenu();
0238:                createSmileMenu();
0239:
0240:                initializeTranscriptTemplate();
0241:
0242:                // Listen to clicked links
0243:                transcriptPane.addHyperlinkListener(this );
0244:
0245:                // Create a scroll pane to contain the conversation transcript
0246:                JScrollPane transcriptScrollPane1 = new JScrollPane(
0247:                        transcriptPane);
0248:                transcriptScrollPane1
0249:                        .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
0250:
0251:                JPanel transcriptPanel = new JPanel(new BorderLayout());
0252:                transcriptPanel.add(transcriptScrollPane1, BorderLayout.CENTER);
0253:                splitPanel.add(transcriptPanel, JSplitPane.TOP);
0254:
0255:                // Panel to hold the various input components
0256:                JPanel inputPanel = new JPanel();
0257:                inputPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
0258:                inputPanel.setLayout(new GridBagLayout());
0259:
0260:                boolean canSendMessages = false;
0261:
0262:                try {
0263:                    if ((getChannel().getConversation().getPrivilege() == ConversationPrivilege.MANAGE)
0264:                            || (getChannel().getConversation().getPrivilege() == ConversationPrivilege.WRITE)) {
0265:                        canSendMessages = true;
0266:                    }
0267:                } catch (CollabException e) {
0268:                    canSendMessages = false;
0269:                }
0270:
0271:                if (canSendMessages) {
0272:                    // Create a send button
0273:                    sendButton = new JButton() {
0274:                        public void transferFocusBackward() {
0275:                            // Make sure the prior component is always the input pane
0276:                            getInputPane().requestFocus();
0277:                        }
0278:                    };
0279:                    Mnemonics.setLocalizedText(sendButton, NbBundle
0280:                            .getMessage(ChatComponent.class,
0281:                                    "LBL_ChatComponent_SendButton"));
0282:                    sendButton
0283:                            .addActionListener(new SendButtonActionListener());
0284:
0285:                    // Add the toolbar
0286:                    GridBagConstraints gbc = new GridBagConstraints();
0287:                    gbc.fill = gbc.HORIZONTAL;
0288:                    gbc.gridx = 0;
0289:                    gbc.gridy = 1;
0290:                    gbc.weightx = 0.0;
0291:                    gbc.weighty = 0.0;
0292:                    inputPanel.add(initializeToolbar(), gbc);
0293:                    gbc = new GridBagConstraints();
0294:                    gbc.fill = gbc.NONE;
0295:                    gbc.anchor = gbc.EAST;
0296:                    gbc.gridx = 2;
0297:                    gbc.gridy = 1;
0298:                    gbc.weightx = 0.0;
0299:                    gbc.weighty = 0.0;
0300:                    inputPanel.add(sendButton, gbc);
0301:
0302:                    // Create an input pane
0303:                    inputPane = new ChatInputPane(this );
0304:                    inputPane.setEditable(true);
0305:                    inputPane._setContentType(inputContentType);
0306:                    inputPane.setTransferHandler(new InputPaneTransferHandler(
0307:                            inputPane.getTransferHandler()));
0308:
0309:                    KeyStroke snd = KeyStroke.getKeyStroke("control ENTER"); // NOI18N
0310:                    inputPane.getInputMap().put(snd, "sendAction"); // NOI18N
0311:                    inputPane.getActionMap().put("sendAction",
0312:                            new SendButtonActionListener());
0313:
0314:                    // registers itself
0315:                    InputPaneDocumentListener lst = new InputPaneDocumentListener();
0316:
0317:                    // Create a scroll pane to contain the input pane
0318:                    JScrollPane inputScrollPane = new JScrollPane(inputPane);
0319:                    inputScrollPane
0320:                            .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
0321:                    gbc = new GridBagConstraints();
0322:                    gbc.fill = gbc.BOTH;
0323:                    gbc.gridx = 0;
0324:                    gbc.gridy = 0;
0325:                    gbc.gridwidth = 3;
0326:                    gbc.weightx = 1.0;
0327:                    gbc.weighty = 1.0;
0328:                    inputPanel.add(inputScrollPane, gbc);
0329:
0330:                    typingMessageLabel = new JLabel();
0331:                    gbc = new GridBagConstraints();
0332:                    gbc.fill = gbc.HORIZONTAL;
0333:                    gbc.anchor = gbc.CENTER;
0334:                    gbc.gridx = 1;
0335:                    gbc.weightx = 1.0;
0336:                    gbc.weighty = 0.0;
0337:                    inputPanel.add(typingMessageLabel, gbc);
0338:                } else {
0339:                    // Instead, add a label that indicates that the user cannot
0340:                    // send messages in this conversation
0341:                    JLabel messageLabel = new JLabel(NbBundle.getMessage(
0342:                            ChatComponent.class,
0343:                            "LBL_ChatComponent_NoPrivilege"), // NOI18N
0344:                            SwingConstants.CENTER);
0345:                    GridBagConstraints gbc = new GridBagConstraints();
0346:                    gbc.fill = gbc.HORIZONTAL;
0347:                    gbc.gridx = 0;
0348:                    gbc.gridy = 0;
0349:                    gbc.weightx = 1.0;
0350:                    gbc.weighty = 0.0;
0351:                    inputPanel.add(messageLabel, gbc);
0352:                    typingMessageLabel = new JLabel();
0353:
0354:                    typingMessageLabel.setOpaque(true);
0355:                    gbc.fill = gbc.HORIZONTAL;
0356:                    gbc.gridy = 1;
0357:                    gbc.weightx = 1.0;
0358:                    gbc.weighty = 0.0;
0359:                    inputPanel.add(typingMessageLabel, gbc);
0360:                }
0361:
0362:                splitPanel.add(inputPanel, JSplitPane.BOTTOM);
0363:
0364:                add(splitPanel, BorderLayout.CENTER);
0365:            }
0366:
0367:            /**
0368:             *
0369:             *
0370:             */
0371:            private void initializeTranscriptTemplate() {
0372:                // Initialize the chat transcript template
0373:                try {
0374:                    // Read the template file into memory.  Note, it doesn't seem to
0375:                    // work to get the resource as a URL and call setPage() on the
0376:                    // editor pane.
0377:                    InputStream is = ChatComponent.class
0378:                            .getResourceAsStream(CHAT_TEMPLATE_RESOURCE);
0379:                    BufferedReader reader = new BufferedReader(
0380:                            new InputStreamReader(is));
0381:
0382:                    StringBuffer buffer = new StringBuffer();
0383:                    String line = null;
0384:
0385:                    while ((line = reader.readLine()) != null)
0386:                        buffer.append(line).append("\n");
0387:
0388:                    // Determine the current font size in the IDE
0389:                    int baseFontSize = Math.max(new JLabel().getFont()
0390:                            .getSize(), 12);
0391:                    int smallFontSize = baseFontSize - 1;
0392:
0393:                    // Replace global tokens
0394:                    String templateContent = buffer.toString();
0395:                    templateContent = StringTokenizer2.replace(templateContent,
0396:                            TOKEN_BASE_FONT_SIZE, "" + baseFontSize);
0397:                    templateContent = StringTokenizer2.replace(templateContent,
0398:                            TOKEN_SMALL_FONT_SIZE, "" + smallFontSize);
0399:
0400:                    // Set the template content
0401:                    transcriptPane.setText(templateContent);
0402:
0403:                    // Find and cache the element at which we will insert additional
0404:                    // elements
0405:                    HTMLDocument document = (HTMLDocument) transcriptPane
0406:                            .getDocument();
0407:                    endElement = document.getElement(END_ELEMENT_ID);
0408:
0409:                    // Get the message template HTML from the document itself
0410:                    Element templateParent = document
0411:                            .getElement(MESSAGE_TEMPLATE_ELEMENT_ID);
0412:
0413:                    // Switch to the implied <p> inside the <div>
0414:                    templateParent = templateParent.getElement(0);
0415:
0416:                    // Find the first comment element of the template parent element.
0417:                    // This will be our template string.
0418:                    for (int i = 0; i < templateParent.getElementCount(); i++) {
0419:                        Element element = templateParent.getElement(i);
0420:
0421:                        if (element.getAttributes().isDefined(
0422:                                HTML.Attribute.COMMENT)) {
0423:                            messageTemplate = (String) element.getAttributes()
0424:                                    .getAttribute(HTML.Attribute.COMMENT);
0425:
0426:                            break;
0427:                        }
0428:                    }
0429:
0430:                    // Get the system message template
0431:                    Element systemMsgTemplateParent = document
0432:                            .getElement(SYSTEM_MESSAGE_TEMPLATE_ELEMENT_ID);
0433:
0434:                    // Switch to the implied <p> inside the <div>
0435:                    systemMsgTemplateParent = systemMsgTemplateParent
0436:                            .getElement(0);
0437:
0438:                    // Find the first comment element of the template parent element.
0439:                    // This will be our template string.
0440:                    for (int i = 0; i < systemMsgTemplateParent
0441:                            .getElementCount(); i++) {
0442:                        Element element = systemMsgTemplateParent.getElement(i);
0443:
0444:                        if (element.getAttributes().isDefined(
0445:                                HTML.Attribute.COMMENT)) {
0446:                            systemMessageTemplate = (String) element
0447:                                    .getAttributes().getAttribute(
0448:                                            HTML.Attribute.COMMENT);
0449:
0450:                            break;
0451:                        }
0452:                    }
0453:
0454:                    // Get the chat message template
0455:                    Element chatMessageTemplateParent = document
0456:                            .getElement(CHAT_MESSAGE_TEMPLATE_ELEMENT_ID);
0457:
0458:                    // Switch to the implied <p> inside the <div>
0459:                    chatMessageTemplateParent = chatMessageTemplateParent
0460:                            .getElement(0);
0461:
0462:                    // Find the first comment element of the template parent element.
0463:                    // This will be our template string.
0464:                    for (int i = 0; i < chatMessageTemplateParent
0465:                            .getElementCount(); i++) {
0466:                        Element element = chatMessageTemplateParent
0467:                                .getElement(i);
0468:
0469:                        if (element.getAttributes().isDefined(
0470:                                HTML.Attribute.COMMENT)) {
0471:                            chatMessageTemplate = (String) element
0472:                                    .getAttributes().getAttribute(
0473:                                            HTML.Attribute.COMMENT);
0474:
0475:                            break;
0476:                        }
0477:                    }
0478:                } catch (IOException e) {
0479:                    // Shouldn't happen
0480:                    Debug.errorManager.notify(e);
0481:                }
0482:            }
0483:
0484:            /**
0485:             *
0486:             *
0487:             */
0488:            private void initTypingTimer() {
0489:                TypingTimerActionListener actionListener = new TypingTimerActionListener();
0490:                typingTimer = new javax.swing.Timer(TYPE_TIMER_INTERVAL,
0491:                        actionListener);
0492:                typingTimer.setRepeats(false);
0493:            }
0494:
0495:            /**
0496:             * Code to dynamically add the buttons by using the lookup api of the netbeans
0497:             *
0498:             */
0499:            private JToolBar initializeToolbar() {
0500:                JToolBar inputToolbar = new JToolBar(JToolBar.HORIZONTAL);
0501:                inputToolbar.setFloatable(false);
0502:                inputToolbar.setBorder(new CompoundBorder(new EmptyBorder(3, 0,
0503:                        0, 0), inputToolbar.getBorder()));
0504:
0505:                ContentTypeActionListener actionListener = new ContentTypeActionListener();
0506:
0507:                ButtonGroup group = new ButtonGroup();
0508:
0509:                Lookup.Result result = Lookup.getDefault().lookup(
0510:                        new Lookup.Template(CollabContentType.class));
0511:                Collection messageTypeCollection = result.allInstances();
0512:
0513:                int i = 1;
0514:                for (Iterator it = messageTypeCollection.iterator(); it
0515:                        .hasNext(); i++) {
0516:                    CollabContentType messageType = (CollabContentType) it
0517:                            .next();
0518:                    Image icon = messageType.getIcon();
0519:                    String displayName = messageType.getDisplayName();
0520:                    String contentType = messageType.getContentType();
0521:                    JToggleButton button = new JToggleButton(
0522:                            new ImageIcon(icon));
0523:                    button.putClientProperty("contentType", contentType); //NOI18N
0524:
0525:                    if (i < 9)
0526:                        button.setMnemonic((char) ('0' + i));
0527:                    button.setToolTipText(displayName);
0528:                    if (messageType.getContentType().equals(
0529:                            ContentTypes.UNKNOWN_TEXT)) {
0530:                        chatFocusButton = button;
0531:                    }
0532:                    button.addActionListener(actionListener);
0533:
0534:                    group.add(button);
0535:                    inputToolbar.add(button);
0536:                    contentTypeToButton.put(contentType, button);
0537:                }
0538:
0539:                inputToolbar.addSeparator();
0540:
0541:                Image smileyButtonIcon = org.openide.util.Utilities
0542:                        .loadImage("org/netbeans/modules/collab/channel/chat/"
0543:                                + "resources/emoticons/emo_smiley16.png"); // NOI18N        
0544:                smileyButton = new JButton(new ImageIcon(smileyButtonIcon));
0545:                smileyButton.setMnemonic(NbBundle.getMessage(
0546:                        ChatComponent.class,
0547:                        "MNE_ChatComponent_MIMEType_Smileys").charAt(0));
0548:                smileyButton.setToolTipText(NbBundle.getMessage(
0549:                        ChatComponent.class,
0550:                        "LBL_ChatComponent_MIMEType_Smileys"));
0551:                smileyButton.setRequestFocusEnabled(false);
0552:                smileyButton.addActionListener(new SmileListener());
0553:                inputToolbar.add(smileyButton);
0554:
0555:                return inputToolbar;
0556:            }
0557:
0558:            /*author Smitha Krishna Nagesh*/
0559:            public JPopupMenu createSmileMenu() {
0560:                newMenu = new JPopupMenu();
0561:                newMenu.setLayout(new GridLayout(3, 2));
0562:                newMenu.setPopupSize(50, 50);
0563:                ButtonClickedListener listener = new ButtonClickedListener();
0564:
0565:                newMenu.add(createSmileButton(":-)", "emo_smiley", "Smile",
0566:                        listener));
0567:                newMenu.add(createSmileButton(":-(", "emo_sad", "Frown",
0568:                        listener));
0569:                newMenu.add(createSmileButton(";-)", "emo_wink", "Wink",
0570:                        listener));
0571:                newMenu.add(createSmileButton(":=)", "emo_laughing", "Laugh",
0572:                        listener));
0573:                newMenu.add(createSmileButton("8-)", "emo_cool", "Cool",
0574:                        listener));
0575:                newMenu.add(createSmileButton(":-D", "emo_grin", "Grin",
0576:                        listener));
0577:
0578:                newMenu.pack();
0579:
0580:                return newMenu;
0581:            }
0582:
0583:            private JButton createSmileButton(String smile, String icon,
0584:                    String key, ActionListener listener) {
0585:                Image img = org.openide.util.Utilities
0586:                        .loadImage("org/netbeans/modules/collab/channel/chat/resources/emoticons/"
0587:                                + icon + "16.png"); // NOI18N
0588:                JButton button = new JButton(new ImageIcon(img));
0589:                button.setActionCommand(smile.concat(" "));
0590:                String tip = NbBundle.getMessage(ChatComponent.class,
0591:                        "LBL_Emoticon_" + key);
0592:                button.setToolTipText(tip);
0593:                button.setMnemonic(tip.charAt(0));
0594:                button.addActionListener(listener);
0595:
0596:                button.setContentAreaFilled(false);
0597:                button.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
0598:                button.setBorderPainted(false);
0599:                button.setRequestFocusEnabled(false);
0600:                return button;
0601:            }
0602:
0603:            ////////////////////////////////////////////////////////////////////////////
0604:            // Accessors
0605:            ////////////////////////////////////////////////////////////////////////////
0606:
0607:            /**
0608:             *
0609:             *
0610:             */
0611:            public ChatCollablet getChannel() {
0612:                return channel;
0613:            }
0614:
0615:            /**
0616:             *
0617:             *
0618:             */
0619:            public JEditorPane getTranscriptPane() {
0620:                return transcriptPane;
0621:            }
0622:
0623:            /**
0624:             *
0625:             *
0626:             */
0627:            public ChatInputPane getInputPane() {
0628:                return inputPane;
0629:            }
0630:
0631:            /**
0632:             *
0633:             *
0634:             */
0635:            public JButton getSendButton() {
0636:                return sendButton;
0637:            }
0638:
0639:            ////////////////////////////////////////////////////////////////////////////
0640:            // Event notifications
0641:            ////////////////////////////////////////////////////////////////////////////
0642:
0643:            /**
0644:             *
0645:             *
0646:             */
0647:            public void addNotify() {
0648:                super .addNotify();
0649:                SwingUtilities.invokeLater(new Runnable() {
0650:                    public void run() {
0651:                        if (getInputPane() != null) {
0652:                            getInputPane().requestFocus();
0653:                        }
0654:                    }
0655:                });
0656:            }
0657:
0658:            ////////////////////////////////////////////////////////////////////////////
0659:            // Input support methods
0660:            ////////////////////////////////////////////////////////////////////////////
0661:
0662:            /**
0663:             *
0664:             *
0665:             */
0666:            public String getInputContentType() {
0667:                return inputContentType;
0668:            }
0669:
0670:            /**
0671:             *
0672:             *
0673:             */
0674:            public void setInputContentType(String contentType, boolean syncUI,
0675:                    boolean autoselected) {
0676:                if (contentType == null) {
0677:                    throw new IllegalArgumentException(
0678:                            "contentType cannot be null");
0679:                }
0680:
0681:                // Remember what the content type was if this is happening due to
0682:                // auto-selection during a paste.  Always remember the first content
0683:                // type that user had manually selected.
0684:                if (autoselected) {
0685:                    if (previouslySelectedContentType == null) {
0686:                        previouslySelectedContentType = inputContentType;
0687:                    }
0688:                }
0689:
0690:                //		else
0691:                //		{
0692:                //			previouslySelectedContentType=null;
0693:                //		}
0694:                inputContentType = contentType;
0695:
0696:                // Sync the input pane; remember the text and the selection
0697:                String text = getInputPane().getText();
0698:                int selStart = getInputPane().getSelectionStart();
0699:                int selEnd = getInputPane().getSelectionEnd();
0700:                int caretPos = getInputPane().getCaretPosition();
0701:
0702:                getInputPane()._setContentType(contentType);
0703:                getInputPane().popUpMenu();
0704:                getInputPane().setText(text);
0705:                getInputPane().setCaretPosition(caretPos);
0706:                getInputPane().setSelectionStart(selStart);
0707:                getInputPane().setSelectionEnd(selEnd);
0708:                getInputPane().requestFocus();
0709:
0710:                if (syncUI) {
0711:                    SwingUtilities.invokeLater(new ContentTypeSynchronizer());
0712:                }
0713:            }
0714:
0715:            ////////////////////////////////////////////////////////////////////////////
0716:            // Message management
0717:            ////////////////////////////////////////////////////////////////////////////
0718:
0719:            /**
0720:             *
0721:             *
0722:             */
0723:            protected void sendInput() {
0724:                // Send a message to the conference
0725:                try {
0726:                    CollabMessage message = getChannel().getConversation()
0727:                            .createMessage();
0728:
0729:                    // Set the message content
0730:                    String content = getInputPane().getText();
0731:                    message.setContent(content);
0732:
0733:                    // Set the actual content type to a different, chat-specific header.
0734:                    // The message content type will always be text/plain
0735:                    message.setHeader(
0736:                            ChatCollablet.DISPLAY_CONTENT_TYPE_HEADER,
0737:                            getInputContentType());
0738:
0739:                    // TODO: Tag the message as belonging to the chat channel
0740:                    // Is this necessary if we are sending SOAP?
0741:                    message.setHeader("x-channel", "chat"); // NOI18N
0742:
0743:                    // Send the message
0744:                    getChannel().getConversation().sendMessage(message);
0745:                } catch (CollabException e) {
0746:                    Debug.errorManager.notify(e);
0747:                }
0748:
0749:                // Clear the message text
0750:                getInputPane().setText("");
0751:                getInputPane().requestFocus();
0752:
0753:                // Restore the content type if auto-selection occured
0754:                if (previouslySelectedContentType != null) {
0755:                    setInputContentType(previouslySelectedContentType, true,
0756:                            false);
0757:                    previouslySelectedContentType = null;
0758:                }
0759:            }
0760:
0761:            private String replaceAll(String origStr, String targetStr,
0762:                    String replacedStr) {
0763:                StringBuffer sb = new StringBuffer(origStr);
0764:                int idx;
0765:                while ((idx = sb.indexOf(targetStr)) != -1) {
0766:                    sb.replace(idx, idx + targetStr.length(), replacedStr);
0767:                }
0768:                return sb.toString();
0769:            }
0770:
0771:            private boolean strContains(String str, String pattern) {
0772:                return str.indexOf(pattern) != -1;
0773:            }
0774:
0775:            /**
0776:             *
0777:             *
0778:             */
0779:            public void appendMessage(CollabMessage message) {
0780:                try {
0781:                    // Convert message to HTML
0782:                    String html = convertToHtml(message);
0783:
0784:                    // fixme: pattern ") is first expanded to &quot;) which will then find a smile there.
0785:                    // Replace smiles only in plain text
0786:                    String contentType = message
0787:                            .getHeader(ChatCollablet.DISPLAY_CONTENT_TYPE_HEADER);
0788:                    if ((contentType == null)
0789:                            || contentType.equals(ContentTypes.UNKNOWN_TEXT)) {
0790:                        for (int i = 0; i < smiles.length; i++) {
0791:                            if (strContains(html, smiles[i][0])) {
0792:                                URL smileUrl = ChatComponent.class
0793:                                        .getResource("resources/emoticons/"
0794:                                                + smiles[i][1]);
0795:                                String tag = "<img align=\"center\" src="
0796:                                        + smileUrl + "></img>";
0797:                                html = replaceAll(html, smiles[i][0], tag);
0798:                            }
0799:                        }
0800:                    }
0801:
0802:                    // Insert the message text before the start of the epilogue
0803:                    HTMLDocument document = (HTMLDocument) getTranscriptPane()
0804:                            .getDocument();
0805:                    document.insertBeforeStart(getEndElement(), html);
0806:
0807:                    //Debug.out.println("Appended:\n"+html);
0808:                    // Scroll to bottom of document
0809:                    SwingUtilities.invokeLater(new Runnable() {
0810:                        public void run() {
0811:                            scrollToLastMessage();
0812:                        }
0813:                    });
0814:                } catch (Exception e) {
0815:                    // TODO: Do something appropriate here
0816:                    Debug.errorManager.notify(e);
0817:                }
0818:            }
0819:
0820:            /**
0821:             *
0822:             *
0823:             */
0824:            public void appendSystemMessage(String message) {
0825:                try {
0826:                    String content = SyntaxColoring.convertToHTML(message,
0827:                            ContentTypes.TEXT);
0828:
0829:                    String html = getSystemMessageTemplate();
0830:                    html = StringTokenizer2.replace(html, TOKEN_MESSAGE_CLASS,
0831:                            MESSAGE_CLASS_SYSTEM);
0832:                    html = StringTokenizer2.replace(html, TOKEN_TIMESTAMP,
0833:                            SimpleDateFormat.getTimeInstance().format(
0834:                                    new Date()));
0835:                    html = StringTokenizer2.replace(html, TOKEN_MESSAGE,
0836:                            content);
0837:
0838:                    // Insert the message text before the start of the
0839:                    // epilogue
0840:                    HTMLDocument document = (HTMLDocument) getTranscriptPane()
0841:                            .getDocument();
0842:                    document.insertBeforeStart(getEndElement(), html);
0843:
0844:                    // Scroll to bottom of document
0845:                    SwingUtilities.invokeLater(new Runnable() {
0846:                        public void run() {
0847:                            scrollToLastMessage();
0848:                        }
0849:                    });
0850:                } catch (Exception e) {
0851:                    // TODO: Do something appropriate here
0852:                    Debug.errorManager.notify(e);
0853:                }
0854:            }
0855:
0856:            /**
0857:             *
0858:             *
0859:             */
0860:            public void scrollToLastMessage() {
0861:                try {
0862:                    // Find the parent of the end element
0863:                    Element parentElement = getEndElement().getParentElement();
0864:
0865:                    // Figure out the last element in the parent container (besides
0866:                    // the end element)
0867:                    Element lastElement = parentElement
0868:                            .getElement(parentElement.getElementCount() - 2);
0869:
0870:                    // Get the element rectangle
0871:                    Rectangle rect = getTranscriptPane().modelToView(
0872:                            lastElement.getStartOffset());
0873:
0874:                    if (rect != null) {
0875:                        // Make the height of the element rectangle the same as
0876:                        // the visible size of the component
0877:                        Rectangle visRect = getTranscriptPane()
0878:                                .getVisibleRect();
0879:                        rect.height = visRect.height;
0880:
0881:                        // Scroll to the last element
0882:                        getTranscriptPane().scrollRectToVisible(rect);
0883:                    }
0884:                } catch (Exception e) {
0885:                    Debug.debugNotify(e);
0886:                }
0887:            }
0888:
0889:            ////////////////////////////////////////////////////////////////////////////
0890:            // Formatting methods
0891:            ////////////////////////////////////////////////////////////////////////////
0892:
0893:            /**
0894:             * Returns the element before which new messages should be inserted
0895:             *
0896:             */
0897:            protected Element getEndElement() {
0898:                return endElement;
0899:            }
0900:
0901:            /**
0902:             * Returns the message template string
0903:             *
0904:             */
0905:            protected String getMessageTemplate() {
0906:                return messageTemplate;
0907:            }
0908:
0909:            /**
0910:             * Returns the message template string
0911:             *
0912:             */
0913:            protected String getChatMessageTemplate() {
0914:                return chatMessageTemplate;
0915:            }
0916:
0917:            /**
0918:             * Returns the system message template string
0919:             *
0920:             */
0921:            protected String getSystemMessageTemplate() {
0922:                return systemMessageTemplate;
0923:            }
0924:
0925:            /**
0926:             *
0927:             *
0928:             */
0929:            private Map getSenderStyles() {
0930:                return senderStyles;
0931:            }
0932:
0933:            /**
0934:             *
0935:             *
0936:             */
0937:            protected String convertToHtml(CollabMessage message) {
0938:                String content = null;
0939:                String plainContent = null;
0940:                String messageClass = null;
0941:
0942:                String contentType = message
0943:                        .getHeader(ChatCollablet.DISPLAY_CONTENT_TYPE_HEADER);
0944:
0945:                try {
0946:                    content = message.getContent();
0947:                    assert content != null : "Content was null";
0948:                    plainContent = content;
0949:
0950:                    if ((contentType == null)
0951:                            || contentType.equals(ContentTypes.UNKNOWN_TEXT)) {
0952:                        // Trim the content, with the assumption it is coming from
0953:                        // a plain IM client
0954:                        content = SyntaxColoring.convertToHTML(content.trim(),
0955:                                ContentTypes.UNKNOWN_TEXT);
0956:                        messageClass = MESSAGE_CLASS_CHAT;
0957:                        contentType = ContentTypes.UNKNOWN_TEXT;
0958:
0959:                        // Escape any hyperlinks
0960:                        content = replaceHyperlinks(content);
0961:                    } else if (contentType.equals(ContentTypes.HTML)) {
0962:                        content = SyntaxColoring.convertToHTML(content,
0963:                                ContentTypes.HTML);
0964:                        messageClass = MESSAGE_CLASS_HTML;
0965:
0966:                        // Escape any hyperlinks
0967:                        content = replaceHyperlinks(content);
0968:                    } else if (contentType.equals(ContentTypes.XML)) {
0969:                        content = SyntaxColoring.convertToHTML(content,
0970:                                ContentTypes.XML);
0971:                        messageClass = MESSAGE_CLASS_XML;
0972:
0973:                        // Escape any hyperlinks
0974:                        content = replaceHyperlinks(content);
0975:                    } else if (contentType.equals(ContentTypes.JAVA)) {
0976:                        content = SyntaxColoring.convertToHTML(content,
0977:                                ContentTypes.JAVA);
0978:                        messageClass = MESSAGE_CLASS_JAVA;
0979:                    } else {
0980:                        content = SyntaxColoring.convertToHTML(content,
0981:                                ContentTypes.TEXT);
0982:                        messageClass = MESSAGE_CLASS_TEXT;
0983:
0984:                        // Escape any hyperlinks
0985:                        content = replaceHyperlinks(content);
0986:                    }
0987:                } catch (CollabException e) {
0988:                    // TODO: Proper error handling here
0989:                    content = e.getMessage();
0990:                    Debug.debugNotify(e);
0991:                }
0992:
0993:                // Determine the style for the sender, based on whether we've seen
0994:                // this sender before or not
0995:                String sender = message.getOriginator().getDisplayName();
0996:                String senderClass = DEFAULT_SENDER_CLASS;
0997:
0998:                if (getSenderStyles().containsKey(sender)) {
0999:                    senderClass = (String) getSenderStyles().get(sender);
1000:                } else {
1001:                    // Allocate a new sender style.  Styles for senders are embedded
1002:                    // in the document and referenced numerically from here.
1003:                    if ((++lastSenderStyleIndex) <= MAX_SENDER_CLASSES) {
1004:                        senderClass = allocateNewSenderStyleClass(sender);
1005:                    } else {
1006:                        // Do nothing, leave as default
1007:                    }
1008:                }
1009:
1010:                // Fill in the message template.  Use the chat template if the content
1011:                // type is simple/unknown text.
1012:                String result = (contentType == ContentTypes.UNKNOWN_TEXT) ? getChatMessageTemplate()
1013:                        : getMessageTemplate();
1014:
1015:                //		String result=getMessageTemplate();
1016:                result = StringTokenizer2.replace(result, TOKEN_SENDER_CLASS,
1017:                        senderClass);
1018:                result = StringTokenizer2.replace(result, TOKEN_MESSAGE_CLASS,
1019:                        messageClass);
1020:                result = StringTokenizer2.replace(result, TOKEN_SENDER, sender);
1021:                result = StringTokenizer2.replace(result, TOKEN_MESSAGE,
1022:                        content);
1023:                result = StringTokenizer2.replace(result, TOKEN_MESSAGE_TEXT,
1024:                        plainContent);
1025:                result = StringTokenizer2.replace(result, TOKEN_TIMESTAMP,
1026:                        SimpleDateFormat.getTimeInstance().format(new Date()));
1027:                result = StringTokenizer2.replace(result, TOKEN_CONTENT_TYPE,
1028:                        contentType);
1029:
1030:                return result;
1031:            }
1032:
1033:            /**
1034:             *
1035:             *
1036:             */
1037:            private String replaceHyperlinks(String content) {
1038:                String originalContent = content;
1039:
1040:                try {
1041:                    int index = content.indexOf("http://"); // NOI18N
1042:
1043:                    while (index != -1) {
1044:                        int startIndex = index;
1045:                        int endIndex = startIndex;
1046:
1047:                        // Find the end of the URL
1048:                        LOOP: for (; endIndex < content.length(); endIndex++) {
1049:                            switch (content.charAt(endIndex)) {
1050:                            case ',':
1051:                            case '\'':
1052:                            case '!':
1053:                            case ' ':
1054:                            case '\r':
1055:                            case '\n':
1056:                            case '\t':
1057:                                break LOOP;
1058:
1059:                            case '&': // Check for entities
1060:
1061:                                if (content.startsWith("&quot;", endIndex) || // NOI18N
1062:                                        content.startsWith("&lt;", endIndex) || // NOI18N
1063:                                        content.startsWith("&gt;", endIndex) || // NOI18N
1064:                                        content.startsWith("&nbsp;", endIndex)) // NOI18N
1065:                                {
1066:                                    break LOOP;
1067:                                }
1068:
1069:                            default:
1070:
1071:                                continue;
1072:                            }
1073:                        }
1074:
1075:                        String link = content.substring(startIndex, endIndex);
1076:
1077:                        // Strip any trailing periods
1078:                        if (link.lastIndexOf(".") == (link.length() - 1)) // NOI18N
1079:                        {
1080:                            link = link.substring(0, link.length() - 1);
1081:                            endIndex--;
1082:                        }
1083:
1084:                        try {
1085:                            java.net.URL url = new java.net.URL(link);
1086:
1087:                            // If we got here, the link is valid
1088:                            link = "<a href='" + link + "'>" + link + "</a>"; // NOI18N
1089:                            index += link.length();
1090:
1091:                            // Replace the link with the HTML markup
1092:                            StringBuffer buffer = new StringBuffer(content);
1093:                            buffer.replace(startIndex, endIndex, link);
1094:                            content = buffer.toString();
1095:                        } catch (Exception e) {
1096:                            // Ignore this link
1097:                        }
1098:
1099:                        index = content.indexOf("http://", index); // NOI18N
1100:                    }
1101:
1102:                    return content;
1103:                } catch (Exception e) {
1104:                    Debug.debugNotify(e);
1105:
1106:                    return originalContent;
1107:                }
1108:            }
1109:
1110:            /**
1111:             *
1112:             *
1113:             */
1114:            private String allocateNewSenderStyleClass(String sender) {
1115:                String senderClass = "sender" + lastSenderStyleIndex; // NOI18N
1116:                getSenderStyles().put(sender, senderClass);
1117:
1118:                return senderClass;
1119:            }
1120:
1121:            /**
1122:             * send user typing status to participants
1123:             *
1124:             */
1125:            private void sendTypingStatus(boolean typing) {
1126:                try {
1127:                    CollabMessage message = getChannel().getConversation()
1128:                            .createMessage();
1129:
1130:                    int status = typing ? CollabMessage.TYPING_ON
1131:                            : CollabMessage.TYPING_OFF;
1132:                    message.sendStatus(status);
1133:                } catch (CollabException e) {
1134:                    Debug.errorManager.notify(e);
1135:                }
1136:            }
1137:
1138:            /**
1139:             *
1140:             *
1141:             */
1142:            public void updateStatusMessage(CollabPrincipal principal,
1143:                    boolean typing) {
1144:                // Effectively, we manage a reference count for the set of principals
1145:                // currently typing
1146:                if (typing) {
1147:                    if (!typingParticipants.contains(principal)) {
1148:                        typingParticipants.add(principal);
1149:                    }
1150:                } else {
1151:                    typingParticipants.remove(principal);
1152:                }
1153:
1154:                // Determine what text to show
1155:                String text = "";
1156:
1157:                if (typingParticipants.size() == 1) {
1158:                    // Single user, show their name
1159:                    CollabPrincipal participant = (CollabPrincipal) typingParticipants
1160:                            .iterator().next();
1161:                    text = " "
1162:                            + NbBundle.getMessage(ChatComponent.class,
1163:                                    "LBL_ChatComponent_USER_TYPING", // NOI18N
1164:                                    participant.getDisplayName());
1165:                } else if (typingParticipants.size() > 1) {
1166:                    // Multiple users, show general message
1167:                    text = " "
1168:                            + NbBundle.getMessage(ChatComponent.class,
1169:                                    "LBL_ChatComponent_SERVERAL_USERS_TYPING"); // NOI18N
1170:                }
1171:
1172:                typingMessageLabel.setText(text);
1173:            }
1174:
1175:            /**
1176:             *
1177:             *
1178:             */
1179:            private javax.swing.Timer getTypingTimer() {
1180:                return typingTimer;
1181:            }
1182:
1183:            ////////////////////////////////////////////////////////////////////////////
1184:            // Inner class
1185:            ////////////////////////////////////////////////////////////////////////////
1186:
1187:            /**
1188:             *
1189:             *
1190:             */
1191:            public void hyperlinkUpdate(HyperlinkEvent event) {
1192:                if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
1193:                    try {
1194:                        java.net.URL url = event.getURL();
1195:                        HtmlBrowser.URLDisplayer.getDefault().showURL(url);
1196:                    } catch (Exception e) {
1197:                        // Ignore
1198:                        Debug.debugNotify(e);
1199:                    }
1200:                }
1201:            }
1202:
1203:            /*Creates the popup menu
1204:             *author Smitha Krishna Nagesh
1205:             */
1206:            private void createPopupMenu() {
1207:                JMenuItem menuItem;
1208:                popupMenu = new JPopupMenu();
1209:
1210:                menuItem = new JMenuItem(new DefaultEditorKit.CopyAction());
1211:                menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,
1212:                        KeyEvent.CTRL_DOWN_MASK, false));
1213:                menuItem.setText("Copy");
1214:                popupMenu.add(menuItem);
1215:                popupMenu.addSeparator();
1216:
1217:                menuItem = new JMenuItem("Save");
1218:                popupMenu.add(menuItem);
1219:                menuItem.addActionListener(new FileChooserActionListener());
1220:                menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
1221:                        KeyEvent.CTRL_DOWN_MASK, false));
1222:
1223:                MouseListener popupListener = new PopupListener();
1224:                transcriptPane.addMouseListener(popupListener);
1225:            }
1226:
1227:            /*author Smitha Krishna Nagesh*/
1228:            protected class SmileListener implements  ActionListener {
1229:                public void actionPerformed(ActionEvent event) {
1230:                    newMenu.show(smileyButton, 10, 10);
1231:                    inputPane.grabFocus();
1232:                }
1233:            }
1234:
1235:            /*author Smitha Krishna Nagesh*/
1236:            protected class ButtonClickedListener implements  ActionListener {
1237:                public void actionPerformed(ActionEvent menuEvent) {
1238:                    JButton button = (JButton) menuEvent.getSource();
1239:                    String str = button.getActionCommand();
1240:
1241:                    try {
1242:                        int caretPos = inputPane.getCaretPosition();
1243:                        inputPane.getDocument().insertString(caretPos, str,
1244:                                null);
1245:                        inputPane.setCaretPosition(caretPos + str.length());
1246:                        newMenu.setVisible(false);
1247:                    } catch (Exception e) {
1248:                        ErrorManager.getDefault().notify(e);
1249:                    }
1250:                }
1251:            }
1252:
1253:            ////////////////////////////////////////////////////////////////////////////
1254:            // Inner class
1255:            ////////////////////////////////////////////////////////////////////////////
1256:
1257:            /**
1258:             *
1259:             *
1260:             */
1261:            protected class ChatHTMLFactory extends HTMLEditorKit.HTMLFactory {
1262:                /**
1263:                 *
1264:                 *
1265:                 */
1266:                public View create(Element element) {
1267:                    // Unfortunately, the Swing HTML parser doesn't respect the
1268:                    // display: none style, so we no-op the rendering of the message
1269:                    // template element here.
1270:                    if (element.getAttributes().isDefined(HTML.Attribute.ID)
1271:                            && element.getAttributes().getAttribute(
1272:                                    HTML.Attribute.ID).equals(
1273:                                    MESSAGE_TEMPLATE_ELEMENT_ID)) {
1274:                        return new BlockView(element, View.Y_AXIS) {
1275:                            public void paint(Graphics g, Shape allocation) {
1276:                                // Do nothing
1277:                            }
1278:                        };
1279:                    } else {
1280:                        return super .create(element);
1281:                    }
1282:                }
1283:            }
1284:
1285:            ////////////////////////////////////////////////////////////////////////////
1286:            // Inner class
1287:            ////////////////////////////////////////////////////////////////////////////
1288:
1289:            /**
1290:             *
1291:             *
1292:             */
1293:            protected class ConversationChangeListener extends Object implements 
1294:                    PropertyChangeListener {
1295:                /**
1296:                 *
1297:                 *
1298:                 */
1299:                public void propertyChange(PropertyChangeEvent event) {
1300:                    if (event.getPropertyName().equals(
1301:                            ChatCollablet.PROP_TRANSCRIPT)) {
1302:                        try {
1303:                            CollabMessage message = (CollabMessage) event
1304:                                    .getNewValue();
1305:                            appendMessage(message);
1306:                            CollabManager
1307:                                    .getDefault()
1308:                                    .getUserInterface()
1309:                                    .notifyConversationEvent(
1310:                                            ChatComponent.this .getChannel()
1311:                                                    .getConversation(),
1312:                                            UserInterface.NOTIFY_CHAT_MESSAGE_RECEIVED);
1313:                        } catch (Exception e) {
1314:                            // TODO: Do something appropriate here
1315:                            Debug.errorManager.notify(e);
1316:                        }
1317:                    } else if (event.getPropertyName().equals(
1318:                            Conversation.PROP_PARTICIPANTS)) {
1319:                        boolean joined = event.getNewValue() != null;
1320:                        CollabPrincipal principal = joined ? (CollabPrincipal) event
1321:                                .getNewValue()
1322:                                : (CollabPrincipal) event.getOldValue();
1323:
1324:                        try {
1325:                            String key = joined ? "MSG_ChatComponent_UserJoined" // NOI18N
1326:                                    : "MSG_ChatComponent_UserLeft"; // NOI18N
1327:
1328:                            String message = NbBundle.getMessage(
1329:                                    ChatComponent.class, key, principal
1330:                                            .getDisplayName(), SimpleDateFormat
1331:                                            .getTimeInstance().format(
1332:                                                    new Date()));
1333:                            appendSystemMessage(message);
1334:                        } catch (Exception e) {
1335:                            // TODO: Do something appropriate here
1336:                            Debug.errorManager.notify(e);
1337:                        }
1338:                    } else if (event.getPropertyName().equals(
1339:                            Conversation.USER_TYPING_ON)) {
1340:                        CollabPrincipal principal = (CollabPrincipal) event
1341:                                .getNewValue();
1342:                        updateStatusMessage(principal, true);
1343:                    } else if (event.getPropertyName().equals(
1344:                            Conversation.USER_TYPING_OFF)) {
1345:                        CollabPrincipal principal = (CollabPrincipal) event
1346:                                .getNewValue();
1347:                        updateStatusMessage(principal, false);
1348:                    }
1349:                }
1350:            }
1351:
1352:            ////////////////////////////////////////////////////////////////////////////
1353:            // Inner class
1354:            ////////////////////////////////////////////////////////////////////////////
1355:
1356:            /**
1357:             *
1358:             *
1359:             */
1360:            private class ContentTypeActionListener extends Object implements 
1361:                    ActionListener {
1362:                public void actionPerformed(ActionEvent event) {
1363:                    // This will be invoked only when the user selects the button.
1364:                    // If the user explicitly selects a button, cancel the previous
1365:                    // selection
1366:                    JToggleButton source = (JToggleButton) event.getSource();
1367:                    String type = (String) source
1368:                            .getClientProperty("contentType"); //NOI18N 
1369:                    smileyButton.setEnabled(type
1370:                            .equals(ContentTypes.UNKNOWN_TEXT));
1371:
1372:                    previouslySelectedContentType = null;
1373:
1374:                    setInputContentType(type, false, false);
1375:                }
1376:            }
1377:
1378:            ////////////////////////////////////////////////////////////////////////////
1379:            // Inner class
1380:            ////////////////////////////////////////////////////////////////////////////
1381:
1382:            /**
1383:             * This part of the code has been changed inorder to suit the needs of the dynamic addition of the button
1384:             *
1385:             */
1386:            protected class ContentTypeSynchronizer extends Object implements 
1387:                    Runnable {
1388:                /**
1389:                 *
1390:                 *
1391:                 */
1392:                public void run() {
1393:                    JToggleButton button = (JToggleButton) contentTypeToButton
1394:                            .get(inputContentType);
1395:                    button.setSelected(true);
1396:                }
1397:            }
1398:
1399:            ////////////////////////////////////////////////////////////////////////////
1400:            // Inner class
1401:            ////////////////////////////////////////////////////////////////////////////
1402:
1403:            /**
1404:             *
1405:             *
1406:             */
1407:            protected class TypingTimerActionListener extends AbstractAction
1408:                    implements  ActionListener {
1409:                /**
1410:                 *
1411:                 *
1412:                 */
1413:                public void actionPerformed(ActionEvent event) {
1414:                    getTypingTimer().stop();
1415:                    sendTypingStatus(false);
1416:                }
1417:            }
1418:
1419:            ////////////////////////////////////////////////////////////////////////////
1420:            // Inner class
1421:            ////////////////////////////////////////////////////////////////////////////
1422:
1423:            /**
1424:             *
1425:             *
1426:             */
1427:            protected class InputPaneDocumentListener implements 
1428:                    DocumentListener, PropertyChangeListener {
1429:                private Document oldDoc;
1430:
1431:                public InputPaneDocumentListener() {
1432:                    getInputPane().addPropertyChangeListener(this );
1433:                    updateDocument();
1434:                }
1435:
1436:                public void updateTimer() {
1437:                    if (getTypingTimer() != null) {
1438:                        if (getTypingTimer().isRunning()) {
1439:                            getTypingTimer().restart();
1440:                        } else {
1441:                            if (getInputPane().getDocument().getLength() > 0) {
1442:                                getTypingTimer().start();
1443:                                sendTypingStatus(true);
1444:                            }
1445:                        }
1446:                    }
1447:                }
1448:
1449:                public void changedUpdate(DocumentEvent e) {
1450:                    updateTimer();
1451:                }
1452:
1453:                public void insertUpdate(DocumentEvent e) {
1454:                    updateTimer();
1455:                }
1456:
1457:                public void removeUpdate(DocumentEvent e) {
1458:                    updateTimer();
1459:                }
1460:
1461:                public void propertyChange(PropertyChangeEvent evt) {
1462:                    if (evt.getPropertyName().equals("document")) {
1463:                        updateDocument();
1464:                    }
1465:                }
1466:
1467:                private void updateDocument() {
1468:                    if (oldDoc != null)
1469:                        oldDoc.removeDocumentListener(this );
1470:                    oldDoc = getInputPane().getDocument();
1471:                    oldDoc.addDocumentListener(this );
1472:                }
1473:            }
1474:
1475:            ////////////////////////////////////////////////////////////////////////////
1476:            // Inner class
1477:            ////////////////////////////////////////////////////////////////////////////
1478:
1479:            /**
1480:             *
1481:             *
1482:             */
1483:            protected class SendButtonActionListener extends AbstractAction
1484:                    implements  ActionListener {
1485:                /**
1486:                 *
1487:                 *
1488:                 */
1489:                public void actionPerformed(ActionEvent event) {
1490:                    getTypingTimer().stop();
1491:                    sendTypingStatus(false);
1492:
1493:                    sendInput();
1494:                }
1495:            }
1496:
1497:            ////////////////////////////////////////////////////////////////////////////
1498:            // Inner class
1499:            ////////////////////////////////////////////////////////////////////////////
1500:
1501:            /**
1502:             * HACK: This class implements a proxy pattern in order to allow us to
1503:             * "sniff" pasted content.  Unfortunately, because TransferHandler has
1504:             * protected methods, it requires us to use AccessibleObject to invoke
1505:             * certain methods.
1506:             *
1507:             */
1508:            public class InputPaneTransferHandler extends TransferHandler {
1509:                private TransferHandler delegate;
1510:
1511:                /**
1512:                 *
1513:                 *
1514:                 */
1515:                public InputPaneTransferHandler(TransferHandler delegate) {
1516:                    super ();
1517:                    this .delegate = delegate;
1518:                }
1519:
1520:                /**
1521:                 *
1522:                 *
1523:                 */
1524:                public boolean canImport(JComponent comp,
1525:                        DataFlavor[] transferFlavors) {
1526:                    return delegate.canImport(comp, transferFlavors);
1527:                }
1528:
1529:                /**
1530:                 *
1531:                 *
1532:                 */
1533:                protected Transferable createTransferable(JComponent c) {
1534:                    Method method = null;
1535:
1536:                    try {
1537:                        method = getClass().getMethod("createTransferable", // NOI18N
1538:                                new Class[] { JComponent.class });
1539:                        method.setAccessible(true);
1540:                    } catch (Exception e) {
1541:                        Debug.debugNotify(e);
1542:
1543:                        // Cannot happen
1544:                        assert false : e.getMessage();
1545:                    }
1546:
1547:                    try {
1548:                        return (Transferable) method.invoke(delegate,
1549:                                new Object[] { c });
1550:                    } catch (Exception e) {
1551:                        // Shouldn't happen
1552:                        Debug.debugNotify(e);
1553:                    }
1554:
1555:                    // Fallback, just in case
1556:                    return super .createTransferable(c);
1557:                }
1558:
1559:                /**
1560:                 *
1561:                 *
1562:                 */
1563:                public void exportAsDrag(JComponent comp, InputEvent e,
1564:                        int action) {
1565:                    delegate.exportAsDrag(comp, e, action);
1566:                }
1567:
1568:                /**
1569:                 *
1570:                 *
1571:                 */
1572:                protected void exportDone(JComponent source, Transferable data,
1573:                        int action) {
1574:                    Method method = null;
1575:
1576:                    try {
1577:                        method = getClass().getMethod(
1578:                                "exportDone", // NOI18N
1579:                                new Class[] { JComponent.class,
1580:                                        Transferable.class, Integer.TYPE });
1581:                        method.setAccessible(true);
1582:                    } catch (Exception e) {
1583:                        Debug.debugNotify(e);
1584:
1585:                        // Cannot happen
1586:                        assert false : e.getMessage();
1587:                    }
1588:
1589:                    try {
1590:                        method.invoke(delegate, new Object[] { source, data,
1591:                                new Integer(action) });
1592:                    } catch (Exception e) {
1593:                        // Shouldn't happen
1594:                        Debug.debugNotify(e);
1595:
1596:                        // Fallback, just in case
1597:                        super .exportDone(source, data, action);
1598:                    }
1599:                }
1600:
1601:                /**
1602:                 *
1603:                 *
1604:                 */
1605:                public void exportToClipboard(JComponent comp, Clipboard clip,
1606:                        int action) {
1607:                    delegate.exportToClipboard(comp, clip, action);
1608:                }
1609:
1610:                /**
1611:                 *
1612:                 *
1613:                 */
1614:                public int getSourceActions(JComponent c) {
1615:                    return delegate.getSourceActions(c);
1616:                }
1617:
1618:                /**
1619:                 *
1620:                 *
1621:                 */
1622:                public Icon getVisualRepresentation(Transferable t) {
1623:                    return delegate.getVisualRepresentation(t);
1624:                }
1625:
1626:                /**
1627:                 *
1628:                 *
1629:                 */
1630:                public boolean importData(JComponent component,
1631:                        Transferable transferable) {
1632:                    String content = getInputPane().getText();
1633:
1634:                    // Go ahead and import the data
1635:                    boolean result = delegate.importData(component,
1636:                            transferable);
1637:
1638:                    if (result
1639:                            && ((content == null) || (content.length() == 0))) {
1640:                        // Figure out what the best representation of the just-imported
1641:                        // data is, and set the current input content type accordingly
1642:                        DataFlavor[] flavors = transferable
1643:                                .getTransferDataFlavors();
1644:                        DataFlavor flavor = null;
1645:
1646:                        if ((flavor = containsContentType(flavors,
1647:                                ContentTypes.JAVA)) != null) {
1648:                            autoselectContentType(ContentTypes.JAVA);
1649:                        } else if ((flavor = containsContentType(flavors,
1650:                                ContentTypes.XML)) != null) {
1651:                            autoselectContentType(ContentTypes.XML);
1652:                        } else if ((flavor = containsContentType(flavors,
1653:                                ContentTypes.HTML)) != null) {
1654:                            // See if this is actually HTML or just plain text encoded
1655:                            // as HTML
1656:                            String htmlText = getContent(transferable, flavor);
1657:                            String plainText = getContent(transferable,
1658:                                    containsContentType(flavors,
1659:                                            ContentTypes.TEXT));
1660:
1661:                            if ((htmlText != null) && (plainText != null)) {
1662:                                if (htmlText.equals(plainText)) {
1663:                                    // This is actually HTML
1664:                                    autoselectContentType(ContentTypes.HTML);
1665:                                } else {
1666:                                    // This is actually just plain text encoded as HTML
1667:                                    setTextContentTypeConditionally();
1668:                                }
1669:                            } else {
1670:                                // If the HTML string was here, it's definitely HTML.
1671:                                // I don't know that this condition is actually ever
1672:                                // possible in any case; I think in all cases where
1673:                                // text/html is available, text/plain will also be
1674:                                // available.
1675:                                if (htmlText != null) {
1676:                                    autoselectContentType(ContentTypes.HTML);
1677:                                } else {
1678:                                    setTextContentTypeConditionally();
1679:                                }
1680:                            }
1681:                        } else if ((flavor = containsContentType(flavors,
1682:                                ContentTypes.TEXT)) != null) {
1683:                            setTextContentTypeConditionally();
1684:                        } else {
1685:                            // Do nothing
1686:                        }
1687:                    }
1688:
1689:                    return result;
1690:                }
1691:
1692:                /**
1693:                 *
1694:                 *
1695:                 */
1696:                private String getContent(Transferable transferable,
1697:                        DataFlavor flavor) {
1698:                    if (flavor == null) {
1699:                        return null;
1700:                    }
1701:
1702:                    // Get the data so we can look at it
1703:                    Object data = null;
1704:                    String dataString = null;
1705:
1706:                    try {
1707:                        data = transferable.getTransferData(flavor);
1708:                    } catch (Exception e) {
1709:                        Debug.debugNotify(e);
1710:                        autoselectContentType(ContentTypes.HTML);
1711:                    }
1712:
1713:                    if (data != null) {
1714:                        // Convert to a String
1715:                        if (data instanceof  String) {
1716:                            dataString = (String) data;
1717:                        } else if (data instanceof  Reader) {
1718:                            try {
1719:                                BufferedReader reader = new BufferedReader(
1720:                                        (Reader) data);
1721:                                StringBuffer buffer = new StringBuffer();
1722:                                String line = null;
1723:
1724:                                while ((line = reader.readLine()) != null)
1725:                                    buffer.append(line).append("\n"); // NOI18N
1726:
1727:                                dataString = buffer.toString();
1728:                            } catch (Exception e) {
1729:                                Debug.debugNotify(e);
1730:                            }
1731:                        } else if (data instanceof  InputStream) {
1732:                            try {
1733:                                String charset = flavor.getParameter("charset");
1734:                                BufferedReader reader = null;
1735:
1736:                                if (charset != null) {
1737:                                    reader = new BufferedReader(
1738:                                            new InputStreamReader(
1739:                                                    (InputStream) data, charset));
1740:                                } else {
1741:                                    reader = new BufferedReader(
1742:                                            new InputStreamReader(
1743:                                                    (InputStream) data));
1744:                                }
1745:
1746:                                StringBuffer buffer = new StringBuffer();
1747:                                String line = null;
1748:
1749:                                while ((line = reader.readLine()) != null)
1750:                                    buffer.append(line).append("\n"); // NOI18N
1751:
1752:                                dataString = buffer.toString();
1753:                            } catch (Exception e) {
1754:                                Debug.debugNotify(e);
1755:                            }
1756:                        }
1757:                    }
1758:
1759:                    // We have to normalize line endings in order to compare strings
1760:                    // of different content types
1761:                    dataString = StringTokenizer2.replace(dataString, "\r\n",
1762:                            "\n");
1763:
1764:                    return dataString;
1765:                }
1766:
1767:                /**
1768:                 *
1769:                 *
1770:                 */
1771:                private void setTextContentTypeConditionally() {
1772:                    // If it's not already text, set it to text. Don't
1773:                    // distinguish between formatted and plain text
1774:                    if (!getInputContentType()
1775:                            .equals(ContentTypes.UNKNOWN_TEXT)
1776:                            && !getInputContentType().equals(ContentTypes.TEXT)) {
1777:                        autoselectContentType(ContentTypes.TEXT);
1778:                    }
1779:                }
1780:
1781:                /**
1782:                 *
1783:                 *
1784:                 */
1785:                private void autoselectContentType(String contentType) {
1786:                    setInputContentType(contentType, true, true);
1787:                }
1788:
1789:                /**
1790:                 *
1791:                 *
1792:                 */
1793:                public DataFlavor containsContentType(DataFlavor[] flavors,
1794:                        String contentType) {
1795:                    //			Debug.out.println("----------------------------");
1796:                    //			for (int i=0; i<flavors.length; i++)
1797:                    //				Debug.out.println(flavors[i].getMimeType());
1798:                    for (int i = 0; i < flavors.length; i++) {
1799:                        if (flavors[i].isMimeTypeEqual(contentType)) {
1800:                            return flavors[i];
1801:                        }
1802:                    }
1803:
1804:                    return null;
1805:                }
1806:            }
1807:
1808:            ////////////////////////////////////////////////////////////////////////////
1809:            // Inner class
1810:            ////////////////////////////////////////////////////////////////////////////
1811:
1812:            /* author Smitha Krishna Nagesh*/
1813:            protected class PopupListener extends MouseAdapter {
1814:                public void mousePressed(MouseEvent mouseEvt) {
1815:                    showPopup(mouseEvt);
1816:                }
1817:
1818:                public void mouseReleased(MouseEvent mouseEvt) {
1819:                    showPopup(mouseEvt);
1820:                }
1821:
1822:                private void showPopup(MouseEvent mouseEvt) {
1823:                    if (mouseEvt.isPopupTrigger()) {
1824:                        popupMenu.show(mouseEvt.getComponent(),
1825:                                mouseEvt.getX(), mouseEvt.getY());
1826:                    }
1827:                }
1828:            }
1829:
1830:            ////////////////////////////////////////////////////////////////////////////
1831:            // Inner class
1832:            ////////////////////////////////////////////////////////////////////////////
1833:
1834:            /* author Smitha Krishna Nagesh
1835:            Pops up a FileChooser to choose a directory to save the file.*/
1836:            protected class FileChooserActionListener implements  ActionListener {
1837:                JFileChooser chooseFile = new JFileChooser();
1838:
1839:                public void actionPerformed(ActionEvent saveEvt) {
1840:                    chooseFile
1841:                            .setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
1842:
1843:                    int returnVal = chooseFile.showSaveDialog(null);
1844:
1845:                    if (returnVal == JFileChooser.APPROVE_OPTION) {
1846:                        File file = chooseFile.getSelectedFile();
1847:
1848:                        if (file.exists()) {
1849:                            int option = JOptionPane.showOptionDialog(
1850:                                    null,
1851:                                    NbBundle.getMessage(ChatComponent.class,
1852:                                            "MSG_ChatComponent_FileChoosing"), //NOI18N
1853:                                    NbBundle.getMessage(ChatComponent.class,
1854:                                            "TITLE_Confirmation"), //NOI18N
1855:                                    JOptionPane.OK_CANCEL_OPTION,
1856:                                    JOptionPane.INFORMATION_MESSAGE, null,
1857:                                    null, null);
1858:
1859:                            if ((option == JOptionPane.CANCEL_OPTION)
1860:                                    || (option == JOptionPane.CLOSED_OPTION)) {
1861:                                return;
1862:                            }
1863:                        }
1864:
1865:                        String fileStr = file.toString();
1866:                        file = new File(fileStr);
1867:
1868:                        HTMLDocument document = (HTMLDocument) transcriptPane
1869:                                .getDocument();
1870:
1871:                        try {
1872:                            String string = document.getText(0, document
1873:                                    .getLength());
1874:                            FileWriter fileWriter = new FileWriter(file);
1875:                            fileWriter.write(string, 0, string.length());
1876:                            fileWriter.flush();
1877:                            fileWriter.close();
1878:                        } catch (Exception e) {
1879:                            e.printStackTrace();
1880:                        }
1881:                    }
1882:                }
1883:            }
1884:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.