001: // NewStoreEntry.java
002: // $Id: NewStoreEntry.java,v 1.13 2007/02/09 22:30:20 ylafon Exp $
003: // (c) COPYRIGHT MIT, INRIA and Keio, 1999.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.tools.resources.store;
007:
008: import java.io.File;
009: import java.io.PrintStream;
010:
011: import java.util.Enumeration;
012: import java.util.Hashtable;
013:
014: import org.w3c.tools.resources.Attribute;
015: import org.w3c.tools.resources.AttributeHolder;
016: import org.w3c.tools.resources.AttributeRegistry;
017: import org.w3c.tools.resources.IntegerAttribute;
018: import org.w3c.tools.resources.InvalidResourceException;
019: import org.w3c.tools.resources.Resource;
020: import org.w3c.tools.resources.ResourceContext;
021: import org.w3c.tools.resources.ResourceReference;
022: import org.w3c.tools.resources.ServerInterface;
023: import org.w3c.tools.resources.StringAttribute;
024:
025: import org.w3c.util.LRUAble;
026:
027: class NewReference implements ResourceReference {
028:
029: public static boolean debug = false;
030:
031: // Our entry
032: NewStoreEntry entry = null;
033:
034: // The resource identifier
035: String identifier = null;
036:
037: // The default attributs
038: Hashtable defs = null;
039:
040: public void updateContext(ResourceContext ctxt) {
041: if (defs != null)
042: defs.put("context", ctxt);
043: }
044:
045: /**
046: * The lock count associated to the reference.
047: */
048: protected int lockCount = 0;
049:
050: public int nbLock() {
051: synchronized (identifier) {
052: return lockCount;
053: }
054: }
055:
056: protected void invalidate() {
057: entry = null;
058: }
059:
060: protected boolean isValid() {
061: return (entry != null);
062: }
063:
064: /**
065: * Lock that reference in memory.
066: * @return A pointer to the underlying resource, after lock succeed.
067: */
068: public synchronized Resource lock() throws InvalidResourceException {
069: synchronized (identifier) {
070: lockCount++;
071: }
072: if (entry == null)
073: throw new InvalidResourceException(identifier,
074: "This reference has been invalidated");
075: ResourceStore store = entry.getStore();
076: Resource resource = store.lookupResource(identifier);
077: if (debug) {
078: if (defs.get("context") == null) {
079: System.out.println("**** Context null for : "
080: + identifier);
081: } else if (((ResourceContext) (defs.get("context")))
082: .getServer() == null) {
083: System.out.println("**** Server null for " + identifier
084: + "'s context");
085: }
086: }
087: if (resource == null) {
088: resource = store.loadResource(identifier, defs);
089: }
090: if (debug) {
091: System.out.println("[LOCK] locking [" + lockCount + "]: "
092: + identifier);
093: }
094: return resource;
095: }
096:
097: /**
098: * Lock that reference in memory.
099: * @return A pointer to the underlying resource, after lock succeed.
100: */
101: public Resource unsafeLock() throws InvalidResourceException {
102: synchronized (identifier) {
103: lockCount++;
104: }
105: if (entry == null) {
106: throw new InvalidResourceException(identifier,
107: "This reference has been invalidated");
108: }
109: ResourceStore store = entry.getStore();
110: Resource resource = store.lookupResource(identifier);
111: if (debug) {
112: if (defs.get("context") == null) {
113: System.out.println("**** Context null for : "
114: + identifier);
115: } else if (((ResourceContext) (defs.get("context")))
116: .getServer() == null) {
117: System.out.println("**** Server null for " + identifier
118: + "'s context");
119: }
120: }
121: if (resource == null) {
122: resource = store.loadResource(identifier, defs);
123: }
124: if (debug) {
125: System.out.println("[LOCK] locking [" + lockCount + "]: "
126: + identifier);
127: }
128: return resource;
129: }
130:
131: /**
132: * Unlock that resource reference.
133: */
134: public void unlock() {
135: synchronized (identifier) {
136: lockCount--;
137: }
138: if (debug)
139: System.out.println("[LOCK] unlocking [" + lockCount + "]: "
140: + identifier);
141: }
142:
143: /**
144: * Is that resource locked ?
145: * @return A boolean, <strong>true</strong> if the resource is locked.
146: */
147: public boolean isLocked() {
148: return lockCount != 0;
149: }
150:
151: NewReference(NewStoreEntry entry, String identifier, Hashtable defs) {
152: this .entry = entry;
153: this .identifier = identifier;
154: this .defs = defs;
155: }
156: }
157:
158: public class NewStoreEntry extends AttributeHolder implements LRUAble {
159:
160: protected static int ATTR_REPOSITORY = -1;
161:
162: protected static int ATTR_KEY = -1;
163:
164: static {
165: Attribute a = null;
166: Class cls = null;
167: // Get a pointer to our own class:
168: try {
169: cls = Class
170: .forName("org.w3c.tools.resources.store.NewStoreEntry");
171: } catch (Exception ex) {
172: ex.printStackTrace();
173: System.exit(1);
174: }
175:
176: // The repository attribute:
177: a = new StringAttribute("repository", null, Attribute.MANDATORY);
178: ATTR_REPOSITORY = AttributeRegistry.registerAttribute(cls, a);
179: //The key attribute
180: a = new IntegerAttribute("key", null, Attribute.MANDATORY);
181: ATTR_KEY = AttributeRegistry.registerAttribute(cls, a);
182: }
183:
184: protected Integer getKey() {
185: return (Integer) getValue(ATTR_KEY, null);
186: }
187:
188: protected File getRepository() {
189: String repository = getString(ATTR_REPOSITORY, null);
190: if (rep == null)
191: rep = new File(manager.storedir, repository);
192: return rep;
193: }
194:
195: boolean istransient = false;
196:
197: // LRU management infos:
198: LRUAble next = null;
199: LRUAble prev = null;
200:
201: // ResourceStore infos:
202: ResourceStore store = null;
203:
204: // References
205: Hashtable references = null;
206:
207: //The manager
208: ResourceStoreManager manager = null;
209:
210: //The repository
211: File rep = null;
212:
213: public LRUAble getNext() {
214: return next;
215: }
216:
217: public LRUAble getPrev() {
218: return prev;
219: }
220:
221: public void setNext(LRUAble next) {
222: this .next = next;
223: }
224:
225: public void setPrev(LRUAble prev) {
226: this .prev = prev;
227: }
228:
229: public void setTransient(boolean onoff) {
230: istransient = onoff;
231: }
232:
233: public boolean isTransient() {
234: return istransient;
235: }
236:
237: /**
238: * Load the store of this entry.
239: */
240: ResourceStore getStore() {
241: if (store == null) {
242: synchronized (this ) {
243: if (store == null) {
244: store = new ResourceStoreImpl();
245: store.initialize(manager, this , getRepository(),
246: manager.serializer);
247: manager.incrLoadedStore();
248: }
249: }
250: }
251: return store;
252: }
253:
254: /**
255: * Delete the store of this entry
256: */
257: synchronized void deleteStore() {
258: Enumeration e = references.elements();
259: NewReference rr = null;
260: while (e.hasMoreElements()) {
261: rr = (NewReference) e.nextElement();
262: rr.invalidate();
263: }
264: getRepository().delete();
265: if (store != null) {
266: store = null;
267: manager.decrLoadedStore();
268: }
269: references = null;
270: }
271:
272: /**
273: * Lookup this resource.
274: * @param identifier The resource identifier.
275: * @return A Resource instance, or <strong>null</strong> if either the
276: * resource doesn't exist, or it isn't loaded yet.
277: */
278: public ResourceReference lookupResource(String identifier) {
279: return (ResourceReference) references.get(identifier);
280: }
281:
282: /**
283: * Load a resource, or get one from the cache.
284: * @param identifier The resource identifier.
285: * @return A Resource instance, or <strong>null</strong> if the resource
286: * doesn't exist in that storeEntry.
287: * @exception InvalidResourceException If the resource couldn't be
288: * restored from its pickled format.
289: */
290: synchronized ResourceReference loadResource(String name,
291: Hashtable defs) {
292: ResourceReference rr = lookupResource(name);
293: if (rr != null)
294: return rr;
295: rr = new NewReference(this , name, defs);
296: try {
297: Resource res = rr.lock();
298: if (res == null)
299: return null;
300: } catch (InvalidResourceException ex) {
301: return null;
302: } finally {
303: rr.unlock();
304: }
305: references.put(name, rr);
306: return rr;
307: }
308:
309: /**
310: * Save a given resource.
311: * @param resource The resource to be save right now.
312: */
313: synchronized void saveResource(Resource resource) {
314: getStore();
315: store.saveResource(resource);
316: }
317:
318: /**
319: * Add a new resource to the resource store.
320: * @param resource The resource to add.
321: */
322: ResourceReference addResource(Resource resource, Hashtable defs) {
323: ResourceReference rr = null;
324: synchronized (resource) {
325: synchronized (this ) {
326: getStore();
327: store.addResource(resource);
328: String name = resource.getIdentifier();
329: rr = new NewReference(this , name, defs);
330: references.put(name, rr);
331: }
332: }
333: return rr;
334: }
335:
336: /**
337: * FIXME doc
338: */
339: public void markModified(Resource resource) {
340: getStore();
341: store.markModified(resource);
342: }
343:
344: /**
345: * Rename a resource in this resource store.
346: * @param identifier The identifier of the resource to be renamed.
347: */
348: public synchronized void renameResource(String oldid, String newid) {
349: getStore();
350: store.renameResource(oldid, newid);
351: NewReference rr = (NewReference) lookupResource(oldid);
352: if (rr != null) {
353: rr.identifier = newid;
354: references.remove(oldid);
355: references.put(newid, rr);
356: }
357: }
358:
359: public synchronized Enumeration enumerateResourceIdentifiers() {
360: getStore();
361: return store.enumerateResourceIdentifiers();
362: }
363:
364: /**
365: * Remove a resource from this resource store.
366: * @param identifier The identifier of the resource to be removed.
367: */
368: public synchronized void removeResource(String identifier) {
369: getStore();
370: NewReference rr = (NewReference) references.get(identifier);
371: if (rr != null) {
372: references.remove(identifier);
373: manager.getEventQueue().removeSourceEvents(rr);
374: rr.invalidate();
375: }
376: store.removeResource(identifier);
377: }
378:
379: /**
380: * Try unloading the space for this entry.
381: */
382: synchronized boolean unloadStore() {
383: if (store != null) {
384: Enumeration e = references.elements();
385: ResourceReference rr = null;
386: while (e.hasMoreElements()) {
387: rr = (ResourceReference) e.nextElement();
388: if (rr.isLocked())
389: return false;
390: }
391: // Will the store unload itself ?
392: if (!store.acceptUnload())
393: return false;
394: // Great, proceed:
395: shutdownStore();
396: }
397: return true;
398: }
399:
400: /**
401: * Shutdown the store.
402: */
403: synchronized void shutdownStore() {
404: if (store != null) {
405: store.shutdown();
406: store = null;
407: references = new Hashtable(3);
408: manager.decrLoadedStore();
409: }
410: }
411:
412: /**
413: * Try stabilizing the store.
414: */
415: synchronized void saveStore() {
416: if (store != null) {
417: // Save the resource store:
418: store.save();
419: }
420: }
421:
422: void initialize(ResourceStoreManager manager) {
423: this .manager = manager;
424: this .references = new Hashtable(3);
425: }
426:
427: NewStoreEntry(ResourceStoreManager manager, String repository,
428: Integer key) {
429: this .manager = manager;
430: this .store = null;
431: this .references = new Hashtable(3);
432: setValue(ATTR_REPOSITORY, repository);
433: setValue(ATTR_KEY, key);
434: }
435:
436: NewStoreEntry(ResourceStoreManager manager, File repository,
437: Integer key) {
438: this .manager = manager;
439: this .store = null;
440: this .rep = repository;
441: this .references = new Hashtable(3);
442: setValue(ATTR_KEY, key);
443: }
444:
445: public NewStoreEntry() {
446: }
447:
448: }
|