001: /* Licensed to the Apache Software Foundation (ASF) under one or more
002: * contributor license agreements. See the NOTICE file distributed with
003: * this work for additional information regarding copyright ownership.
004: * The ASF licenses this file to You under the Apache License, Version 2.0
005: * (the "License"); you may not use this file except in compliance with
006: * the License. You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package java.util.prefs;
018:
019: import java.io.File;
020: import java.io.FilenameFilter;
021: import java.security.AccessController;
022: import java.security.PrivilegedAction;
023: import java.util.HashSet;
024: import java.util.Iterator;
025: import java.util.Properties;
026: import java.util.Set;
027:
028: import org.apache.harmony.prefs.internal.nls.Messages;
029:
030: /**
031: * Default implementation of <code>AbstractPreferences</code> for Linux platform,
032: * using file system as back end.
033: *
034: * TODO some sync mechanism with backend, Performance - check file edit date
035: *
036: * @since 1.4
037: */
038: class FilePreferencesImpl extends AbstractPreferences {
039:
040: /*
041: * --------------------------------------------------------------
042: * Class fields
043: * --------------------------------------------------------------
044: */
045:
046: //prefs file name
047: private static final String PREFS_FILE_NAME = "prefs.xml"; //$NON-NLS-1$
048:
049: //home directory for user prefs
050: private static String USER_HOME;
051:
052: //home directory for system prefs
053: private static String SYSTEM_HOME;
054:
055: /*
056: * --------------------------------------------------------------
057: * Class initializer
058: * --------------------------------------------------------------
059: */
060: static {
061: AccessController.doPrivileged(new PrivilegedAction<Void>() {
062: public Void run() {
063: USER_HOME = System.getProperty("user.home") + "/.java/.userPrefs";//$NON-NLS-1$ //$NON-NLS-2$
064: SYSTEM_HOME = System.getProperty("java.home") + "/.systemPrefs";//$NON-NLS-1$//$NON-NLS-2$
065: return null;
066: }
067:
068: });
069: }
070:
071: /*
072: * --------------------------------------------------------------
073: * Instance fields
074: * --------------------------------------------------------------
075: */
076:
077: //file path for this preferences node
078: private String path;
079:
080: //internal cache for prefs key-value pair
081: private Properties prefs;
082:
083: //file represents this preferences node
084: private File prefsFile;
085:
086: //parent dir for this preferences node
087: private File dir;
088:
089: //cache for removed prefs key-value pair
090: private Set<String> removed = new HashSet<String>();
091:
092: //cache for updated prefs key-value pair
093: private Set<String> updated = new HashSet<String>();
094:
095: /*
096: * --------------------------------------------------------------
097: * Constructors
098: * --------------------------------------------------------------
099: */
100:
101: /**
102: * Construct root <code>FilePreferencesImpl</code> instance, construct
103: * user root if userNode is true, system root otherwise
104: */
105: FilePreferencesImpl(boolean userNode) {
106: super (null, ""); //$NON-NLS-1$
107: this .userNode = userNode;
108: path = userNode ? USER_HOME : SYSTEM_HOME;
109: initPrefs();
110: }
111:
112: /**
113: * Construct a prefs using given parent and given name
114: */
115: private FilePreferencesImpl(AbstractPreferences parent, String name) {
116: super (parent, name);
117: path = ((FilePreferencesImpl) parent).path + File.separator
118: + name;
119: initPrefs();
120: }
121:
122: private void initPrefs() {
123: dir = new File(path);
124: newNode = (AccessController
125: .doPrivileged(new PrivilegedAction<Boolean>() {
126: public Boolean run() {
127: return Boolean.valueOf(!dir.exists());
128: }
129: })).booleanValue();
130: prefsFile = new File(path + File.separator + PREFS_FILE_NAME);
131: prefs = XMLParser.loadFilePrefs(prefsFile);
132: }
133:
134: @Override
135: protected String[] childrenNamesSpi() throws BackingStoreException {
136: String[] names = AccessController
137: .doPrivileged(new PrivilegedAction<String[]>() {
138: public String[] run() {
139: return dir.list(new FilenameFilter() {
140: public boolean accept(File parent,
141: String name) {
142: return new File(path + File.separator
143: + name).isDirectory();
144: }
145: });
146:
147: }
148: });
149: if (null == names) {// file is not a directory, exception case
150: // prefs.3=Cannot get children names for {0}!
151: throw new BackingStoreException(Messages.getString(
152: "prefs.3", toString())); //$NON-NLS-1$
153: }
154: return names;
155: }
156:
157: @Override
158: protected AbstractPreferences childSpi(String name) {
159: FilePreferencesImpl child = new FilePreferencesImpl(this , name);
160: return child;
161: }
162:
163: @Override
164: protected void flushSpi() throws BackingStoreException {
165: try {
166: //if removed, return
167: if (isRemoved()) {
168: return;
169: }
170: // reload
171: Properties currentPrefs = XMLParser
172: .loadFilePrefs(prefsFile);
173: // merge
174: Iterator<String> it = removed.iterator();
175: while (it.hasNext()) {
176: currentPrefs.remove(it.next());
177: }
178: removed.clear();
179: it = updated.iterator();
180: while (it.hasNext()) {
181: Object key = it.next();
182: currentPrefs.put(key, prefs.get(key));
183: }
184: updated.clear();
185: // flush
186: prefs = currentPrefs;
187: XMLParser.flushFilePrefs(prefsFile, prefs);
188: } catch (Exception e) {
189: throw new BackingStoreException(e);
190: }
191: }
192:
193: @Override
194: protected String getSpi(String key) {
195: try {
196: if (null == prefs) {
197: prefs = XMLParser.loadFilePrefs(prefsFile);
198: }
199: return prefs.getProperty(key);
200: } catch (Exception e) {// if Exception happened, return null
201: return null;
202: }
203: }
204:
205: @Override
206: protected String[] keysSpi() throws BackingStoreException {
207: return prefs.keySet().toArray(new String[0]);
208: }
209:
210: @Override
211: protected void putSpi(String name, String value) {
212: prefs.setProperty(name, value);
213: updated.add(name);
214: }
215:
216: @Override
217: protected void removeNodeSpi() throws BackingStoreException {
218: boolean removeSucceed = (AccessController
219: .doPrivileged(new PrivilegedAction<Boolean>() {
220: public Boolean run() {
221: prefsFile.delete();
222: return Boolean.valueOf(dir.delete());
223: }
224: })).booleanValue();
225: if (!removeSucceed) {
226: // prefs.4=Cannot remove {0}!
227: throw new BackingStoreException(Messages.getString(
228: "prefs.4", toString())); //$NON-NLS-1$
229: }
230: }
231:
232: @Override
233: protected void removeSpi(String key) {
234: prefs.remove(key);
235: updated.remove(key);
236: removed.add(key);
237: }
238:
239: @Override
240: protected void syncSpi() throws BackingStoreException {
241: flushSpi();
242: }
243: }
|