KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > web > core > jsploader > ServletEditor


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.web.core.jsploader;
21
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.InputStreamReader JavaDoc;
25 import java.io.OutputStream JavaDoc;
26 import java.io.ObjectInput JavaDoc;
27 import java.io.ObjectInputStream JavaDoc;
28 import java.util.Date JavaDoc;
29 import java.beans.*;
30 import javax.swing.JEditorPane JavaDoc;
31 import javax.swing.text.BadLocationException JavaDoc;
32 import javax.swing.text.EditorKit JavaDoc;
33 import javax.swing.text.StyledDocument JavaDoc;
34 import javax.swing.text.Document JavaDoc;
35 import javax.swing.Timer JavaDoc;
36 import javax.swing.event.CaretListener JavaDoc;
37 import javax.swing.text.Caret JavaDoc;
38 import javax.swing.event.CaretEvent JavaDoc;
39
40 import org.openide.cookies.EditorCookie;
41 import org.openide.cookies.CloseCookie;
42 import org.openide.cookies.PrintCookie;
43 import org.openide.filesystems.FileObject;
44 import org.openide.filesystems.FileUtil;
45 import org.openide.loaders.DataObject;
46 import org.openide.loaders.MultiDataObject;
47 import org.openide.loaders.DataNode;
48 import org.openide.nodes.Node;
49 import org.openide.text.*;
50 import org.openide.windows.CloneableOpenSupport;
51 import org.openide.util.NbBundle;
52 import org.openide.util.actions.SystemAction;
53
54 import org.openide.filesystems.FileChangeAdapter;
55 import org.openide.filesystems.FileEvent;
56 import org.openide.util.WeakListeners;
57  
58 /** Editor for servlet files generated from JSP files. Main features:
59  * <ul>
60  * <li>All text is read-only (guarded) </li>
61  * <li>The editor can work on different files, reloads after recomplilation.</li>
62  * </ul>
63  *
64  * @author Petr Jiricka, Yury Kamen
65  */

66
67 public class ServletEditor extends CloneableEditorSupport
68     implements EditorCookie.Observable, CloseCookie, PrintCookie, PropertyChangeListener {
69
70     static final String JavaDoc ATTR_FILE_ENCODING = "Content-Encoding"; // NOI18N
71

72     /** Create a new Editor support for the given Java source.
73      * @param entry the (primary) file entry representing the Java source file
74      */

75     public ServletEditor(JspDataObject jspdo) {
76         super(new JspEnv(jspdo));
77         jspdo.addPropertyChangeListener(WeakListeners.propertyChange(this, jspdo));
78     }
79     
80     protected CloneableEditor createCloneableEditor () {
81         return new ServletEditorComponent (this);
82     }
83     
84     protected JspEnv jspEnv() {
85         return (JspEnv)env;
86     }
87     
88     /** Overriding the default loading from stream - need to look at encoding */
89     protected void loadFromStreamToKit (StyledDocument JavaDoc doc, InputStream JavaDoc stream, EditorKit JavaDoc kit) throws IOException JavaDoc, BadLocationException JavaDoc {
90         FileObject fo = getServlet().getPrimaryFile();
91         String JavaDoc encoding = (String JavaDoc) fo.getAttribute(ATTR_FILE_ENCODING); //NOI18N
92

93         if (encoding == null) {
94             encoding = "ISO-8859-1"; // NOI18N
95
}
96         InputStreamReader JavaDoc reader = new InputStreamReader JavaDoc(stream, encoding);
97         kit.read(reader, doc, 0);
98     }
99
100     protected JspServletDataObject getServlet() {
101         return jspEnv().getJspDataObject().getServletDataObject();
102     }
103
104     /** Constructs message that should be displayed when the data object
105     * is modified and is being closed.
106     *
107     * @return text to show to the user
108     */

109     protected String JavaDoc messageSave () {
110         return "";
111     }
112
113     /** Constructs message that should be used to name the editor component.
114     *
115     * @return name of the editor
116     */

117     protected String JavaDoc messageName () {
118         DataObject dobj = getServlet();
119         if (dobj == null) return "..."; // NOI18N
120
if (! dobj.isValid()) return ""; // NOI18N
121

122         if(DataNode.getShowFileExtensions()) {
123             return dobj.getPrimaryFile().getNameExt();
124         } else {
125             return dobj.getPrimaryFile().getName();
126         }
127     }
128     
129     /** Text to use as tooltip for component.
130     *
131     * @return text to show to the user
132     */

133     protected String JavaDoc messageToolTip () {
134         DataObject dobj = getServlet();
135         if (dobj != null) {
136              //update tooltip
137
return FileUtil.getFileDisplayName(dobj.getPrimaryFile());
138         }
139         else
140             return "..."; // NOI18N
141
}
142
143     /** Message to display when an object is being opened.
144     * @return the message or null if nothing should be displayed
145     */

146     protected String JavaDoc messageOpening () {
147         DataObject obj = getServlet();
148         if (obj == null)
149             return "";
150
151         return NbBundle.getMessage (ServletEditor.class , "CTL_ObjectOpen", // NOI18N
152
obj.getPrimaryFile().getNameExt(),
153             FileUtil.getFileDisplayName(obj.getPrimaryFile())
154         );
155     }
156     
157
158     /** Message to display when an object has been opened.
159     * @return the message or null if nothing should be displayed
160     */

161     protected String JavaDoc messageOpened () {
162         DataObject obj = getServlet();
163         if (obj == null)
164             return "";
165
166         return NbBundle.getMessage (ServletEditor.class, "CTL_ObjectOpened", // NOI18N
167
obj.getPrimaryFile().getNameExt(),
168             FileUtil.getFileDisplayName(obj.getPrimaryFile())
169         );
170     }
171
172     /** only accessibility method */
173     MultiDataObject.Entry getJavaEntry() {
174         return getServlet().getPrimaryEntry();
175     }
176
177     /** Let's the super method create the document and also annotates it
178      * with Title and StreamDescription properities.
179      *
180      * @param kit kit to user to create the document
181      * @return the document annotated by the properties
182      */

183     protected StyledDocument JavaDoc createStyledDocument(EditorKit JavaDoc kit) {
184         StyledDocument JavaDoc doc = super.createStyledDocument(kit);
185         
186         setDocumentProperties(doc);
187         
188         return doc;
189     }
190     
191     /** Sets the correct properties of the given StyledDocument
192      */

193     void setDocumentProperties(Document JavaDoc doc) {
194         DataObject obj = getServlet();
195         if (obj != null) {
196             //set document name property
197
doc.putProperty(javax.swing.text.Document.TitleProperty, obj.getPrimaryFile().getPath());
198             //set dataobject to stream desc property
199
doc.putProperty(javax.swing.text.Document.StreamDescriptionProperty, obj);
200         }
201     }
202     
203     public void propertyChange(PropertyChangeEvent evt) {
204         if (evt.getPropertyName().equals(JspDataObject.PROP_SERVLET_DATAOBJECT)) {
205             StyledDocument JavaDoc doc = getDocument();
206             if (doc != null) {
207                 setDocumentProperties(doc);
208             }
209         }
210     }
211
212     public static class ServletEditorComponent extends CloneableEditor {
213
214         static final int SELECTED_NODES_DELAY = 1000;//copied from the JavaEditor
215
Timer JavaDoc timerSelNodes;//copied from the JavaEditor
216
/** Listener on caret movements */
217         CaretListener JavaDoc caretListener; //copied from the JavaEditor
218
/** The last caret offset position. */
219         int lastCaretOffset = -1; //copied from the JavaEditor
220

221         /** For externalization. */
222         public ServletEditorComponent() {
223             super();
224         }
225
226         public ServletEditorComponent(ServletEditor support) {
227             super(support);
228             init();
229         }
230
231         protected void componentShowing() {
232             super.componentShowing(); // just this initializes the pane now
233
pane.setEditable(false);
234         }
235
236         public void readExternal(ObjectInput JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
237             super.readExternal(in);
238             init();
239         }
240
241         protected JEditorPane JavaDoc getPane() {
242             return pane;
243         }
244         
245         /*protected CloneableEditorSupport cloneableEditorSupport() {
246             return super.cloneableEditorSupport();
247         }*/

248
249         /** Called after creation of this object and after deexternalization. */
250         private void init() {
251             //set the pane read only
252
if ( null != getPane()) {
253                 getPane().setEditable(false);
254             }
255             //set the activated nodes
256
// setCorrectActivatedNodes();
257
//register a listener to set activated nodes after a change of the servlet
258
ServletEditor se = (ServletEditor)cloneableEditorSupport();
259             if (se != null) {
260                 se.jspEnv().addPropertyChangeListener(
261                     new PropertyChangeListener() {
262                         public void propertyChange(PropertyChangeEvent evt) {
263                             if (JspEnv.PROP_TIME.equals(evt.getPropertyName()))
264                                 initializeJavaNodes();
265                             ServletEditorComponent.this.updateName();
266                         }
267                     }
268                 );
269             }
270             initializeJavaNodes();
271         }
272         
273         /* This method is called when parent window of this component has focus,
274          * and this component is preferred one in it.
275          *
276          * copied from the JavaEditor
277         */

278         protected void componentActivated () {
279             pane.addCaretListener(caretListener);
280             super.componentActivated ();
281         }
282         
283         /** Selects element at the given position.
284          *
285          * copied from the JavaEditor
286          */

287         void selectElementsAtOffset(final int offset) {
288             ServletEditor se = (ServletEditor)cloneableEditorSupport();
289             if (se != null) {
290                 JspDataObject jspdo = se.jspEnv().getJspDataObject();
291                 if (javax.swing.SwingUtilities.isEventDispatchThread()) {
292                     setNodes(jspdo, offset);
293                 }
294                 else{
295                     javax.swing.SwingUtilities.invokeLater(new NodesThread(jspdo, offset));
296                 }
297             }
298         }
299         
300         private class NodesThread implements Runnable JavaDoc {
301             JspDataObject jspdo;
302             int offset;
303             
304             NodesThread (JspDataObject jspdo, int offset){
305                 this.jspdo = jspdo;
306                 this.offset = offset;
307             }
308             
309             public void run() {
310                 setNodes(jspdo, offset);
311             }
312         }
313         
314         private void setNodes (JspDataObject jspdo, final int offset){
315             JspServletDataObject servlet = jspdo.getServletDataObject();
316             if (servlet==null) {
317                     setActivatedNodes(new Node[] { jspdo.getNodeDelegate() });
318                     return;
319                 }
320             
321 //RETOUCHE
322
// SourceCookie.Editor seditor = (SourceCookie.Editor) servlet.getCookie(SourceCookie.Editor.class);
323
//
324
// org.openide.src.Element element = seditor.findElement(offset);
325
// org.openide.src.nodes.ElementNodeFactory factory = JavaDataObject.getExplorerFactory();
326
// Node n = null;
327
// if (element instanceof org.openide.src.MethodElement) {
328
// n = factory.createMethodNode((org.openide.src.MethodElement)element);
329
// }
330
// else if (element instanceof org.openide.src.ClassElement) {
331
// n = factory.createClassNode((org.openide.src.ClassElement)element);
332
// }
333
// else if (element instanceof org.openide.src.ConstructorElement) {
334
// n = factory.createConstructorNode((org.openide.src.ConstructorElement)element);
335
// }
336
// else if (element instanceof org.openide.src.FieldElement) {
337
// n = factory.createFieldNode((org.openide.src.FieldElement)element);
338
// }
339
// else if (element instanceof org.openide.src.InitializerElement) {
340
// n = factory.createInitializerNode((org.openide.src.InitializerElement)element);
341
// }
342
// else if (element instanceof org.openide.src.SourceElement) {
343
// n = servlet.getNodeDelegate();
344
// }
345
// setActivatedNodes((n != null) ? new Node[] { n } : new Node[] { jspdo.getNodeDelegate() });
346
}
347         
348         /** Obtain a support for this component
349          * copied from the JavaEditor
350          */

351         private void initializeJavaNodes() {
352             //This local is to keep javac 1.2 happy.
353
ServletEditor se = (ServletEditor)cloneableEditorSupport();
354             if (se != null) {
355                 timerSelNodes = new Timer JavaDoc(100, new java.awt.event.ActionListener JavaDoc() {
356                                               public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
357                                                   if (lastCaretOffset == -1 && pane != null) {
358                                                       Caret JavaDoc caret = pane.getCaret();
359                                                       if (caret != null)
360                                                         lastCaretOffset = caret.getDot();
361                                                   }
362                                                   selectElementsAtOffset(lastCaretOffset);
363                                               }
364                                           });
365                 timerSelNodes.setInitialDelay(100);
366                 timerSelNodes.setRepeats(false);
367                 timerSelNodes.restart();
368                 caretListener = new CaretListener JavaDoc() {
369                                     public void caretUpdate(CaretEvent JavaDoc e) {
370                                         restartTimerSelNodes(e.getDot());
371                                     }
372                                 };
373             }
374             if (lastCaretOffset == -1 && pane != null) {
375                 Caret JavaDoc caret = pane.getCaret();
376                 if (caret != null) lastCaretOffset = caret.getDot();
377             }
378             selectElementsAtOffset(lastCaretOffset);
379         }
380
381         /**
382          * Refreshes the activated node immediately. Provides system actions
383          * based on the node activated at the time of popu invoke.
384          *
385          *copied from the JavaEditor
386          */

387         public SystemAction[] getSystemActions() {
388             selectElementsAtOffset(lastCaretOffset);
389             timerSelNodes.stop();
390             return super.getSystemActions();
391         }
392         
393         /** Restart the timer which updates the selected nodes after the specified delay from
394          * last caret movement.
395          *
396          * copied from the JavaEditor
397         */

398         void restartTimerSelNodes(int pos) {
399             timerSelNodes.setInitialDelay(SELECTED_NODES_DELAY);
400             timerSelNodes.restart();
401             lastCaretOffset = pos;
402         }
403
404     } // JspServletEditorComponent
405

406     private static class JspEnv extends FileChangeAdapter implements CloneableEditorSupport.Env,
407         java.io.Serializable JavaDoc, PropertyChangeListener {
408             
409         private static final long serialVersionUID = -5748207023470614141L;
410         
411         /** JSP page for which we are displaying the servlets. */
412         protected JspDataObject jspdo;
413         
414         private DataObject servlet;
415         
416         /** support for firing of property changes
417         */

418         private transient PropertyChangeSupport propSupp;
419
420         public JspEnv(JspDataObject jspdo) {
421             this.jspdo = jspdo;
422             init();
423         }
424         
425         private DataObject getServlet() {
426             synchronized (jspdo) {
427                 DataObject newServlet = jspdo.getServletDataObject();
428                 if (servlet != newServlet) {
429                     if (servlet != null) {
430                         servlet.getPrimaryFile().removeFileChangeListener(this);
431                     }
432                     if (newServlet != null) {
433                         newServlet.getPrimaryFile().addFileChangeListener(this);
434                     }
435                     servlet = newServlet;
436                 }
437                 return servlet;
438             }
439         }
440         
441         private void readObject (ObjectInputStream JavaDoc ois)
442         throws IOException JavaDoc, ClassNotFoundException JavaDoc {
443             ois.defaultReadObject();
444             init();
445         }
446         
447         private void init() {
448             jspdo.addPropertyChangeListener(WeakListeners.propertyChange (this, jspdo));
449         }
450         
451         public JspDataObject getJspDataObject() {
452             return jspdo;
453         }
454         
455         public void propertyChange(PropertyChangeEvent ev) {
456             if (JspDataObject.PROP_SERVLET_DATAOBJECT.equals (ev.getPropertyName())) {
457                 DataObject servlet = getServlet();
458                 if (servlet == null) {
459                     firePropertyChange(PROP_VALID, Boolean.TRUE, Boolean.FALSE);
460                 }
461                 else {
462                     firePropertyChange(PROP_TIME, null, null);
463                 }
464             }
465             
466             firePropertyChange (
467                 ev.getPropertyName (),
468                 ev.getOldValue (),
469                 ev.getNewValue ()
470             );
471         }
472         
473         /** Fires property change.
474         * @param name the name of property that changed
475         * @param oldValue old value
476         * @param newValue new value
477         */

478         protected void firePropertyChange (String JavaDoc name, Object JavaDoc oldValue, Object JavaDoc newValue) {
479             prop ().firePropertyChange (name, oldValue, newValue);
480         }
481         
482         /** Lazy getter for change support.
483         */

484         private PropertyChangeSupport prop () {
485             if (propSupp == null) {
486                 synchronized (this) {
487                     if (propSupp == null) {
488                         propSupp = new PropertyChangeSupport (this);
489                     }
490                 }
491             }
492             return propSupp;
493         }
494         
495         /** Obtains the input stream.
496         * @exception IOException if an I/O error occures
497         */

498         public InputStream JavaDoc inputStream () throws IOException JavaDoc {
499             DataObject servlet = getServlet();
500             if (servlet != null)
501                 return servlet.getPrimaryFile().getInputStream();
502             else
503                 return null;
504         }
505
506         /** Obtains the output stream.
507         * @exception IOException if an I/O error occures
508         */

509         public OutputStream JavaDoc outputStream () throws IOException JavaDoc {
510             // this file is read only, don't need an input stream
511
return null;
512         }
513
514         /** The time when the data has been modified
515         */

516         public Date JavaDoc getTime () {
517             /*DataObject servlet = getServlet();
518             if (servlet != null)
519                 return servlet.getPrimaryFile().lastModified();
520             else*/

521                 return null;
522         }
523
524         /** Mime type of the document.
525         * @return the mime type to use for the document
526         */

527         public String JavaDoc getMimeType () {
528             return "text/x-java"; // NOI18N
529
}
530         /** Adds property listener.
531         */

532         public void addPropertyChangeListener (PropertyChangeListener l) {
533             prop ().addPropertyChangeListener (l);
534         }
535         /** Removes property listener.
536         */

537         public void removePropertyChangeListener (PropertyChangeListener l) {
538             prop ().removePropertyChangeListener (l);
539         }
540
541         /** Adds veto listener.
542         */

543         public void addVetoableChangeListener (VetoableChangeListener l) {
544         }
545         /** Removes veto listener.
546         */

547         public void removeVetoableChangeListener (VetoableChangeListener l) {
548         }
549
550         /** Test whether the support is in valid state or not.
551         * It could be invalid after deserialization when the object it
552         * referenced to does not exist anymore.
553         *
554         * @return true or false depending on its state
555         */

556         public boolean isValid () {
557             DataObject servlet = getServlet();
558             return (servlet != null);
559         }
560         /** Test whether the object is modified or not.
561         * @return true if the object is modified
562         */

563         public boolean isModified () {
564             return false;
565         }
566
567         /** Support for marking the environement modified.
568         * @exception IOException if the environment cannot be marked modified
569         * (for example when the file is readonly), when such exception
570         * is the support should discard all previous changes
571         */

572         public void markModified () throws java.io.IOException JavaDoc {
573             // do nothing
574
}
575
576         /** Reverse method that can be called to make the environment
577         * unmodified.
578         */

579         public void unmarkModified () {
580         }
581
582         /** Method that allows environment to find its
583         * cloneable open support.
584         */

585         public CloneableOpenSupport findCloneableOpenSupport () {
586             return (CloneableOpenSupport)jspdo.getServletEditor();
587         }
588         
589         // methods from FileChangeAdapter
590

591         /** Handles <code>FileObject</code> deletion event. */
592         public void fileDeleted(FileEvent fe) {
593             fe.getFile().removeFileChangeListener(this);
594             
595             jspdo.refreshPlugin(true);
596         }
597         
598         /** Fired when a file is changed.
599          * @param fe the event describing context where action has taken place
600          */

601         public void fileChanged(FileEvent fe) {
602             firePropertyChange(PROP_TIME, null, null);
603         }
604         
605         
606     }
607 }
608
Popular Tags