001: /*
002: * @(#)memcache.java 1.2 04/12/06
003: *
004: * Copyright (c) 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package org.pnuts.lib;
010:
011: import pnuts.lang.*;
012: import java.util.*;
013: import java.lang.ref.*;
014:
015: /*
016: * function memcache(func)
017: */
018: public class memcache extends PnutsFunction {
019:
020: static Object[] NO_ARGS = new Object[] {};
021:
022: public memcache() {
023: super ("memcache");
024: }
025:
026: public boolean defined(int narg) {
027: return (narg == 1);
028: }
029:
030: protected Object exec(Object[] args, Context context) {
031: if (args.length != 1) {
032: undefined(args, context);
033: return null;
034: }
035: PnutsFunction handler = (PnutsFunction) args[0];
036: Context ctx = (Context) context.clone();
037: if (handler.defined(0)) {
038: return new MemoryCache(handler.call(NO_ARGS, ctx), handler,
039: ctx);
040: } else if (handler.defined(-1)) {
041: return new MemoryCache(handler.call(NO_ARGS, ctx), handler,
042: ctx);
043: } else if (handler.defined(1)) {
044: return new MemoryCache(null, handler, ctx);
045: } else {
046: throw new IllegalArgumentException();
047: }
048: }
049:
050: public String toString() {
051: return "function memcache(func()) or (func(key))";
052: }
053:
054: static class MemoryCache extends PnutsFunction implements Map {
055: SoftReference ref;
056: ResourceCache cache;
057: Context context;
058: PnutsFunction handler;
059:
060: MemoryCache(Object initial, final PnutsFunction handler,
061: final Context context) {
062: this .handler = handler;
063: this .context = context;
064: if (initial != null) {
065: this .ref = new SoftReference(initial);
066: }
067: this .cache = new ResourceCache() {
068: protected Object createResource(Object key) {
069: return handler.call(new Object[] { key }, context);
070: }
071: };
072: }
073:
074: public boolean defined(int nargs) {
075: return nargs == 0;
076: }
077:
078: protected Object exec(Object[] args, Context context) {
079: if (args.length != 0) {
080: undefined(args, context);
081: }
082: Object value;
083: synchronized (this ) {
084: if (ref == null || (value = ref.get()) == null) {
085: value = handler.call(NO_ARGS, this .context);
086: this .ref = new SoftReference(value);
087: }
088: }
089: return value;
090: }
091:
092: /**
093: * Gets a resource associated with the specified key.
094: * If the resource has been expired, a new one is created.
095: *
096: * @param name the key of the resource
097: * @return a resource associated with the key
098: */
099: public Object get(Object key) {
100: return cache.getResource(key);
101: }
102:
103: /**
104: * Throws an exception, since this operation is not supported in this class.
105: *
106: * @param name the key of the resource
107: * @param value the value of the resource
108: */
109: public Object put(Object key, Object value) {
110: throw new UnsupportedOperationException();
111: }
112:
113: /**
114: * Throws an exception, since this operation is not supported in this class.
115: */
116: public int size() {
117: throw new UnsupportedOperationException();
118: }
119:
120: /**
121: * Throws an exception, since this operation is not supported in this class.
122: */
123: public boolean isEmpty() {
124: throw new UnsupportedOperationException();
125: }
126:
127: /**
128: * Throws an exception, since this operation is not supported in this class.
129: */
130: public boolean containsKey(Object key) {
131: throw new UnsupportedOperationException();
132: }
133:
134: /**
135: * Throws an exception, since this operation is not supported in this class.
136: */
137: public boolean containsValue(Object value) {
138: throw new UnsupportedOperationException();
139: }
140:
141: /**
142: * Throws an exception, since this operation is not supported in this class.
143: */
144: public Object remove(Object key) {
145: throw new UnsupportedOperationException();
146: }
147:
148: public void invalidate(Object key) {
149: cache.invalidate(key);
150: }
151:
152: public synchronized void invalidate() {
153: ref = null;
154: }
155:
156: /**
157: * Throws an exception, since this operation is not supported in this class.
158: */
159: public void putAll(Map t) {
160: throw new UnsupportedOperationException();
161: }
162:
163: /**
164: * Throws an exception, since this operation is not supported in this class.
165: */
166: public void clear() {
167: throw new UnsupportedOperationException();
168: }
169:
170: /**
171: * Throws an exception, since this operation is not supported in this class.
172: */
173: public Set keySet() {
174: throw new UnsupportedOperationException();
175: }
176:
177: /**
178: * Throws an exception, since this operation is not supported in this class.
179: */
180: public Collection values() {
181: throw new UnsupportedOperationException();
182: }
183:
184: /**
185: * Throws an exception, since this operation is not supported in this class.
186: */
187: public Set entrySet() {
188: throw new UnsupportedOperationException();
189: }
190: }
191: }
|