KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > web > struts > StrutsConfigEditorSupport


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.struts;
21
22 import java.beans.PropertyChangeEvent JavaDoc;
23 import java.beans.PropertyChangeListener JavaDoc;
24 import javax.swing.event.DocumentEvent JavaDoc;
25 import javax.swing.event.DocumentListener JavaDoc;
26 import javax.swing.text.BadLocationException JavaDoc;
27 import org.netbeans.modules.xml.api.EncodingUtil;
28 import org.openide.DialogDescriptor;
29 import org.openide.DialogDisplayer;
30 import org.openide.ErrorManager;
31 import org.openide.NotifyDescriptor;
32 import org.openide.filesystems.FileLock;
33 import org.openide.filesystems.FileObject;
34 import org.openide.nodes.Node.Cookie;
35 import org.openide.text.DataEditorSupport;
36 import org.openide.cookies.*;
37 import org.openide.text.NbDocument;
38 import org.openide.util.NbBundle;
39 import org.openide.util.RequestProcessor;
40
41 /**
42  *
43  * @author Petr Pisl
44  */

45 public class StrutsConfigEditorSupport extends DataEditorSupport
46 implements OpenCookie, EditCookie, EditorCookie.Observable, PrintCookie, CloseCookie {
47     
48     /** SaveCookie for this support instance. The cookie is adding/removing
49      * data object's cookie set depending on if modification flag was set/unset. */

50     private final SaveCookie saveCookie = new SaveCookie() {
51         /** Implements <code>SaveCookie</code> interface. */
52         public void save() throws java.io.IOException JavaDoc {
53             StrutsConfigDataObject obj = (StrutsConfigDataObject) getDataObject ();
54             // invoke parsing before save
55
restartTimer();
56             obj.parsingDocument();
57             if (obj.isDocumentValid()) {
58                 saveDocument();
59             }else {
60                 DialogDescriptor dialog = new DialogDescriptor(
61                     NbBundle.getMessage (StrutsConfigEditorSupport.class, "MSG_invalidXmlWarning"), //NOI18N
62
NbBundle.getMessage (StrutsConfigEditorSupport.class, "TTL_invalidXmlWarning")); //NOI18N
63
java.awt.Dialog JavaDoc d = org.openide.DialogDisplayer.getDefault().createDialog(dialog);
64                 d.setVisible(true);
65                 if (dialog.getValue() == org.openide.DialogDescriptor.OK_OPTION) {
66                     saveDocument();
67                 }
68             }
69         }
70     };
71     
72     private StrutsConfigDataObject dataObject;
73     private RequestProcessor.Task parsingDocumentTask;
74     /** Delay for automatic parsing - in miliseconds */
75     private static final int AUTO_PARSING_DELAY = 2000;
76     
77     public StrutsConfigEditorSupport(StrutsConfigDataObject dobj) {
78         super(dobj,new XmlEnv(dobj));
79         setMIMEType("text/x-struts+xml"); //NOI18N
80
dataObject = dobj;
81         //initialize the listeners on the document
82
initialize();
83     }
84     
85     private void initialize() {
86         // Create DocumentListener
87
final DocumentListener JavaDoc docListener = new DocumentListener JavaDoc() {
88                 public void insertUpdate(DocumentEvent JavaDoc e) { change(e); }
89                 public void changedUpdate(DocumentEvent JavaDoc e) { }
90                 public void removeUpdate(DocumentEvent JavaDoc e) { change(e); }
91             
92                 private void change(DocumentEvent JavaDoc e) {
93                     if (!dataObject.isNodeDirty()) restartTimer();
94                 }
95             };
96             
97         // the listener add only when the document is move to memory
98
addPropertyChangeListener(new PropertyChangeListener JavaDoc() {
99             public void propertyChange(PropertyChangeEvent JavaDoc evt) {
100                 if (EditorCookie.Observable.PROP_DOCUMENT.equals(evt.getPropertyName())
101                         && isDocumentLoaded() && getDocument() != null) {
102                     getDocument().addDocumentListener(docListener);
103                 }
104             }
105         });
106     }
107     
108     /*
109      * Save document using encoding declared in XML prolog if possible otherwise
110      * at UTF-8 (in such case it updates the prolog).
111      */

112     public void saveDocument () throws java.io.IOException JavaDoc {
113         final javax.swing.text.StyledDocument JavaDoc doc = getDocument();
114         String JavaDoc defaultEncoding = "UTF-8"; // NOI18N
115
// dependency on xml/core
116
String JavaDoc enc = EncodingUtil.detectEncoding(doc);
117         boolean changeEncodingToDefault = false;
118         if (enc == null) enc = defaultEncoding;
119         
120         //test encoding
121
if (!isSupportedEncoding(enc)){
122             NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
123             NbBundle.getMessage (StrutsConfigEditorSupport.class, "MSG_BadEncodingDuringSave", //NOI18N
124
new Object JavaDoc [] { getDataObject().getPrimaryFile().getNameExt(),
125                                 enc,
126                                 defaultEncoding} ),
127                         NotifyDescriptor.YES_NO_OPTION,
128                         NotifyDescriptor.WARNING_MESSAGE);
129             nd.setValue(NotifyDescriptor.NO_OPTION);
130             DialogDisplayer.getDefault().notify(nd);
131             if(nd.getValue() != NotifyDescriptor.YES_OPTION) return;
132             changeEncodingToDefault = true;
133         }
134         
135         if (!changeEncodingToDefault){
136             // is it possible to save the document in the encoding?
137
try {
138                 java.nio.charset.CharsetEncoder JavaDoc coder = java.nio.charset.Charset.forName(enc).newEncoder();
139                 if (!coder.canEncode(doc.getText(0, doc.getLength()))){
140                     NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
141                     NbBundle.getMessage (StrutsConfigEditorSupport.class, "MSG_BadCharConversion", //NOI18N
142
new Object JavaDoc [] { getDataObject().getPrimaryFile().getNameExt(),
143                                     enc}),
144                             NotifyDescriptor.YES_NO_OPTION,
145                             NotifyDescriptor.WARNING_MESSAGE);
146                     nd.setValue(NotifyDescriptor.NO_OPTION);
147                     DialogDisplayer.getDefault().notify(nd);
148                     if(nd.getValue() != NotifyDescriptor.YES_OPTION) return;
149                 }
150             }
151             catch (javax.swing.text.BadLocationException JavaDoc e){
152                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
153             }
154             super.saveDocument();
155             //moved from Env.save()
156
getDataObject().setModified (false);
157         }
158         else {
159                 // update prolog to new valid encoding
160

161             try {
162                 final int MAX_PROLOG = 1000;
163                 int maxPrologLen = Math.min(MAX_PROLOG, doc.getLength());
164                 final char prolog[] = doc.getText(0, maxPrologLen).toCharArray();
165                 int prologLen = 0; // actual prolog length
166

167                 //parse prolog and get prolog end
168
if (prolog[0] == '<' && prolog[1] == '?' && prolog[2] == 'x') {
169
170                     // look for delimitting ?>
171
for (int i = 3; i<maxPrologLen; i++) {
172                         if (prolog[i] == '?' && prolog[i+1] == '>') {
173                             prologLen = i + 1;
174                             break;
175                         }
176                     }
177                 }
178
179                 final int passPrologLen = prologLen;
180
181                 Runnable JavaDoc edit = new Runnable JavaDoc() {
182                      public void run() {
183                          try {
184
185                             doc.remove(0, passPrologLen + 1); // +1 it removes exclusive
186
doc.insertString(0, "<?xml version='1.0' encoding='UTF-8' ?> \n<!-- was: " + new String JavaDoc(prolog, 0, passPrologLen + 1) + " -->", null); // NOI18N
187

188                          } catch (BadLocationException JavaDoc e) {
189                              if (System.getProperty("netbeans.debug.exceptions") != null) // NOI18N
190
e.printStackTrace();
191                          }
192                      }
193                 };
194
195                 NbDocument.runAtomic(doc, edit);
196
197                 super.saveDocument();
198                 //moved from Env.save()
199
getDataObject().setModified (false);
200             }
201             catch (javax.swing.text.BadLocationException JavaDoc e){
202                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
203             }
204         }
205     }
206     
207     private boolean isSupportedEncoding(String JavaDoc encoding){
208         boolean supported;
209         try{
210             supported = java.nio.charset.Charset.isSupported(encoding);
211         }
212         catch (java.nio.charset.IllegalCharsetNameException JavaDoc e){
213             supported = false;
214         }
215         
216         return supported;
217     }
218     
219     /** Restart the timer which starts the parser after the specified delay.
220     * @param onlyIfRunning Restarts the timer only if it is already running
221     */

222     public void restartTimer() {
223         if (parsingDocumentTask==null || parsingDocumentTask.isFinished() ||
224             parsingDocumentTask.cancel()) {
225             dataObject.setDocumentDirty(true);
226             Runnable JavaDoc r = new Runnable JavaDoc() {
227                             public void run() {
228                                 dataObject.parsingDocument();
229                         }
230                     };
231             if (parsingDocumentTask != null)
232                 parsingDocumentTask = RequestProcessor.getDefault().post(r, AUTO_PARSING_DELAY);
233             else
234                 parsingDocumentTask = RequestProcessor.getDefault().post(r, 100);
235         }
236     }
237     
238     /**
239      * Overrides superclass method. Adds adding of save cookie if the document has been marked modified.
240      * @return true if the environment accepted being marked as modified
241      * or false if it has refused and the document should remain unmodified
242      */

243     protected boolean notifyModified () {
244         if (!super.notifyModified())
245             return false;
246
247         addSaveCookie();
248
249         return true;
250     }
251
252     /** Overrides superclass method. Adds removing of save cookie. */
253     protected void notifyUnmodified () {
254         super.notifyUnmodified();
255
256         removeSaveCookie();
257     }
258
259     /** Helper method. Adds save cookie to the data object. */
260     private void addSaveCookie() {
261         StrutsConfigDataObject obj = (StrutsConfigDataObject)getDataObject();
262
263         // Adds save cookie to the data object.
264
if(obj.getCookie(SaveCookie.class) == null) {
265             obj.getCookieSet0().add(saveCookie);
266             obj.setModified(true);
267         }
268     }
269
270     /** Helper method. Removes save cookie from the data object. */
271     private void removeSaveCookie() {
272         StrutsConfigDataObject obj = (StrutsConfigDataObject)getDataObject();
273         
274         // Remove save cookie from the data object.
275
Cookie cookie = obj.getCookie(SaveCookie.class);
276
277         if(cookie != null && cookie.equals(saveCookie)) {
278             obj.getCookieSet0().remove(saveCookie);
279             obj.setModified(false);
280         }
281     }
282     
283     /** A description of the binding between the editor support and the object.
284      * Note this may be serialized as part of the window system and so
285      * should be static, and use the transient modifier where needed.
286      */

287     private static class XmlEnv extends DataEditorSupport.Env {
288
289         private static final long serialVersionUID = -800036748848958489L;
290         
291         //private static final long serialVersionUID = ...L;
292

293         /** Create a new environment based on the data object.
294          * @param obj the data object to edit
295          */

296         public XmlEnv (StrutsConfigDataObject obj) {
297             super (obj);
298         }
299
300         /** Get the file to edit.
301          * @return the primary file normally
302          */

303         protected FileObject getFile () {
304             return getDataObject ().getPrimaryFile ();
305         }
306
307         /** Lock the file to edit.
308          * Should be taken from the file entry if possible, helpful during
309          * e.g. deletion of the file.
310          * @return a lock on the primary file normally
311          * @throws IOException if the lock could not be taken
312          */

313         protected FileLock takeLock () throws java.io.IOException JavaDoc {
314             return ((StrutsConfigDataObject) getDataObject ()).getPrimaryEntry ().takeLock ();
315         }
316
317         /** Find the editor support this environment represents.
318          * Note that we have to look it up, as keeping a direct
319          * reference would not permit this environment to be serialized.
320          * @return the editor support
321          */

322         public org.openide.windows.CloneableOpenSupport findCloneableOpenSupport () {
323             return (StrutsConfigEditorSupport) getDataObject ().getCookie (StrutsConfigEditorSupport.class);
324         }
325     }
326 }
327
Popular Tags