1 19 20 package org.netbeans.modules.settings; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.lang.ref.SoftReference ; 24 import java.io.IOException ; 25 import java.util.logging.Level ; 26 import java.util.logging.Logger ; 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 44 final class InstanceProvider extends org.openide.filesystems.FileChangeAdapter 45 implements java.beans.PropertyChangeListener , FileSystem.AtomicAction { 46 47 private static final Logger LOG = Logger.getLogger(InstanceProvider.class.getName()); 49 50 private final org.openide.util.lookup.InstanceContent lkpContent; 51 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 private SaveSupport saver; 59 private SaveCookie scCache; 60 private boolean wasReportedProblem = false; 61 private java.util.Set <String > instanceOfSet; 62 private String instanceClassName; 63 64 final Object READWRITE_LOCK = new Object (); 65 66 67 public InstanceProvider(org.openide.loaders.DataObject dobj, FileObject providerFO) { 68 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 84 public Lookup getLookup() { 85 return lookup; 86 } 87 90 FileObject getProvider() { 91 return providerFO; 92 } 93 94 FileObject getFile () { 95 return settingFO; 96 } 97 98 org.openide.loaders.DataObject getDataObject() { 99 return dobj; 100 } 101 102 public void propertyChange(PropertyChangeEvent evt) { 103 if (evt == null) return; 104 105 String 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 119 public void fileChanged(org.openide.filesystems.FileEvent fe) { 120 if (saver != null && fe.firedFrom((FileSystem.AtomicAction) saver.getSaveCookie())) return; 121 propertyChange(new PropertyChangeEvent (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 132 private synchronized void attachToInstance(Object inst) { 133 if (saver != null) { 134 saver.removePropertyChangeListener(this); 135 getScheduledRequest().forceToFinish(); 136 } 137 saver = createSaveSupport(inst); 138 saver.addPropertyChangeListener(this); 139 } 140 141 142 private InstanceCookie.Of createInstance(Object inst) { 143 return new InstanceCookieImpl(inst); 144 } 145 146 147 private SaveSupport createSaveSupport(Object 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); 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); 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); lkpContent.remove(scCache); 179 getScheduledRequest().cancel(); 180 scCache = null; 181 } 182 183 lkpContent.remove(this, node); 184 } 185 186 private void instanceCookieChanged(Object inst) { 187 if (LOG.isLoggable(Level.FINE)) LOG.fine("instanceCookieChanged: " + dobj + " inst: " + inst); releaseInstance(); 189 190 lkpContent.add(this, node); 191 192 Object ic = lookup.lookup(InstanceCookie.class); 193 lkpContent.remove(ic); 194 195 Object newCookie = createInstance(inst); 196 lkpContent.add(newCookie); 197 if (LOG.isLoggable(Level.FINE)) LOG.fine("cookie replaced: " + dobj + " old: " + ic + " new: " + newCookie); } 199 200 private Convertor convertor; 201 202 203 Convertor getConvertor() throws IOException { 204 if (convertor == null) { 205 Object attrb = providerFO.getAttribute(Env.EA_CONVERTOR); 206 if (attrb == null || !(attrb instanceof Convertor)) { 207 throw new IOException ("cannot create convertor: " + attrb + ", provider:" +providerFO); } 209 convertor = (Convertor) attrb; 210 } 211 return convertor; 212 } 213 214 215 private synchronized String getInstanceClassName() { 216 if (instanceClassName == null) { 217 Object name = providerFO.getAttribute(Env.EA_INSTANCE_CLASS_NAME); 218 if (name != null && name instanceof String ) { 219 instanceClassName = org.openide.util.Utilities.translate((String ) name); 220 } else { 221 instanceClassName = null; 222 } 223 } 224 return instanceClassName; 225 } 226 227 public String toString() { 228 return this.getClass().getName() + '@' + 229 Integer.toHexString(System.identityHashCode(this)) + 230 '[' + getDataObject() + ", " + getProvider() + ']'; 231 } 232 233 234 235 public void run() throws IOException { 236 saver.writeDown(); 237 } 238 239 240 private ScheduledRequest request; 241 242 243 synchronized ScheduledRequest getScheduledRequest() { 244 if (request == null) { 245 request = new ScheduledRequest(settingFO, this); 246 } 247 return request; 248 } 249 250 254 255 final class InstanceCookieImpl implements InstanceCookie.Of { 256 private SoftReference <Object > cachedInstance; 258 public InstanceCookieImpl(Object inst) { 259 setCachedInstance(inst); 260 } 261 262 public Class instanceClass() throws IOException , ClassNotFoundException { 263 String name = getInstanceClassName(); 264 if (name == null) { 265 return instanceCreate().getClass(); 266 } else { 267 return ((ClassLoader )Lookup.getDefault().lookup(ClassLoader .class)).loadClass(name); 268 } 269 } 270 271 public Object instanceCreate() throws java.io.IOException , ClassNotFoundException { 272 Object 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 r = ContextProvider.createReaderContextProvider( 282 new java.io.InputStreamReader (settingFO.getInputStream(),"UTF-8"), getFile() 284 ); 285 inst = getConvertor().read(r); 286 } 287 } catch (IOException ex) { 288 throw (IOException ) Exceptions.attachLocalizedMessage(ex, 289 InstanceProvider.this.toString()); 290 } catch (ClassNotFoundException ex) { 291 throw (ClassNotFoundException ) Exceptions.attachLocalizedMessage(ex, 292 InstanceProvider.this.toString()); 293 } 294 295 synchronized (this) { 296 Object existing = getCachedInstance(); 297 if (existing != null) return existing; 298 setCachedInstance(inst); 299 } 300 attachToInstance(inst); 301 302 return inst; 303 } 304 305 public String instanceName() { 306 String name = getInstanceClassName(); 307 if (name != null) return name; 308 309 Exception e = null; 310 try { 311 return instanceClass().getName(); 312 } catch (IOException ex) { 313 e = ex; 314 } catch (ClassNotFoundException 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"; } 324 325 public boolean instanceOf(Class <?> type) { 326 synchronized (InstanceProvider.this) { 327 if (instanceOfSet == null) { 328 instanceOfSet = Env.parseAttribute(providerFO.getAttribute(Env.EA_INSTANCE_OF)); 329 java.util.Iterator <String > it = instanceOfSet.iterator(); 330 instanceOfSet = new java.util.HashSet <String >(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 e = null; 338 try { 339 return type.isAssignableFrom(instanceClass()); 340 } catch (IOException ex) { 341 e = ex; 342 } catch (ClassNotFoundException 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 public void setInstance(Object inst, boolean save) throws IOException { 358 instanceCookieChanged(inst); 359 if (inst != null) { 360 attachToInstance(inst); 361 if (save) getScheduledRequest().runAndWait(); 362 } 363 } 364 365 private Object getCachedInstance() { 366 return cachedInstance.get(); 367 } 368 private void setCachedInstance(Object inst) { 369 cachedInstance = new SoftReference <Object >(inst); 370 } 371 } 372 373 377 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 <Node> type(InstanceProvider o) { 387 return Node.class; 388 } 389 390 public String id(InstanceProvider o) { 391 return o.toString(); 393 } 394 395 public String displayName(InstanceProvider o) { 396 return o.toString(); 398 } 399 400 } 401 } 402 | Popular Tags |