+ xattr support for Mac OSX
This commit is contained in:
parent
1ba888713b
commit
d810af37d2
|
@ -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.
Binary file not shown.
|
@ -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) {
|
|
||||||
throw new IOException("UserDefinedFileAttributeView is not supported");
|
// 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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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 {
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(attributeView.size(key.toString()));
|
if (xattr instanceof UserDefinedFileAttributeView) {
|
||||||
attributeView.read(key.toString(), buffer);
|
UserDefinedFileAttributeView attributeView = (UserDefinedFileAttributeView) xattr;
|
||||||
buffer.flip();
|
ByteBuffer buffer = ByteBuffer.allocate(attributeView.size(key.toString()));
|
||||||
|
attributeView.read(key.toString(), buffer);
|
||||||
|
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 (value == null || value.isEmpty()) {
|
if (xattr instanceof UserDefinedFileAttributeView) {
|
||||||
attributeView.delete(key);
|
UserDefinedFileAttributeView attributeView = (UserDefinedFileAttributeView) xattr;
|
||||||
} else {
|
if (value == null || value.isEmpty()) {
|
||||||
attributeView.write(key, encoding.encode(value));
|
attributeView.delete(key);
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
return new MetaAttributeView(self);
|
if (Settings.useExtendedFileAttributes()) {
|
||||||
|
return new MetaAttributeView(self);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
// ignore
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object getMetadata(File self) {
|
public static Object getMetadata(File self) {
|
||||||
try {
|
try {
|
||||||
return new MetaAttributes(self);
|
if (Settings.useExtendedFileAttributes()) {
|
||||||
|
return new MetaAttributes(self);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
// ignore
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue