/* 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 java.util.prefs;
import java.io.File;
import java.io.FilenameFilter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
/**
* The default implementation of AbstractPreferences for the Linux
* platform, using the file system as its back end.
*
* TODO some sync mechanism with backend, Performance - check file edit date
*
* @since 1.4
*
* @hide
*/
public class FilePreferencesImpl extends AbstractPreferences {
//prefs file name
private static final String PREFS_FILE_NAME = "prefs.xml";
//file path for this preferences node
private final String path;
//internal cache for prefs key-value pair
private Properties prefs;
//file represents this preferences node
private File prefsFile;
//parent dir for this preferences node
private File dir;
//cache for removed prefs key-value pair
private Set removed = new HashSet();
//cache for updated prefs key-value pair
private Set updated = new HashSet();
/*
* --------------------------------------------------------------
* Constructors
* --------------------------------------------------------------
*/
/**
* Construct root FilePreferencesImpl instance rooted
* at the given path.
*
* @hide
*/
public FilePreferencesImpl(String path, boolean isUserNode) {
super(null, "");
this.path = path;
this.userNode = isUserNode;
initPrefs();
}
/**
* Construct a prefs using given parent and given name
*/
private FilePreferencesImpl(AbstractPreferences parent, String name) {
super(parent, name);
path = ((FilePreferencesImpl) parent).path + File.separator + name;
initPrefs();
}
private void initPrefs() {
dir = new File(path);
newNode = !dir.exists();
prefsFile = new File(path + File.separator + PREFS_FILE_NAME);
prefs = XMLParser.readXmlPreferences(prefsFile);
}
@Override
protected String[] childrenNamesSpi() throws BackingStoreException {
String[] names = dir.list(new FilenameFilter() {
public boolean accept(File parent, String name) {
return new File(path + File.separator + name).isDirectory();
}
});
if (names == null) {// file is not a directory, exception case
throw new BackingStoreException("Cannot get child names for " + toString()
+ " (path is " + path + ")");
}
return names;
}
@Override
protected AbstractPreferences childSpi(String name) {
FilePreferencesImpl child = new FilePreferencesImpl(this, name);
return child;
}
@Override
protected void flushSpi() throws BackingStoreException {
try {
//if removed, return
if(isRemoved()){
return;
}
// reload
Properties currentPrefs = XMLParser.readXmlPreferences(prefsFile);
// merge
Iterator it = removed.iterator();
while (it.hasNext()) {
currentPrefs.remove(it.next());
}
removed.clear();
it = updated.iterator();
while (it.hasNext()) {
Object key = it.next();
currentPrefs.put(key, prefs.get(key));
}
updated.clear();
// flush
prefs = currentPrefs;
XMLParser.writeXmlPreferences(prefsFile, prefs);
} catch (Exception e) {
throw new BackingStoreException(e);
}
}
@Override
protected String getSpi(String key) {
try {
if (prefs == null) {
prefs = XMLParser.readXmlPreferences(prefsFile);
}
return prefs.getProperty(key);
} catch (Exception e) {
// if Exception happened, return null
return null;
}
}
@Override
protected String[] keysSpi() throws BackingStoreException {
final Set