1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/java/alt2xml-in-fs/src/cz/frantovo/alt2xml/in/fs/ExtendedAttribute.java Wed Oct 29 02:03:14 2014 +0100
1.3 @@ -0,0 +1,77 @@
1.4 +/**
1.5 + * Alt2XML
1.6 + * Copyright © 2014 František Kučera (frantovo.cz)
1.7 + *
1.8 + * This program is free software: you can redistribute it and/or modify
1.9 + * it under the terms of the GNU General Public License as published by
1.10 + * the Free Software Foundation, either version 3 of the License, or
1.11 + * (at your option) any later version.
1.12 + *
1.13 + * This program is distributed in the hope that it will be useful,
1.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.16 + * GNU General Public License for more details.
1.17 + *
1.18 + * You should have received a copy of the GNU General Public License
1.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
1.20 + */
1.21 +package cz.frantovo.alt2xml.in.fs;
1.22 +
1.23 +import java.nio.ByteBuffer;
1.24 +import java.nio.charset.Charset;
1.25 +
1.26 +public class ExtendedAttribute {
1.27 +
1.28 + private String key;
1.29 + private String value;
1.30 +
1.31 + public ExtendedAttribute(String key, String value) {
1.32 + this.key = key;
1.33 + this.value = value;
1.34 + }
1.35 +
1.36 + public ExtendedAttribute(String key, ByteBuffer value) {
1.37 + this.key = key;
1.38 + setValue(value);
1.39 + }
1.40 +
1.41 + public ExtendedAttribute() {
1.42 + }
1.43 +
1.44 + public String getKey() {
1.45 + return key;
1.46 + }
1.47 +
1.48 + public void setKey(String key) {
1.49 + this.key = key;
1.50 + }
1.51 +
1.52 + public String getValue() {
1.53 + return value;
1.54 + }
1.55 +
1.56 + public final ByteBuffer getValueBytes() {
1.57 + return encode(getValue());
1.58 + }
1.59 +
1.60 + public void setValue(String value) {
1.61 + this.value = value;
1.62 + }
1.63 +
1.64 + public final void setValue(ByteBuffer value) {
1.65 + setValue(decode(value));
1.66 + }
1.67 +
1.68 + private static String decode(ByteBuffer bytes) {
1.69 + bytes.flip();
1.70 + return Charset.defaultCharset().decode(bytes).toString();
1.71 + }
1.72 +
1.73 + private static ByteBuffer encode(String text) {
1.74 + if (text == null) {
1.75 + return null;
1.76 + } else {
1.77 + return Charset.defaultCharset().encode(text);
1.78 + }
1.79 + }
1.80 +}
2.1 --- a/java/alt2xml-in-fs/src/cz/frantovo/alt2xml/in/fs/Reader.java Wed Oct 29 01:25:06 2014 +0100
2.2 +++ b/java/alt2xml-in-fs/src/cz/frantovo/alt2xml/in/fs/Reader.java Wed Oct 29 02:03:14 2014 +0100
2.3 @@ -22,6 +22,16 @@
2.4 import java.io.IOException;
2.5 import java.net.URI;
2.6 import java.net.URISyntaxException;
2.7 +import java.nio.ByteBuffer;
2.8 +import java.nio.file.Files;
2.9 +import java.nio.file.LinkOption;
2.10 +import java.nio.file.Path;
2.11 +import java.nio.file.attribute.PosixFilePermission;
2.12 +import java.nio.file.attribute.UserDefinedFileAttributeView;
2.13 +import java.nio.file.spi.FileSystemProvider;
2.14 +import java.util.List;
2.15 +import java.util.ArrayList;
2.16 +import java.util.Set;
2.17 import java.util.logging.Logger;
2.18 import org.xml.sax.Attributes;
2.19 import org.xml.sax.InputSource;
2.20 @@ -38,10 +48,21 @@
2.21 public static final String ROOT_ELEMENT = "fs";
2.22 public static final String DIR_ELEMENT = "dir";
2.23 public static final String FILE_ELEMENT = "file";
2.24 - public static final String ROOT_ATTRIBUTE = "root";
2.25 + public static final String XATTR_ELEMENT = "xattr";
2.26 + public static final String PERMISSIONS_ELEMENT = "mode";
2.27 + public static final String PERMISSIONS_U_ELEMENT = "user";
2.28 + public static final String PERMISSIONS_G_ELEMENT = "group";
2.29 + public static final String PERMISSIONS_O_ELEMENT = "others";
2.30 public static final String NAME_ATTRIBUTE = "name";
2.31 + public static final String ABSOLUTE_PATH_ATTRIBUTE = "path";
2.32 + public static final String SIZE_ATTRIBUTE = "size";
2.33 private static final Logger log = Logger.getLogger(Reader.class.getName());
2.34
2.35 + /**
2.36 + * indentation level
2.37 + */
2.38 + private int level = 0;
2.39 +
2.40 @Override
2.41 public void parse(InputSource input) throws IOException, SAXException {
2.42 File dir = getFile(input.getSystemId());
2.43 @@ -59,16 +80,38 @@
2.44 }
2.45 }
2.46
2.47 + private String getAbsolutePath(File file) throws IOException {
2.48 + return file.getCanonicalFile().getAbsolutePath();
2.49 + }
2.50 +
2.51 + private Attributes singleAttribute(String name, int value) {
2.52 + AttributesImpl attributes = new AttributesImpl();
2.53 + addAttribute(attributes, name, value);
2.54 + return attributes;
2.55 + }
2.56 +
2.57 private Attributes singleAttribute(String name, String value) {
2.58 AttributesImpl attributes = new AttributesImpl();
2.59 - attributes.addAttribute(null, name, name, "xs:string", value);
2.60 + addAttribute(attributes, name, value);
2.61 return attributes;
2.62 }
2.63
2.64 - private void outputStart(File root) throws SAXException {
2.65 + private void addAttribute(AttributesImpl attributes, String name, int value) {
2.66 + attributes.addAttribute(null, name, name, "xs:int", String.valueOf(value));
2.67 + }
2.68 +
2.69 + private void addAttribute(AttributesImpl attributes, String name, long value) {
2.70 + attributes.addAttribute(null, name, name, "xs:long", String.valueOf(value));
2.71 + }
2.72 +
2.73 + private void addAttribute(AttributesImpl attributes, String name, String value) {
2.74 + attributes.addAttribute(null, name, name, "xs:string", value);
2.75 + }
2.76 +
2.77 + private void outputStart(File root) throws SAXException, IOException {
2.78 contentHandler.startDocument();
2.79 contentHandler.lineBreak();
2.80 - contentHandler.startElement(null, null, ROOT_ELEMENT, singleAttribute(ROOT_ATTRIBUTE, root.getAbsolutePath()));
2.81 + contentHandler.startElement(null, null, ROOT_ELEMENT, singleAttribute(ABSOLUTE_PATH_ATTRIBUTE, getAbsolutePath(root)));
2.82 contentHandler.lineBreak();
2.83 }
2.84
2.85 @@ -78,22 +121,46 @@
2.86 contentHandler.endDocument();
2.87 }
2.88
2.89 - private void outputFile(File file) throws SAXException {
2.90 - contentHandler.startElement(null, null, FILE_ELEMENT, singleAttribute(NAME_ATTRIBUTE, file.getName()));
2.91 + private void outputFile(File file) throws SAXException, IOException {
2.92 + level++;
2.93 +
2.94 + AttributesImpl attributes = new AttributesImpl();
2.95 + addAttribute(attributes, NAME_ATTRIBUTE, file.getName());
2.96 + addAttribute(attributes, ABSOLUTE_PATH_ATTRIBUTE, getAbsolutePath(file));
2.97 + addAttribute(attributes, SIZE_ATTRIBUTE, file.length());
2.98 +
2.99 + contentHandler.indentation(level);
2.100 + contentHandler.startElement(null, null, FILE_ELEMENT, attributes);
2.101 contentHandler.lineBreak();
2.102
2.103 - //contentHandler.characters(file.getName());
2.104 + outputPermissions(file.toPath());
2.105 + outputExtendedAttributes(file);
2.106
2.107 + contentHandler.indentation(level);
2.108 contentHandler.endElement(null, null, FILE_ELEMENT);
2.109 contentHandler.lineBreak();
2.110 +
2.111 + level--;
2.112 }
2.113
2.114 - private void outputDir(File dir) throws SAXException {
2.115 + private void outputDir(File dir) throws SAXException, IOException {
2.116 + level++;
2.117
2.118 - contentHandler.startElement(null, null, DIR_ELEMENT, singleAttribute(NAME_ATTRIBUTE, dir.getName()));
2.119 + final File[] children = dir.listFiles();
2.120 +
2.121 + AttributesImpl attributes = new AttributesImpl();
2.122 + addAttribute(attributes, NAME_ATTRIBUTE, dir.getName());
2.123 + addAttribute(attributes, ABSOLUTE_PATH_ATTRIBUTE, getAbsolutePath(dir));
2.124 + addAttribute(attributes, SIZE_ATTRIBUTE, children.length);
2.125 +
2.126 + contentHandler.indentation(level);
2.127 + contentHandler.startElement(null, null, DIR_ELEMENT, attributes);
2.128 contentHandler.lineBreak();
2.129
2.130 - for (File file : dir.listFiles()) {
2.131 + outputPermissions(dir.toPath());
2.132 + outputExtendedAttributes(dir);
2.133 +
2.134 + for (File file : children) {
2.135 if (file.isDirectory()) {
2.136 outputDir(file);
2.137 } else {
2.138 @@ -101,7 +168,112 @@
2.139 }
2.140 }
2.141
2.142 + contentHandler.indentation(level);
2.143 contentHandler.endElement(null, null, DIR_ELEMENT);
2.144 contentHandler.lineBreak();
2.145 +
2.146 + level--;
2.147 + }
2.148 +
2.149 + private String encodeElementName(String originalName) {
2.150 + /**
2.151 + * TODO: encode and/or skip invalid characters
2.152 + */
2.153 + return originalName;
2.154 + }
2.155 +
2.156 + private void outputPermissions(Path path) throws IOException, SAXException {
2.157 + level++;
2.158 + Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(path, LinkOption.NOFOLLOW_LINKS);
2.159 +
2.160 + contentHandler.indentation(level);
2.161 + contentHandler.startElement(null, PERMISSIONS_ELEMENT, PERMISSIONS_ELEMENT, singleAttribute("octal", getOctal(permissions)));
2.162 + contentHandler.lineBreak();
2.163 +
2.164 + level++;
2.165 +
2.166 + outputPermission("owner", permissions.contains(PosixFilePermission.OWNER_READ), permissions.contains(PosixFilePermission.OWNER_WRITE), permissions.contains(PosixFilePermission.OWNER_EXECUTE));
2.167 + outputPermission("group", permissions.contains(PosixFilePermission.GROUP_READ), permissions.contains(PosixFilePermission.GROUP_WRITE), permissions.contains(PosixFilePermission.GROUP_EXECUTE));
2.168 + outputPermission("others", permissions.contains(PosixFilePermission.OTHERS_READ), permissions.contains(PosixFilePermission.OTHERS_WRITE), permissions.contains(PosixFilePermission.OTHERS_EXECUTE));
2.169 +
2.170 + level--;
2.171 +
2.172 + contentHandler.indentation(level);
2.173 + contentHandler.endElement(null, PERMISSIONS_ELEMENT, PERMISSIONS_ELEMENT);
2.174 + contentHandler.lineBreak();
2.175 +
2.176 + level--;
2.177 + }
2.178 +
2.179 + private int getOctal(Set<PosixFilePermission> permissions) {
2.180 + int octal = 0;
2.181 +
2.182 + octal = octal + 100 * (permissions.contains(PosixFilePermission.OWNER_READ) ? 4 : 0);
2.183 + octal = octal + 100 * (permissions.contains(PosixFilePermission.OWNER_WRITE) ? 2 : 0);
2.184 + octal = octal + 100 * (permissions.contains(PosixFilePermission.OWNER_EXECUTE) ? 1 : 0);
2.185 +
2.186 + octal = octal + 10 * (permissions.contains(PosixFilePermission.GROUP_READ) ? 4 : 0);
2.187 + octal = octal + 10 * (permissions.contains(PosixFilePermission.GROUP_WRITE) ? 2 : 0);
2.188 + octal = octal + 10 * (permissions.contains(PosixFilePermission.GROUP_EXECUTE) ? 1 : 0);
2.189 +
2.190 + octal = octal + 1 * (permissions.contains(PosixFilePermission.OTHERS_READ) ? 4 : 0);
2.191 + octal = octal + 1 * (permissions.contains(PosixFilePermission.OTHERS_WRITE) ? 2 : 0);
2.192 + octal = octal + 1 * (permissions.contains(PosixFilePermission.OTHERS_EXECUTE) ? 1 : 0);
2.193 +
2.194 + return octal;
2.195 + }
2.196 +
2.197 + private void outputPermission(String name, boolean read, boolean write, boolean execute) throws SAXException {
2.198 + contentHandler.indentation(level);
2.199 + AttributesImpl attributes = new AttributesImpl();
2.200 + attributes.addAttribute(null, "read", "read", "xs:boolean", String.valueOf(read));
2.201 + attributes.addAttribute(null, "write", "write", "xs:boolean", String.valueOf(write));
2.202 + attributes.addAttribute(null, "execute", "execute", "xs:boolean", String.valueOf(execute));
2.203 + contentHandler.startElement(null, name, name, attributes);
2.204 + contentHandler.endElement(null, name, name);
2.205 + contentHandler.lineBreak();
2.206 + }
2.207 +
2.208 + private void outputExtendedAttributes(File file) throws IOException, SAXException {
2.209 + level++;
2.210 +
2.211 + final List<ExtendedAttribute> extendedAttributes = getExtendedAttributes(file);
2.212 +
2.213 + if (!extendedAttributes.isEmpty()) {
2.214 + contentHandler.indentation(level);
2.215 + contentHandler.startElement(null, XATTR_ELEMENT, XATTR_ELEMENT, null);
2.216 + contentHandler.lineBreak();
2.217 + level++;
2.218 + for (ExtendedAttribute ea : extendedAttributes) {
2.219 + contentHandler.indentation(level);
2.220 + String elementName = encodeElementName(ea.getKey());
2.221 + contentHandler.textElement(ea.getValue(), null, elementName, elementName, null);
2.222 + contentHandler.lineBreak();
2.223 + }
2.224 + level--;
2.225 + contentHandler.indentation(level);
2.226 + contentHandler.endElement(null, XATTR_ELEMENT, XATTR_ELEMENT);
2.227 + contentHandler.lineBreak();
2.228 + }
2.229 +
2.230 + level--;
2.231 + }
2.232 +
2.233 + private List<ExtendedAttribute> getExtendedAttributes(File file) throws IOException {
2.234 +
2.235 + List<ExtendedAttribute> l = new ArrayList<>();
2.236 +
2.237 + Path path = file.toPath();
2.238 + FileSystemProvider provider = path.getFileSystem().provider();
2.239 + UserDefinedFileAttributeView attributes = provider.getFileAttributeView(path, UserDefinedFileAttributeView.class);
2.240 +
2.241 + for (String jménoAtributu : attributes.list()) {
2.242 + ByteBuffer hodnotaAtributu = ByteBuffer.allocate(attributes.size(jménoAtributu));
2.243 + attributes.read(jménoAtributu, hodnotaAtributu);
2.244 + l.add(new ExtendedAttribute(jménoAtributu, hodnotaAtributu));
2.245 + }
2.246 +
2.247 + return l;
2.248 +
2.249 }
2.250 }