| /* 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.security.AccessController; |
| import java.security.PrivilegedAction; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Properties; |
| import java.util.Set; |
| |
| import org.apache.harmony.prefs.internal.nls.Messages; |
| |
| /** |
| * The default implementation of <code>AbstractPreferences</code> for the Linux platform, |
| * using the file system as its back end. |
| * |
| * TODO some sync mechanism with backend, Performance - check file edit date |
| * |
| * @since Android 1.0 |
| */ |
| class FilePreferencesImpl extends AbstractPreferences { |
| |
| /* |
| * -------------------------------------------------------------- |
| * Class fields |
| * -------------------------------------------------------------- |
| */ |
| |
| //prefs file name |
| private static final String PREFS_FILE_NAME = "prefs.xml"; //$NON-NLS-1$ |
| |
| //home directory for user prefs |
| private static String USER_HOME; |
| |
| //home directory for system prefs |
| private static String SYSTEM_HOME; |
| |
| /* |
| * -------------------------------------------------------------- |
| * Class initializer |
| * -------------------------------------------------------------- |
| */ |
| static { |
| AccessController.doPrivileged(new PrivilegedAction<Void>() { |
| public Void run() { |
| USER_HOME = System.getProperty("user.home") + "/.java/.userPrefs";//$NON-NLS-1$ //$NON-NLS-2$ |
| SYSTEM_HOME = System.getProperty("java.home") + "/.systemPrefs";//$NON-NLS-1$//$NON-NLS-2$ |
| return null; |
| } |
| |
| }); |
| } |
| |
| /* |
| * -------------------------------------------------------------- |
| * Instance fields |
| * -------------------------------------------------------------- |
| */ |
| |
| //file path for this preferences node |
| private 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<String> removed = new HashSet<String>(); |
| |
| //cache for updated prefs key-value pair |
| private Set<String> updated = new HashSet<String>(); |
| |
| /* |
| * -------------------------------------------------------------- |
| * Constructors |
| * -------------------------------------------------------------- |
| */ |
| |
| /** |
| * Construct root <code>FilePreferencesImpl</code> instance, construct |
| * user root if userNode is true, system root otherwise |
| */ |
| FilePreferencesImpl(boolean userNode) { |
| super(null, ""); //$NON-NLS-1$ |
| this.userNode = userNode; |
| path = userNode ? USER_HOME : SYSTEM_HOME; |
| 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 = (AccessController.doPrivileged(new PrivilegedAction<Boolean>() { |
| public Boolean run() { |
| return Boolean.valueOf(!dir.exists()); |
| } |
| })).booleanValue(); |
| prefsFile = new File(path + File.separator + PREFS_FILE_NAME); |
| prefs = XMLParser.loadFilePrefs(prefsFile); |
| } |
| |
| @Override |
| protected String[] childrenNamesSpi() throws BackingStoreException { |
| String[] names = AccessController |
| .doPrivileged(new PrivilegedAction<String[]>() { |
| public String[] run() { |
| return dir.list(new FilenameFilter() { |
| public boolean accept(File parent, String name) { |
| return new File(path + File.separator + name).isDirectory(); |
| } |
| }); |
| |
| } |
| }); |
| if (null == names) {// file is not a directory, exception case |
| // prefs.3=Cannot get children names for {0}! |
| throw new BackingStoreException( |
| Messages.getString("prefs.3", toString())); //$NON-NLS-1$ |
| } |
| 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.loadFilePrefs(prefsFile); |
| // merge |
| Iterator<String> 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.flushFilePrefs(prefsFile, prefs); |
| } catch (Exception e) { |
| throw new BackingStoreException(e); |
| } |
| } |
| |
| @Override |
| protected String getSpi(String key) { |
| try { |
| if (null == prefs) { |
| prefs = XMLParser.loadFilePrefs(prefsFile); |
| } |
| return prefs.getProperty(key); |
| } catch (Exception e) {// if Exception happened, return null |
| return null; |
| } |
| } |
| |
| @Override |
| protected String[] keysSpi() throws BackingStoreException { |
| return prefs.keySet().toArray(new String[0]); |
| } |
| |
| @Override |
| protected void putSpi(String name, String value) { |
| prefs.setProperty(name, value); |
| updated.add(name); |
| } |
| |
| @Override |
| protected void removeNodeSpi() throws BackingStoreException { |
| boolean removeSucceed = (AccessController.doPrivileged(new PrivilegedAction<Boolean>() { |
| public Boolean run() { |
| prefsFile.delete(); |
| return Boolean.valueOf(dir.delete()); |
| } |
| })).booleanValue(); |
| if (!removeSucceed) { |
| // prefs.4=Cannot remove {0}! |
| throw new BackingStoreException(Messages.getString("prefs.4", toString())); //$NON-NLS-1$ |
| } |
| } |
| |
| @Override |
| protected void removeSpi(String key) { |
| prefs.remove(key); |
| updated.remove(key); |
| removed.add(key); |
| } |
| |
| @Override |
| protected void syncSpi() throws BackingStoreException { |
| flushSpi(); |
| } |
| } |