001: package vicazh.hyperpool.stream;
002:
003: import java.io.*;
004: import java.util.*;
005: import vicazh.hyperpool.Reader;
006: import vicazh.hyperpool.Start;
007:
008: /**
009: * The file service
010: *
011: * @author Victor Zhigunov
012: * @version 0.4.0
013: */
014: abstract public class FileService extends Service implements
015: FileServiceMBean, Runnable, Serializable {
016: public FileService() {
017: }
018:
019: private int cachesize;
020:
021: private TreeMap<Object, File> map;
022:
023: /**
024: * @param cachesize
025: * cache size
026: */
027: public FileService(int cachesize) {
028: this .cachesize = cachesize;
029: map = new TreeMap<Object, File>();
030: }
031:
032: private String dir;
033:
034: /**
035: * Get the service directory
036: */
037: public String getDir() {
038: return dir;
039: }
040:
041: /**
042: * Set the service directory
043: */
044: synchronized public void setDir(String dir) {
045: if (this .dir != null && !this .dir.equals(dir)) {
046: c = true;
047: while (!noscan || !nozap || clear)
048: try {
049: wait();
050: } catch (InterruptedException e) {
051: }
052: c = false;
053: this .dir = dir;
054: map.clear();
055: pack();
056: } else
057: this .dir = dir;
058: }
059:
060: public String dir2path() {
061: return dir.replace('/', File.separatorChar);
062: }
063:
064: public void path2dir(String dir) {
065: setDir(dir.replace(File.separatorChar, '/'));
066: }
067:
068: private boolean noscan;
069:
070: public void run() {
071: File d = new File(dir2path());
072: if (d.exists())
073: scan(d);
074: zap();
075: synchronized (this ) {
076: noscan = true;
077: notifyAll();
078: }
079: }
080:
081: private void scan(File file) {
082: File[] l = file.listFiles();
083: if (l == null || l.length == 0)
084: delete(file);
085: else
086: for (int i = 0; i < l.length; i++) {
087: if (c)
088: return;
089: Thread.yield();
090: if (l[i].isFile())
091: if (checkPut(l[i]))
092: put(l[i]);
093: else
094: delete(l[i]);
095: else
096: scan(l[i]);
097: }
098: }
099:
100: abstract public boolean checkPut(File file);
101:
102: private boolean nozap;
103:
104: public void pack() {
105: synchronized (this ) {
106: if (!noscan || !nozap || clear)
107: return;
108: if (map.size() == 0)
109: noscan = false;
110: else
111: nozap = false;
112: }
113: if (map.size() == 0)
114: fill();
115: else
116: new Thread() {
117: public void run() {
118: zap();
119: }
120: }.start();
121: }
122:
123: protected void zap() {
124: while (!c && map.size() > 0) {
125: Thread.yield();
126: Object k = map.firstKey();
127: File file = map.get(k);
128: if (!checkRemove(file))
129: break;
130: remove(file);
131: delete(file);
132: if (map.size() > 0 && k == map.firstKey())
133: map.remove(k);
134: }
135: synchronized (this ) {
136: sendAttribute(FileServiceMBean.ZAP, getFileData());
137: nozap = true;
138: notifyAll();
139: }
140: }
141:
142: abstract public boolean checkRemove(File file);
143:
144: synchronized protected void delete(File file) {
145: delpath(file);
146: }
147:
148: public void delpath(File file) {
149: file.delete();
150: if (file.equals(new File(dir2path())))
151: return;
152: File f = file.getParentFile();
153: if (f == null)
154: return;
155: File[] l = f.listFiles();
156: if (l == null)
157: return;
158: if (l.length == 0)
159: delpath(f);
160: }
161:
162: private boolean clear;
163:
164: protected void clear() {
165: synchronized (this ) {
166: if (clear)
167: return;
168: while (!noscan || !nozap)
169: try {
170: wait();
171: } catch (InterruptedException e) {
172: }
173: clear = true;
174: }
175: clear(new File(dir2path()));
176: map.clear();
177: synchronized (this ) {
178: clear = false;
179: notifyAll();
180: }
181: }
182:
183: protected void clear(File file) {
184: File[] l = file.listFiles();
185: if (l != null)
186: for (int i = 0; i < l.length; i++) {
187: if (c)
188: return;
189: Thread.yield();
190: if (l[i].isFile())
191: l[i].delete();
192: else
193: clear(l[i]);
194: }
195: file.delete();
196: }
197:
198: synchronized protected void put(File file) {
199: map.put(file.lastModified() + file.getPath(), file);
200: if (map.size() > cachesize)
201: map.remove(map.lastKey());
202: Start.logger.finest("map.size:" + map.size());
203: }
204:
205: synchronized public void remove(File file) {
206: map.remove(file.lastModified() + file.getPath());
207: Start.logger.finest("map.size:" + map.size());
208: }
209:
210: protected void fill() {
211: Thread t = new Thread(this );
212: t.setPriority(Thread.MIN_PRIORITY);
213: t.start();
214: }
215:
216: public void start() throws Exception {
217: super .start();
218: fill();
219: }
220:
221: protected boolean c;
222:
223: synchronized public void stop() throws Exception {
224: c = true;
225: super .stop();
226: }
227:
228: public byte[] get(File file) throws IOException {
229: return Reader.get(file);
230: }
231:
232: public void setAttribute(String name, Object value)
233: throws Exception {
234: if (name.equals(FileServiceMBean.OPTIONS)) {
235: path2dir(((FileService) value).getDir());
236: super .setAttribute(name, value);
237: } else {
238: if (name.equals(FileServiceMBean.CLEAR))
239: clear();
240: super .setAttribute(name, getFileData());
241: }
242: }
243:
244: protected FileData getFileData() {
245: return new FileData(new File(dir2path()).exists());
246: }
247:
248: public char getSeparator() {
249: return File.separatorChar;
250: }
251: }
|