1 /*
2 * Copyright (c) 2005 The University of Reading
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University of Reading, nor the names of the
14 * authors or contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 package uk.ac.rdg.resc.jstyx.client.callbacks;
30
31 import java.util.Vector;
32
33 import org.apache.mina.common.ByteBuffer;
34
35 import uk.ac.rdg.resc.jstyx.client.StyxConnection;
36 import uk.ac.rdg.resc.jstyx.client.CStyxFile;
37 import uk.ac.rdg.resc.jstyx.client.MessageCallback;
38
39 import uk.ac.rdg.resc.jstyx.messages.StyxMessage;
40 import uk.ac.rdg.resc.jstyx.messages.RstatMessage;
41 import uk.ac.rdg.resc.jstyx.messages.RreadMessage;
42 import uk.ac.rdg.resc.jstyx.messages.StyxBuffer;
43
44 import uk.ac.rdg.resc.jstyx.types.DirEntry;
45
46 /***
47 * Callback that is used when reading the children of a directory. See
48 * CStyxFile.getChildrenAsync()
49 *
50 * @author jdb
51 * $Revision: 380 $
52 * $Date: 2005-08-31 18:07:59 +0100 (Wed, 31 Aug 2005) $
53 * $Log$
54 * Revision 1.2 2005/08/31 17:07:59 jonblower
55 * Fixed bug with clunking fids and released ByteBuffer correctly
56 *
57 * Revision 1.1 2005/08/05 13:46:40 jonblower
58 * Factored out all callback objects from CStyxFile into separate classes
59 *
60 */
61
62 public class GetChildrenCallback extends MessageCallback
63 {
64 private Vector dirEntries;
65 private long offset;
66 private boolean wasOpen;
67 private boolean firstTime;
68 private MessageCallback callback;
69 private CStyxFile file;
70 private StyxConnection conn;
71
72 public GetChildrenCallback(CStyxFile file, MessageCallback callback)
73 {
74 this.file = file;
75 this.conn = this.file.getConnection();
76 this.dirEntries = new Vector();
77 this.offset = 0;
78 this.callback = callback;
79 this.firstTime = true;
80 }
81
82 public void nextStage()
83 {
84 // First check that this is a directory
85 if (this.file.getDirEntry() == null)
86 {
87 // We need to get the stat for this file
88 this.file.refreshAsync(this);
89 }
90 else if (this.file.getQid().getType() == 128)
91 {
92 // this is a directory (or we don't care if this is a directory
93 // or not).
94 if (this.firstTime)
95 {
96 // First check to see if we already have it open
97 this.wasOpen = this.file.isOpen();
98 this.firstTime = false;
99 }
100 // Now find the children
101 this.file.readAsync(this.offset, this);
102 }
103 else
104 {
105 // This is not a directory. raise an error
106 this.error("not a directory", null);
107 }
108 }
109
110 public void replyArrived(StyxMessage rMessage, StyxMessage tMessage)
111 {
112 if (rMessage instanceof RstatMessage)
113 {
114 // We've just got the stat of the file. Proceed to the next
115 // stage (i.e. start reading data)
116 this.nextStage();
117 }
118 else
119 {
120 // this must be an RreadMessage
121 RreadMessage rReadMsg = (RreadMessage)rMessage;
122 ByteBuffer data = rReadMsg.getData();
123 this.offset += data.remaining();
124 if (data.remaining() > 0)
125 {
126 // Wrap data as a StyxBuffer
127 StyxBuffer styxBuf = new StyxBuffer(data);
128 // Get all the DirEntries from this buffer
129 while(data.hasRemaining())
130 {
131 DirEntry dirEntry = styxBuf.getDirEntry();
132 CStyxFile newFile = this.conn.getFile(this.file.getPath()
133 + "/" + dirEntry.getFileName());
134 newFile.setDirEntry(dirEntry);
135 this.dirEntries.add(newFile);
136 }
137 // Read from this file again
138 this.nextStage();
139 }
140 else
141 {
142 // We've read all the data from the file
143 if (!this.wasOpen)
144 {
145 // If this file wasn't open before we started reading
146 // the children, close it
147 this.file.close();
148 }
149 this.file.setChildren((CStyxFile[])this.dirEntries.toArray(new CStyxFile[0]));
150 if (this.callback != null)
151 {
152 this.callback.replyArrived(rMessage, tMessage);
153 }
154 else
155 {
156 this.file.fireChildrenFound();
157 }
158 }
159 // We need to release the buffer
160 data.release();
161 }
162 }
163
164 public void error(String message, StyxMessage tMessage)
165 {
166 String errMsg = "Error getting directory contents from " + this.file.getPath()
167 + ": " + message;
168 if (this.callback != null)
169 {
170 this.callback.error(errMsg, tMessage);
171 }
172 else
173 {
174 this.file.fireError(errMsg);
175 }
176 }
177 }