KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > settings > SaveSupport


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.settings;
21
22 import java.beans.*;
23 import java.io.IOException JavaDoc;
24 import java.util.logging.Level JavaDoc;
25 import java.util.logging.Logger JavaDoc;
26
27 import org.openide.cookies.SaveCookie;
28 import org.openide.filesystems.FileSystem;
29 import org.openide.filesystems.FileObject;
30
31 import org.netbeans.spi.settings.Convertor;
32 import org.netbeans.spi.settings.Saver;
33 import org.openide.util.Exceptions;
34
35 /** Support handles automatic storing/upgrading; notifies about changes in file.
36  *
37  * @author Jan Pokorsky
38  */

39 final class SaveSupport {
40     /** property means setting is changed and should be changed */
41     public final static String JavaDoc PROP_SAVE = "savecookie"; //NOI18N
42
/** property means setting file content is changed */
43     public final static String JavaDoc PROP_FILE_CHANGED = "fileChanged"; //NOI18N
44
/** data object name cached in the attribute to prevent instance creation when
45      * its node is displayed.
46      * @see org.openide.loaders.InstanceDataObject#EA_NAME
47      */

48     static final String JavaDoc EA_NAME = "name"; // NOI18N
49

50     /** support for PropertyChangeListeners */
51     private PropertyChangeSupport changeSupport;
52     
53     /** convertor for possible format upgrade */
54     private Convertor convertor;
55     /** SaveCookie implementation */
56     private final SaveCookieImpl instToSave = new SaveCookieImpl();
57     /** setting is already changed */
58     private boolean isChanged = false;
59     /** .settings file */
60     private final FileObject file;
61     /** reference to setting object */
62     private final java.lang.ref.SoftReference JavaDoc<Object JavaDoc> instance;
63     private final InstanceProvider ip;
64     /** remember whether the DataObject is a template or not; calling isTemplate() is slow */
65     private Boolean JavaDoc knownToBeTemplate = null;
66     
67     /** Creates a new instance of SaveSupport
68      * @param ip instance provider
69      * @param inst setting object
70      */

71     public SaveSupport(InstanceProvider ip, Object JavaDoc inst) {
72         this.ip = ip;
73         this.instance = new java.lang.ref.SoftReference JavaDoc<Object JavaDoc>(inst);
74         this.file = ip.getFile();
75     }
76     
77     /** get convertor for possible upgrade; can be null */
78     private Convertor getConvertor() {
79         return convertor;
80     }
81     
82     /** try to find out convertor for possible upgrade and cache it; can be null */
83     private Convertor initConvertor() {
84         Object JavaDoc inst = instance.get();
85         if (inst == null) {
86             throw new IllegalStateException JavaDoc("setting object cannot be null: " + ip);// NOI18N
87
}
88         
89         try {
90             FileObject newProviderFO = Env.findProvider(inst.getClass());
91             if (newProviderFO != null) {
92                 if (getPublicID(newProviderFO).equals(getPublicID(ip.getProvider()))) {
93                     // nothing to upgrade
94
convertor = ip.getConvertor();
95                     return convertor;
96                 }
97                 Object JavaDoc attrb = newProviderFO.getAttribute(Env.EA_CONVERTOR);
98                 if (attrb == null || !(attrb instanceof Convertor)) {
99                     throw new IOException JavaDoc("cannot create convertor: " + attrb + ", provider: " + newProviderFO); //NOI18N
100
} else {
101                     convertor = (Convertor) attrb;
102                     return convertor;
103                 }
104             }
105             convertor = ip.getConvertor();
106         } catch (IOException JavaDoc ex) {
107             Logger.getLogger(SaveSupport.class.getName()).log(Level.WARNING, null, ex);
108         }
109         return convertor;
110     }
111     
112     /** get publicid of the file fo */
113     private String JavaDoc getPublicID(FileObject fo) throws IOException JavaDoc {
114         FileObject foEntity = Env.findEntityRegistration(fo);
115         if (foEntity == null) foEntity = fo;
116         Object JavaDoc publicId = foEntity.getAttribute(Env.EA_PUBLICID);
117         if (publicId == null || !(publicId instanceof String JavaDoc)) {
118             throw new IOException JavaDoc("missing or invalid attribute: " + //NOI18N
119
Env.EA_PUBLICID + ", provider: " + foEntity); //NOI18N
120
}
121         return (String JavaDoc) publicId;
122     }
123     
124     /** return SaveCookie impl */
125     public final SaveCookie getSaveCookie () {
126             return instToSave;
127     }
128     
129     /** is setting object changed? */
130     public final boolean isChanged() {
131         return isChanged;
132     }
133     
134     /** Registers PropertyChangeListener to receive events; initialize
135      * listening to events comming from the setting object and file object.
136      * @param listener The listener to register.
137      */

138     public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
139         if (changeSupport == null) {
140             changeSupport = new PropertyChangeSupport(this);
141             Object JavaDoc inst = instance.get();
142             if (inst == null) return;
143             Convertor conv = initConvertor();
144             if (conv != null) {
145                 conv.registerSaver(inst, instToSave);
146             }
147         }
148         changeSupport.addPropertyChangeListener(listener);
149     }
150     
151     /** Removes PropertyChangeListener from the list of listeners.
152      * @param listener The listener to remove.
153      */

154     public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
155         if (changeSupport != null) {
156             changeSupport.removePropertyChangeListener(listener);
157             Object JavaDoc inst = instance.get();
158             if (inst == null) return;
159             Convertor conv = getConvertor();
160             if (conv != null) {
161                 conv.unregisterSaver(inst, instToSave);
162             }
163         }
164     }
165     
166     /** Notifies all registered listeners about the event.
167      * @param event The event to be fired
168      * @see #PROP_FILE_CHANGED
169      * @see #PROP_SAVE
170      */

171     private void firePropertyChange(String JavaDoc name) {
172         if (changeSupport != null)
173             changeSupport.firePropertyChange(name, null, null);
174     }
175     
176     /** called by ScheduledRequest in order to perform the request */
177     public void writeDown() throws IOException JavaDoc {
178         instToSave.writeDown();
179     }
180     
181     /** Support for storing instances allowing identify the origin of file events
182      * fired as a consequence of this storing.
183      */

184     private class SaveCookieImpl implements FileSystem.AtomicAction, SaveCookie, Saver {
185     
186         private java.io.ByteArrayOutputStream JavaDoc buf;
187         
188         private SaveCookieImpl() {
189         }
190         
191         /** store buffer to the file. */
192         public void run () throws IOException JavaDoc {
193             if (!ip.getDataObject().isValid()) {
194                 //invalid data object cannot be used for storing
195
Logger.getAnonymousLogger().fine("invalid data object cannot be used for storing " + ip.getDataObject()); // NOI18N
196
return;
197             }
198             org.openide.filesystems.FileLock lock = null;
199             java.io.OutputStream JavaDoc los;
200             synchronized (ip.READWRITE_LOCK) {
201 // if (err.isLoggable(ErrorManager.INFORMATIONAL)) {
202
// err.log("saving " + dobj); // NOI18N
203
// }
204
lock = ip.getScheduledRequest().getFileLock();
205                 if (lock == null) return;
206                 los = file.getOutputStream(lock);
207
208                 java.io.OutputStream JavaDoc os = new java.io.BufferedOutputStream JavaDoc(los, 1024);
209                 try {
210                     buf.writeTo(os);
211 // if (err.isLoggable(ErrorManager.INFORMATIONAL)) {
212
// dobj.err.log("saved " + dobj); // NOI18N
213
// }
214
} finally {
215                     os.close();
216                 }
217             }
218         }
219         
220         /** Implementation of SaveCookie. */
221         public void save() throws IOException JavaDoc {
222             if (!isChanged) return;
223             ip.getScheduledRequest().runAndWait();
224         }
225         
226         private void writeDown() throws IOException JavaDoc {
227             Object JavaDoc inst = instance.get();
228             if (inst == null) return ;
229             Convertor conv = getConvertor();
230             if (conv == null) return ;
231             java.io.ByteArrayOutputStream JavaDoc b = new java.io.ByteArrayOutputStream JavaDoc(1024);
232             java.io.Writer JavaDoc w = ContextProvider.createWriterContextProvider(
233                 new java.io.OutputStreamWriter JavaDoc(b, "UTF-8"), // NOI18N
234
SaveSupport.this.file
235             );
236             isChanged = false;
237             try {
238                 conv.write(w, inst);
239             } finally {
240                 w.close();
241             }
242             
243             buf = b;
244             file.getFileSystem().runAtomicAction(this);
245             buf = null;
246             synchronizeName(inst);
247             if (!isChanged) firePropertyChange(PROP_SAVE);
248         }
249         
250         public void markDirty() {
251             if (isChanged || !ip.getDataObject().isValid()) return;
252             if (knownToBeTemplate == null) knownToBeTemplate = ip.getDataObject().isTemplate() ? Boolean.TRUE : Boolean.FALSE;
253             if (knownToBeTemplate.booleanValue()) return;
254             isChanged = true;
255             firePropertyChange(PROP_SAVE);
256         }
257         
258         public void requestSave() throws java.io.IOException JavaDoc {
259             if (isChanged || !ip.getDataObject().isValid()) return;
260             if (knownToBeTemplate == null) knownToBeTemplate = ip.getDataObject().isTemplate() ? Boolean.TRUE : Boolean.FALSE;
261             if (knownToBeTemplate.booleanValue()) return;
262             isChanged = true;
263             firePropertyChange(PROP_SAVE);
264             ip.getScheduledRequest().schedule(instance.get());
265         }
266         
267         /** try to synchronize file name with instance name */
268         private void synchronizeName(Object JavaDoc inst) {
269             java.lang.reflect.Method JavaDoc getter;
270             try {
271                 try {
272                     getter = inst.getClass().getMethod("getDisplayName"); // NOI18N
273
} catch (NoSuchMethodException JavaDoc me) {
274                     getter = inst.getClass().getMethod("getName"); // NOI18N
275
}
276             } catch (Exception JavaDoc ex) { // do nothing
277
return;
278             }
279             if (!getter.isAccessible()) return;
280             
281             try {
282                 String JavaDoc name = (String JavaDoc) getter.invoke(inst);
283                 String JavaDoc oldName = ip.getDataObject().getName();
284                 if (!name.equals(oldName)) {
285                     file.setAttribute(EA_NAME, name);
286                 } else if (file.getAttribute(EA_NAME) == null) {
287                     file.setAttribute(EA_NAME, name);
288                 }
289             } catch (Exception JavaDoc ex) {
290                 Exceptions.attachLocalizedMessage(ex, file.toString());
291             Logger.getLogger(SaveSupport.class.getName()).log(Level.WARNING, null, ex);
292             }
293         }
294         
295     }
296     
297 }
298
Popular Tags