org.netbeans.modules.masterfs.providers.Attributes Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.masterfs.providers;
import org.netbeans.modules.masterfs.ExLocalFileSystem;
import org.openide.util.BaseUtilities;
import org.openide.filesystems.AbstractFileSystem;
import org.openide.filesystems.DefaultAttributes;
import org.openide.filesystems.FileUtil;
import java.beans.PropertyVetoException;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import org.netbeans.modules.masterfs.filebasedfs.utils.FileChangedManager;
import org.openide.modules.Places;
import org.openide.util.Exceptions;
/**
* Implementation of DefaultAttributes that should be shared by all
* filesystems that are mounted into MasterFileSystem.
*
* Ensures that .nbattrs file is stored in netbeans.user/var/cache/attribs/.nbattrs.
* There exist just one file for all attributes. This implemenation is supposed
* to provide backward compatibility.
*
*/
public class Attributes extends DefaultAttributes {
public static String ATTRNAME = "attributes.xml";
private static final String LOCATION = "var";//NOI18N
private static DefaultAttributes sharedUserAttributes;
private final String attributePrefix;
private AbstractFileSystem.List list;
private static final boolean BACKWARD_COMPATIBILITY = false;
private static File rootForAttributes;
public Attributes(File mountPoint, AbstractFileSystem.Info info, AbstractFileSystem.Change change, AbstractFileSystem.List list) {
super(info, change, list);
this.list = list;
this.attributePrefix = preparePrefix(mountPoint);
}
public Attributes(AbstractFileSystem.Info info, AbstractFileSystem.Change change, AbstractFileSystem.List list) {
super(info, change, list);
this.list = list;
this.attributePrefix = "";
}
private String preparePrefix(File fileSystemRoot) {
fileSystemRoot = FileUtil.normalizeFile(fileSystemRoot);
String rootPath = fileSystemRoot.getAbsolutePath().replace('\\', '/');
return ((BaseUtilities.isWindows () || (BaseUtilities.getOperatingSystem () == BaseUtilities.OS_OS2))) ? rootPath.toLowerCase() : rootPath;
}
public static File getRootForAttributes() {
synchronized (ExLocalFileSystem.class) {
if (rootForAttributes == null) {
File userDir = Places.getUserDirectory();
if (userDir != null) {
rootForAttributes = new File(userDir, LOCATION);
} else {
rootForAttributes = new File(System.getProperty("java.io.tmpdir"));//NOI18N
File tmpAttrs = new File (rootForAttributes, ATTRNAME);
if (FileChangedManager.getInstance().exists(tmpAttrs)) {
tmpAttrs.delete();
}
tmpAttrs.deleteOnExit();
}
if (!FileChangedManager.getInstance().exists(rootForAttributes)) {
rootForAttributes.mkdirs();
}
}
}
return rootForAttributes;
}
/** isn't filtered anymore as it was in DefaultAttributes*/
@Override
public String[] children(String f) {
return list.children(f);
}
/* Get the file attribute with the specified name.
* @param name the file
* @param attrName name of the attribute
* @return appropriate (serializable) value or null
if the attribute is unset (or could not be properly restored for some reason)
*/
@Override
public Object readAttribute(String name, String attrName) {
final String translatedName = translateName(name);
final DefaultAttributes pa = getPreferedAttributes();
Object retVal = pa == null ? null : pa.readAttribute(translatedName, attrName);
if (retVal == null && isBackwardCompatible()) {
retVal = super.readAttribute(name, attrName);
if (retVal != null) {
copyAllToUserDir(name, super.attributes(name));
retVal = getPreferedAttributes().readAttribute(translatedName, attrName);
}
}
return retVal;
}
/* Set the file attribute with the specified name.
* @param name the file
* @param attrName name of the attribute
* @param value new value or null
to clear the attribute. Must be serializable, although particular filesystems may or may not use serialization to store attribute values.
* @exception IOException if the attribute cannot be set. If serialization is used to store it, this may in fact be a subclass such as {@link NotSerializableException}.
*/
@Override
public void writeAttribute(String name, String attrName, Object value)
throws IOException {
getPreferedAttributes().writeAttribute(translateName(name), attrName, value);
}
/* Get all file attribute names for the file.
* @param name the file
* @return enumeration of keys (as strings)
*/
@Override
public synchronized Enumeration attributes(String name) {
Enumeration retVal = getPreferedAttributes().attributes(translateName(name));
if ((retVal == null || !retVal.hasMoreElements()) && isBackwardCompatible()) {
retVal = copyAllToUserDir(name, super.attributes(name));
}
return retVal;
}
private Enumeration copyAllToUserDir(String name, Enumeration attributeNames) {
if (attributeNames != null && attributeNames.hasMoreElements() && isBackwardCompatible()) {
final String translatedName = translateName(name);
while (attributeNames.hasMoreElements()) {
String attrName = attributeNames.nextElement();
Object value = super.readAttribute(name, attrName);
try {
getPreferedAttributes().writeAttribute(translatedName, attrName, value);
} catch (IOException e) {
Exceptions.printStackTrace(e);
}
}
super.deleteAttributes(name);
attributeNames = getPreferedAttributes().attributes(translatedName);
}
return attributeNames;
}
/* Called when a file is renamed, to appropriatelly update its attributes.
*
* @param oldName old name of the file
* @param newName new name of the file
*/
@Override
public synchronized void renameAttributes(String oldName, String newName) {
if (isBackwardCompatible()) {
copyAllToUserDir(oldName, super.attributes(oldName));
}
getPreferedAttributes().renameAttributes(translateName(oldName), translateName(newName));
}
/* Called when a file is deleted to also delete its attributes.
*
* @param name name of the file
*/
@Override
public synchronized void deleteAttributes(String name) {
if (isBackwardCompatible()) {
super.deleteAttributes(name);
}
getPreferedAttributes().deleteAttributes(translateName(name));
}
/** adds prefix: systemName of FileSystem */
private String translateName(String name) {
return (attributePrefix.endsWith("/"))? attributePrefix+"/"+name: attributePrefix+name; // NOI18N
}
private DefaultAttributes getPreferedAttributes() {
synchronized (Attributes.class) {
if (sharedUserAttributes == null) {
ExLocalFileSystem exLFs = null;
try {
exLFs = ExLocalFileSystem.getInstance(getRootForAttributes());
} catch (PropertyVetoException e) {
Exceptions.printStackTrace(e);
} catch (IOException e) {
Exceptions.printStackTrace(e);
}
sharedUserAttributes = exLFs.getAttributes();
}
}
assert sharedUserAttributes != null;
return (sharedUserAttributes != null) ? sharedUserAttributes : this;
}
private boolean isBackwardCompatible() {
return BACKWARD_COMPATIBILITY && (getPreferedAttributes() != this);
}
}