1 package fr.in2p3.jsaga.impl.namespace;
2
3 import fr.in2p3.jsaga.EngineProperties;
4 import fr.in2p3.jsaga.adaptor.data.DataAdaptor;
5 import fr.in2p3.jsaga.adaptor.data.link.LinkAdaptor;
6 import fr.in2p3.jsaga.adaptor.data.link.NotLink;
7 import fr.in2p3.jsaga.adaptor.data.optimise.DataRename;
8 import fr.in2p3.jsaga.adaptor.data.read.DataReaderAdaptor;
9 import fr.in2p3.jsaga.adaptor.data.read.FileAttributes;
10 import fr.in2p3.jsaga.adaptor.data.write.DataWriterAdaptor;
11 import fr.in2p3.jsaga.adaptor.data.write.DataWriterTimes;
12 import fr.in2p3.jsaga.impl.permissions.AbstractDataPermissionsImpl;
13 import fr.in2p3.jsaga.impl.url.URLFactoryImpl;
14 import fr.in2p3.jsaga.impl.url.URLHelper;
15 import fr.in2p3.jsaga.sync.namespace.SyncNSEntry;
16 import org.apache.log4j.Logger;
17 import org.ogf.saga.SagaObject;
18 import org.ogf.saga.error.*;
19 import org.ogf.saga.namespace.*;
20 import org.ogf.saga.session.Session;
21 import org.ogf.saga.url.URL;
22 import org.ogf.saga.url.URLFactory;
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public abstract class AbstractSyncNSEntryImpl extends AbstractDataPermissionsImpl implements SyncNSEntry {
37
38 private static Logger s_logger = Logger.getLogger(AbstractSyncNSEntryImpl.class);
39 protected int m_flags;
40 private boolean m_disconnectable;
41 private Integer m_implicitCloseTimeout;
42
43
44 protected AbstractSyncNSEntryImpl(Session session, URL url, DataAdaptor adaptor, int flags) throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, DoesNotExistException, TimeoutException, NoSuccessException {
45 super(session, url, adaptor);
46 m_flags = flags;
47 m_disconnectable = true;
48 m_implicitCloseTimeout = EngineProperties.getInteger(EngineProperties.DATA_IMPLICIT_CLOSE_TIMEOUT);
49 }
50
51
52 protected AbstractSyncNSEntryImpl(AbstractNSDirectoryImpl dir, URL relativeUrl, int flags) throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, DoesNotExistException, TimeoutException, NoSuccessException {
53 super(dir.m_session, _resolveRelativeUrl(dir.m_url, relativeUrl), dir.m_adaptor);
54 m_flags = flags;
55 m_disconnectable = false;
56 m_implicitCloseTimeout = EngineProperties.getInteger(EngineProperties.DATA_IMPLICIT_CLOSE_TIMEOUT);
57 }
58
59 protected static URL _resolveRelativeUrl(URL baseUrl, URL relativeUrl) throws NotImplementedException, IncorrectURLException, BadParameterException, NoSuccessException {
60 if (relativeUrl == null) {
61 throw new IncorrectURLException("URL must not be null");
62 } else if (relativeUrl.getUserInfo() != null && !relativeUrl.getUserInfo().equals(baseUrl.getUserInfo())) {
63 throw new IncorrectURLException("You must not modify the user part of the URL: " + baseUrl.getUserInfo());
64 } else if (relativeUrl.getHost() != null && !relativeUrl.getHost().equals(baseUrl.getHost())) {
65 throw new IncorrectURLException("You must not modify the host of the URL: " + baseUrl.getHost());
66 }
67 return URLHelper.createURL(baseUrl, relativeUrl);
68 }
69
70
71 protected AbstractSyncNSEntryImpl(AbstractNSEntryImpl entry, String absolutePath, int flags) throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, DoesNotExistException, TimeoutException, NoSuccessException {
72 super(entry.m_session, _resolveAbsolutePath(entry.m_url, absolutePath), entry.m_adaptor);
73 m_flags = flags;
74 m_disconnectable = false;
75 m_implicitCloseTimeout = EngineProperties.getInteger(EngineProperties.DATA_IMPLICIT_CLOSE_TIMEOUT);
76 }
77
78 private static URL _resolveAbsolutePath(URL baseUrl, String absolutePath) throws NotImplementedException, IncorrectURLException, BadParameterException, NoSuccessException {
79 if (absolutePath == null) {
80 throw new IncorrectURLException("URL must not be null");
81 } else if (!absolutePath.startsWith("/")) {
82 throw new IncorrectURLException("URL must contain an absolute path: " + baseUrl.getPath());
83 }
84 return URLHelper.createURL(baseUrl, absolutePath);
85 }
86
87
88 public SagaObject clone() throws CloneNotSupportedException {
89 AbstractSyncNSEntryImpl clone = (AbstractSyncNSEntryImpl) super.clone();
90 clone.m_flags = m_flags;
91 clone.m_disconnectable = m_disconnectable;
92 clone.m_implicitCloseTimeout = m_implicitCloseTimeout;
93 return clone;
94 }
95
96
97 public URL getURLSync() throws NotImplementedException, IncorrectStateException, TimeoutException, NoSuccessException {
98 return m_url;
99 }
100
101 public URL getCWDSync() throws NotImplementedException, IncorrectStateException, TimeoutException, NoSuccessException {
102 try {
103 return m_url.resolve(URLFactory.createURL(JSAGA_FACTORY, "."));
104 } catch (BadParameterException e) {
105 throw new NoSuccessException(e);
106 }
107 }
108
109 public URL getNameSync() throws NotImplementedException, TimeoutException, NoSuccessException {
110 try {
111 return URLFactoryImpl.createRelativePath(this._getEntryName());
112 } catch (BadParameterException e) {
113 throw new NoSuccessException(e);
114 }
115 }
116
117 public boolean exists() throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, TimeoutException, NoSuccessException {
118 if (m_adaptor instanceof DataReaderAdaptor) {
119 return ((DataReaderAdaptor) m_adaptor).exists(
120 m_url.getPath(),
121 m_url.getQuery());
122 } else {
123 throw new NotImplementedException("Not supported for this protocol: " + m_url.getScheme(), this);
124 }
125 }
126
127 public boolean isDirSync() throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, TimeoutException, NoSuccessException {
128 FileAttributes attrs = this._getFileAttributes();
129 return (attrs.getType() == FileAttributes.TYPE_DIRECTORY);
130 }
131
132 public boolean isEntrySync() throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, TimeoutException, NoSuccessException {
133 FileAttributes attrs = this._getFileAttributes();
134 return (attrs.getType() == FileAttributes.TYPE_FILE);
135 }
136
137 public boolean isLinkSync() throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, TimeoutException, NoSuccessException {
138 FileAttributes attrs = this._getFileAttributes();
139 return (attrs.getType() == FileAttributes.TYPE_LINK);
140 }
141
142 public URL readLinkSync() throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, TimeoutException, NoSuccessException {
143 if (m_adaptor instanceof LinkAdaptor) {
144 String absolutePath;
145 try {
146 try {
147 absolutePath = ((LinkAdaptor) m_adaptor).readLink(
148 m_url.getPath());
149 } catch (DoesNotExistException doesNotExist) {
150 throw new IncorrectStateException("Link does not exist: " + m_url, doesNotExist);
151 }
152 } catch (NotLink notLink) {
153 throw new IncorrectStateException("Not a link: " + m_url, this);
154 }
155 try {
156 return URLHelper.createURL(URLHelper.getParentURL(m_url), absolutePath);
157 } catch (BadParameterException e) {
158 throw new IncorrectStateException(e);
159 }
160 } else {
161 throw new NotImplementedException("Not supported for this protocol: " + m_url.getScheme(), this);
162 }
163 }
164
165 public abstract void copySync(URL target, int flags) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, DoesNotExistException, AlreadyExistsException, TimeoutException, NoSuccessException, IncorrectURLException;
166
167 public void copySync(URL target) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, DoesNotExistException, TimeoutException, NoSuccessException, IncorrectURLException {
168 this.copySync(target, Flags.NONE.getValue());
169 }
170
171 public abstract void copyFromSync(URL source, int flags) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, DoesNotExistException, TimeoutException, NoSuccessException, IncorrectURLException;
172
173 public void copyFromSync(URL target) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, DoesNotExistException, TimeoutException, NoSuccessException, IncorrectURLException {
174 this.copyFromSync(target, Flags.NONE.getValue());
175 }
176
177
178
179
180
181
182 public void linkSync(URL link, int flags) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, DoesNotExistException, TimeoutException, NoSuccessException, IncorrectURLException {
183 new FlagsHelper(flags).allowed(Flags.DEREFERENCE, Flags.RECURSIVE, Flags.OVERWRITE, Flags.CREATEPARENTS);
184 if (Flags.RECURSIVE.isSet(flags)) {
185 throw new NotImplementedException("Support of RECURSIVE flags with method link() is not implemented by the SAGA engine", this);
186 }
187 if (Flags.DEREFERENCE.isSet(flags)) {
188 AbstractSyncNSEntryImpl entry = this._dereferenceEntry();
189 try {
190 entry.linkSync(link, flags - Flags.DEREFERENCE.getValue());
191 } finally {
192 entry.close();
193 }
194 return;
195 }
196 URL effectiveLink = this._getEffectiveURL(link);
197 if (m_adaptor instanceof LinkAdaptor) {
198 boolean overwrite = Flags.OVERWRITE.isSet(flags);
199 try {
200 try {
201 ((LinkAdaptor) m_adaptor).link(
202 m_url.getPath(),
203 effectiveLink.getPath(),
204 overwrite);
205 } catch (DoesNotExistException doesNotExist) {
206 throw new DoesNotExistException("Entry does not exist: " + m_url, doesNotExist);
207 } catch (AlreadyExistsException alreadyExists) {
208 throw new AlreadyExistsException("Target entry already exists: " + effectiveLink, alreadyExists.getCause());
209 }
210 } catch (DoesNotExistException e) {
211 if (Flags.CREATEPARENTS.isSet(flags)) {
212
213 this._makeParentDirs();
214
215 try {
216 ((LinkAdaptor) m_adaptor).link(
217 m_url.getPath(),
218 effectiveLink.getPath(),
219 overwrite);
220 } catch (DoesNotExistException doesNotExist) {
221 throw new DoesNotExistException("Entry does not exist: " + m_url, doesNotExist);
222 } catch (AlreadyExistsException alreadyExists) {
223 throw new AlreadyExistsException("Target entry already exists: " + effectiveLink, alreadyExists.getCause());
224 }
225 } else {
226 throw e;
227 }
228 }
229 } else {
230 throw new NotImplementedException("Not supported for this protocol: " + m_url.getScheme());
231 }
232 }
233
234 public void linkSync(URL target) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, DoesNotExistException, TimeoutException, NoSuccessException, IncorrectURLException {
235 this.linkSync(target, Flags.NONE.getValue());
236 }
237
238 public void moveSync(URL target, int flags) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, DoesNotExistException, AlreadyExistsException, TimeoutException, NoSuccessException, IncorrectURLException {
239 new FlagsHelper(flags).allowed(Flags.DEREFERENCE, Flags.OVERWRITE, Flags.CREATEPARENTS);
240 if (Flags.DEREFERENCE.isSet(flags)) {
241 AbstractSyncNSEntryImpl entry = this._dereferenceEntry();
242 try {
243 entry.moveSync(target, flags - Flags.DEREFERENCE.getValue());
244 } finally {
245 entry.close();
246 }
247 return;
248 }
249 URL effectiveTarget = this._getEffectiveURL(target);
250 boolean overwrite = Flags.OVERWRITE.isSet(flags);
251 if (m_adaptor instanceof DataRename
252 && m_url.getScheme().equals(effectiveTarget.getScheme())
253 && (m_url.getUserInfo() == null || m_url.getUserInfo().equals(effectiveTarget.getUserInfo()))
254 && (m_url.getHost() == null || m_url.getHost().equals(effectiveTarget.getHost()))
255 && (m_url.getPort() == effectiveTarget.getPort())) {
256 try {
257 ((DataRename) m_adaptor).rename(
258 m_url.getPath(),
259 effectiveTarget.getPath(),
260 overwrite,
261 m_url.getQuery());
262 } catch (DoesNotExistException doesNotExist) {
263 throw new IncorrectStateException("File does not exist: " + m_url, doesNotExist);
264 } catch (AlreadyExistsException alreadyExists) {
265 throw new AlreadyExistsException("Target entry already exists: " + effectiveTarget, alreadyExists.getCause());
266 }
267 } else {
268 this.copySync(effectiveTarget, flags);
269 if (overwrite) {
270 flags = flags - Flags.OVERWRITE.getValue();
271 }
272 this.removeSync(flags);
273 }
274 }
275
276 public void moveSync(URL target) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, DoesNotExistException, TimeoutException, NoSuccessException, IncorrectURLException {
277 this.moveSync(target, Flags.NONE.getValue());
278 }
279
280 public void removeSync(int flags) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, TimeoutException, NoSuccessException {
281 new FlagsHelper(flags).allowed(Flags.DEREFERENCE);
282 if (Flags.DEREFERENCE.isSet(flags)) {
283 try {
284 AbstractSyncNSEntryImpl entry = this._dereferenceEntry();
285 try {
286 entry.removeSync(flags - Flags.DEREFERENCE.getValue());
287 } finally {
288 entry.close();
289 }
290 } catch (IncorrectURLException e) {
291 throw new NoSuccessException(e);
292 }
293 return;
294 }
295 if (m_adaptor instanceof DataWriterAdaptor) {
296 URL parent = this._getParentDirURL();
297 String fileName = this._getEntryName();
298 try {
299 ((DataWriterAdaptor) m_adaptor).removeFile(
300 parent.getPath(),
301 fileName,
302 m_url.getQuery());
303 } catch (DoesNotExistException doesNotExist) {
304 throw new IncorrectStateException("File does not exist: " + m_url, doesNotExist);
305 }
306 } else {
307 throw new NotImplementedException("Not supported for this protocol: " + m_url.getScheme());
308 }
309 }
310
311 public void removeSync() throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, TimeoutException, NoSuccessException {
312 this.removeSync(Flags.NONE.getValue());
313 }
314
315 private boolean m_disconnected = false;
316
317 public synchronized void close() throws NotImplementedException, NoSuccessException {
318 if (m_disconnectable && !m_disconnected) {
319 m_disconnected = true;
320 m_adaptor.disconnect();
321 }
322 }
323
324
325 public abstract void close(float timeoutInSeconds) throws NotImplementedException, NoSuccessException;
326
327 public void permissionsAllowSync(String id, int permissions, int flags) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, BadParameterException, TimeoutException, NoSuccessException {
328 new FlagsHelper(flags).allowed(Flags.DEREFERENCE);
329 if (Flags.DEREFERENCE.isSet(flags)) {
330 try {
331 AbstractSyncNSEntryImpl entry = this._dereferenceEntry();
332 try {
333 entry.permissionsAllowSync(id, permissions, flags - Flags.DEREFERENCE.getValue());
334 } finally {
335 entry.close();
336 }
337 } catch (IncorrectURLException e) {
338 throw new NoSuccessException(e);
339 }
340 return;
341 }
342 super.permissionsAllow(id, permissions);
343 }
344
345 public void permissionsDenySync(String id, int permissions, int flags) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, BadParameterException, TimeoutException, NoSuccessException {
346 new FlagsHelper(flags).allowed(Flags.DEREFERENCE);
347 if (Flags.DEREFERENCE.isSet(flags)) {
348 try {
349 AbstractSyncNSEntryImpl entry = this._dereferenceEntry();
350 try {
351 entry.permissionsDenySync(id, permissions, flags - Flags.DEREFERENCE.getValue());
352 } finally {
353 entry.close();
354 }
355 } catch (IncorrectURLException e) {
356 throw new NoSuccessException(e);
357 } catch (IncorrectStateException e) {
358 throw new NoSuccessException(e);
359 }
360 return;
361 }
362 super.permissionsDeny(id, permissions);
363 }
364
365
366 public void finalize() throws Throwable {
367 if (m_implicitCloseTimeout == null) {
368
369 if (m_disconnectable && !m_disconnected) {
370 s_logger.error("NSEntry objects MUST be closed in order to free resources " + this.getURLSync());
371 }
372 } else {
373 this.close((float) m_implicitCloseTimeout);
374 }
375 super.finalize();
376 }
377
378 public long getMTimeSync() throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, TimeoutException, NoSuccessException {
379 FileAttributes attrs = this._getFileAttributes();
380 if (attrs != null && attrs.getLastModified() > 0) {
381 return attrs.getLastModified();
382 }
383 throw new NotImplementedException("Not supported for this protocol: " + m_url.getScheme(), this);
384 }
385
386
387 public void setMTime(long lastModified) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, TimeoutException, NoSuccessException {
388 if (m_adaptor instanceof DataWriterTimes) {
389 try {
390 ((DataWriterTimes) m_adaptor).setLastModified(
391 m_url.getPath(),
392 m_url.getQuery(),
393 lastModified);
394 } catch (DoesNotExistException doesNotExist) {
395 throw new IncorrectStateException("Entry does not exist: " + m_url, doesNotExist);
396 }
397 } else {
398 throw new NotImplementedException("Not supported for this protocol: " + m_url.getScheme(), this);
399 }
400 }
401
402
403 public abstract NSDirectory openAbsoluteDir(String absolutePath, int flags) throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, DoesNotExistException, TimeoutException, NoSuccessException;
404
405 public abstract NSEntry openAbsolute(String absolutePath, int flags) throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, DoesNotExistException, TimeoutException, NoSuccessException;
406
407 protected AbstractSyncNSDirectoryImpl _dereferenceDir() throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, TimeoutException, NoSuccessException {
408 try {
409 String absolutePath = this.readLinkSync().getPath();
410 return (AbstractSyncNSDirectoryImpl) this.openAbsoluteDir(absolutePath, Flags.NONE.getValue());
411 } catch (AlreadyExistsException e) {
412 throw new IncorrectStateException(e);
413 } catch (DoesNotExistException e) {
414 throw new IncorrectStateException(e);
415 }
416 }
417
418 protected AbstractSyncNSEntryImpl _dereferenceEntry() throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, TimeoutException, NoSuccessException {
419 try {
420 String absolutePath = this.readLinkSync().getPath();
421 return (AbstractSyncNSEntryImpl) this.openAbsolute(absolutePath, Flags.NONE.getValue());
422 } catch (AlreadyExistsException e) {
423 throw new IncorrectStateException(e);
424 } catch (DoesNotExistException e) {
425 throw new IncorrectStateException(e);
426 }
427 }
428
429 protected URL _getEffectiveURL(URL target) throws NotImplementedException, BadParameterException, IncorrectStateException, TimeoutException, NoSuccessException {
430 if (target.getPath().endsWith("/")) {
431 return URLHelper.createURL(target, this._getEntryName());
432 } else {
433 return target;
434 }
435 }
436
437 protected URL _getParentDirURL() throws NotImplementedException, BadParameterException, NoSuccessException {
438 return URLHelper.getParentURL(m_url);
439 }
440
441 protected String _getEntryName() throws NotImplementedException {
442 return URLHelper.getName(m_url);
443 }
444
445 protected void _makeParentDirs() throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, AlreadyExistsException, TimeoutException, NoSuccessException {
446 try {
447 String parentAbsolutePath = this._getParentDirURL().getPath();
448 this.openAbsoluteDir(parentAbsolutePath, Flags.CREATE.or(Flags.CREATEPARENTS)).close();
449 } catch (DoesNotExistException e) {
450 throw new NoSuccessException(e);
451 } catch (IncorrectStateException e) {
452 throw new NoSuccessException(e);
453 }
454 }
455
456 protected AbstractNSEntryImpl _getTargetEntry_checkPreserveTimes(URL target) throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, TimeoutException, NoSuccessException {
457 AbstractNSEntryImpl targetEntry;
458 try {
459 targetEntry = (AbstractNSEntryImpl) NSFactory.createNSEntry(JSAGA_FACTORY, m_session, target, JSAGAFlags.BYPASSEXIST.getValue());
460 } catch (DoesNotExistException e) {
461 throw new NoSuccessException("Unexpected exception", e);
462 }
463 if (!(targetEntry.m_adaptor instanceof DataWriterTimes)) {
464 targetEntry.close();
465 throw new NotImplementedException("Flag PRESERVETIMES (" + JSAGAFlags.PRESERVETIMES + ") not supported for protocol: " + target.getScheme());
466 }
467 return targetEntry;
468 }
469
470 protected long _getSourceTimes_checkPreserveTimes(URL source) throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, DoesNotExistException, TimeoutException, NoSuccessException {
471 if (!(m_adaptor instanceof DataWriterTimes)) {
472 throw new NotImplementedException("Flag PRESERVETIMES (" + JSAGAFlags.PRESERVETIMES + ") not supported for protocol: " + m_url.getScheme());
473 }
474 AbstractNSEntryImpl sourceEntry;
475 try {
476 sourceEntry = (AbstractNSEntryImpl) NSFactory.createNSEntry(JSAGA_FACTORY, m_session, source);
477 try {
478 long mtime = sourceEntry.getMTime();
479 return mtime;
480 } finally {
481 sourceEntry.close();
482 }
483 } catch (AlreadyExistsException e) {
484 throw new NoSuccessException("Unexpected exception", e);
485 }
486
487 }
488 }