"Fossies" - the Fresh Open Source Software Archive 
Member "opengroupware-5.5rc3/DocumentAPI/OGoDatabaseProject/SkyProjectFileManager+Internals.m" (5 Dec 2015, 28831 Bytes) of package /linux/privat/opengroupware-5.5rc3.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Matlab source code syntax highlighting (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the latest
Fossies "Diffs" side-by-side code changes report for "SkyProjectFileManager+Internals.m":
5.5rc2_vs_5.5rc3.
1 /*
2 Copyright (C) 2000-2005 SKYRIX Software AG
3
4 This file is part of OpenGroupware.org.
5
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.
20 */
21
22 #include <OGoDatabaseProject/SkyProjectFileManager.h>
23 #include <OGoDatabaseProject/SkyProjectFileManagerCache.h>
24 #include <OGoProject/SkyContentHandler.h>
25
26 @class NSString, NSMutableArray, NSArray, EOGenericRecord, NGHashMap;
27 @class EOAdaptorChannel;
28
29 static NSDictionary *er_dict(int _i) {
30 return [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:_i]
31 forKey:@"errorNumber"];
32 }
33
34 @interface SkyProjectFileManager(DeleteDocument)
35 - (BOOL)prepareDeletionOf:(NSDictionary *)_dict;
36 - (BOOL)deleteVersions:(NSDictionary *)_attrs
37 filesToRemove:(NSMutableArray *)_array;
38 - (BOOL)deleteDocumentEditing:(NSDictionary *)_attrs
39 filesToRemove:(NSMutableArray *)_array;
40 - (BOOL)deleteDoc:(NSDictionary *)_attrs;
41 - (BOOL)reallyDeleteFile:(NSDictionary *)_attrs;
42 - (void)removeAllFiles:(NSArray *)_files;
43 @end
44
45 @interface SkyProjectFileManager(ErrorHandling_Internals)
46 - (void)_initializeErrorDict;
47 - (BOOL)_buildErrorWithSource:(NSString *)_src dest:(NSString *)_dest
48 msg:(int)_msgId handler:(id)_handler cmd:(SEL)_sel;
49 - (NSDictionary *)errorDict;
50 - (BOOL)_buildErrorWithSource:(NSString *)_src dest:(NSString *)_dest
51 msg:(int)_msgId handler:(id)_handler cmd:(SEL)_sel doFlush:(BOOL)_cache
52 doRollback:(BOOL)_doRollback;
53 @end /* SkyProjectFileManager(ErrorHandling+Internals) */
54
55 @interface SkyProjectFileManager(Locking_Internals)
56 - (NSArray *)allVersionAttributesAtPath:(NSString *)_path;
57 @end /* SkyProjectFileManager(Locking_Internals) */
58
59 @interface SkyProjectFileManager(Internals)
60 - (void)_checkCWDFor:(NSString *)_source;
61 - (id)_project;
62 - (NSString *)_defaultCompleteProjectDocumentNamespace;
63 - (NSArray *)subDirectoryNamesForPath:(NSString *)_path;
64 - (NSString *)_makeAbsolute:(NSString *)_path;
65 - (void)_subpathsAtPath:(NSString *)_path array:(NSMutableArray *)_array;
66 - (BOOL)_copyPath:(NSString*)_src toPath:(NSString*)_dest handler:(id)_handler;
67
68 - (BOOL)moveDir:(EOGenericRecord *)_srcGen
69 toPath:(EOGenericRecord *)_destGen
70 name:(NSString *)_dirName
71 extension:(NSString *)_dirExt
72 handler:(id)_handler;
73
74 - (BOOL)moveDir:(EOGenericRecord *)_srcGen
75 toPath:(EOGenericRecord *)_destGen
76 name:(NSString *)_dirName
77 extension:(NSString *)_dirExt
78 handler:(id)_handler
79 doFlush:(BOOL)_doFlush;
80
81 - (BOOL)moveLink:(EOGenericRecord *)_srcGen
82 toPath:(EOGenericRecord *)_destGen
83 name:(NSString *)_linkName
84 extension:(NSString *)_linkExt
85 handler:(id)_handler;
86
87 - (BOOL)moveLink:(EOGenericRecord *)_srcGen
88 toPath:(EOGenericRecord *)_destGen
89 name:(NSString *)_linkName
90 extension:(NSString *)_linkExt
91 handler:(id)_handler
92 doFlush:(BOOL)_doFlush;
93
94 - (BOOL)moveFile:(EOGenericRecord *)_srcGen
95 toPath:(EOGenericRecord *)_destGen
96 name:(NSString *)_fileName
97 extension:(NSString *)_fileExt
98 handler:(id)_handler;
99
100 - (BOOL)moveFile:(EOGenericRecord *)_srcGen
101 toPath:(EOGenericRecord *)_destGen
102 name:(NSString *)_fileName
103 extension:(NSString *)_fileExt
104 handler:(id)_handler
105 doFlush:(BOOL)_doFlush;
106
107 @end /* SkyProjectFileManager(Internals) */
108
109 @interface SkyProjectFileManagerCache(Internals)
110 - (NGHashMap *)parent2ChildDirectoriesCache;
111 - (EOAdaptorChannel *)beginTransaction;
112 - (void)commitTransaction;
113 - (void)rollbackTransaction;
114 @end /* SkyProjectFileManagerCache(Internals) */
115
116 @interface SkyProjectFileManager(Removing)
117 - (BOOL)_removeFileAttrs:(NSArray *)_paths handler:(id)_handler
118 failed:(BOOL*)failed_;
119 - (BOOL)_removeFiles:(NSArray *)_fileAttrs handler:(id)_handler
120 failed:(BOOL*)failed_;
121 - (BOOL)_removeDirs:(NSArray *)_dirAttr handler:(id)_handler failed:(BOOL*)failed_;
122 @end
123
124 #include <OGoDatabaseProject/SkyProjectFileManagerCache.h>
125 #include "common.h"
126
127 @implementation SkyProjectFileManager(Internals)
128
129 static NSNumber *yesNum = nil, *noNum = nil;
130 static inline NSNumber *boolNum(BOOL value) {
131 if (value) {
132 if (yesNum == nil)
133 yesNum = [[NSNumber numberWithBool:YES] retain];
134 return yesNum;
135 }
136 else {
137 if (noNum == nil)
138 noNum = [[NSNumber numberWithBool:NO] retain];
139 return noNum;
140 }
141 }
142
143 - (void)_checkCWDFor:(NSString *)_source {
144 if ([self->cwd isEqualToString: @"/"])
145 return;
146 if (![self->cwd hasPrefix:_source])
147 return;
148
149 ASSIGN(self->cwd, @"/");
150 }
151
152 - (id)_project {
153 return [self->cache project];
154 }
155
156 - (NSString *)_defaultCompleteProjectDocumentNamespace {
157 return @"{http://www.skyrix.com/namespaces/project-document}";
158 }
159
160 - (NSArray *)subDirectoryNamesForPath:(NSString *)_path {
161 return [[self->cache parent2ChildDirectoriesCache] objectsForKey:_path];
162 }
163
164 - (NSString *)_makeAbsolute:(NSString *)_path {
165 static Class NSStringClass = Nil;
166 NSString *version;
167 NSString *path;
168 NSArray *pathComponents;
169
170 #if LIB_FOUNDATION_LIBRARY
171 // TODO: hh asks: why is that?!
172 _path = [_path stringByTrimmingWhiteSpaces];
173 #else
174 if (![_path isNotNull])
175 return nil;
176 #endif
177
178 if (NSStringClass == Nil)
179 NSStringClass = [NSString class];
180
181 if (_path == nil) {
182 NSLog(@"WARNING[%s]: missing path argument.", __PRETTY_FUNCTION__);
183 return nil;
184 }
185 if (![_path isKindOfClass:NSStringClass])
186 return nil;
187
188 if ((version = [_path pathVersion]))
189 _path = [_path stringByDeletingPathVersion];
190
191 _path = ([_path isAbsolutePath] || ![_path isNotNull])
192 ? _path
193 : [[self currentDirectoryPath] stringByAppendingPathComponent:_path];
194
195 if ([_path length] == 0)
196 return @"/";
197
198 while ([_path hasSuffix:@"/"]) {
199 _path = [_path substringToIndex:([_path length] - 1)];
200 }
201 pathComponents = [_path pathComponents];
202
203 if ([_path rangeOfString:@"."].length > 0) { /* skip '.' and '..' entries */
204 int cnt = 0;
205
206 if ((cnt = [pathComponents count]) > 0) {
207 int i = 0;
208 int pnCnt = 0;
209 id *pathNames = NULL;
210
211 pathNames = calloc(cnt + 1, sizeof(id));
212 pathNames[pnCnt++] = @"/"; /* absolute path */
213
214 for (i = 1; i < cnt; i++) {
215 NSString *name = nil;
216
217 name = [pathComponents objectAtIndex:i];
218 if ([name isEqualToString:@"."] || ![name length])
219 // if ([name isEqualToString:@"."])
220 continue;
221 if ([name isEqualToString:@".."]) {
222 if (pnCnt > 1) /* first is '/' */
223 pnCnt--;
224 continue;
225 }
226 pathNames[pnCnt++] = name;
227 }
228 pathComponents = [NSArray arrayWithObjects:pathNames count:pnCnt];
229 if (pathNames) free(pathNames); pathNames = NULL;
230 }
231 else
232 return @"/";
233 }
234 if ([pathComponents count] == 0)
235 return @"/";
236
237 path = [NSString pathWithComponents:pathComponents];
238 if (version)
239 path = [path stringByAppendingPathVersion:version];
240
241 return path;
242 }
243
244 - (BOOL)moveDir:(EOGenericRecord *)_srcGen
245 toPath:(EOGenericRecord *)_destGen
246 name:(NSString *)_dirName
247 extension:(NSString *)_dirExt
248 handler:(id)_handler
249 doFlush:(BOOL)_doFlush
250 {
251 int ec;
252
253 if (_dirName == nil)
254 _dirName = (id)[NSNull null];
255
256 if (![_dirExt isNotNull])
257 _dirExt = (id)[NSNull null];
258 else if (![_dirExt length])
259 _dirExt = (id)[NSNull null];
260
261 if (_doFlush)
262 [self flush];
263
264 NS_DURING {
265 ec = 0;
266 [[self context] runCommand:@"doc::set-folder",
267 @"object", _srcGen,
268 @"title", _dirName,
269 @"fileType", _dirExt,
270 @"folder", _destGen, nil];
271 }
272 NS_HANDLER {
273 [self setLastException:localException];
274 ec = 13;
275 }
276 NS_ENDHANDLER;
277 if (ec) {
278 return [self _buildErrorWithSource:nil dest:nil msg:ec handler:_handler
279 cmd:_cmd];
280 }
281 return YES;
282 }
283
284 - (BOOL)moveDir:(EOGenericRecord *)_srcGen
285 toPath:(EOGenericRecord *)_destGen
286 name:(NSString *)_dirName
287 extension:(NSString *)_dirExt
288 handler:(id)_handler
289 {
290 return [self moveDir:_srcGen toPath:_destGen name:_dirName
291 extension:_dirExt handler:_handler doFlush:YES];
292 }
293
294 - (BOOL)moveLink:(EOGenericRecord *)_srcGen
295 toPath:(EOGenericRecord *)_destGen
296 name:(NSString *)_linkName
297 extension:(NSString *)_linkExt
298 handler:(id)_handler
299 doFlush:(BOOL)_doFlush
300 {
301 int ec;
302
303 if (_linkName == nil)
304 _linkName = (id)[NSNull null];
305
306 if (![_linkExt isNotNull])
307 _linkExt = (id)[NSNull null];
308 else if (![_linkExt length])
309 _linkExt = (id)[NSNull null];
310
311 if (_doFlush)
312 [self flush];
313
314 NS_DURING {
315 ec = 0;
316 [[self context] runCommand:@"doc::set-object-link",
317 @"object", _srcGen,
318 @"title", _linkName,
319 @"fileType", _linkExt,
320 @"folder", _destGen, nil];
321 }
322 NS_HANDLER {
323 ec = 14;
324 [self setLastException:localException];
325 }
326 NS_ENDHANDLER;
327 if (ec)
328 return [self _buildErrorWithSource:nil dest:nil msg:ec handler:_handler
329 cmd:_cmd];
330 return YES;
331 }
332
333 - (BOOL)moveLink:(EOGenericRecord *)_srcGen
334 toPath:(EOGenericRecord *)_destGen
335 name:(NSString *)_linkName
336 extension:(NSString *)_linkExt
337 handler:(id)_handler
338 {
339 return [self moveLink:_srcGen toPath:_destGen name:_linkName extension:_linkExt
340 handler:_handler doFlush:YES];
341 }
342
343 - (BOOL)moveFile:(EOGenericRecord *)_srcGen
344 toPath:(EOGenericRecord *)_destGen
345 name:(NSString *)_fileName
346 extension:(NSString *)_fileExt
347 handler:(id)_handler
348 doFlush:(BOOL)_doFlush
349 {
350 int ec;
351 BOOL checkin;
352 NSString *title, *ext;
353 id doc;
354
355 title = [SkyProjectFileManager formatTitle:[_srcGen valueForKey:@"title"]];
356
357 if (![title isNotNull])
358 title = (id)[NSNull null];
359
360 ext = [_srcGen valueForKey:@"fileType"];
361
362 if (![ext isNotNull])
363 ext = (id)[NSNull null];
364 else if (![ext length])
365 ext = (id)[NSNull null];
366
367 if (![_fileName isNotNull])
368 _fileName = (id)[NSNull null];
369
370 if (_fileExt == nil || [_fileExt length] == 0)
371 return [self _buildErrorWithSource:nil dest:nil msg:15
372 handler:_handler cmd:_cmd];
373
374 if (_doFlush)
375 [self flush];
376
377 checkin = NO;
378 doc = nil;
379 if (![_fileName isEqual:title] || ![_fileExt isEqual:ext]) {
380 if ([[_srcGen valueForKey:@"status"] isEqualToString:@"released"]) {
381 /* now checkout */
382 checkin = YES;
383
384 NS_DURING {
385 ec = 0;
386 doc = [[self context] runCommand:@"doc::checkout",
387 @"object", _srcGen, nil];
388 _srcGen = [doc valueForKey:@"toDocumentEditing"];
389 }
390 NS_HANDLER {
391 ec = 16;
392 [self setLastException:localException];
393 }
394 NS_ENDHANDLER;
395 if (ec)
396 return [self _buildErrorWithSource:nil dest:nil msg:ec handler:_handler
397 cmd:_cmd];
398 }
399 NS_DURING {
400 ec = 0;
401 if ([_srcGen isNotNull])
402 _srcGen = [[self context] runCommand:@"doc::set",
403 @"object", _srcGen,
404 @"title", _fileName,
405 @"fileType", _fileExt, nil];
406 else
407 ec = 4;
408 }
409 NS_HANDLER {
410 ec = 17;
411 [self setLastException:localException];
412 }
413 NS_ENDHANDLER;
414 if (ec)
415 return [self _buildErrorWithSource:nil dest:nil msg:ec handler:_handler
416 cmd:_cmd];
417
418 if (checkin) {
419 NS_DURING {
420 ec = 0;
421 if ([doc isNotNull])
422 [[self context] runCommand:@"doc::release", @"object", doc, nil];
423 else
424 ec = 4;
425 }
426 NS_HANDLER {
427 ec = 18;
428 [self setLastException:localException];
429 }
430 NS_ENDHANDLER;
431 if (ec)
432 return [self _buildErrorWithSource:nil dest:nil msg:ec handler:_handler
433 cmd:_cmd];
434 }
435 }
436 if (doc == nil) {
437 doc = (![[_srcGen entityName] isEqualToString:@"Doc"])
438 ? [_srcGen valueForKey:@"toDoc"]
439 : (id)_srcGen;
440 }
441
442 if (![[doc valueForKey:@"parentDocumentId"]
443 isEqual:[_destGen valueForKey:@"documentId"]]) {
444 NS_DURING {
445 ec = 0;
446 if ([doc isNotNull])
447 [[self context] runCommand:@"doc::move", @"object", doc,
448 @"folder", _destGen, nil];
449 else
450 ec = 4;
451 }
452 NS_HANDLER {
453 ec = 19;
454 [self setLastException:localException];
455 }
456 NS_ENDHANDLER;
457 if (ec)
458 return [self _buildErrorWithSource:nil dest:nil msg:ec handler:_handler
459 cmd:_cmd];
460 }
461 return YES;
462 }
463
464 - (BOOL)moveFile:(EOGenericRecord *)_srcGen
465 toPath:(EOGenericRecord *)_destGen
466 name:(NSString *)_fileName
467 extension:(NSString *)_fileExt
468 handler:(id)_handler
469 {
470 return [self moveFile:_srcGen toPath:_destGen name:_fileName extension:_fileExt
471 handler:_handler doFlush:YES];
472 }
473
474 - (void)_subpathsAtPath:(NSString *)_path
475 array:(NSMutableArray *)_array
476 {
477 NSDictionary *attrs;
478
479 if (_array == nil) {
480 NSLog(@"ERROR[%s] internal inconsistency ...", __PRETTY_FUNCTION__);
481 return;
482 }
483 attrs = [self fileAttributesAtPath:_path traverseLink:NO];
484
485 if ([[attrs objectForKey:NSFileType] isEqualToString:NSFileTypeDirectory]) {
486 NSEnumerator *enumerator;
487 NSDictionary *obj;
488
489 enumerator = [[self->cache childAttributesAtPath:_path manager:self]
490 objectEnumerator];
491
492 while ((obj = [enumerator nextObject])) {
493 NSString *path;
494
495 path = [obj objectForKey:NSFilePath];
496 [_array addObject:path];
497 if ([[obj objectForKey:NSFileType] isEqualToString:NSFileTypeDirectory])
498 [self _subpathsAtPath:path array:_array];
499 }
500 }
501 }
502
503 /* got absolute paths */
504 - (BOOL)_copyPath:(NSString*)_src
505 toPath:(NSString*)_dest
506 handler:(id)_handler
507 {
508 BOOL srcIsFolder;
509 NSDictionary *attrs;
510 NSEnumerator *enumerator;
511 NSArray *contents;
512
513 srcIsFolder = NO;
514 if (![self fileExistsAtPath:_src isDirectory:&srcIsFolder]) {
515 return [self _buildErrorWithSource:_src dest:_dest msg:4 handler:_handler
516 cmd:_cmd];
517 }
518 if (!srcIsFolder) {
519 return [self _buildErrorWithSource:_src dest:_dest msg:32 handler:_handler
520 cmd:_cmd];
521 }
522 if (!(_dest = [self _makeAbsolute:_dest])) {
523 return [self _buildErrorWithSource:_dest dest:nil msg:20 handler:_handler
524 cmd:_cmd];
525 }
526 if ([self fileExistsAtPath:_dest isDirectory:NULL]) {
527 return [self _buildErrorWithSource:_src dest:_dest msg:7 handler:_handler
528 cmd:_cmd];
529 }
530 if (!(attrs = [self fileAttributesAtPath:_src traverseLink:NO])) {
531 return [self _buildErrorWithSource:_src dest:_dest msg:6 handler:_handler
532 cmd:_cmd];
533 }
534 if (![self createDirectoryAtPath:_dest attributes:attrs]) {
535 return NO;
536 }
537 contents = [self->cache childAttributesAtPath:_src manager:self];
538 enumerator = [contents objectEnumerator];
539 {
540 NSMutableDictionary *dict;
541 id keys[3];
542
543 keys[0] = @"contentHandler";
544 keys[1] = @"attributes";
545 keys[2] = @"sourceGID";
546 dict = [NSMutableDictionary dictionaryWithCapacity:[contents count]];
547
548 while ((attrs = [enumerator nextObject])) {
549 if ([[attrs objectForKey:NSFileType] isEqualToString:NSFileTypeDirectory]) {
550 if (![self _copyPath:[attrs objectForKey:NSFilePath]
551 toPath:[_dest stringByAppendingPathComponent:
552 [attrs objectForKey:NSFileName]] handler:_handler]) {
553 return NO;
554 }
555 }
556 else if ([[attrs objectForKey:NSFileType]
557 isEqualToString:NSFileTypeSymbolicLink]) {
558 if (![self createSymbolicLinkAtPath:
559 [_dest stringByAppendingPathComponent:
560 [attrs objectForKey:NSFileName]]
561 pathContent:[attrs objectForKey:@"SkyLinkTarget"]])
562 return NO;
563
564 }
565 else if ([[attrs objectForKey:NSFileType] isEqualToString:NSFileTypeRegular]) {
566 NSDictionary *d;
567 id vals[3];
568
569 vals[0] = [self blobHandlerAtPath:[attrs objectForKey:NSFilePath]];
570 vals[1] = attrs;
571 vals[2] = [attrs objectForKey:@"globalID"];
572
573 d = [NSDictionary dictionaryWithObjects:vals forKeys:keys count:3];
574 [dict setObject:d forKey:[attrs objectForKey:NSFileName]];
575 }
576 }
577 if (![self createFiles:dict atPath:_dest]) {
578 return NO;
579 }
580 }
581 [self postChangeNotificationForPath:
582 [_dest stringByDeletingLastPathComponent]];
583 return YES;
584 }
585
586 @end /* SkyProjectFileManager(Internals) */
587
588 @implementation SkyProjectFileManager(ErrorHandling_Internals)
589
590 static NSDictionary *errorDict = NULL;
591
592 static NSNumber *num(int _i) {
593 return [NSNumber numberWithInt:_i];
594 }
595
596 - (void)_initializeErrorDict {
597 if (!errorDict) {
598 errorDict =
599 [[NSDictionary alloc]
600 initWithObjectsAndKeys:
601 @"try to move from/to version", num(1),
602 @"try to move root folder", num(2),
603 @"try to move do descendant", num(3),
604 @"missing source", num(4),
605 @"missing destination", num(5),
606 @"source path doesn`t exist", num(6),
607 @"destination path already exist", num(7),
608 @"missing global id for parent folder", num(8),
609 @"missing access for move", num(9),
610 @"only current owner or root can move edited files", num(10),
611 @"missing access for insert", num(11),
612 @"move failed", num(12),
613 @"doc::set-folder failed", num(13),
614 @"doc::set-object-link failed", num(14),
615 @"missing path extension", num(15),
616 @"doc::checkout failed", num(16),
617 @"doc::set failed", num(17),
618 @"doc::release failed", num(18),
619 @"doc::move failed", num(19),
620 @"missing file", num(20),
621 @"missing access for delete", num(21),
622 @"couldn`t delete", num(22),
623 @"only current owner or root can delete edited files",
624 num(23),
625 @"path isn`t a directory", num(24),
626 @"couldn't create file", num(25),
627 @"missing target", num(26),
628 @"missing directory", num(27),
629 @"couldn`t create link", num(28),
630 @"missing access for read", num(29),
631 @"directories or symbolic links has no content", num(30),
632 @"try to copy do descendant", num(31),
633 @"source is a folder", num(32),
634 @"couldn't create directory", num(33),
635 @"missing path", num(34),
636 @"missing access for write", num(35),
637 @"operation is not allowed for versions", num(36),
638 @"only current owner or root can edit edited files", num(37),
639 @"unsupported file attributes", num(38),
640 @"missing doc", num(39),
641 @"uncomplete document", num(40),
642 @"couldn`t autocreate document", num(41),
643 @"couldn`t delete tmp file after exception", num(42),
644 @"missing propertymanager", num(43),
645 @"missing globalID", num(44),
646 @"error during add properties", num(45),
647 @"error during delete properties", num(46),
648 @"error during update properties", num(47),
649 @"couldn`t checkout directory", num(48),
650 @"file is already in edit mode", num(49),
651 @"doc::checkout failed", num(50),
652 @"file is already released", num(51),
653 @"doc::release failed", num(52),
654 @"doc::reject failed", num(53),
655 @"missing version", num(54),
656 @"documentversion::checkout failed", num(55),
657 @"missing blob name", num(56),
658 @"reject failed after doc::set failed", num(57),
659 @"source path isn`t a directory", num(58),
660 @"destination path isn`t a directory", num(59),
661 nil];
662 }
663 }
664
665 - (NSDictionary *)errorDict {
666 if (!errorDict)
667 [self _initializeErrorDict];
668 return errorDict;
669 }
670
671 static BOOL logError_value = NO;
672 static BOOL logError_flag = NO;
673
674 static inline BOOL _logError(id self) {
675 if (!logError_flag) {
676 logError_flag = YES;
677 logError_value =
678 [[NSUserDefaults standardUserDefaults]
679 boolForKey:@"SkyProjectFileManagerErrorLogEnabled"];
680 }
681 return logError_value;
682 }
683
684 static BOOL abortError_value = NO;
685 static BOOL abortError_flag = NO;
686
687 static inline BOOL _abortError(id self) {
688 if (!abortError_flag) {
689 abortError_flag = YES;
690 abortError_value =
691 [[NSUserDefaults standardUserDefaults]
692 boolForKey:@"SkyProjectFileManagerAbortOnErrors"];
693 }
694 return abortError_value;
695 }
696
697 - (BOOL)_buildErrorWithSource:(NSString *)_src dest:(NSString *)_dest
698 msg:(int)_msgId handler:(id)_handler cmd:(SEL)_sel
699 {
700 return [self _buildErrorWithSource:_src dest:_dest msg:_msgId handler:_handler
701 cmd:_sel doFlush:YES doRollback:YES];
702 }
703
704 - (BOOL)_buildErrorWithSource:(NSString *)_src dest:(NSString *)_dest
705 msg:(int)_msgId handler:(id)_handler cmd:(SEL)_sel doFlush:(BOOL)_doFlush
706 doRollback:(BOOL)_doRollback
707 {
708 NSString *errMsg;
709
710 self->lastErrorCode = _msgId;
711 errMsg = [[self errorDict] objectForKey:num(_msgId)];
712
713 if (_handler != nil) {
714 id obj[3];
715 id key[3];
716 int cnt = 0;
717 NSDictionary *errMsg = nil;
718
719 if (_src != nil) {
720 obj[cnt] = _src;
721 key[cnt] = @"Path";
722 cnt++;
723 }
724 if (_dest != nil) {
725 obj[cnt] = _dest;
726 key[cnt] = @"toPath";
727 cnt++;
728 }
729 if (errMsg != nil) {
730 obj[cnt] = errMsg;
731 key[cnt] = @"Error";
732 cnt++;
733 }
734 if (_msgId) {
735 obj[cnt] = num(_msgId);
736 key[cnt] = @"ErrorCode";
737 cnt++;
738 }
739 errMsg = [NSDictionary dictionaryWithObjects:obj forKeys:key count:cnt];
740
741 if ([_handler respondsToSelector:
742 @selector(fileManager:shouldProceedAfterError:)]) {
743 if ([_handler fileManager:(id)self shouldProceedAfterError:errMsg]) {
744 return YES;
745 }
746 }
747 }
748 if (_logError(self) || _abortError(self)) {
749 NSLog(@"ERROR(%@): _src <%@> _dest <%@> msgCode <%d> msg <%@> "
750 @"handler <%@> exception: %@",
751 NSStringFromSelector(_sel), _src, _dest,
752 _msgId, errMsg, _handler, self->lastException);
753 }
754 if (_abortError(self))
755 abort();
756
757 if (_doRollback)
758 [self->cache rollbackTransaction];
759
760 if (_doFlush)
761 [self flush];
762
763 return NO;
764 }
765
766 @end /* SkyProjectFileManager(ErrorHandling+Internals) */
767
768 @implementation SkyProjectFileManager(Locking_Internals)
769
770 - (NSArray *)allVersionAttributesAtPath:(NSString *)_path {
771 return [self->cache allVersionAttrsAtPath:_path manager:self];
772 }
773
774 @end /* SkyProjectFileManager(Locking_Internals) */
775
776 @implementation SkyProjectFileManager(Removing)
777
778 - (BOOL)_removeFileAttrs:(NSArray *)_paths handler:(id)_handler failed:(BOOL*)failed_
779 {
780 NSMutableArray *files;
781 NSMutableArray *dirs;
782 NSEnumerator *enumerator;
783 NSDictionary *attrs;
784
785 enumerator = [_paths objectEnumerator];
786
787 files = [NSMutableArray array];
788 dirs = [NSMutableArray array];
789
790 while ((attrs = [enumerator nextObject])) {
791
792 if ([[attrs objectForKey:NSFileType] isEqual:NSFileTypeDirectory]) {
793 [dirs addObject:attrs];
794 }
795 else {
796 [files addObject:attrs];
797 }
798 }
799 if (![self _removeFiles:files handler:_handler failed:failed_]) {
800 return NO;
801 }
802 if (![self _removeDirs:dirs handler:_handler failed:failed_]) {
803 return NO;
804 }
805 return YES;
806 }
807
808 - (BOOL)_removeFiles:(NSArray *)_fileAttrs handler:(id)_handler failed:(BOOL*)failed_
809 {
810 NSEnumerator *enumerator;
811 NSDictionary *attrs;
812 id handler;
813
814 if (failed_)
815 *failed_ = NO;
816
817 handler = nil;
818 if ([_handler respondsToSelector:
819 @selector(fileManager:shouldProceedAfterError:)]) {
820 handler = _handler;
821 }
822
823 enumerator = [_fileAttrs objectEnumerator];
824
825 while ((attrs = [enumerator nextObject])) {
826 NSString *_path;
827 int ec;
828
829 _path = [attrs objectForKey:NSFilePath];
830
831 if ([[attrs objectForKey:@"SkyStatus"] isEqualToString:@"edited"]) {
832 id a, aid;
833
834 a = [[self context] valueForKey:LSAccountKey];
835 aid = [a valueForKey:@"companyId"];
836
837 if (![[attrs objectForKey:@"SkyOwnerId"] isEqual:aid] &&
838 ([aid intValue] != 10000)) {
839 if (![handler fileManager:(id)self
840 shouldProceedAfterError:er_dict(23)]) {
841 return NO;
842 }
843 if (failed_)
844 *failed_ = YES;
845
846 return YES;
847 }
848 }
849 NS_DURING {
850 ec = 0;
851 #if 1
852 if (![self reallyDeleteFile:attrs])
853 ec = 22;
854 #else
855 id d;
856 if ((d = [self->cache genericRecordForAttrs:attrs manager:self])) {
857
858 if ([[d entityName] isEqualToString:@"DocumentEditing"]) {
859 d = [d valueForKey:@"toDoc"];
860 }
861 [[self context] runCommand:@"doc::delete",
862 @"object", d,
863 @"reallyDelete", [NSNumber numberWithBool:YES], nil];
864 }
865 else {
866 ec = 22;
867 }
868 #endif
869 }
870 NS_HANDLER {
871 ec = 22;
872 [self setLastException:localException];
873 [self _buildErrorWithSource:_path dest:nil msg:ec handler:_handler
874 cmd:_cmd];
875 }
876 NS_ENDHANDLER;
877
878 if (ec) {
879 if (![_handler fileManager:(id)self shouldProceedAfterError:er_dict(23)]) {
880 return NO;
881 }
882 if (failed_)
883 *failed_ = YES;
884 }
885 [self postChangeNotificationForPath:[_path stringByDeletingLastPathComponent]];
886 [self postUnvalidateNotificationForPath:_path];
887 [self postSkyGlobalIDWasDeleted:[attrs objectForKey:@"globalID"]];
888 }
889 return YES;
890 }
891
892 - (BOOL)_removeDirs:(NSArray *)_dirAttr handler:(id)_handler failed:(BOOL*)failed_ {
893 NSEnumerator *enumerator;
894 NSDictionary *attrs;
895 NSMutableArray *dirs;
896
897 dirs = [NSMutableArray arrayWithCapacity:[_dirAttr count]];
898 enumerator = [_dirAttr objectEnumerator];
899
900 while ((attrs = [enumerator nextObject])) {
901 NSArray *files;
902 BOOL failed;
903
904 files = [self->cache childAttributesAtPath:[attrs objectForKey:NSFilePath]
905 manager:self];
906
907 if (![self _removeFileAttrs:files handler:_handler failed:&failed])
908 return NO;
909
910 if (failed)
911 continue;
912
913 [dirs addObject:attrs];
914 }
915 return [self _removeFiles:dirs handler:_handler failed:failed_];
916 }
917
918 @end /* SkyProjectFileManager(Removing) */