1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.datamodel.niofs;
20
21 import static org.mycore.datamodel.niofs.MCRAbstractFileSystem.SEPARATOR;
22 import static org.mycore.datamodel.niofs.MCRAbstractFileSystem.SEPARATOR_STRING;
23
24 import java.io.IOException;
25 import java.io.UncheckedIOException;
26 import java.nio.file.DirectoryStream;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.SecureDirectoryStream;
30 import java.nio.file.attribute.BasicFileAttributes;
31 import java.nio.file.attribute.FileTime;
32 import java.util.Collection;
33 import java.util.Map;
34 import java.util.SortedMap;
35 import java.util.TreeMap;
36 import java.util.concurrent.TimeUnit;
37 import java.util.function.Function;
38
39 import org.apache.logging.log4j.LogManager;
40 import org.apache.logging.log4j.Logger;
41 import org.jdom2.Document;
42 import org.jdom2.Element;
43 import org.mycore.common.MCRConstants;
44 import org.mycore.datamodel.classifications2.MCRCategLinkReference;
45 import org.mycore.datamodel.classifications2.MCRCategLinkServiceFactory;
46 import org.mycore.datamodel.classifications2.MCRCategoryID;
47 import org.mycore.datamodel.metadata.MCRMetadataManager;
48 import org.mycore.datamodel.metadata.MCRObjectID;
49
50
51
52
53
54 public class MCRPathXML {
55
56 static Logger LOGGER = LogManager.getLogger(MCRPathXML.class);
57
58 private MCRPathXML() {
59 }
60
61 public static Document getDirectoryXML(MCRPath path) throws IOException {
62 BasicFileAttributes attr = path.getFileSystem().provider().readAttributes(path, BasicFileAttributes.class);
63 return getDirectoryXML(path, attr);
64 }
65
66
67
68
69 public static Document getDirectoryXML(MCRPath path, BasicFileAttributes attr) throws IOException {
70 LOGGER.debug("MCRDirectoryXML: start listing of directory {}", path);
71
72 Element root = new Element("mcr_directory");
73 Document doc = new Document(root);
74
75 addString(root, "uri", path.toUri().toString(), false);
76 addString(root, "ownerID", path.getOwner(), false);
77 MCRPath relativePath = path.getRoot().relativize(path);
78 boolean isRoot = relativePath.toString().isEmpty();
79 addString(root, "name", (isRoot ? "" : relativePath.getFileName().toString()), true);
80 addString(root, "path", toStringValue(relativePath), true);
81 if (!isRoot) {
82 addString(root, "parentPath", toStringValue(relativePath.getParent()), true);
83 }
84 addBasicAttributes(root, attr, path);
85 Element numChildren = new Element("numChildren");
86 Element here = new Element("here");
87 root.addContent(numChildren);
88 numChildren.addContent(here);
89
90 Element nodes = new Element("children");
91 root.addContent(nodes);
92 SortedMap<MCRPath, MCRFileAttributes<?>> directories = new TreeMap<>();
93 SortedMap<MCRPath, MCRFileAttributes<?>> files = new TreeMap<>();
94 try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(path)) {
95 LOGGER.debug(() -> "Opened DirectoryStream for " + path);
96 Function<Path, MCRFileAttributes<?>> attrResolver = p -> {
97 try {
98 return Files.readAttributes(p, MCRFileAttributes.class);
99 } catch (IOException e) {
100 throw new UncheckedIOException(e);
101 }
102 };
103 if (dirStream instanceof SecureDirectoryStream) {
104
105 LOGGER.debug(() -> "Using SecureDirectoryStream code path for " + path);
106 attrResolver = p -> {
107 try {
108 MCRMD5AttributeView attributeView = ((SecureDirectoryStream<Path>) dirStream)
109 .getFileAttributeView(p.getFileName(), MCRMD5AttributeView.class);
110 return attributeView.readAllAttributes();
111 } catch (IOException e) {
112 throw new UncheckedIOException(e);
113 }
114 };
115
116 }
117 for (Path child : dirStream) {
118 MCRFileAttributes<?> childAttrs;
119 try {
120 childAttrs = attrResolver.apply(child);
121 } catch (UncheckedIOException e) {
122 throw e.getCause();
123 }
124 if (childAttrs.isDirectory()) {
125 directories.put(MCRPath.toMCRPath(child), childAttrs);
126 } else {
127 files.put(MCRPath.toMCRPath(child), childAttrs);
128 }
129 }
130 }
131
132 addString(here, "directories", Integer.toString(directories.size()), false);
133 addString(here, "files", Integer.toString(files.size()), false);
134 for (Map.Entry<MCRPath, MCRFileAttributes<?>> dirEntry : directories.entrySet()) {
135 Element child = new Element("child");
136 child.setAttribute("type", "directory");
137 addString(child, "name", dirEntry.getKey().getFileName().toString(), true);
138 addString(child, "uri", dirEntry.getKey().toUri().toString(), false);
139 nodes.addContent(child);
140 addBasicAttributes(child, dirEntry.getValue(), dirEntry.getKey());
141 }
142 for (Map.Entry<MCRPath, MCRFileAttributes<?>> fileEntry : files.entrySet()) {
143 Element child = new Element("child");
144 child.setAttribute("type", "file");
145 addString(child, "name", fileEntry.getKey().getFileName().toString(), true);
146 addString(child, "uri", fileEntry.getKey().toUri().toString(), false);
147 nodes.addContent(child);
148 addAttributes(child, fileEntry.getValue(), fileEntry.getKey());
149 }
150
151 LOGGER.debug("MCRDirectoryXML: end listing of directory {}", path);
152
153 return doc;
154
155 }
156
157
158
159
160
161 public static Document getFileXML(MCRPath path) throws IOException {
162 MCRFileAttributes<?> attrs = Files.readAttributes(path, MCRFileAttributes.class);
163 return getFileXML(path, attrs);
164 }
165
166
167
168
169
170
171
172
173
174 public static Document getFileXML(MCRPath path, BasicFileAttributes attrs) throws IOException {
175 Element root = new Element("file");
176 root.setAttribute("uri", path.toUri().toString());
177 root.setAttribute("ownerID", path.getOwner());
178 String fileName = path.getFileName().toString();
179 root.setAttribute("name", fileName);
180 String absolutePath = path.getOwnerRelativePath();
181 root.setAttribute("path", absolutePath);
182 root.setAttribute("extension", getFileExtension(fileName));
183 root.setAttribute("returnId",
184 MCRMetadataManager.getObjectId(MCRObjectID.getInstance(path.getOwner()), 10, TimeUnit.SECONDS).toString());
185 Collection<MCRCategoryID> linksFromReference = MCRCategLinkServiceFactory.getInstance().getLinksFromReference(
186 new MCRCategLinkReference(path));
187 for (MCRCategoryID category : linksFromReference) {
188 Element catEl = new Element("category");
189 catEl.setAttribute("id", category.toString());
190 root.addContent(catEl);
191 }
192 if (!attrs.isDirectory() && attrs instanceof MCRFileAttributes<?>) {
193 addAttributes(root, (MCRFileAttributes<?>) attrs, path);
194 } else {
195 addBasicAttributes(root, attrs, path);
196 }
197 return new Document(root);
198 }
199
200 private static String getFileExtension(String fileName) {
201 if (fileName.endsWith(".")) {
202 return "";
203 }
204 int pos = fileName.lastIndexOf(".");
205 return pos == -1 ? "" : fileName.substring(pos + 1);
206 }
207
208 private static String toStringValue(MCRPath relativePath) {
209 if (relativePath == null) {
210 return SEPARATOR_STRING;
211 }
212 String pathString = relativePath.toString();
213 if (pathString.isEmpty()) {
214 return SEPARATOR_STRING;
215 }
216 if (pathString.equals(SEPARATOR_STRING)) {
217 return pathString;
218 }
219 return SEPARATOR + pathString + SEPARATOR;
220 }
221
222 private static void addBasicAttributes(Element root, BasicFileAttributes attr, MCRPath path) throws IOException {
223 addString(root, "size", String.valueOf(attr.size()), false);
224 addDate(root, "created", attr.creationTime());
225 addDate(root, "lastModified", attr.lastModifiedTime());
226 addDate(root, "lastAccessed", attr.lastAccessTime());
227 if (attr.isRegularFile()) {
228 addString(root, "contentType", MCRContentTypes.probeContentType(path), false);
229 }
230 }
231
232 private static void addAttributes(Element root, MCRFileAttributes<?> attr, MCRPath path) throws IOException {
233 addBasicAttributes(root, attr, path);
234 addString(root, "md5", attr.md5sum(), false);
235 }
236
237 private static void addDate(Element parent, String type, FileTime date) {
238 Element xDate = new Element("date");
239 parent.addContent(xDate);
240 xDate.setAttribute("type", type);
241 xDate.addContent(date.toString());
242 }
243
244 private static void addString(Element parent, String itemName, String content, boolean preserve) {
245 if (content == null) {
246 return;
247 }
248 Element child = new Element(itemName).addContent(content);
249 if (preserve) {
250 child.setAttribute("space", "preserve", MCRConstants.XML_NAMESPACE);
251 }
252 parent.addContent(child);
253 }
254 }