1 package org.modeshape.connector.filesystem;
2
3 import java.io.BufferedInputStream;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.Collection;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.concurrent.TimeUnit;
19 import org.modeshape.common.i18n.I18n;
20 import org.modeshape.common.util.FileUtil;
21 import org.modeshape.common.util.IoUtil;
22 import org.modeshape.common.util.Logger;
23 import org.modeshape.graph.ExecutionContext;
24 import org.modeshape.graph.JcrLexicon;
25 import org.modeshape.graph.JcrNtLexicon;
26 import org.modeshape.graph.Location;
27 import org.modeshape.graph.ModeShapeLexicon;
28 import org.modeshape.graph.connector.RepositorySourceException;
29 import org.modeshape.graph.connector.base.PathNode;
30 import org.modeshape.graph.connector.base.PathWorkspace;
31 import org.modeshape.graph.mimetype.MimeTypeDetector;
32 import org.modeshape.graph.property.Binary;
33 import org.modeshape.graph.property.BinaryFactory;
34 import org.modeshape.graph.property.DateTimeFactory;
35 import org.modeshape.graph.property.Name;
36 import org.modeshape.graph.property.NameFactory;
37 import org.modeshape.graph.property.NamespaceRegistry;
38 import org.modeshape.graph.property.Path;
39 import org.modeshape.graph.property.PathFactory;
40 import org.modeshape.graph.property.PathNotFoundException;
41 import org.modeshape.graph.property.Property;
42 import org.modeshape.graph.property.PropertyFactory;
43 import org.modeshape.graph.property.ValueFactory;
44 import org.modeshape.graph.property.Path.Segment;
45 import org.modeshape.graph.property.basic.FileSystemBinary;
46 import org.modeshape.graph.request.Request;
47
48
49
50
51 class FileSystemWorkspace extends PathWorkspace<PathNode> {
52 private static final Map<Name, Property> NO_PROPERTIES = Collections.emptyMap();
53 private static final String DEFAULT_MIME_TYPE = "application/octet";
54 private static final Set<Name> VALID_PRIMARY_TYPES = new HashSet<Name>(Arrays.asList(new Name[] {JcrNtLexicon.FOLDER,
55 JcrNtLexicon.FILE, JcrNtLexicon.RESOURCE, ModeShapeLexicon.RESOURCE}));
56
57 private final FileSystemSource source;
58 private final FileSystemRepository repository;
59 private final ExecutionContext context;
60 private final File workspaceRoot;
61 private final boolean eagerLoading;
62 private final boolean contentUsedToDetermineMimeType;
63 private final Logger logger;
64 private final ValueFactory<String> stringFactory;
65 private final NameFactory nameFactory;
66
67 public FileSystemWorkspace( String name,
68 FileSystemWorkspace originalToClone,
69 File workspaceRoot ) {
70 super(name, originalToClone.getRootNodeUuid());
71
72 this.source = originalToClone.source;
73 this.context = originalToClone.context;
74 this.workspaceRoot = workspaceRoot;
75 this.repository = originalToClone.repository;
76 this.eagerLoading = this.source.isEagerFileLoading();
77 this.contentUsedToDetermineMimeType = this.source.isContentUsedToDetermineMimeType();
78 this.logger = Logger.getLogger(getClass());
79 this.stringFactory = context.getValueFactories().getStringFactory();
80 this.nameFactory = context.getValueFactories().getNameFactory();
81
82 cloneWorkspace(originalToClone);
83 }
84
85 public FileSystemWorkspace( FileSystemRepository repository,
86 String name ) {
87 super(name, repository.getRootNodeUuid());
88 this.workspaceRoot = repository.getWorkspaceDirectory(name);
89 this.repository = repository;
90 this.context = repository.getContext();
91 this.source = repository.source;
92 this.eagerLoading = this.source.isEagerFileLoading();
93 this.contentUsedToDetermineMimeType = this.source.isContentUsedToDetermineMimeType();
94 this.logger = Logger.getLogger(getClass());
95 this.stringFactory = context.getValueFactories().getStringFactory();
96 this.nameFactory = context.getValueFactories().getNameFactory();
97 }
98
99 private void cloneWorkspace( FileSystemWorkspace original ) {
100 File originalRoot = repository.getWorkspaceDirectory(original.getName());
101 File newRoot = repository.getWorkspaceDirectory(this.getName());
102
103 try {
104 FileUtil.copy(originalRoot, newRoot, source.filenameFilter(false));
105 } catch (IOException ioe) {
106 throw new IllegalStateException(ioe);
107 }
108 }
109
110 private void moveFile( File originalFileOrDirectory,
111 File newFileOrDirectory ) {
112 if (originalFileOrDirectory.renameTo(newFileOrDirectory)) return;
113
114
115
116
117
118
119 try {
120 FileUtil.copy(originalFileOrDirectory, newFileOrDirectory);
121 FileUtil.delete(originalFileOrDirectory);
122 } catch (IOException ioe) {
123 throw new RepositorySourceException(FileSystemI18n.couldNotCopyData.text(source.getName(),
124 originalFileOrDirectory.getAbsolutePath(),
125 newFileOrDirectory.getAbsolutePath()), ioe);
126 }
127
128 }
129
130 @Override
131 public PathNode moveNode( PathNode node,
132 PathNode newNode ) {
133 PathFactory pathFactory = context.getValueFactories().getPathFactory();
134 Path newPath = pathFactory.create(newNode.getParent(), newNode.getName());
135 Path oldPath = pathFactory.create(node.getParent(), node.getName());
136 File originalFile = fileFor(oldPath);
137 File newFile = fileFor(newPath, false);
138
139 if (newFile.exists()) {
140 newFile.delete();
141 }
142
143
144 CustomPropertiesFactory customPropertiesFactory = source.customPropertiesFactory();
145 Collection<Property> existingProps = null;
146 Collection<Property> existingResourceProps = null;
147 String sourceName = source.getName();
148 Location originalLocation = Location.create(oldPath);
149 if (originalFile.isDirectory()) {
150 existingProps = customPropertiesFactory.getDirectoryProperties(context, originalLocation, originalFile);
151 customPropertiesFactory.recordDirectoryProperties(context, sourceName, originalLocation, originalFile, NO_PROPERTIES);
152 } else {
153 Path resourcePath = pathFactory.create(oldPath, JcrLexicon.CONTENT);
154 Location originalResourceLocation = Location.create(resourcePath);
155 existingProps = customPropertiesFactory.getFileProperties(context, originalLocation, originalFile);
156 existingResourceProps = customPropertiesFactory.getResourceProperties(context,
157 originalResourceLocation,
158 originalFile,
159 null);
160 customPropertiesFactory.recordFileProperties(context, sourceName, originalLocation, originalFile, NO_PROPERTIES);
161 customPropertiesFactory.recordResourceProperties(context,
162 sourceName,
163 originalResourceLocation,
164 originalFile,
165 NO_PROPERTIES);
166 }
167
168 moveFile(originalFile, newFile);
169
170
171 Location newLocation = Location.create(newPath);
172 if (originalFile.isDirectory()) {
173 customPropertiesFactory.recordDirectoryProperties(context,
174 sourceName,
175 newLocation,
176 newFile,
177 extraFolder(mapOf(existingProps)));
178 } else {
179 Path resourcePath = pathFactory.create(newPath, JcrLexicon.CONTENT);
180 Location resourceLocation = Location.create(resourcePath);
181 customPropertiesFactory.recordFileProperties(context,
182 sourceName,
183 newLocation,
184 newFile,
185 extraFile(mapOf(existingProps)));
186 customPropertiesFactory.recordResourceProperties(context,
187 sourceName,
188 resourceLocation,
189 newFile,
190 extraResource(mapOf(existingResourceProps)));
191 }
192
193 return getNode(newPath);
194 }
195
196 protected Map<Name, Property> mapOf( Collection<Property> properties ) {
197 if (properties == null || properties.isEmpty()) return Collections.emptyMap();
198 Map<Name, Property> result = new HashMap<Name, Property>();
199 for (Property property : properties) {
200 result.put(property.getName(), property);
201 }
202 return result;
203 }
204
205 @Override
206 public PathNode putNode( PathNode node ) {
207 PathFactory pathFactory = context.getValueFactories().getPathFactory();
208 NamespaceRegistry registry = context.getNamespaceRegistry();
209 CustomPropertiesFactory customPropertiesFactory = source.customPropertiesFactory();
210
211 Map<Name, Property> properties = node.getProperties();
212
213 if (node.getParent() == null) {
214
215 Path rootPath = pathFactory.createRootPath();
216 Location rootLocation = Location.create(rootPath, repository.getRootNodeUuid());
217 customPropertiesFactory.recordDirectoryProperties(context,
218 source.getName(),
219 rootLocation,
220 workspaceRoot,
221 extraFolder(node.getProperties()));
222 return getNode(rootPath);
223 }
224
225
226
227
228 Path parentPath = node.getParent();
229 boolean isRoot = parentPath == null;
230 File parentFile = fileFor(parentPath);
231
232 Path newPath = isRoot ? pathFactory.createRootPath() : pathFactory.create(parentPath, node.getName());
233 Name name = node.getName().getName();
234 String newName = name.getString(registry);
235 File newFile = new File(parentFile, newName);
236
237
238
239
240 Property primaryTypeProp = properties.get(JcrLexicon.PRIMARY_TYPE);
241
242
243 Name primaryType = primaryTypeProp == null ? JcrNtLexicon.FOLDER : nameFactory.create(primaryTypeProp.getFirstValue());
244
245 if (JcrNtLexicon.FILE.equals(primaryType)) {
246
247
248 if (!parentFile.canWrite()) {
249 I18n msg = FileSystemI18n.parentIsReadOnly;
250 throw new RepositorySourceException(source.getName(), msg.text(parentPath, this.getName(), source.getName()));
251 }
252
253 try {
254 ensureValidPathLength(newFile);
255
256
257 if (!newFile.exists() && !newFile.createNewFile()) {
258 I18n msg = FileSystemI18n.fileAlreadyExists;
259 throw new RepositorySourceException(source.getName(), msg.text(parentPath, getName(), source.getName()));
260 }
261 } catch (IOException ioe) {
262 I18n msg = FileSystemI18n.couldNotCreateFile;
263 throw new RepositorySourceException(source.getName(), msg.text(parentPath,
264 getName(),
265 source.getName(),
266 ioe.getMessage()), ioe);
267 }
268
269 customPropertiesFactory.recordFileProperties(context,
270 source.getName(),
271 Location.create(newPath),
272 newFile,
273 extraFile(properties));
274 } else if (JcrNtLexicon.RESOURCE.equals(primaryType) || ModeShapeLexicon.RESOURCE.equals(primaryType)) {
275 assert parentFile != null;
276
277 if (!JcrLexicon.CONTENT.equals(name)) {
278 I18n msg = FileSystemI18n.invalidNameForResource;
279 String nodeName = name.getString();
280 throw new RepositorySourceException(source.getName(), msg.text(parentPath, getName(), source.getName(), nodeName));
281 }
282
283 if (!parentFile.isFile()) {
284 I18n msg = FileSystemI18n.invalidPathForResource;
285 throw new RepositorySourceException(source.getName(), msg.text(parentPath, getName(), source.getName()));
286 }
287
288 if (!parentFile.canWrite()) {
289 I18n msg = FileSystemI18n.parentIsReadOnly;
290 throw new RepositorySourceException(source.getName(), msg.text(parentPath, getName(), source.getName()));
291 }
292
293
294 FileOutputStream fos = null;
295 try {
296 File temp = File.createTempFile("modeshape", null);
297 fos = new FileOutputStream(temp);
298
299 Property dataProp = properties.get(JcrLexicon.DATA);
300 BinaryFactory binaryFactory = context.getValueFactories().getBinaryFactory();
301 Binary binary = null;
302 if (dataProp == null) {
303
304 binary = binaryFactory.create(new byte[] {});
305 dataProp = context.getPropertyFactory().create(JcrLexicon.DATA, new Object[] {binary});
306 } else {
307
308 binary = binaryFactory.create(properties.get(JcrLexicon.DATA).getFirstValue());
309 }
310
311 IoUtil.write(binary.getStream(), fos);
312
313 if (!FileUtil.delete(parentFile)) {
314 I18n msg = FileSystemI18n.deleteFailed;
315 throw new RepositorySourceException(source.getName(), msg.text(parentPath, getName(), source.getName()));
316 }
317
318 moveFile(temp, parentFile);
319 } catch (IOException ioe) {
320 I18n msg = FileSystemI18n.couldNotWriteData;
321 throw new RepositorySourceException(source.getName(), msg.text(parentPath,
322 getName(),
323 source.getName(),
324 ioe.getMessage()), ioe);
325
326 } finally {
327 try {
328 if (fos != null) fos.close();
329 } catch (Exception ex) {
330 }
331 }
332 customPropertiesFactory.recordResourceProperties(context,
333 source.getName(),
334 Location.create(parentPath),
335 parentFile,
336 extraResource(properties));
337
338 } else if (JcrNtLexicon.FOLDER.equals(primaryType) || primaryType == null) {
339 ensureValidPathLength(newFile);
340
341 if (!newFile.exists() && !newFile.mkdir()) {
342 I18n msg = FileSystemI18n.couldNotCreateFile;
343 throw new RepositorySourceException(source.getName(),
344 msg.text(parentPath,
345 getName(),
346 source.getName(),
347 primaryType == null ? "null" : primaryType.getString(registry)));
348 }
349 customPropertiesFactory.recordDirectoryProperties(context,
350 source.getName(),
351 Location.create(newPath),
352 newFile,
353 extraFolder(properties));
354
355 } else {
356
357 I18n msg = FileSystemI18n.unsupportedPrimaryType;
358 throw new RepositorySourceException(source.getName(), msg.text(primaryType.getString(registry),
359 parentPath,
360 getName(),
361 source.getName()));
362 }
363
364 node = getNode(newPath);
365
366 return node;
367 }
368
369 @Override
370 public PathNode removeNode( Path nodePath ) {
371 File nodeFile;
372
373 CustomPropertiesFactory customPropertiesFactory = source.customPropertiesFactory();
374
375 if (!nodePath.isRoot() && JcrLexicon.CONTENT.equals(nodePath.getLastSegment().getName())) {
376 nodeFile = fileFor(nodePath.getParent());
377
378
379 customPropertiesFactory.recordResourceProperties(context,
380 source.getName(),
381 Location.create(nodePath),
382 nodeFile,
383 NO_PROPERTIES);
384 if (!nodeFile.exists()) return null;
385
386 FileOutputStream fos = null;
387 try {
388 fos = new FileOutputStream(nodeFile);
389 IoUtil.write("", fos);
390 } catch (IOException ioe) {
391 throw new RepositorySourceException(source.getName(), FileSystemI18n.deleteFailed.text(nodePath,
392 getName(),
393 source.getName()));
394 } finally {
395 if (fos != null) try {
396 fos.close();
397 } catch (IOException ioe) {
398 }
399 }
400 } else {
401 nodeFile = fileFor(nodePath);
402
403 customPropertiesFactory.recordResourceProperties(context,
404 source.getName(),
405 Location.create(nodePath),
406 nodeFile,
407 NO_PROPERTIES);
408 if (!nodeFile.exists()) return null;
409
410 FileUtil.delete(nodeFile);
411 }
412
413 return null;
414 }
415
416 @Override
417 public PathNode getRootNode() {
418 return getNode(context.getValueFactories().getPathFactory().createRootPath());
419 }
420
421 @Override
422 public PathNode getNode( Path path ) {
423 Map<Name, Property> properties = new HashMap<Name, Property>();
424
425 long startTime = System.nanoTime();
426 Name nodeType = null;
427 try {
428
429 PropertyFactory factory = context.getPropertyFactory();
430 PathFactory pathFactory = context.getValueFactories().getPathFactory();
431 DateTimeFactory dateFactory = context.getValueFactories().getDateFactory();
432 MimeTypeDetector mimeTypeDetector = context.getMimeTypeDetector();
433 CustomPropertiesFactory customPropertiesFactory = source.customPropertiesFactory();
434 NamespaceRegistry registry = context.getNamespaceRegistry();
435 Location location = Location.create(path);
436
437 if (!path.isRoot() && JcrLexicon.CONTENT.equals(path.getLastSegment().getName())) {
438 File file = fileFor(path.getParent());
439 if (file == null) return null;
440
441
442 Collection<Property> customProps = customPropertiesFactory.getResourceProperties(context, location, file, null);
443 for (Property customProp : customProps) {
444 properties.put(customProp.getName(), customProp);
445 }
446
447 if (!properties.containsKey(JcrLexicon.MIMETYPE)) {
448
449 String mimeType = null;
450 InputStream contents = null;
451 try {
452
453
454 mimeType = mimeTypeDetector.mimeTypeOf(file.getName(), null);
455 if (mimeType == null && contentUsedToDetermineMimeType) {
456
457 contents = new BufferedInputStream(new FileInputStream(file));
458 mimeType = mimeTypeDetector.mimeTypeOf(null, contents);
459 }
460 if (mimeType == null) mimeType = DEFAULT_MIME_TYPE;
461 properties.put(JcrLexicon.MIMETYPE, factory.create(JcrLexicon.MIMETYPE, mimeType));
462 } catch (IOException e) {
463 I18n msg = FileSystemI18n.couldNotReadData;
464 throw new RepositorySourceException(source.getName(), msg.text(source.getName(),
465 getName(),
466 path.getString(registry)));
467 } finally {
468 if (contents != null) {
469 try {
470 contents.close();
471 } catch (IOException e) {
472 }
473 }
474 }
475 }
476
477
478
479
480 Property primaryType = properties.get(JcrLexicon.PRIMARY_TYPE);
481 if (primaryType == null) {
482 nodeType = JcrNtLexicon.RESOURCE;
483 properties.put(JcrLexicon.PRIMARY_TYPE, factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.RESOURCE));
484 } else {
485 nodeType = nameValueFor(primaryType);
486 }
487 properties.put(JcrLexicon.LAST_MODIFIED, factory.create(JcrLexicon.LAST_MODIFIED,
488 dateFactory.create(file.lastModified())));
489
490
491 Binary binary = binaryForContent(file);
492 properties.put(JcrLexicon.DATA, factory.create(JcrLexicon.DATA, binary));
493
494
495
496
497
498 return new PathNode(null, path.getParent(), path.getLastSegment(), properties, Collections.<Segment>emptyList());
499 }
500
501 File file = fileFor(path);
502 if (file == null) return null;
503
504 if (file.isDirectory()) {
505 String[] childNames = file.list(source.filenameFilter(true));
506 Arrays.sort(childNames);
507
508 List<Segment> childSegments = new ArrayList<Segment>(childNames.length);
509 for (String childName : childNames) {
510 childSegments.add(pathFactory.createSegment(childName));
511 }
512
513 Collection<Property> customProps = customPropertiesFactory.getDirectoryProperties(context, location, file);
514 for (Property customProp : customProps) {
515 properties.put(customProp.getName(), customProp);
516 }
517
518 if (path.isRoot()) {
519 nodeType = ModeShapeLexicon.ROOT;
520 properties.put(JcrLexicon.PRIMARY_TYPE, factory.create(JcrLexicon.PRIMARY_TYPE, ModeShapeLexicon.ROOT));
521
522 return new PathNode(source.getRootNodeUuidObject(), path.getParent(), path.getLastSegment(), properties,
523 childSegments);
524
525 }
526 Property primaryType = properties.get(JcrLexicon.PRIMARY_TYPE);
527 if (primaryType == null) {
528 nodeType = JcrNtLexicon.FOLDER;
529 properties.put(JcrLexicon.PRIMARY_TYPE, factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.FOLDER));
530 } else {
531 nodeType = nameValueFor(primaryType);
532 }
533
534 return new PathNode(null, path.getParent(), path.getLastSegment(), properties, childSegments);
535
536 }
537
538 Collection<Property> customProps = customPropertiesFactory.getFileProperties(context, location, file);
539 for (Property customProp : customProps) {
540 properties.put(customProp.getName(), customProp);
541 }
542
543 Property primaryType = properties.get(JcrLexicon.PRIMARY_TYPE);
544 if (primaryType == null) {
545 nodeType = JcrNtLexicon.FILE;
546 properties.put(JcrLexicon.PRIMARY_TYPE, factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.FILE));
547 } else {
548 nodeType = nameValueFor(primaryType);
549 }
550 if (!properties.containsKey(JcrLexicon.CREATED)) {
551 properties.put(JcrLexicon.CREATED, factory.create(JcrLexicon.CREATED, dateFactory.create(file.lastModified())));
552 }
553
554
555
556
557 return new PathNode(null, path.getParent(), path.getLastSegment(), properties,
558 Collections.singletonList(pathFactory.createSegment(JcrLexicon.CONTENT)));
559 } finally {
560 if (nodeType != null && logger.isTraceEnabled()) {
561 long stopTime = System.nanoTime();
562 long ms = TimeUnit.MICROSECONDS.convert(stopTime - startTime, TimeUnit.NANOSECONDS);
563 String pathStr = stringFactory.create(path);
564 String typeStr = stringFactory.create(nodeType);
565 logger.trace("Loaded '{0}' node '{1}' in {2}microsec", typeStr, pathStr, ms);
566 }
567 }
568 }
569
570
571
572
573
574
575 @Override
576 public Location verifyNodeExists( Path path ) {
577 File file = fileFor(path, true);
578 return file != null ? Location.create(path) : null;
579 }
580
581
582
583
584
585
586
587
588 protected Binary binaryForContent( File file ) {
589 if (file == null) return null;
590 if (eagerLoading) {
591 BinaryFactory binaryFactory = context.getValueFactories().getBinaryFactory();
592 return binaryFactory.create(file);
593 }
594
595 return new FileSystemBinary(file);
596 }
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617 protected File fileFor( Path path ) {
618 return fileFor(path, true);
619 }
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641 protected File fileFor( Path path,
642 boolean existingFilesOnly ) {
643 if (path == null || path.isRoot()) {
644 return workspaceRoot;
645 }
646
647 if (path.getLastSegment().getName().equals(JcrLexicon.CONTENT)) {
648
649 path = path.getParent();
650 }
651 File file = workspaceRoot;
652 for (Path.Segment segment : path) {
653 String localName = segment.getName().getLocalName();
654
655 if (segment.getIndex() > 1) {
656 I18n msg = FileSystemI18n.sameNameSiblingsAreNotAllowed;
657 throw new RepositorySourceException(source.getName(), msg.text(source.getName()));
658 }
659
660 String defaultNamespaceUri = context.getNamespaceRegistry().getDefaultNamespaceUri();
661 if (!segment.getName().getNamespaceUri().equals(defaultNamespaceUri)) {
662 I18n msg = FileSystemI18n.onlyTheDefaultNamespaceIsAllowed;
663 throw new RepositorySourceException(source.getName(), msg.text(source.getName()));
664 }
665
666
667 file = new File(file, localName);
668
669 if (existingFilesOnly && (!file.canRead() || !file.exists())) {
670 return null;
671 }
672 }
673 assert file != null;
674 return file;
675 }
676
677 protected void validate( PathNode node ) {
678
679 if (node.getParent() == null) return;
680
681 Map<Name, Property> properties = node.getProperties();
682 Property primaryTypeProp = properties.get(JcrLexicon.PRIMARY_TYPE);
683 Name primaryType = primaryTypeProp == null ? JcrNtLexicon.FOLDER : nameFactory.create(primaryTypeProp.getFirstValue());
684
685 if (!VALID_PRIMARY_TYPES.contains(primaryType)) {
686
687 I18n msg = FileSystemI18n.unsupportedPrimaryType;
688 NamespaceRegistry registry = context.getNamespaceRegistry();
689 Path parentPath = node.getParent();
690 throw new RepositorySourceException(source.getName(), msg.text(primaryType.getString(registry),
691 parentPath,
692 getName(),
693 source.getName()));
694
695 }
696
697 Path nodePath = context.getValueFactories().getPathFactory().create(node.getParent(), node.getName());
698 ensureValidPathLength(fileFor(nodePath, false));
699 }
700
701 protected void ensureValidPathLength( File file ) {
702 ensureValidPathLength(file, 0);
703 }
704
705
706
707
708
709
710
711
712
713
714
715
716 protected void ensureValidPathLength( File root,
717 int delta ) {
718 try {
719 int len = root.getCanonicalPath().length();
720 if (len > source.getMaxPathLength() - delta) {
721 String msg = FileSystemI18n.maxPathLengthExceeded.text(source.getMaxPathLength(),
722 source.getName(),
723 root.getCanonicalPath(),
724 delta);
725 throw new RepositorySourceException(source.getName(), msg);
726 }
727
728 if (root.isDirectory()) {
729 for (File child : root.listFiles(source.filenameFilter(false))) {
730 ensureValidPathLength(child, delta);
731 }
732
733 }
734 } catch (IOException ioe) {
735 throw new RepositorySourceException(source.getName(), FileSystemI18n.getCanonicalPathFailed.text(), ioe);
736 }
737 }
738
739
740
741
742
743
744
745 protected Map<Name, Property> extraFolder( Map<Name, Property> properties ) {
746 if (properties == null) return null;
747 if (properties.isEmpty()) return properties;
748 Map<Name, Property> extra = new HashMap<Name, Property>();
749 for (Property property : properties.values()) {
750 Name name = property.getName();
751 if (name.equals(JcrLexicon.PRIMARY_TYPE) && primaryTypeIs(property, JcrNtLexicon.FOLDER)) continue;
752 extra.put(name, property);
753 }
754 return extra;
755 }
756
757
758
759
760
761
762
763 protected Map<Name, Property> extraFile( Map<Name, Property> properties ) {
764 if (properties == null) return null;
765 if (properties.isEmpty()) return properties;
766 Map<Name, Property> extra = new HashMap<Name, Property>();
767 for (Property property : properties.values()) {
768 Name name = property.getName();
769 if (name.equals(JcrLexicon.PRIMARY_TYPE) && primaryTypeIs(property, JcrNtLexicon.FILE)) continue;
770 extra.put(name, property);
771 }
772 return extra;
773 }
774
775
776
777
778
779
780
781 protected Map<Name, Property> extraResource( Map<Name, Property> properties ) {
782 if (properties == null) return null;
783 if (properties.isEmpty()) return properties;
784 Map<Name, Property> extra = new HashMap<Name, Property>();
785 for (Property property : properties.values()) {
786 Name name = property.getName();
787 if (name.equals(JcrLexicon.PRIMARY_TYPE) && primaryTypeIs(property, JcrNtLexicon.RESOURCE)) continue;
788 else if (name.equals(JcrLexicon.DATA)) continue;
789 extra.put(name, property);
790 }
791 return extra;
792 }
793
794 protected boolean primaryTypeIs( Property property,
795 Name primaryType ) {
796 Name actualPrimaryType = nameValueFor(property);
797 return actualPrimaryType.equals(primaryType);
798 }
799
800 protected Name nameValueFor( Property property ) {
801 return nameFactory.create(property.getFirstValue());
802 }
803 }