KickJava   Java API By Example, From Geeks To Geeks.

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


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 2002-2003 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.settings;
21
22 import java.beans.PropertyChangeEvent JavaDoc;
23 import java.lang.ref.SoftReference JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.util.logging.Level JavaDoc;
26 import java.util.logging.Logger JavaDoc;
27 import org.netbeans.modules.settings.convertors.SerialDataNode;
28
29 import org.openide.filesystems.FileObject;
30 import org.openide.filesystems.FileSystem;
31 import org.openide.filesystems.FileUtil;
32 import org.openide.nodes.Node;
33 import org.openide.util.Lookup;
34 import org.openide.cookies.SaveCookie;
35 import org.openide.cookies.InstanceCookie;
36
37 import org.netbeans.spi.settings.Convertor;
38 import org.openide.util.Exceptions;
39
40 /** Provides the Lookup content.
41  *
42  * @author Jan Pokorsky
43  */

44 final class InstanceProvider extends org.openide.filesystems.FileChangeAdapter
45 implements java.beans.PropertyChangeListener JavaDoc, FileSystem.AtomicAction {
46     /** Logging for events in this class */
47     private static final Logger JavaDoc LOG = Logger.getLogger(InstanceProvider.class.getName()); // NOI18N
48

49     /** container handling objects provided by {@link #lookup} */
50     private final org.openide.util.lookup.InstanceContent lkpContent;
51     /** container exposing setting to the outside world */
52     private final org.openide.util.Lookup lookup;
53     private final org.openide.loaders.DataObject dobj;
54     private final FileObject settingFO;
55     private final FileObject providerFO;
56     private final NodeConvertor node;
57     //save support
58
private SaveSupport saver;
59     private SaveCookie scCache;
60     private boolean wasReportedProblem = false;
61     private java.util.Set JavaDoc<String JavaDoc> instanceOfSet;
62     private String JavaDoc instanceClassName;
63     /** lock used to sync read/write operations for .settings file */
64     final Object JavaDoc READWRITE_LOCK = new Object JavaDoc();
65     
66     /** Creates a new instance of InstanceCooikeProvider */
67     public InstanceProvider(org.openide.loaders.DataObject dobj, FileObject providerFO) {
68 // System.out.println("new IP: " + dobj);
69
this.settingFO = dobj.getPrimaryFile();
70         this.providerFO = providerFO;
71         this.dobj = dobj;
72         
73         settingFO.addFileChangeListener(
74             FileUtil.weakFileChangeListener(this, settingFO));
75         
76         lkpContent = new org.openide.util.lookup.InstanceContent();
77         lkpContent.add(createInstance(null));
78         node = new NodeConvertor();
79         lkpContent.add(this, node);
80         lookup = new org.openide.util.lookup.AbstractLookup(lkpContent);
81     }
82     
83     /** provides content like InstanceCookie, SaveCokie */
84     public Lookup getLookup() {
85         return lookup;
86     }
87     /** file contanining various attributes related to setting like convertor
88      * class, ...
89      */

90     FileObject getProvider() {
91         return providerFO;
92     }
93     /** file containing a persisted setting object */
94     FileObject getFile () {
95         return settingFO;
96     }
97     
98     org.openide.loaders.DataObject getDataObject() {
99         return dobj;
100     }
101     
102     public void propertyChange(PropertyChangeEvent JavaDoc evt) {
103         if (evt == null) return;
104
105         String JavaDoc name = evt.getPropertyName();
106         if (name == null)
107             return;
108         else if (name == SaveSupport.PROP_SAVE)
109             provideSaveCookie();
110         else if (name == SaveSupport.PROP_FILE_CHANGED) {
111             synchronized (this) {
112                 instanceOfSet = null;
113             }
114             instanceCookieChanged(null);
115         }
116     }
117     
118     /** process events coming from the file object*/
119     public void fileChanged(org.openide.filesystems.FileEvent fe) {
120         if (saver != null && fe.firedFrom((FileSystem.AtomicAction) saver.getSaveCookie())) return;
121         propertyChange(new PropertyChangeEvent JavaDoc(this, SaveSupport.PROP_FILE_CHANGED, null, null));
122     }
123   
124     public void fileDeleted(org.openide.filesystems.FileEvent fe) {
125         if (saver != null && fe.firedFrom((FileSystem.AtomicAction) saver.getSaveCookie())) return;
126         releaseInstance();
127     }
128     
129     
130     /** allow to listen on changes of the object inst; should be called when
131      * new instance is created */

132     private synchronized void attachToInstance(Object JavaDoc inst) {
133         if (saver != null) {
134             saver.removePropertyChangeListener(this);
135             getScheduledRequest().forceToFinish();
136         }
137         saver = createSaveSupport(inst);
138         saver.addPropertyChangeListener(this);
139     }
140     
141     /** create own InstanceCookie implementation */
142     private InstanceCookie.Of createInstance(Object JavaDoc inst) {
143         return new InstanceCookieImpl(inst);
144     }
145     
146     /** method provides a support storing the setting */
147     private SaveSupport createSaveSupport(Object JavaDoc inst) {
148         return new SaveSupport(this, inst);
149     }
150     
151     private void provideSaveCookie() {
152         SaveCookie scNew = saver.getSaveCookie();
153         if (scCache != null) {
154             if (!saver.isChanged()) {
155                 if (LOG.isLoggable(Level.FINE)) LOG.fine("remove save cookie: " + dobj); // NOI18N
156
lkpContent.remove(scCache);
157                 scCache = null;
158                 return;
159             }
160         } else {
161             if (saver.isChanged()) {
162                 scCache = scNew;
163                 if (LOG.isLoggable(Level.FINE)) LOG.fine("add save cookie: " + dobj + " cookie: " + scNew); // NOI18N
164
lkpContent.add(scNew);
165                 return;
166             }
167         }
168     }
169     
170     private void releaseInstance() {
171         SaveSupport _saver = saver;
172         if (_saver != null) {
173             _saver.removePropertyChangeListener(this);
174         }
175         
176         if (scCache != null) {
177             if (LOG.isLoggable(Level.FINE)) LOG.fine("release instance and remove save cookie: " + dobj); // NOI18N
178
lkpContent.remove(scCache);
179             getScheduledRequest().cancel();
180             scCache = null;
181         }
182         
183         lkpContent.remove(this, node);
184     }
185     
186     private void instanceCookieChanged(Object JavaDoc inst) {
187         if (LOG.isLoggable(Level.FINE)) LOG.fine("instanceCookieChanged: " + dobj + " inst: " + inst); // NOI18N
188
releaseInstance();
189         
190         lkpContent.add(this, node);
191         
192         Object JavaDoc ic = lookup.lookup(InstanceCookie.class);
193         lkpContent.remove(ic);
194
195         Object JavaDoc newCookie = createInstance(inst);
196         lkpContent.add(newCookie);
197         if (LOG.isLoggable(Level.FINE)) LOG.fine("cookie replaced: " + dobj + " old: " + ic + " new: " + newCookie); // NOI18N
198
}
199     
200     private Convertor convertor;
201     
202     /** find out proper convertor */
203     Convertor getConvertor() throws IOException JavaDoc {
204         if (convertor == null) {
205             Object JavaDoc attrb = providerFO.getAttribute(Env.EA_CONVERTOR);
206             if (attrb == null || !(attrb instanceof Convertor)) {
207                 throw new IOException JavaDoc("cannot create convertor: " + attrb + ", provider:" +providerFO); //NOI18N
208
}
209             convertor = (Convertor) attrb;
210         }
211         return convertor;
212     }
213     
214     /** find out setting object class name */
215     private synchronized String JavaDoc getInstanceClassName() {
216         if (instanceClassName == null) {
217             Object JavaDoc name = providerFO.getAttribute(Env.EA_INSTANCE_CLASS_NAME);
218             if (name != null && name instanceof String JavaDoc) {
219                 instanceClassName = org.openide.util.Utilities.translate((String JavaDoc) name);
220             } else {
221                 instanceClassName = null;
222             }
223         }
224         return instanceClassName;
225     }
226     
227     public String JavaDoc toString() {
228         return this.getClass().getName() + '@' +
229             Integer.toHexString(System.identityHashCode(this)) +
230             '[' + getDataObject() + ", " + getProvider() + ']';
231     }
232     
233     
234     /** called by ScheduledRequest in order to perform the request */
235     public void run() throws IOException JavaDoc {
236         saver.writeDown();
237     }
238     
239     /** scheduled request to store setting */
240     private ScheduledRequest request;
241     
242     /** get the scheduled request to store setting */
243     synchronized ScheduledRequest getScheduledRequest() {
244         if (request == null) {
245             request = new ScheduledRequest(settingFO, this);
246         }
247         return request;
248     }
249     
250     /////////////////////////////////////////////////////////////////////////
251
// InstanceCookieImpl
252
/////////////////////////////////////////////////////////////////////////
253

254     /** InstanceCookie implementation. */
255     final class InstanceCookieImpl implements InstanceCookie.Of {
256         private SoftReference JavaDoc<Object JavaDoc> cachedInstance;// = new SoftReference(null);
257

258         public InstanceCookieImpl(Object JavaDoc inst) {
259             setCachedInstance(inst);
260         }
261         
262         public Class JavaDoc instanceClass() throws IOException JavaDoc, ClassNotFoundException JavaDoc {
263             String JavaDoc name = getInstanceClassName();
264             if (name == null) {
265                 return instanceCreate().getClass();
266             } else {
267                 return ((ClassLoader JavaDoc)Lookup.getDefault().lookup(ClassLoader JavaDoc.class)).loadClass(name);
268             }
269         }
270
271         public Object JavaDoc instanceCreate() throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
272             Object JavaDoc inst;
273             
274             synchronized (this) {
275                 inst = getCachedInstance();
276                 if (inst != null) return inst;
277             }
278             
279             try {
280                 synchronized (READWRITE_LOCK) {
281                     java.io.Reader JavaDoc r = ContextProvider.createReaderContextProvider(
282                         new java.io.InputStreamReader JavaDoc(settingFO.getInputStream(),"UTF-8"), //NOI18N
283
getFile()
284                     );
285                     inst = getConvertor().read(r);
286                 }
287             } catch (IOException JavaDoc ex) {
288                 throw (IOException JavaDoc) Exceptions.attachLocalizedMessage(ex,
289                                                   InstanceProvider.this.toString());
290             } catch (ClassNotFoundException JavaDoc ex) {
291                 throw (ClassNotFoundException JavaDoc) Exceptions.attachLocalizedMessage(ex,
292                                                   InstanceProvider.this.toString());
293             }
294             
295             synchronized (this) {
296                 Object JavaDoc existing = getCachedInstance();
297                 if (existing != null) return existing;
298                 setCachedInstance(inst);
299             }
300             attachToInstance(inst);
301             
302             return inst;
303         }
304
305         public String JavaDoc instanceName() {
306             String JavaDoc name = getInstanceClassName();
307             if (name != null) return name;
308             
309             Exception JavaDoc e = null;
310             try {
311                 return instanceClass().getName();
312             } catch (IOException JavaDoc ex) {
313                 e = ex;
314             } catch (ClassNotFoundException JavaDoc ex) {
315                 e = ex;
316             }
317             if (e != null && !wasReportedProblem) {
318                 wasReportedProblem = true;
319                 Exceptions.attachLocalizedMessage(e, dobj.toString());
320                 Logger.getLogger(InstanceProvider.class.getName()).log(Level.WARNING, null, e);
321             }
322             return "Unknown"; // NOI18N
323
}
324
325         public boolean instanceOf(Class JavaDoc<?> type) {
326             synchronized (InstanceProvider.this) {
327                 if (instanceOfSet == null) {
328                     instanceOfSet = Env.parseAttribute(providerFO.getAttribute(Env.EA_INSTANCE_OF));
329                     java.util.Iterator JavaDoc<String JavaDoc> it = instanceOfSet.iterator();
330                     instanceOfSet = new java.util.HashSet JavaDoc<String JavaDoc>(instanceOfSet.size() * 5 / 4);
331                     while (it.hasNext()) {
332                         instanceOfSet.add(org.openide.util.Utilities.translate(it.next()));
333                     }
334                 }
335             }
336             if (instanceOfSet.isEmpty()) {
337                 Exception JavaDoc e = null;
338                 try {
339                     return type.isAssignableFrom(instanceClass());
340                 } catch (IOException JavaDoc ex) {
341                     e = ex;
342                 } catch (ClassNotFoundException JavaDoc ex) {
343                     e = ex;
344                 }
345                 if (e != null && !wasReportedProblem) {
346                     wasReportedProblem = true;
347                     Exceptions.attachLocalizedMessage(e, dobj.toString());
348                     Logger.getLogger(InstanceProvider.class.getName()).log(Level.WARNING, null, e);
349                 }
350                 return false;
351             } else {
352                 return instanceOfSet.contains(type.getName());
353             }
354         }
355         
356         // called by InstanceDataObject to set new object
357
public void setInstance(Object JavaDoc inst, boolean save) throws IOException JavaDoc {
358             instanceCookieChanged(inst);
359             if (inst != null) {
360                 attachToInstance(inst);
361                 if (save) getScheduledRequest().runAndWait();
362             }
363         }
364     
365         private Object JavaDoc getCachedInstance() {
366             return cachedInstance.get();
367         }
368         private void setCachedInstance(Object JavaDoc inst) {
369             cachedInstance = new SoftReference JavaDoc<Object JavaDoc>(inst);
370         }
371     }
372     
373 ////////////////////////////////////////////////////////////////////////////
374
// NodeConvertor
375
////////////////////////////////////////////////////////////////////////////
376

377     /** allow to postpone the node creation */
378     private static final class NodeConvertor
379             implements org.openide.util.lookup.InstanceContent.Convertor<InstanceProvider, Node> {
380         NodeConvertor() {}
381      
382         public Node convert(InstanceProvider o) {
383             return new SerialDataNode(o.getDataObject());
384         }
385      
386         public Class JavaDoc<Node> type(InstanceProvider o) {
387             return Node.class;
388         }
389      
390         public String JavaDoc id(InstanceProvider o) {
391             // Generally irrelevant in this context.
392
return o.toString();
393         }
394      
395         public String JavaDoc displayName(InstanceProvider o) {
396             // Again, irrelevant here.
397
return o.toString();
398         }
399      
400     }
401 }
402
Popular Tags