KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > websvc > wsdl > xmlutils > XMLJ2eeEditorSupport


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.websvc.wsdl.xmlutils;
21
22 import java.io.*;
23
24 import org.openide.cookies.*;
25 import org.openide.filesystems.FileLock;
26 import org.openide.filesystems.FileObject;
27 import org.openide.text.DataEditorSupport;
28 import org.openide.text.NbDocument;
29 import org.openide.windows.CloneableOpenSupport;
30
31 import javax.swing.event.*;
32 import javax.swing.text.*;
33 import org.openide.awt.UndoRedo;
34 import org.openide.util.RequestProcessor;
35 import org.openide.util.NbBundle;
36 import org.openide.DialogDisplayer;
37 import org.openide.NotifyDescriptor;
38
39 import org.netbeans.modules.xml.api.EncodingUtil;
40
41 /** Support for editing a XMLJ2eeDataObject as text.
42  *
43  * @author mkuchtiak
44  */

45
46 public class XMLJ2eeEditorSupport extends DataEditorSupport
47 implements EditCookie, EditorCookie.Observable,/* OpenCookie, */LineCookie, CloseCookie, PrintCookie {
48
49     /** Delay for automatic parsing - in miliseconds */
50     private static final int AUTO_PARSING_DELAY = 2000;
51     private org.openide.DialogDescriptor dialog;
52     private RequestProcessor.Task parsingDocumentTask;
53     XMLJ2eeDataObject dataObject;
54
55     /** Create a new editor support.
56      * @param obj the data object whose primary file will be edited as text
57      */

58     public XMLJ2eeEditorSupport(XMLJ2eeDataObject obj) {
59         super (obj, new XmlEnv (obj));
60         dataObject=obj;
61
62         // Set a MIME type as needed, e.g.:
63
setMIMEType ("text/xml"); // NOI18N
64

65         final DocumentListener docListener = new DocumentListener() {
66                 public void changedUpdate(javax.swing.event.DocumentEvent JavaDoc e) {
67                     doUpdate();
68                 }
69
70                 public void insertUpdate(javax.swing.event.DocumentEvent JavaDoc e) {
71                     doUpdate();
72                 }
73
74                 public void removeUpdate(javax.swing.event.DocumentEvent JavaDoc e) {
75                     doUpdate();
76                 }
77
78                 private void doUpdate() {
79                     if (!((XMLJ2eeDataObject)XMLJ2eeEditorSupport.this.getDataObject()).isNodeDirty())
80                         restartTimer();
81                 }
82             };
83             
84         // the listener is added when the document is loaded
85
addPropertyChangeListener(new java.beans.PropertyChangeListener JavaDoc() {
86             public void propertyChange(java.beans.PropertyChangeEvent JavaDoc evt) {
87                 if (EditorCookie.Observable.PROP_DOCUMENT.equals(evt.getPropertyName())
88                         && isDocumentLoaded() && getDocument() != null) {
89                     getDocument().addDocumentListener(docListener);
90                 }
91             }
92         });
93     }
94
95     /**
96      * Overridden method from CloneableEditorSupport.
97      */

98     protected void saveFromKitToStream (StyledDocument doc, EditorKit kit,
99                                             OutputStream stream)
100                     throws IOException, BadLocationException {
101         // kit and kit() are not accessible so we pretend
102
// to create the kit; actually this should just return kit.
103
EditorKit k = this.createEditorKit();
104         OutputStreamWriter osw = new OutputStreamWriter(stream, "UTF8"); // NOI18N
105
Writer writer = new BufferedWriter(osw);
106         k.write(writer, doc, 0, doc.getLength());
107         writer.close();
108     }
109
110     /**
111      * Overridden method from CloneableEditorSupport.
112      */

113     protected void loadFromStreamToKit (StyledDocument doc, InputStream stream,
114                                             EditorKit kit)
115                     throws IOException, BadLocationException {
116         // kit and kit() are not accessible so we pretend
117
// to create the kit; actually this should just return kit.
118
EditorKit k = this.createEditorKit();
119         InputStreamReader isr = new InputStreamReader(stream, "UTF8"); // NOI18N
120
Reader reader = new BufferedReader(isr);
121         k.read(reader, doc, 0);
122         reader.close();
123     }
124
125     /** Restart the timer which starts the parser after the specified delay.
126     * @param onlyIfRunning Restarts the timer only if it is already running
127     */

128     public void restartTimer() {
129         //System.out.println("XMLJ2eeEditorSupport:restartTimer "+this.hashCode());
130
dataObject.setDocumentDirty(true);
131         Runnable JavaDoc r = new Runnable JavaDoc() {
132             public void run() {
133                 dataObject.parsingDocument();
134             }
135     };
136         if (parsingDocumentTask==null || parsingDocumentTask.isFinished() ||
137             parsingDocumentTask.cancel()) {
138             parsingDocumentTask = RequestProcessor.getDefault().post(r,100);
139         } else {
140             parsingDocumentTask = RequestProcessor.getDefault().post(r,AUTO_PARSING_DELAY);
141         }
142     }
143
144     /** Called when the document is modified.
145      * Here, adding a save cookie to the object and marking it modified.
146      * @return true if the modification is acceptable
147      */

148     protected boolean notifyModified () {
149         boolean notif = super.notifyModified();
150         if (!notif){
151             return false;
152         }
153         XMLJ2eeDataObject obj = (XMLJ2eeDataObject) getDataObject ();
154         //System.out.println("notifyModified(), nodeDirty="+obj.isNodeDirty());
155
if (obj.getCookie (SaveCookie.class) == null) {
156             obj.addSaveCookie (new Save ());
157         }
158         return true;
159     }
160
161     /** Called when the document becomes unmodified.
162      * Here, removing the save cookie from the object and marking it unmodified.
163      */

164     protected void notifyUnmodified () {
165         super.notifyUnmodified ();
166         XMLJ2eeDataObject obj = (XMLJ2eeDataObject) getDataObject ();
167         obj.removeSaveCookie();
168     }
169
170     /** A save cookie to use for the editor support.
171      * When saved, saves the document to disk and marks the object unmodified.
172      */

173     private class Save implements SaveCookie {
174         public Save () {
175         }
176
177         public void save () throws IOException {
178             XMLJ2eeDataObject obj = (XMLJ2eeDataObject) getDataObject ();
179             if (obj.isDocumentValid()) {
180                 obj.setSavingDocument(true);
181                 saveDocument();
182             }else {
183                 obj.displayErrorMessage();
184                 dialog = new org.openide.DialogDescriptor(
185                     NbBundle.getMessage (XMLJ2eeEditorSupport.class, "MSG_invalidXmlWarning"),
186                     NbBundle.getMessage (XMLJ2eeEditorSupport.class, "TTL_invalidXmlWarning"));
187                 java.awt.Dialog JavaDoc d = org.openide.DialogDisplayer.getDefault().createDialog(dialog);
188                 d.show();
189                 if (dialog.getValue() == org.openide.DialogDescriptor.OK_OPTION) {
190                     obj.setSavingDocument(true);
191                     saveDocument();
192                 }
193             }
194         }
195     }
196     /*
197      * Save document using encoding declared in XML prolog if possible otherwise
198      * at UTF-8 (in such case it updates the prolog).
199      */

200     public void saveDocument () throws java.io.IOException JavaDoc {
201         final javax.swing.text.StyledDocument JavaDoc doc = getDocument();
202         // dependency on xml/core
203
String JavaDoc enc = EncodingUtil.detectEncoding(doc);
204         if (enc == null) enc = "UTF8"; //!!! // NOI18N
205

206         try {
207             //test encoding on dummy stream
208
new java.io.OutputStreamWriter JavaDoc(new java.io.ByteArrayOutputStream JavaDoc(1), enc);
209             super.saveDocument();
210             //moved from Env.save()
211
getDataObject().setModified (false);
212         } catch (java.io.UnsupportedEncodingException JavaDoc ex) {
213             // ask user what next?
214
String JavaDoc message = java.text.MessageFormat.format(NbBundle.getMessage(XMLJ2eeEditorSupport.class,"TEXT_SAVE_AS_UTF"),
215                                                             new Object JavaDoc[] {enc});
216             NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(message);
217             Object JavaDoc res = DialogDisplayer.getDefault().notify(descriptor);
218
219             if (res.equals(NotifyDescriptor.YES_OPTION)) {
220
221                 // update prolog to new valid encoding
222

223                 try {
224                     final int MAX_PROLOG = 1000;
225                     int maxPrologLen = Math.min(MAX_PROLOG, doc.getLength());
226                     final char prolog[] = doc.getText(0, maxPrologLen).toCharArray();
227                     int prologLen = 0; // actual prolog length
228

229                     //parse prolog and get prolog end
230
if (prolog[0] == '<' && prolog[1] == '?' && prolog[2] == 'x') {
231
232                         // look for delimitting ?>
233
for (int i = 3; i<maxPrologLen; i++) {
234                             if (prolog[i] == '?' && prolog[i+1] == '>') {
235                                 prologLen = i + 1;
236                                 break;
237                             }
238                         }
239                     }
240
241                     final int passPrologLen = prologLen;
242
243                     Runnable JavaDoc edit = new Runnable JavaDoc() {
244                          public void run() {
245                              try {
246
247                                 doc.remove(0, passPrologLen + 1); // +1 it removes exclusive
248
doc.insertString(0, "<?xml version='1.0' encoding='UTF-8' ?> \n<!-- was: " + new String JavaDoc(prolog, 0, passPrologLen + 1) + " -->", null); // NOI18N
249

250                              } catch (BadLocationException e) {
251                                  if (System.getProperty("netbeans.debug.exceptions") != null) // NOI18N
252
e.printStackTrace();
253                              }
254                          }
255                     };
256
257                     NbDocument.runAtomic(doc, edit);
258
259                     super.saveDocument();
260                     //moved from Env.save()
261
getDataObject().setModified (false);
262
263                 } catch (BadLocationException lex) {
264                     org.openide.ErrorManager.getDefault().notify(lex);
265                 }
266
267             } else { // NotifyDescriptor != YES_OPTION
268
return;
269             }
270         }
271     }
272
273     public UndoRedo.Manager getUndo(){
274         return getUndoRedo();
275     }
276
277     /** A description of the binding between the editor support and the object.
278      * Note this may be serialized as part of the window system and so
279      * should be static, and use the transient modifier where needed.
280      */

281     private static class XmlEnv extends DataEditorSupport.Env {
282
283         private static final long serialVersionUID = -800036748848958489L;
284
285         //private static final long serialVersionUID = ...L;
286

287         /** Create a new environment based on the data object.
288          * @param obj the data object to edit
289          */

290         public XmlEnv (XMLJ2eeDataObject obj) {
291             super (obj);
292         }
293
294         /** Get the file to edit.
295          * @return the primary file normally
296          */

297         protected FileObject getFile () {
298             return getDataObject ().getPrimaryFile ();
299         }
300
301         /** Lock the file to edit.
302          * Should be taken from the file entry if possible, helpful during
303          * e.g. deletion of the file.
304          * @return a lock on the primary file normally
305          * @throws IOException if the lock could not be taken
306          */

307         protected FileLock takeLock () throws IOException {
308             return ((XMLJ2eeDataObject) getDataObject ()).getPrimaryEntry ().takeLock ();
309         }
310
311         /** Find the editor support this environment represents.
312          * Note that we have to look it up, as keeping a direct
313          * reference would not permit this environment to be serialized.
314          * @return the editor support
315          */

316         public CloneableOpenSupport findCloneableOpenSupport () {
317             return (XMLJ2eeEditorSupport) getDataObject ().getCookie (XMLJ2eeEditorSupport.class);
318         }
319     }
320 }
321
Popular Tags