+ xattr support for Mac OSX

This commit is contained in:
Reinhard Pointner 2014-04-25 06:59:18 +00:00
parent 1ba888713b
commit d810af37d2
7 changed files with 114 additions and 47 deletions

View File

@ -182,6 +182,10 @@
<include name="net/sf/sevenzipjbinding/**" /> <include name="net/sf/sevenzipjbinding/**" />
</zipfileset> </zipfileset>
<zipfileset src="${dir.lib}/xattrj.jar">
<include name="org/securityvision/**" />
</zipfileset>
<!-- Ivy for @Grapes automatic dependency management --> <!-- Ivy for @Grapes automatic dependency management -->
<zipfileset src="${dir.lib}/scripting/ivy.jar"> <zipfileset src="${dir.lib}/scripting/ivy.jar">
<include name="org/apache/ivy/**" /> <include name="org/apache/ivy/**" />

Binary file not shown.

BIN
lib/xattrj.jar Normal file

Binary file not shown.

View File

@ -10,13 +10,30 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.attribute.UserDefinedFileAttributeView; import java.nio.file.attribute.UserDefinedFileAttributeView;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.Arrays;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.securityvision.xattrj.Xattrj;
import com.sun.jna.Platform;
public class MetaAttributeView extends AbstractMap<String, String> { public class MetaAttributeView extends AbstractMap<String, String> {
private final UserDefinedFileAttributeView attributeView; // UserDefinedFileAttributeView (for Windows and Linux) OR 3rd party Xattrj (for Mac) because UserDefinedFileAttributeView is not supported (Oracle Java 7/8)
private final Charset encoding; private Object xattr;
private File file;
private Charset encoding;
private static Xattrj MacXattrSupport;
private static synchronized Xattrj getMacXattrSupport() throws Throwable {
if (MacXattrSupport == null) {
MacXattrSupport = new Xattrj();
}
return MacXattrSupport;
}
public MetaAttributeView(File file) throws IOException { public MetaAttributeView(File file) throws IOException {
Path path = file.getCanonicalFile().toPath(); Path path = file.getCanonicalFile().toPath();
@ -28,49 +45,98 @@ public class MetaAttributeView extends AbstractMap<String, String> {
path = link; path = link;
} }
attributeView = Files.getFileAttributeView(path, UserDefinedFileAttributeView.class); xattr = Files.getFileAttributeView(path, UserDefinedFileAttributeView.class);
if (attributeView == null) {
// try 3rd party Xattrj library
if (xattr == null) {
if (Platform.isMac()) {
try {
xattr = getMacXattrSupport();
} catch (Throwable e) {
throw new IOException("Unable to load library: xattrj", e);
}
} else {
throw new IOException("UserDefinedFileAttributeView is not supported"); throw new IOException("UserDefinedFileAttributeView is not supported");
} }
encoding = Charset.forName("UTF-8"); }
this.file = path.toFile();
this.encoding = Charset.forName("UTF-8");
} }
@Override @Override
public String get(Object key) { public String get(Object key) {
try { try {
if (xattr instanceof UserDefinedFileAttributeView) {
UserDefinedFileAttributeView attributeView = (UserDefinedFileAttributeView) xattr;
ByteBuffer buffer = ByteBuffer.allocate(attributeView.size(key.toString())); ByteBuffer buffer = ByteBuffer.allocate(attributeView.size(key.toString()));
attributeView.read(key.toString(), buffer); attributeView.read(key.toString(), buffer);
buffer.flip(); buffer.flip();
return encoding.decode(buffer).toString(); return encoding.decode(buffer).toString();
} catch (IOException e) {
return null;
} }
if (xattr instanceof Xattrj) {
Xattrj macXattr = (Xattrj) xattr;
return macXattr.readAttribute(file, key.toString());
}
} catch (Exception e) {
// ignore
}
return null;
} }
@Override @Override
public String put(String key, String value) { public String put(String key, String value) {
try { try {
if (xattr instanceof UserDefinedFileAttributeView) {
UserDefinedFileAttributeView attributeView = (UserDefinedFileAttributeView) xattr;
if (value == null || value.isEmpty()) { if (value == null || value.isEmpty()) {
attributeView.delete(key); attributeView.delete(key);
} else { } else {
attributeView.write(key, encoding.encode(value)); attributeView.write(key, encoding.encode(value));
} }
} catch (IOException e) { }
if (xattr instanceof Xattrj) {
Xattrj macXattr = (Xattrj) xattr;
if (value == null || value.isEmpty()) {
macXattr.removeAttribute(file, key);
} else {
macXattr.writeAttribute(file, key, value);
}
}
} catch (Exception e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
return null; // since we don't know the old value return null; // since we don't know the old value
} }
public List<String> list() throws IOException {
if (xattr instanceof UserDefinedFileAttributeView) {
UserDefinedFileAttributeView attributeView = (UserDefinedFileAttributeView) xattr;
return attributeView.list();
}
if (xattr instanceof Xattrj) {
Xattrj macXattr = (Xattrj) xattr;
return Arrays.asList(macXattr.listAttributes(file));
}
return null;
}
@Override @Override
public Set<Entry<String, String>> entrySet() { public Set<Entry<String, String>> entrySet() {
try { try {
Set<Entry<String, String>> entries = new LinkedHashSet<Entry<String, String>>(); Set<Entry<String, String>> entries = new LinkedHashSet<Entry<String, String>>();
for (String name : attributeView.list()) { for (String name : this.list()) {
entries.add(new AttributeEntry(name)); entries.add(new AttributeEntry(name));
} }
return entries; return entries;
} catch (IOException e) { } catch (Exception e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
} }
@ -78,28 +144,10 @@ public class MetaAttributeView extends AbstractMap<String, String> {
@Override @Override
public void clear() { public void clear() {
try { try {
for (String it : attributeView.list()) { for (String key : this.list()) {
attributeView.delete(it); this.put(key, null);
} }
} catch (IOException e) { } catch (Exception e) {
throw new IllegalStateException(e);
}
}
@Override
public int size() {
try {
return attributeView.list().size();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
@Override
public boolean isEmpty() {
try {
return attributeView.list().isEmpty();
} catch (IOException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
} }

View File

@ -24,6 +24,7 @@ import java.util.Map;
import net.filebot.MediaTypes; import net.filebot.MediaTypes;
import net.filebot.MetaAttributeView; import net.filebot.MetaAttributeView;
import net.filebot.Settings;
import net.filebot.media.MediaDetection; import net.filebot.media.MediaDetection;
import net.filebot.media.MetaAttributes; import net.filebot.media.MetaAttributes;
import net.filebot.similarity.NameSimilarityMetric; import net.filebot.similarity.NameSimilarityMetric;
@ -362,17 +363,24 @@ public class ScriptShellMethods {
public static MetaAttributeView getXattr(File self) { public static MetaAttributeView getXattr(File self) {
try { try {
if (Settings.useExtendedFileAttributes()) {
return new MetaAttributeView(self); return new MetaAttributeView(self);
} catch (Exception e) {
return null;
} }
} catch (Exception e) {
// ignore
}
return null;
} }
public static Object getMetadata(File self) { public static Object getMetadata(File self) {
try { try {
if (Settings.useExtendedFileAttributes()) {
return new MetaAttributes(self); return new MetaAttributes(self);
}
} catch (Exception e) { } catch (Exception e) {
// ignore
}
return null; return null;
} }
}
} }

View File

@ -61,8 +61,8 @@ public class MetaAttributes {
} }
public void clear() { public void clear() {
metaAttributeView.remove(FILENAME_KEY); metaAttributeView.put(FILENAME_KEY, null);
metaAttributeView.remove(METADATA_KEY); metaAttributeView.put(METADATA_KEY, null);
} }
} }

View File

@ -68,6 +68,8 @@ import net.filebot.History;
import net.filebot.History.Element; import net.filebot.History.Element;
import net.filebot.History.Sequence; import net.filebot.History.Sequence;
import net.filebot.ResourceManager; import net.filebot.ResourceManager;
import net.filebot.Settings;
import net.filebot.media.MetaAttributes;
import net.filebot.ui.transfer.FileExportHandler; import net.filebot.ui.transfer.FileExportHandler;
import net.filebot.ui.transfer.FileTransferablePolicy; import net.filebot.ui.transfer.FileTransferablePolicy;
import net.filebot.ui.transfer.LoadAction; import net.filebot.ui.transfer.LoadAction;
@ -534,8 +536,13 @@ class HistoryDialog extends JDialog {
for (Entry<File, File> entry : getRenameMap(directory).entrySet()) { for (Entry<File, File> entry : getRenameMap(directory).entrySet()) {
try { try {
moveRename(entry.getKey(), entry.getValue()); File destination = moveRename(entry.getKey(), entry.getValue());
count++; count++;
// remove xattr that may have been set
if (Settings.useExtendedFileAttributes()) {
new MetaAttributes(destination).clear();
}
} catch (Exception e) { } catch (Exception e) {
Logger.getLogger(HistoryDialog.class.getName()).log(Level.SEVERE, e.getMessage(), e); Logger.getLogger(HistoryDialog.class.getName()).log(Level.SEVERE, e.getMessage(), e);
} }