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 org.apache.harmony.prefs.internal.nls.Messages;
020:
021: /**
022: * Default implementation of <code>AbstractPreferences</code> for windows platform,
023: * using windows registry as back end.
024: *
025: * @since 1.4
026: */
027: class RegistryPreferencesImpl extends AbstractPreferences {
028:
029: static {
030: System.loadLibrary("hyprefs"); //$NON-NLS-1$
031: }
032:
033: /*
034: * --------------------------------------------------------------
035: * Class fields
036: * --------------------------------------------------------------
037: */
038: //registry path for root preferences
039: private static final String ROOT_PATH = "SOFTWARE\\JavaSoft\\Prefs"; //$NON-NLS-1$
040:
041: //index for returned error code
042: private static final int ERROR_CODE = 0;
043:
044: //error code for registry access
045: private static final int RETURN_SUCCESS = 0;
046:
047: @SuppressWarnings("unused")
048: private static final int RETURN_FILE_NOT_FOUND = 1;
049:
050: private static final int RETURN_ACCESS_DENIED = 2;
051:
052: @SuppressWarnings("unused")
053: private static final int RETURN_UNKNOWN_ERROR = 3;
054:
055: /*
056: * --------------------------------------------------------------
057: * Instance fields
058: * --------------------------------------------------------------
059: */
060: //registry path for this preferences, default value is the root path
061: private byte[] path = ROOT_PATH.getBytes();
062:
063: /*
064: * --------------------------------------------------------------
065: * Constructors
066: * --------------------------------------------------------------
067: */
068: /**
069: * Construct <code>RegistryPreferencesImpl</code> instance using given parent
070: * and given name
071: */
072: public RegistryPreferencesImpl(AbstractPreferences parent,
073: String name) {
074: super (parent, name);
075: this .userNode = parent.isUserNode();
076: path = (ROOT_PATH + encodeWindowsStr(absolutePath()))
077: .getBytes();
078: }
079:
080: /**
081: * Construct root <code>RegistryPreferencesImpl</code> instance, construct
082: * user root if userNode is true, system root otherwise
083: */
084: public RegistryPreferencesImpl(boolean userNode) {
085: super (null, ""); //$NON-NLS-1$
086: this .userNode = userNode;
087: }
088:
089: @Override
090: protected String[] childrenNamesSpi() throws BackingStoreException {
091: int[] error = new int[1];
092: byte[][] names = getChildNames(path, userNode, error);
093: if (error[ERROR_CODE] != RETURN_SUCCESS) {
094: // prefs.B=Enumerate child nodes error\!
095: throw new BackingStoreException(Messages
096: .getString("prefs.B")); //$NON-NLS-1$
097: }
098: String[] result = new String[names.length];
099: for (int i = 0; i < result.length; i++) {
100: result[i] = decodeWindowsStr(new String(names[i]));
101: }
102: return result;
103: }
104:
105: @Override
106: protected AbstractPreferences childSpi(String name) {
107: int[] error = new int[1];
108: RegistryPreferencesImpl result = new RegistryPreferencesImpl(
109: this , name);
110: //FIXME: is it right thing to set newNode here?
111: result.newNode = getNode(path, encodeWindowsStr(name)
112: .getBytes(), result.userNode, error);
113: if (error[ERROR_CODE] == RETURN_ACCESS_DENIED) {
114: throw new SecurityException();
115: }
116: return result;
117: }
118:
119: @Override
120: protected void flushSpi() throws BackingStoreException {
121: int[] error = new int[1];
122: flushPrefs(path, userNode, error);
123: if (error[ERROR_CODE] != RETURN_SUCCESS) {
124: // prefs.C=Flush error\!
125: throw new BackingStoreException(Messages
126: .getString("prefs.C")); //$NON-NLS-1$
127: }
128: }
129:
130: @Override
131: protected String getSpi(String key) {
132: int[] error = new int[1];
133: byte[] result = getValue(path,
134: encodeWindowsStr(key).getBytes(), userNode, error);
135: if (error[ERROR_CODE] != 0) {
136: return null;
137: }
138: return new String(result);
139: }
140:
141: @Override
142: protected String[] keysSpi() throws BackingStoreException {
143: int[] errorCode = new int[1];
144: byte[][] keys = keys(path, userNode, errorCode);
145: if (errorCode[ERROR_CODE] != RETURN_SUCCESS) {
146: // prefs.D=Enumerate keys error\!
147: throw new BackingStoreException(Messages
148: .getString("prefs.D")); //$NON-NLS-1$
149: }
150: String[] result = new String[keys.length];
151: for (int i = 0; i < result.length; i++) {
152: result[i] = decodeWindowsStr(new String(keys[i]));
153: }
154: return result;
155: }
156:
157: @Override
158: protected void putSpi(String name, String value) {
159: int[] errorCode = new int[1];
160: putValue(path, encodeWindowsStr(name).getBytes(), value
161: .getBytes(), userNode, errorCode);
162: if (errorCode[ERROR_CODE] == RETURN_ACCESS_DENIED) {
163: // prefs.E=Access denied\!
164: throw new SecurityException(Messages.getString("prefs.E")); //$NON-NLS-1$
165: }
166: }
167:
168: @Override
169: protected void removeNodeSpi() throws BackingStoreException {
170: int[] error = new int[1];
171: removeNode(((RegistryPreferencesImpl) parent()).path,
172: encodeWindowsStr(name()).getBytes(), userNode, error);
173: if (error[ERROR_CODE] != RETURN_SUCCESS) {
174: // prefs.F=Remove node error\!
175: throw new BackingStoreException(Messages
176: .getString("prefs.F")); //$NON-NLS-1$
177: }
178: }
179:
180: @Override
181: protected void removeSpi(String key) {
182: int[] errorCode = new int[1];
183: removeKey(path, encodeWindowsStr(key).getBytes(), userNode,
184: errorCode);
185: if (errorCode[ERROR_CODE] == RETURN_ACCESS_DENIED) {
186: // prefs.E=Access denied\!
187: throw new SecurityException(Messages.getString("prefs.E")); //$NON-NLS-1$
188: }
189: }
190:
191: @Override
192: protected void syncSpi() throws BackingStoreException {
193: flushSpi();
194: }
195:
196: //handle the lower/upper case pitfall
197: private static String encodeWindowsStr(String str) {
198: char[] chars = str.toCharArray();
199: StringBuffer buffer = new StringBuffer();
200: for (int i = 0; i < chars.length; i++) {
201: char c = chars[i];
202: if (c == '/') {
203: buffer.append("\\"); //$NON-NLS-1$
204: } else if (c == '\\') {
205: buffer.append("//"); //$NON-NLS-1$
206: } else if ((c >= 'A') && (c <= 'Z')) {
207: buffer.append('/').append(c);
208: } else {
209: buffer.append(c);
210: }
211: }
212: return buffer.toString();
213: }
214:
215: private static String decodeWindowsStr(String str) {
216: StringBuffer buffer = new StringBuffer();
217: char[] chars = str.toCharArray();
218: for (int i = 0; i < chars.length; i++) {
219: char c = chars[i];
220: if (c == '\\') {
221: buffer.append('/');
222: } else if (c == '/') {
223: if ((c = chars[++i]) == '/') {
224: buffer.append('\\');
225: } else {
226: buffer.append(c);
227: }
228: } else {
229: buffer.append(c);
230: }
231: }
232: return buffer.toString();
233: }
234:
235: /*
236: * --------------------------------------------------------------
237: * Native methods declaration
238: * --------------------------------------------------------------
239: */
240: private native byte[] getValue(byte[] registryPath, byte[] key,
241: boolean isUserNode, int[] errorCode);
242:
243: private native void putValue(byte[] registryPath, byte[] key,
244: byte[] value, boolean isUserNode, int[] errorCode);
245:
246: private native void removeKey(byte[] registryPath, byte[] key,
247: boolean isUserNode, int[] errorCode);
248:
249: private native byte[][] keys(byte[] registryPath,
250: boolean isUserNode, int[] errorCode);
251:
252: private native void removeNode(byte[] registryPath, byte[] name,
253: boolean isUserNode, int[] errorCode);
254:
255: private native boolean getNode(byte[] registryPath, byte[] name,
256: boolean isUserNode, int[] errorCode);
257:
258: private native byte[][] getChildNames(byte[] registryPath,
259: boolean isUserNode, int[] errorCode);
260:
261: private native void flushPrefs(byte[] registryPath,
262: boolean isUserNode, int[] errorCode)
263: throws SecurityException;
264: }
|