716 |
02 Jun 08 |
nicklas |
1 |
/** |
716 |
02 Jun 08 |
nicklas |
$Id $ |
716 |
02 Jun 08 |
nicklas |
3 |
|
716 |
02 Jun 08 |
nicklas |
Copyright (C) 2008 Nicklas Nordborg |
716 |
02 Jun 08 |
nicklas |
5 |
|
1381 |
15 Aug 11 |
martin |
This file is part of the FTP Server extension for BASE. |
716 |
02 Jun 08 |
nicklas |
Available at http://baseplugins.thep.lu.se/ |
1381 |
15 Aug 11 |
martin |
BASE main site: http://base.thep.lu.se/ |
1381 |
15 Aug 11 |
martin |
9 |
----------------------------------------------------------- |
1381 |
15 Aug 11 |
martin |
10 |
|
1381 |
15 Aug 11 |
martin |
This is free software; you can redistribute it and/or |
716 |
02 Jun 08 |
nicklas |
modify it under the terms of the GNU General Public License |
1381 |
15 Aug 11 |
martin |
as published by the Free Software Foundation; either version 3 |
716 |
02 Jun 08 |
nicklas |
of the License, or (at your option) any later version. |
1381 |
15 Aug 11 |
martin |
15 |
|
1381 |
15 Aug 11 |
martin |
The software is distributed in the hope that it will be useful, |
716 |
02 Jun 08 |
nicklas |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
716 |
02 Jun 08 |
nicklas |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
716 |
02 Jun 08 |
nicklas |
GNU General Public License for more details. |
1381 |
15 Aug 11 |
martin |
20 |
|
1381 |
15 Aug 11 |
martin |
You should have received a copy of the GNU General Public License |
1381 |
15 Aug 11 |
martin |
along with BASE. If not, see <http://www.gnu.org/licenses/>. |
716 |
02 Jun 08 |
nicklas |
23 |
|
716 |
02 Jun 08 |
nicklas |
24 |
*/ |
714 |
30 May 08 |
nicklas |
25 |
package net.sf.basedb.clients.ftp; |
714 |
30 May 08 |
nicklas |
26 |
|
714 |
30 May 08 |
nicklas |
27 |
import java.io.IOException; |
714 |
30 May 08 |
nicklas |
28 |
import java.io.InputStream; |
714 |
30 May 08 |
nicklas |
29 |
import java.io.OutputStream; |
714 |
30 May 08 |
nicklas |
30 |
import java.util.ArrayList; |
939 |
21 Jan 09 |
nicklas |
31 |
import java.util.Date; |
714 |
30 May 08 |
nicklas |
32 |
import java.util.List; |
714 |
30 May 08 |
nicklas |
33 |
|
714 |
30 May 08 |
nicklas |
34 |
import net.sf.basedb.core.DbControl; |
714 |
30 May 08 |
nicklas |
35 |
import net.sf.basedb.core.Directory; |
714 |
30 May 08 |
nicklas |
36 |
import net.sf.basedb.core.File; |
714 |
30 May 08 |
nicklas |
37 |
import net.sf.basedb.core.Include; |
714 |
30 May 08 |
nicklas |
38 |
import net.sf.basedb.core.Item; |
714 |
30 May 08 |
nicklas |
39 |
import net.sf.basedb.core.ItemQuery; |
1225 |
05 May 10 |
nicklas |
40 |
import net.sf.basedb.core.Location; |
714 |
30 May 08 |
nicklas |
41 |
import net.sf.basedb.core.OwnedItem; |
714 |
30 May 08 |
nicklas |
42 |
import net.sf.basedb.core.Path; |
714 |
30 May 08 |
nicklas |
43 |
import net.sf.basedb.core.Permission; |
714 |
30 May 08 |
nicklas |
44 |
import net.sf.basedb.core.query.Hql; |
714 |
30 May 08 |
nicklas |
45 |
import net.sf.basedb.core.query.Orders; |
714 |
30 May 08 |
nicklas |
46 |
|
915 |
11 Dec 08 |
nicklas |
47 |
import org.apache.ftpserver.ftplet.FtpFile; |
716 |
02 Jun 08 |
nicklas |
48 |
import org.slf4j.Logger; |
716 |
02 Jun 08 |
nicklas |
49 |
import org.slf4j.LoggerFactory; |
714 |
30 May 08 |
nicklas |
50 |
|
714 |
30 May 08 |
nicklas |
51 |
/** |
714 |
30 May 08 |
nicklas |
A file object can represent three different things: |
714 |
30 May 08 |
nicklas |
<ol> |
714 |
30 May 08 |
nicklas |
<li>An existing file on the BASE server (LIST, RETR) |
714 |
30 May 08 |
nicklas |
<li>An existing directory on the BASE server (CWD, LIST) |
714 |
30 May 08 |
nicklas |
<li>An path name that doesn't exists and may be created as either |
714 |
30 May 08 |
nicklas |
a directory (MKDIR) or file (STOR) |
714 |
30 May 08 |
nicklas |
</ol> |
716 |
02 Jun 08 |
nicklas |
@author Nicklas |
716 |
02 Jun 08 |
nicklas |
@version 1.0 |
714 |
30 May 08 |
nicklas |
61 |
*/ |
915 |
11 Dec 08 |
nicklas |
62 |
public class BaseFtpFile |
915 |
11 Dec 08 |
nicklas |
63 |
implements FtpFile |
714 |
30 May 08 |
nicklas |
64 |
{ |
915 |
11 Dec 08 |
nicklas |
65 |
private static final Logger log = LoggerFactory.getLogger(BaseFtpFile.class); |
714 |
30 May 08 |
nicklas |
66 |
|
714 |
30 May 08 |
nicklas |
67 |
private BaseUser user; |
714 |
30 May 08 |
nicklas |
68 |
private File file; |
714 |
30 May 08 |
nicklas |
69 |
private Directory directory; |
714 |
30 May 08 |
nicklas |
70 |
private String owner; |
714 |
30 May 08 |
nicklas |
71 |
private String name; |
714 |
30 May 08 |
nicklas |
72 |
private String path; |
714 |
30 May 08 |
nicklas |
73 |
|
714 |
30 May 08 |
nicklas |
74 |
/** |
714 |
30 May 08 |
nicklas |
Create a file object that represents an existing file on |
714 |
30 May 08 |
nicklas |
the BASE server. |
714 |
30 May 08 |
nicklas |
77 |
*/ |
915 |
11 Dec 08 |
nicklas |
78 |
public BaseFtpFile(BaseUser user, File file) |
714 |
30 May 08 |
nicklas |
79 |
{ |
714 |
30 May 08 |
nicklas |
80 |
this.user = user; |
714 |
30 May 08 |
nicklas |
81 |
this.file = file; |
714 |
30 May 08 |
nicklas |
82 |
this.name = file.getName(); |
714 |
30 May 08 |
nicklas |
83 |
this.owner = getOwner(file); |
714 |
30 May 08 |
nicklas |
84 |
this.path = file.getPath().toString(); |
714 |
30 May 08 |
nicklas |
85 |
} |
714 |
30 May 08 |
nicklas |
86 |
|
714 |
30 May 08 |
nicklas |
87 |
/** |
714 |
30 May 08 |
nicklas |
Create a file object that represents an existing directory on |
714 |
30 May 08 |
nicklas |
the BASE server. |
714 |
30 May 08 |
nicklas |
90 |
*/ |
915 |
11 Dec 08 |
nicklas |
91 |
public BaseFtpFile(BaseUser user, Directory directory) |
714 |
30 May 08 |
nicklas |
92 |
{ |
714 |
30 May 08 |
nicklas |
93 |
this.user = user; |
714 |
30 May 08 |
nicklas |
94 |
this.directory = directory; |
714 |
30 May 08 |
nicklas |
95 |
this.name = directory.getName(); |
714 |
30 May 08 |
nicklas |
96 |
this.owner = getOwner(directory); |
714 |
30 May 08 |
nicklas |
97 |
this.path = directory.getPath().toString(); |
714 |
30 May 08 |
nicklas |
98 |
} |
714 |
30 May 08 |
nicklas |
99 |
|
714 |
30 May 08 |
nicklas |
100 |
/** |
714 |
30 May 08 |
nicklas |
Create a file object that represents an non-existing file or |
714 |
30 May 08 |
nicklas |
directory. |
714 |
30 May 08 |
nicklas |
103 |
*/ |
915 |
11 Dec 08 |
nicklas |
104 |
public BaseFtpFile(BaseUser user, String path) |
714 |
30 May 08 |
nicklas |
105 |
{ |
714 |
30 May 08 |
nicklas |
106 |
this.user = user; |
714 |
30 May 08 |
nicklas |
107 |
this.path = path; |
714 |
30 May 08 |
nicklas |
108 |
this.name = path.substring(path.lastIndexOf('/')+1); |
714 |
30 May 08 |
nicklas |
109 |
this.owner = user.getName(); |
714 |
30 May 08 |
nicklas |
110 |
} |
714 |
30 May 08 |
nicklas |
111 |
|
714 |
30 May 08 |
nicklas |
112 |
/* |
915 |
11 Dec 08 |
nicklas |
From the FtpFile interface |
714 |
30 May 08 |
nicklas |
114 |
------------------------------------------ |
714 |
30 May 08 |
nicklas |
115 |
*/ |
714 |
30 May 08 |
nicklas |
116 |
@Override |
915 |
11 Dec 08 |
nicklas |
117 |
public String getAbsolutePath() |
714 |
30 May 08 |
nicklas |
118 |
{ |
714 |
30 May 08 |
nicklas |
119 |
return path; |
714 |
30 May 08 |
nicklas |
120 |
} |
714 |
30 May 08 |
nicklas |
121 |
|
714 |
30 May 08 |
nicklas |
122 |
@Override |
915 |
11 Dec 08 |
nicklas |
123 |
public String getName() |
714 |
30 May 08 |
nicklas |
124 |
{ |
714 |
30 May 08 |
nicklas |
125 |
return name; |
714 |
30 May 08 |
nicklas |
126 |
} |
714 |
30 May 08 |
nicklas |
127 |
|
714 |
30 May 08 |
nicklas |
128 |
/** |
714 |
30 May 08 |
nicklas |
Check if this represents an existing file or directory on |
714 |
30 May 08 |
nicklas |
the BASE server. |
714 |
30 May 08 |
nicklas |
131 |
*/ |
714 |
30 May 08 |
nicklas |
132 |
@Override |
714 |
30 May 08 |
nicklas |
133 |
public boolean doesExist() |
714 |
30 May 08 |
nicklas |
134 |
{ |
714 |
30 May 08 |
nicklas |
135 |
return file != null || directory != null; |
714 |
30 May 08 |
nicklas |
136 |
} |
714 |
30 May 08 |
nicklas |
137 |
|
714 |
30 May 08 |
nicklas |
138 |
/** |
714 |
30 May 08 |
nicklas |
Checks if this represents an existing file on the |
714 |
30 May 08 |
nicklas |
BASE server. |
714 |
30 May 08 |
nicklas |
141 |
*/ |
714 |
30 May 08 |
nicklas |
142 |
@Override |
714 |
30 May 08 |
nicklas |
143 |
public boolean isFile() |
714 |
30 May 08 |
nicklas |
144 |
{ |
714 |
30 May 08 |
nicklas |
145 |
return file != null; |
714 |
30 May 08 |
nicklas |
146 |
} |
714 |
30 May 08 |
nicklas |
147 |
|
714 |
30 May 08 |
nicklas |
148 |
/** |
714 |
30 May 08 |
nicklas |
Checks if this represents an existing directory on the |
714 |
30 May 08 |
nicklas |
BASE server. |
714 |
30 May 08 |
nicklas |
151 |
*/ |
714 |
30 May 08 |
nicklas |
152 |
@Override |
714 |
30 May 08 |
nicklas |
153 |
public boolean isDirectory() |
714 |
30 May 08 |
nicklas |
154 |
{ |
714 |
30 May 08 |
nicklas |
155 |
return directory != null; |
714 |
30 May 08 |
nicklas |
156 |
} |
714 |
30 May 08 |
nicklas |
157 |
|
714 |
30 May 08 |
nicklas |
158 |
/** |
714 |
30 May 08 |
nicklas |
Existing files or directories that have been marked for removal |
714 |
30 May 08 |
nicklas |
are hidden. |
714 |
30 May 08 |
nicklas |
161 |
*/ |
714 |
30 May 08 |
nicklas |
162 |
@Override |
714 |
30 May 08 |
nicklas |
163 |
public boolean isHidden() |
714 |
30 May 08 |
nicklas |
164 |
{ |
714 |
30 May 08 |
nicklas |
165 |
return file != null && file.isRemoved() || directory != null && directory.isRemoved(); |
714 |
30 May 08 |
nicklas |
166 |
} |
714 |
30 May 08 |
nicklas |
167 |
|
714 |
30 May 08 |
nicklas |
168 |
/** |
714 |
30 May 08 |
nicklas |
Get the size of the file if it exists in BASE, |
714 |
30 May 08 |
nicklas |
or 0 otherwise. |
714 |
30 May 08 |
nicklas |
171 |
*/ |
714 |
30 May 08 |
nicklas |
172 |
@Override |
714 |
30 May 08 |
nicklas |
173 |
public long getSize() |
714 |
30 May 08 |
nicklas |
174 |
{ |
1225 |
05 May 10 |
nicklas |
175 |
return file == null || file.getSize() < 0 ? 0 : file.getSize(); |
714 |
30 May 08 |
nicklas |
176 |
} |
714 |
30 May 08 |
nicklas |
177 |
|
714 |
30 May 08 |
nicklas |
178 |
/** |
716 |
02 Jun 08 |
nicklas |
3 for directories, 1 for files (TODO - I don't understand why, but this is how |
716 |
02 Jun 08 |
nicklas |
the {@link NativeFileObject} object does it). |
714 |
30 May 08 |
nicklas |
181 |
*/ |
714 |
30 May 08 |
nicklas |
182 |
@Override |
714 |
30 May 08 |
nicklas |
183 |
public int getLinkCount() |
714 |
30 May 08 |
nicklas |
184 |
{ |
714 |
30 May 08 |
nicklas |
185 |
return directory == null ? 1 : 3; |
714 |
30 May 08 |
nicklas |
186 |
} |
714 |
30 May 08 |
nicklas |
187 |
|
714 |
30 May 08 |
nicklas |
188 |
@Override |
714 |
30 May 08 |
nicklas |
189 |
public String getOwnerName() |
714 |
30 May 08 |
nicklas |
190 |
{ |
714 |
30 May 08 |
nicklas |
191 |
return owner; |
714 |
30 May 08 |
nicklas |
192 |
} |
714 |
30 May 08 |
nicklas |
193 |
|
714 |
30 May 08 |
nicklas |
194 |
/** |
714 |
30 May 08 |
nicklas |
Always an empty string. |
714 |
30 May 08 |
nicklas |
196 |
*/ |
714 |
30 May 08 |
nicklas |
197 |
@Override |
714 |
30 May 08 |
nicklas |
198 |
public String getGroupName() |
714 |
30 May 08 |
nicklas |
199 |
{ |
714 |
30 May 08 |
nicklas |
200 |
return ""; |
714 |
30 May 08 |
nicklas |
201 |
} |
714 |
30 May 08 |
nicklas |
202 |
|
714 |
30 May 08 |
nicklas |
203 |
/** |
716 |
02 Jun 08 |
nicklas |
If it is a file, get it's last update time. |
716 |
02 Jun 08 |
nicklas |
If it is a directory, return the current time. |
716 |
02 Jun 08 |
nicklas |
Otherwise, return 0. |
714 |
30 May 08 |
nicklas |
207 |
*/ |
714 |
30 May 08 |
nicklas |
208 |
@Override |
714 |
30 May 08 |
nicklas |
209 |
public long getLastModified() |
714 |
30 May 08 |
nicklas |
210 |
{ |
939 |
21 Jan 09 |
nicklas |
211 |
Date time = null; |
939 |
21 Jan 09 |
nicklas |
212 |
if (file != null) time = file.getLastUpdate(); |
939 |
21 Jan 09 |
nicklas |
213 |
return time == null ? System.currentTimeMillis() : time.getTime(); |
714 |
30 May 08 |
nicklas |
214 |
} |
714 |
30 May 08 |
nicklas |
215 |
|
714 |
30 May 08 |
nicklas |
216 |
/** |
917 |
12 Dec 08 |
nicklas |
Ignored since BASE doesn't allow us to change this. |
985 |
11 Mar 09 |
nicklas |
@return Always "false" |
917 |
12 Dec 08 |
nicklas |
219 |
*/ |
917 |
12 Dec 08 |
nicklas |
220 |
@Override |
985 |
11 Mar 09 |
nicklas |
221 |
public boolean setLastModified(long lastModified) |
985 |
11 Mar 09 |
nicklas |
222 |
{ |
985 |
11 Mar 09 |
nicklas |
223 |
return false; |
985 |
11 Mar 09 |
nicklas |
224 |
} |
917 |
12 Dec 08 |
nicklas |
225 |
|
917 |
12 Dec 08 |
nicklas |
226 |
/** |
714 |
30 May 08 |
nicklas |
Always true. |
714 |
30 May 08 |
nicklas |
228 |
*/ |
714 |
30 May 08 |
nicklas |
229 |
@Override |
915 |
11 Dec 08 |
nicklas |
230 |
public boolean isReadable() |
714 |
30 May 08 |
nicklas |
231 |
{ |
714 |
30 May 08 |
nicklas |
232 |
return true; |
714 |
30 May 08 |
nicklas |
233 |
} |
714 |
30 May 08 |
nicklas |
234 |
|
714 |
30 May 08 |
nicklas |
235 |
/** |
714 |
30 May 08 |
nicklas |
Check the existing file or directory for delete permission. |
714 |
30 May 08 |
nicklas |
FALSE in other cases. |
714 |
30 May 08 |
nicklas |
238 |
*/ |
714 |
30 May 08 |
nicklas |
239 |
@Override |
915 |
11 Dec 08 |
nicklas |
240 |
public boolean isRemovable() |
714 |
30 May 08 |
nicklas |
241 |
{ |
714 |
30 May 08 |
nicklas |
242 |
boolean permission = false; |
714 |
30 May 08 |
nicklas |
243 |
if (file != null) |
714 |
30 May 08 |
nicklas |
244 |
{ |
714 |
30 May 08 |
nicklas |
245 |
permission = file.hasPermission(Permission.DELETE); |
714 |
30 May 08 |
nicklas |
246 |
} |
714 |
30 May 08 |
nicklas |
247 |
else if (directory != null) |
714 |
30 May 08 |
nicklas |
248 |
{ |
714 |
30 May 08 |
nicklas |
249 |
permission = directory.hasPermission(Permission.DELETE); |
714 |
30 May 08 |
nicklas |
250 |
} |
714 |
30 May 08 |
nicklas |
251 |
return permission; |
714 |
30 May 08 |
nicklas |
252 |
} |
714 |
30 May 08 |
nicklas |
253 |
|
714 |
30 May 08 |
nicklas |
254 |
/** |
714 |
30 May 08 |
nicklas |
Check the existing file or directory for write permission. |
714 |
30 May 08 |
nicklas |
TRUE in other cases. |
714 |
30 May 08 |
nicklas |
257 |
*/ |
714 |
30 May 08 |
nicklas |
258 |
@Override |
915 |
11 Dec 08 |
nicklas |
259 |
public boolean isWritable() |
714 |
30 May 08 |
nicklas |
260 |
{ |
714 |
30 May 08 |
nicklas |
261 |
boolean permission = true; |
714 |
30 May 08 |
nicklas |
262 |
if (file != null) |
714 |
30 May 08 |
nicklas |
263 |
{ |
1225 |
05 May 10 |
nicklas |
264 |
permission = file.hasPermission(Permission.WRITE) && |
1225 |
05 May 10 |
nicklas |
265 |
file.getLocation() != Location.EXTERNAL; |
714 |
30 May 08 |
nicklas |
266 |
} |
714 |
30 May 08 |
nicklas |
267 |
else if (directory != null) |
714 |
30 May 08 |
nicklas |
268 |
{ |
714 |
30 May 08 |
nicklas |
269 |
permission = directory.hasPermission(Permission.WRITE); |
714 |
30 May 08 |
nicklas |
270 |
} |
714 |
30 May 08 |
nicklas |
271 |
return permission; |
714 |
30 May 08 |
nicklas |
272 |
} |
714 |
30 May 08 |
nicklas |
273 |
|
714 |
30 May 08 |
nicklas |
274 |
/** |
714 |
30 May 08 |
nicklas |
If this represents an existing directory, returns all subdirectories and |
714 |
30 May 08 |
nicklas |
files inside it. Otherwise null is returned. |
714 |
30 May 08 |
nicklas |
277 |
*/ |
714 |
30 May 08 |
nicklas |
278 |
@Override |
915 |
11 Dec 08 |
nicklas |
279 |
public List<FtpFile> listFiles() |
714 |
30 May 08 |
nicklas |
280 |
{ |
716 |
02 Jun 08 |
nicklas |
281 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
282 |
{ |
716 |
02 Jun 08 |
nicklas |
283 |
log.debug("List files"); |
716 |
02 Jun 08 |
nicklas |
284 |
log.debug(" dir=" + this); |
716 |
02 Jun 08 |
nicklas |
285 |
} |
714 |
30 May 08 |
nicklas |
286 |
if (directory == null) return null; |
714 |
30 May 08 |
nicklas |
287 |
|
915 |
11 Dec 08 |
nicklas |
288 |
List<FtpFile> all = new ArrayList<FtpFile>(); |
714 |
30 May 08 |
nicklas |
289 |
DbControl dc = user.sc.newDbControl(); |
714 |
30 May 08 |
nicklas |
290 |
try |
714 |
30 May 08 |
nicklas |
291 |
{ |
714 |
30 May 08 |
nicklas |
// Add subdirectories |
714 |
30 May 08 |
nicklas |
293 |
ItemQuery<Directory> dirQuery = directory.getSubDirectories(); |
714 |
30 May 08 |
nicklas |
294 |
dirQuery.order(Orders.asc(Hql.property("name"))); |
714 |
30 May 08 |
nicklas |
295 |
dirQuery.include(Include.ALL); |
714 |
30 May 08 |
nicklas |
296 |
for (Directory dir : dirQuery.list(dc)) |
714 |
30 May 08 |
nicklas |
297 |
{ |
915 |
11 Dec 08 |
nicklas |
298 |
all.add(new BaseFtpFile(user, dir)); |
714 |
30 May 08 |
nicklas |
299 |
} |
714 |
30 May 08 |
nicklas |
// Add files |
714 |
30 May 08 |
nicklas |
301 |
ItemQuery<File> fileQuery = directory.getFiles(); |
714 |
30 May 08 |
nicklas |
302 |
fileQuery.order(Orders.asc(Hql.property("name"))); |
714 |
30 May 08 |
nicklas |
303 |
fileQuery.include(Include.ALL); |
714 |
30 May 08 |
nicklas |
304 |
for (File file : fileQuery.list(dc)) |
714 |
30 May 08 |
nicklas |
305 |
{ |
915 |
11 Dec 08 |
nicklas |
306 |
all.add(new BaseFtpFile(user, file)); |
714 |
30 May 08 |
nicklas |
307 |
} |
714 |
30 May 08 |
nicklas |
308 |
} |
716 |
02 Jun 08 |
nicklas |
309 |
catch (RuntimeException ex) |
716 |
02 Jun 08 |
nicklas |
310 |
{ |
716 |
02 Jun 08 |
nicklas |
311 |
log.error("Could not list files in directory: " + this, ex); |
716 |
02 Jun 08 |
nicklas |
312 |
throw ex; |
716 |
02 Jun 08 |
nicklas |
313 |
} |
714 |
30 May 08 |
nicklas |
314 |
finally |
714 |
30 May 08 |
nicklas |
315 |
{ |
714 |
30 May 08 |
nicklas |
316 |
if (dc != null) dc.close(); |
714 |
30 May 08 |
nicklas |
317 |
} |
716 |
02 Jun 08 |
nicklas |
318 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
319 |
{ |
716 |
02 Jun 08 |
nicklas |
320 |
log.debug("List files ok: size=" + all.size()); |
716 |
02 Jun 08 |
nicklas |
321 |
} |
915 |
11 Dec 08 |
nicklas |
322 |
return all; |
714 |
30 May 08 |
nicklas |
323 |
} |
714 |
30 May 08 |
nicklas |
324 |
|
714 |
30 May 08 |
nicklas |
325 |
/** |
714 |
30 May 08 |
nicklas |
Try to create the directory if this file object represents |
714 |
30 May 08 |
nicklas |
a non-existing item. |
714 |
30 May 08 |
nicklas |
328 |
*/ |
714 |
30 May 08 |
nicklas |
329 |
@Override |
714 |
30 May 08 |
nicklas |
330 |
public boolean mkdir() |
714 |
30 May 08 |
nicklas |
331 |
{ |
716 |
02 Jun 08 |
nicklas |
332 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
333 |
{ |
716 |
02 Jun 08 |
nicklas |
334 |
log.debug("Make directory"); |
716 |
02 Jun 08 |
nicklas |
335 |
log.debug(" dir=" + this); |
716 |
02 Jun 08 |
nicklas |
336 |
} |
714 |
30 May 08 |
nicklas |
337 |
if (file != null || directory != null) return false; |
714 |
30 May 08 |
nicklas |
338 |
if (!user.sc.hasPermission(Permission.CREATE, Item.DIRECTORY)) return false; |
714 |
30 May 08 |
nicklas |
339 |
|
714 |
30 May 08 |
nicklas |
340 |
Path p = new Path(path, Path.Type.DIRECTORY); |
714 |
30 May 08 |
nicklas |
341 |
DbControl dc = user.sc.newDbControl(); |
714 |
30 May 08 |
nicklas |
342 |
try |
714 |
30 May 08 |
nicklas |
343 |
{ |
714 |
30 May 08 |
nicklas |
344 |
directory = Directory.getNew(dc, p); |
714 |
30 May 08 |
nicklas |
345 |
dc.commit(); |
714 |
30 May 08 |
nicklas |
346 |
} |
716 |
02 Jun 08 |
nicklas |
347 |
catch (RuntimeException ex) |
716 |
02 Jun 08 |
nicklas |
348 |
{ |
716 |
02 Jun 08 |
nicklas |
349 |
log.error("Could not create directory: " + this, ex); |
716 |
02 Jun 08 |
nicklas |
350 |
throw ex; |
716 |
02 Jun 08 |
nicklas |
351 |
} |
714 |
30 May 08 |
nicklas |
352 |
finally |
714 |
30 May 08 |
nicklas |
353 |
{ |
714 |
30 May 08 |
nicklas |
354 |
if (dc != null) dc.close(); |
714 |
30 May 08 |
nicklas |
355 |
} |
716 |
02 Jun 08 |
nicklas |
356 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
357 |
{ |
716 |
02 Jun 08 |
nicklas |
358 |
log.debug("Make directory ok: " + this); |
716 |
02 Jun 08 |
nicklas |
359 |
} |
714 |
30 May 08 |
nicklas |
360 |
return true; |
714 |
30 May 08 |
nicklas |
361 |
} |
714 |
30 May 08 |
nicklas |
362 |
|
714 |
30 May 08 |
nicklas |
363 |
/** |
714 |
30 May 08 |
nicklas |
If this file objects represents an existing file or directory, try |
714 |
30 May 08 |
nicklas |
to delete it. Otherwise do nothing. |
714 |
30 May 08 |
nicklas |
366 |
*/ |
714 |
30 May 08 |
nicklas |
367 |
@Override |
714 |
30 May 08 |
nicklas |
368 |
public boolean delete() |
714 |
30 May 08 |
nicklas |
369 |
{ |
716 |
02 Jun 08 |
nicklas |
370 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
371 |
{ |
716 |
02 Jun 08 |
nicklas |
372 |
log.debug("Delete"); |
716 |
02 Jun 08 |
nicklas |
373 |
log.debug(" file/dir=" + this); |
716 |
02 Jun 08 |
nicklas |
374 |
} |
915 |
11 Dec 08 |
nicklas |
375 |
if (!isRemovable()) return false; |
714 |
30 May 08 |
nicklas |
376 |
|
714 |
30 May 08 |
nicklas |
377 |
DbControl dc = user.sc.newDbControl(); |
714 |
30 May 08 |
nicklas |
378 |
try |
714 |
30 May 08 |
nicklas |
379 |
{ |
714 |
30 May 08 |
nicklas |
380 |
if (file != null) |
714 |
30 May 08 |
nicklas |
381 |
{ |
714 |
30 May 08 |
nicklas |
382 |
file = File.getById(dc, file.getId()); |
714 |
30 May 08 |
nicklas |
383 |
dc.deleteItem(file); |
714 |
30 May 08 |
nicklas |
384 |
} |
714 |
30 May 08 |
nicklas |
385 |
else if (directory != null) |
714 |
30 May 08 |
nicklas |
386 |
{ |
714 |
30 May 08 |
nicklas |
387 |
directory = Directory.getById(dc, directory.getId()); |
714 |
30 May 08 |
nicklas |
388 |
dc.deleteItem(directory); |
714 |
30 May 08 |
nicklas |
389 |
} |
714 |
30 May 08 |
nicklas |
390 |
dc.commit(); |
716 |
02 Jun 08 |
nicklas |
391 |
file = null; |
716 |
02 Jun 08 |
nicklas |
392 |
directory = null; |
714 |
30 May 08 |
nicklas |
393 |
} |
716 |
02 Jun 08 |
nicklas |
394 |
catch (RuntimeException ex) |
716 |
02 Jun 08 |
nicklas |
395 |
{ |
716 |
02 Jun 08 |
nicklas |
396 |
log.error("Could not delete file/directory: " + this, ex); |
716 |
02 Jun 08 |
nicklas |
397 |
throw ex; |
716 |
02 Jun 08 |
nicklas |
398 |
} |
714 |
30 May 08 |
nicklas |
399 |
finally |
714 |
30 May 08 |
nicklas |
400 |
{ |
714 |
30 May 08 |
nicklas |
401 |
if (dc != null) dc.close(); |
714 |
30 May 08 |
nicklas |
402 |
} |
716 |
02 Jun 08 |
nicklas |
403 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
404 |
{ |
716 |
02 Jun 08 |
nicklas |
405 |
log.debug("Delete ok: " + this); |
716 |
02 Jun 08 |
nicklas |
406 |
} |
714 |
30 May 08 |
nicklas |
407 |
return true; |
714 |
30 May 08 |
nicklas |
408 |
} |
714 |
30 May 08 |
nicklas |
409 |
|
714 |
30 May 08 |
nicklas |
410 |
/** |
714 |
30 May 08 |
nicklas |
Move this existing file or directory to a non-existing location. |
714 |
30 May 08 |
nicklas |
412 |
*/ |
714 |
30 May 08 |
nicklas |
413 |
@Override |
915 |
11 Dec 08 |
nicklas |
414 |
public boolean move(FtpFile dest) |
714 |
30 May 08 |
nicklas |
415 |
{ |
716 |
02 Jun 08 |
nicklas |
416 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
417 |
{ |
716 |
02 Jun 08 |
nicklas |
418 |
log.debug("Move"); |
716 |
02 Jun 08 |
nicklas |
419 |
log.debug(" this=" + this); |
716 |
02 Jun 08 |
nicklas |
420 |
log.debug(" dest=" + dest); |
716 |
02 Jun 08 |
nicklas |
421 |
} |
714 |
30 May 08 |
nicklas |
422 |
if (!doesExist() || dest.doesExist()) return false; |
714 |
30 May 08 |
nicklas |
423 |
DbControl dc = user.sc.newDbControl(); |
714 |
30 May 08 |
nicklas |
424 |
try |
714 |
30 May 08 |
nicklas |
425 |
{ |
714 |
30 May 08 |
nicklas |
426 |
Directory newParentDir = null; |
716 |
02 Jun 08 |
nicklas |
// Do we need to change the parent directory? |
716 |
02 Jun 08 |
nicklas |
// If we don't have to we should not call File.setDirectory since it |
716 |
02 Jun 08 |
nicklas |
// may cause a PermissionDeniedException |
714 |
30 May 08 |
nicklas |
430 |
if (!hasSameParentDirectory(this, dest)) |
714 |
30 May 08 |
nicklas |
431 |
{ |
915 |
11 Dec 08 |
nicklas |
432 |
Path to = new Path(dest.getAbsolutePath(), isDirectory() ? Path.Type.DIRECTORY : Path.Type.FILE); |
714 |
30 May 08 |
nicklas |
433 |
newParentDir = Directory.getByPath(dc, to.getParent()); |
714 |
30 May 08 |
nicklas |
434 |
} |
716 |
02 Jun 08 |
nicklas |
435 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
436 |
{ |
716 |
02 Jun 08 |
nicklas |
437 |
log.debug(" new parent directory=" + newParentDir); |
716 |
02 Jun 08 |
nicklas |
438 |
} |
714 |
30 May 08 |
nicklas |
439 |
if (file != null) |
714 |
30 May 08 |
nicklas |
440 |
{ |
714 |
30 May 08 |
nicklas |
441 |
file = File.getById(dc, file.getId()); |
714 |
30 May 08 |
nicklas |
442 |
if (newParentDir != null) file.setDirectory(newParentDir); |
915 |
11 Dec 08 |
nicklas |
443 |
file.setName(dest.getName()); |
714 |
30 May 08 |
nicklas |
444 |
} |
714 |
30 May 08 |
nicklas |
445 |
else if (directory != null) |
714 |
30 May 08 |
nicklas |
446 |
{ |
714 |
30 May 08 |
nicklas |
447 |
directory = Directory.getById(dc, directory.getId()); |
714 |
30 May 08 |
nicklas |
448 |
if (newParentDir != null) directory.setParent(newParentDir); |
915 |
11 Dec 08 |
nicklas |
449 |
directory.setName(dest.getName()); |
714 |
30 May 08 |
nicklas |
450 |
} |
714 |
30 May 08 |
nicklas |
451 |
dc.commit(); |
714 |
30 May 08 |
nicklas |
452 |
} |
716 |
02 Jun 08 |
nicklas |
453 |
catch (RuntimeException ex) |
716 |
02 Jun 08 |
nicklas |
454 |
{ |
716 |
02 Jun 08 |
nicklas |
455 |
log.error("Could not move: " + this + " --> " + dest, ex); |
716 |
02 Jun 08 |
nicklas |
456 |
throw ex; |
716 |
02 Jun 08 |
nicklas |
457 |
} |
714 |
30 May 08 |
nicklas |
458 |
finally |
714 |
30 May 08 |
nicklas |
459 |
{ |
714 |
30 May 08 |
nicklas |
460 |
if (dc != null) dc.close(); |
714 |
30 May 08 |
nicklas |
461 |
} |
716 |
02 Jun 08 |
nicklas |
462 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
463 |
{ |
716 |
02 Jun 08 |
nicklas |
464 |
log.debug("Move ok: " + this + " --> " + dest); |
716 |
02 Jun 08 |
nicklas |
465 |
} |
714 |
30 May 08 |
nicklas |
466 |
return true; |
714 |
30 May 08 |
nicklas |
467 |
} |
714 |
30 May 08 |
nicklas |
468 |
|
714 |
30 May 08 |
nicklas |
469 |
|
714 |
30 May 08 |
nicklas |
470 |
@Override |
714 |
30 May 08 |
nicklas |
471 |
public InputStream createInputStream(long offset) |
714 |
30 May 08 |
nicklas |
472 |
throws IOException |
714 |
30 May 08 |
nicklas |
473 |
{ |
716 |
02 Jun 08 |
nicklas |
474 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
475 |
{ |
716 |
02 Jun 08 |
nicklas |
476 |
log.debug("Reading from file " + this + "[offset="+offset + "]"); |
716 |
02 Jun 08 |
nicklas |
477 |
} |
714 |
30 May 08 |
nicklas |
478 |
if (file == null) |
714 |
30 May 08 |
nicklas |
479 |
{ |
714 |
30 May 08 |
nicklas |
480 |
throw new IOException("Not a file: " + this); |
714 |
30 May 08 |
nicklas |
481 |
} |
2569 |
11 Aug 14 |
nicklas |
482 |
DbControl dc = null; |
2569 |
11 Aug 14 |
nicklas |
483 |
InputStream in = null; |
2569 |
11 Aug 14 |
nicklas |
484 |
try |
2569 |
11 Aug 14 |
nicklas |
485 |
{ |
2569 |
11 Aug 14 |
nicklas |
486 |
if (file.getLocation() == Location.EXTERNAL) |
2569 |
11 Aug 14 |
nicklas |
487 |
{ |
2569 |
11 Aug 14 |
nicklas |
488 |
dc = user.sc.newDbControl(); |
2569 |
11 Aug 14 |
nicklas |
489 |
dc.reattachItem(file, false); |
2569 |
11 Aug 14 |
nicklas |
490 |
} |
2569 |
11 Aug 14 |
nicklas |
491 |
in = file.getDownloadStream(offset); |
2569 |
11 Aug 14 |
nicklas |
492 |
} |
2569 |
11 Aug 14 |
nicklas |
493 |
finally |
2569 |
11 Aug 14 |
nicklas |
494 |
{ |
2569 |
11 Aug 14 |
nicklas |
495 |
if (dc != null) dc.close(); |
2569 |
11 Aug 14 |
nicklas |
496 |
} |
2569 |
11 Aug 14 |
nicklas |
497 |
return in; |
714 |
30 May 08 |
nicklas |
498 |
} |
714 |
30 May 08 |
nicklas |
499 |
|
714 |
30 May 08 |
nicklas |
500 |
/** |
714 |
30 May 08 |
nicklas |
If this object represents an existing directory, return null. |
714 |
30 May 08 |
nicklas |
If this object represents an existing file, return an upload |
714 |
30 May 08 |
nicklas |
stream to it. If this object represents a non-existing item, |
714 |
30 May 08 |
nicklas |
try to create the file. |
714 |
30 May 08 |
nicklas |
505 |
*/ |
714 |
30 May 08 |
nicklas |
506 |
@Override |
714 |
30 May 08 |
nicklas |
507 |
public OutputStream createOutputStream(long offset) |
714 |
30 May 08 |
nicklas |
508 |
throws IOException |
714 |
30 May 08 |
nicklas |
509 |
{ |
716 |
02 Jun 08 |
nicklas |
510 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
511 |
{ |
716 |
02 Jun 08 |
nicklas |
512 |
log.debug("Writing to file " + this + "[offset="+offset + "]"); |
716 |
02 Jun 08 |
nicklas |
513 |
} |
714 |
30 May 08 |
nicklas |
514 |
if (directory != null) return null; |
714 |
30 May 08 |
nicklas |
515 |
|
714 |
30 May 08 |
nicklas |
516 |
OutputStream upload = null; |
714 |
30 May 08 |
nicklas |
517 |
DbControl dc = user.sc.newDbControl(); |
714 |
30 May 08 |
nicklas |
518 |
try |
714 |
30 May 08 |
nicklas |
519 |
{ |
714 |
30 May 08 |
nicklas |
520 |
if (file != null) |
714 |
30 May 08 |
nicklas |
521 |
{ |
714 |
30 May 08 |
nicklas |
// Upload to an existing file |
1225 |
05 May 10 |
nicklas |
523 |
dc.reattachItem(file, false); |
714 |
30 May 08 |
nicklas |
524 |
} |
714 |
30 May 08 |
nicklas |
525 |
else |
714 |
30 May 08 |
nicklas |
526 |
{ |
714 |
30 May 08 |
nicklas |
// Upload to a new file; always ignore offset |
915 |
11 Dec 08 |
nicklas |
528 |
file = File.getByPath(dc, new Path(getAbsolutePath(), Path.Type.FILE), true); |
714 |
30 May 08 |
nicklas |
529 |
dc.saveItem(file); |
714 |
30 May 08 |
nicklas |
530 |
offset = 0; |
714 |
30 May 08 |
nicklas |
531 |
} |
716 |
02 Jun 08 |
nicklas |
532 |
|
716 |
02 Jun 08 |
nicklas |
533 |
if (log.isDebugEnabled()) |
716 |
02 Jun 08 |
nicklas |
534 |
{ |
716 |
02 Jun 08 |
nicklas |
535 |
log.debug("Uploading to BASE file: " + file); |
716 |
02 Jun 08 |
nicklas |
536 |
} |
716 |
02 Jun 08 |
nicklas |
537 |
|
714 |
30 May 08 |
nicklas |
538 |
file.setMimeTypeAuto(null, null); |
714 |
30 May 08 |
nicklas |
539 |
InputStream in = offset > 0 ? file.getDownloadStream(0) : null; |
714 |
30 May 08 |
nicklas |
540 |
|
714 |
30 May 08 |
nicklas |
// The TransactionOutputStream will make sure DbControl is committed |
716 |
02 Jun 08 |
nicklas |
542 |
upload = new TransactionalOutputStream(dc, file.getUploadStream(false), toString()); |
714 |
30 May 08 |
nicklas |
543 |
if (in != null) |
714 |
30 May 08 |
nicklas |
544 |
{ |
716 |
02 Jun 08 |
nicklas |
545 |
long remain = offset; |
716 |
02 Jun 08 |
nicklas |
546 |
while (remain > 0) |
714 |
30 May 08 |
nicklas |
547 |
{ |
714 |
30 May 08 |
nicklas |
548 |
int b = in.read(); |
716 |
02 Jun 08 |
nicklas |
549 |
if (b == -1) break; |
716 |
02 Jun 08 |
nicklas |
550 |
upload.write(b); |
716 |
02 Jun 08 |
nicklas |
551 |
remain--; |
714 |
30 May 08 |
nicklas |
552 |
} |
714 |
30 May 08 |
nicklas |
553 |
in.close(); |
716 |
02 Jun 08 |
nicklas |
554 |
log.debug((offset - remain) + " bytes copied from existing file"); |
714 |
30 May 08 |
nicklas |
555 |
} |
714 |
30 May 08 |
nicklas |
556 |
dc.disconnect(); |
714 |
30 May 08 |
nicklas |
557 |
} |
714 |
30 May 08 |
nicklas |
558 |
catch (RuntimeException ex) |
714 |
30 May 08 |
nicklas |
559 |
{ |
716 |
02 Jun 08 |
nicklas |
560 |
log.error("Could not create upload stream to " + this, ex); |
714 |
30 May 08 |
nicklas |
561 |
if (dc != null) dc.close(); |
714 |
30 May 08 |
nicklas |
562 |
throw ex; |
714 |
30 May 08 |
nicklas |
563 |
} |
714 |
30 May 08 |
nicklas |
564 |
return upload; |
714 |
30 May 08 |
nicklas |
565 |
} |
714 |
30 May 08 |
nicklas |
566 |
// ------------------------------------------- |
714 |
30 May 08 |
nicklas |
567 |
|
716 |
02 Jun 08 |
nicklas |
568 |
/* |
716 |
02 Jun 08 |
nicklas |
From the Object class |
716 |
02 Jun 08 |
nicklas |
570 |
--------------------- |
716 |
02 Jun 08 |
nicklas |
571 |
*/ |
716 |
02 Jun 08 |
nicklas |
572 |
@Override |
716 |
02 Jun 08 |
nicklas |
573 |
public String toString() |
716 |
02 Jun 08 |
nicklas |
574 |
{ |
716 |
02 Jun 08 |
nicklas |
575 |
String type = "path"; |
716 |
02 Jun 08 |
nicklas |
576 |
if (file != null) |
716 |
02 Jun 08 |
nicklas |
577 |
{ |
716 |
02 Jun 08 |
nicklas |
578 |
type = "file"; |
716 |
02 Jun 08 |
nicklas |
579 |
} |
716 |
02 Jun 08 |
nicklas |
580 |
else if (directory != null) |
716 |
02 Jun 08 |
nicklas |
581 |
{ |
716 |
02 Jun 08 |
nicklas |
582 |
type = "dir"; |
716 |
02 Jun 08 |
nicklas |
583 |
} |
915 |
11 Dec 08 |
nicklas |
584 |
return "BaseFtpFile[" + type + "=" + path + "]"; |
716 |
02 Jun 08 |
nicklas |
585 |
} |
716 |
02 Jun 08 |
nicklas |
586 |
// ------------------------------------------- |
716 |
02 Jun 08 |
nicklas |
587 |
|
716 |
02 Jun 08 |
nicklas |
588 |
|
714 |
30 May 08 |
nicklas |
589 |
private String getOwner(OwnedItem item) |
714 |
30 May 08 |
nicklas |
590 |
{ |
714 |
30 May 08 |
nicklas |
591 |
String owner = "unknown"; |
714 |
30 May 08 |
nicklas |
592 |
try |
714 |
30 May 08 |
nicklas |
593 |
{ |
714 |
30 May 08 |
nicklas |
594 |
owner = item.getOwner().getLogin(); |
714 |
30 May 08 |
nicklas |
595 |
} |
714 |
30 May 08 |
nicklas |
596 |
catch (Exception ex) |
714 |
30 May 08 |
nicklas |
597 |
{} |
714 |
30 May 08 |
nicklas |
598 |
return owner; |
714 |
30 May 08 |
nicklas |
599 |
} |
714 |
30 May 08 |
nicklas |
600 |
|
714 |
30 May 08 |
nicklas |
601 |
/** |
714 |
30 May 08 |
nicklas |
Check if two file objects are located in the same or different directories. |
714 |
30 May 08 |
nicklas |
603 |
*/ |
915 |
11 Dec 08 |
nicklas |
604 |
private boolean hasSameParentDirectory(FtpFile fo1, FtpFile fo2) |
714 |
30 May 08 |
nicklas |
605 |
{ |
915 |
11 Dec 08 |
nicklas |
606 |
int index1 = fo1.getAbsolutePath().length() - fo1.getName().length(); |
915 |
11 Dec 08 |
nicklas |
607 |
String parent1 = fo1.getAbsolutePath().substring(0, index1); |
915 |
11 Dec 08 |
nicklas |
608 |
int index2 = fo2.getAbsolutePath().length() - fo2.getName().length(); |
915 |
11 Dec 08 |
nicklas |
609 |
String parent2 = fo2.getAbsolutePath().substring(0, index2); |
714 |
30 May 08 |
nicklas |
610 |
return parent1.equals(parent2); |
714 |
30 May 08 |
nicklas |
611 |
} |
915 |
11 Dec 08 |
nicklas |
612 |
|
714 |
30 May 08 |
nicklas |
613 |
} |