Source Code Cross Referenced for WindowsPreferences.java in  » 6.0-JDK-Platform » windows » java » util » prefs » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Platform » windows » java.util.prefs 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2000-2002 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package java.util.prefs;
0027:
0028:        import java.util.Map;
0029:        import java.util.TreeMap;
0030:        import java.util.StringTokenizer;
0031:        import java.io.ByteArrayOutputStream;
0032:        import java.util.logging.Logger;
0033:
0034:        /**
0035:         * Windows registry based implementation of  <tt>Preferences</tt>.
0036:         * <tt>Preferences</tt>' <tt>systemRoot</tt> and <tt>userRoot</tt> are stored in 
0037:         * <tt>HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs</tt> and 
0038:         * <tt>HKEY_CURRENT_USER\Software\JavaSoft\Prefs</tt> correspondingly.
0039:         *
0040:         * @author  Konstantin Kladko
0041:         * @version 1.24, 05/05/07
0042:         * @see Preferences
0043:         * @see PreferencesFactory
0044:         * @since 1.4
0045:         */
0046:
0047:        class WindowsPreferences extends AbstractPreferences {
0048:
0049:            /** 
0050:             * Logger for error messages 
0051:             */
0052:            private static Logger logger;
0053:
0054:            /** 
0055:             * Windows registry path to <tt>Preferences</tt>'s root nodes.         
0056:             */
0057:            private static final byte[] WINDOWS_ROOT_PATH = stringToByteArray("Software\\JavaSoft\\Prefs");
0058:
0059:            /** 
0060:             * Windows handles to <tt>HKEY_CURRENT_USER</tt> and 
0061:             * <tt>HKEY_LOCAL_MACHINE</tt> hives.
0062:             */
0063:            private static final int HKEY_CURRENT_USER = 0x80000001;
0064:            private static final int HKEY_LOCAL_MACHINE = 0x80000002;
0065:
0066:            /** 
0067:             * Mount point for <tt>Preferences</tt>'  user root.
0068:             */
0069:            private static final int USER_ROOT_NATIVE_HANDLE = HKEY_CURRENT_USER;
0070:
0071:            /** 
0072:             * Mount point for <tt>Preferences</tt>'  system root.
0073:             */
0074:            private static final int SYSTEM_ROOT_NATIVE_HANDLE = HKEY_LOCAL_MACHINE;
0075:
0076:            /**
0077:             * Maximum byte-encoded path length for Windows native functions,
0078:             * ending <tt>null</tt> character not included.
0079:             */
0080:            private static final int MAX_WINDOWS_PATH_LENGTH = 256;
0081:
0082:            /** 
0083:             * User root node.
0084:             */
0085:            static final Preferences userRoot = new WindowsPreferences(
0086:                    USER_ROOT_NATIVE_HANDLE, WINDOWS_ROOT_PATH);
0087:
0088:            /** 
0089:             * System root node.
0090:             */
0091:            static final Preferences systemRoot = new WindowsPreferences(
0092:                    SYSTEM_ROOT_NATIVE_HANDLE, WINDOWS_ROOT_PATH);
0093:
0094:            /*  Windows error codes. */
0095:            private static final int ERROR_SUCCESS = 0;
0096:            private static final int ERROR_FILE_NOT_FOUND = 2;
0097:            private static final int ERROR_ACCESS_DENIED = 5;
0098:
0099:            /* Constants used to interpret returns of native functions    */
0100:            private static final int NATIVE_HANDLE = 0;
0101:            private static final int ERROR_CODE = 1;
0102:            private static final int SUBKEYS_NUMBER = 0;
0103:            private static final int VALUES_NUMBER = 2;
0104:            private static final int MAX_KEY_LENGTH = 3;
0105:            private static final int MAX_VALUE_NAME_LENGTH = 4;
0106:            private static final int DISPOSITION = 2;
0107:            private static final int REG_CREATED_NEW_KEY = 1;
0108:            private static final int REG_OPENED_EXISTING_KEY = 2;
0109:            private static final int NULL_NATIVE_HANDLE = 0;
0110:
0111:            /* Windows security masks */
0112:            private static final int DELETE = 0x10000;
0113:            private static final int KEY_QUERY_VALUE = 1;
0114:            private static final int KEY_SET_VALUE = 2;
0115:            private static final int KEY_CREATE_SUB_KEY = 4;
0116:            private static final int KEY_ENUMERATE_SUB_KEYS = 8;
0117:            private static final int KEY_READ = 0x20019;
0118:            private static final int KEY_WRITE = 0x20006;
0119:            private static final int KEY_ALL_ACCESS = 0xf003f;
0120:
0121:            /**
0122:             * Initial time between registry access attempts, in ms. The time is doubled
0123:             * after each failing attempt (except the first).
0124:             */
0125:            private static int INIT_SLEEP_TIME = 50;
0126:
0127:            /**
0128:             * Maximum number of registry access attempts.
0129:             */
0130:            private static int MAX_ATTEMPTS = 5;
0131:
0132:            /**
0133:             * BackingStore availability flag.
0134:             */
0135:            private boolean isBackingStoreAvailable = true;
0136:
0137:            /** 
0138:             * Java wrapper for Windows registry API RegOpenKey()
0139:             */
0140:            private static native int[] WindowsRegOpenKey(int hKey,
0141:                    byte[] subKey, int securityMask);
0142:
0143:            /**
0144:             * Retries RegOpenKey() MAX_ATTEMPTS times before giving up.
0145:             */
0146:            private static int[] WindowsRegOpenKey1(int hKey, byte[] subKey,
0147:                    int securityMask) {
0148:                int[] result = WindowsRegOpenKey(hKey, subKey, securityMask);
0149:                if (result[ERROR_CODE] == ERROR_SUCCESS) {
0150:                    return result;
0151:                } else if (result[ERROR_CODE] == ERROR_FILE_NOT_FOUND) {
0152:                    logger().warning(
0153:                            "Trying to recreate Windows registry node "
0154:                                    + byteArrayToString(subKey) + " at root 0x"
0155:                                    + Integer.toHexString(hKey) + ".");
0156:                    // Try recreation
0157:                    int handle = WindowsRegCreateKeyEx(hKey, subKey)[NATIVE_HANDLE];
0158:                    WindowsRegCloseKey(handle);
0159:                    return WindowsRegOpenKey(hKey, subKey, securityMask);
0160:                } else if (result[ERROR_CODE] != ERROR_ACCESS_DENIED) {
0161:                    long sleepTime = INIT_SLEEP_TIME;
0162:                    for (int i = 0; i < MAX_ATTEMPTS; i++) {
0163:                        try {
0164:                            Thread.sleep(sleepTime);
0165:                        } catch (InterruptedException e) {
0166:                            return result;
0167:                        }
0168:                        sleepTime *= 2;
0169:                        result = WindowsRegOpenKey(hKey, subKey, securityMask);
0170:                        if (result[ERROR_CODE] == ERROR_SUCCESS) {
0171:                            return result;
0172:                        }
0173:                    }
0174:                }
0175:                return result;
0176:            }
0177:
0178:            /** 
0179:             * Java wrapper for Windows registry API RegCloseKey()
0180:             */
0181:            private static native int WindowsRegCloseKey(int hKey);
0182:
0183:            /** 
0184:             * Java wrapper for Windows registry API RegCreateKeyEx()
0185:             */
0186:            private static native int[] WindowsRegCreateKeyEx(int hKey,
0187:                    byte[] subKey);
0188:
0189:            /**
0190:             * Retries RegCreateKeyEx() MAX_ATTEMPTS times before giving up.
0191:             */
0192:            private static int[] WindowsRegCreateKeyEx1(int hKey, byte[] subKey) {
0193:                int[] result = WindowsRegCreateKeyEx(hKey, subKey);
0194:                if (result[ERROR_CODE] == ERROR_SUCCESS) {
0195:                    return result;
0196:                } else {
0197:                    long sleepTime = INIT_SLEEP_TIME;
0198:                    for (int i = 0; i < MAX_ATTEMPTS; i++) {
0199:                        try {
0200:                            Thread.sleep(sleepTime);
0201:                        } catch (InterruptedException e) {
0202:                            return result;
0203:                        }
0204:                        sleepTime *= 2;
0205:                        result = WindowsRegCreateKeyEx(hKey, subKey);
0206:                        if (result[ERROR_CODE] == ERROR_SUCCESS) {
0207:                            return result;
0208:                        }
0209:                    }
0210:                }
0211:                return result;
0212:            }
0213:
0214:            /** 
0215:             * Java wrapper for Windows registry API RegDeleteKey()
0216:             */
0217:            private static native int WindowsRegDeleteKey(int hKey,
0218:                    byte[] subKey);
0219:
0220:            /** 
0221:             * Java wrapper for Windows registry API RegFlushKey()
0222:             */
0223:            private static native int WindowsRegFlushKey(int hKey);
0224:
0225:            /**
0226:             * Retries RegFlushKey() MAX_ATTEMPTS times before giving up.
0227:             */
0228:            private static int WindowsRegFlushKey1(int hKey) {
0229:                int result = WindowsRegFlushKey(hKey);
0230:                if (result == ERROR_SUCCESS) {
0231:                    return result;
0232:                } else {
0233:                    long sleepTime = INIT_SLEEP_TIME;
0234:                    for (int i = 0; i < MAX_ATTEMPTS; i++) {
0235:                        try {
0236:                            Thread.sleep(sleepTime);
0237:                        } catch (InterruptedException e) {
0238:                            return result;
0239:                        }
0240:                        sleepTime *= 2;
0241:                        result = WindowsRegFlushKey(hKey);
0242:                        if (result == ERROR_SUCCESS) {
0243:                            return result;
0244:                        }
0245:                    }
0246:                }
0247:                return result;
0248:            }
0249:
0250:            /** 
0251:             * Java wrapper for Windows registry API RegQueryValueEx()
0252:             */
0253:            private static native byte[] WindowsRegQueryValueEx(int hKey,
0254:                    byte[] valueName);
0255:
0256:            /** 
0257:             * Java wrapper for Windows registry API RegSetValueEx()
0258:             */
0259:            private static native int WindowsRegSetValueEx(int hKey,
0260:                    byte[] valueName, byte[] value);
0261:
0262:            /**
0263:             * Retries RegSetValueEx() MAX_ATTEMPTS times before giving up.
0264:             */
0265:            private static int WindowsRegSetValueEx1(int hKey,
0266:                    byte[] valueName, byte[] value) {
0267:                int result = WindowsRegSetValueEx(hKey, valueName, value);
0268:                if (result == ERROR_SUCCESS) {
0269:                    return result;
0270:                } else {
0271:                    long sleepTime = INIT_SLEEP_TIME;
0272:                    for (int i = 0; i < MAX_ATTEMPTS; i++) {
0273:                        try {
0274:                            Thread.sleep(sleepTime);
0275:                        } catch (InterruptedException e) {
0276:                            return result;
0277:                        }
0278:                        sleepTime *= 2;
0279:                        result = WindowsRegSetValueEx(hKey, valueName, value);
0280:                        if (result == ERROR_SUCCESS) {
0281:                            return result;
0282:                        }
0283:                    }
0284:                }
0285:                return result;
0286:            }
0287:
0288:            /** 
0289:             * Java wrapper for Windows registry API RegDeleteValue()
0290:             */
0291:            private static native int WindowsRegDeleteValue(int hKey,
0292:                    byte[] valueName);
0293:
0294:            /** 
0295:             * Java wrapper for Windows registry API RegQueryInfoKey()
0296:             */
0297:            private static native int[] WindowsRegQueryInfoKey(int hKey);
0298:
0299:            /**
0300:             * Retries RegQueryInfoKey() MAX_ATTEMPTS times before giving up.
0301:             */
0302:            private static int[] WindowsRegQueryInfoKey1(int hKey) {
0303:                int[] result = WindowsRegQueryInfoKey(hKey);
0304:                if (result[ERROR_CODE] == ERROR_SUCCESS) {
0305:                    return result;
0306:                } else {
0307:                    long sleepTime = INIT_SLEEP_TIME;
0308:                    for (int i = 0; i < MAX_ATTEMPTS; i++) {
0309:                        try {
0310:                            Thread.sleep(sleepTime);
0311:                        } catch (InterruptedException e) {
0312:                            return result;
0313:                        }
0314:                        sleepTime *= 2;
0315:                        result = WindowsRegQueryInfoKey(hKey);
0316:                        if (result[ERROR_CODE] == ERROR_SUCCESS) {
0317:                            return result;
0318:                        }
0319:                    }
0320:                }
0321:                return result;
0322:            }
0323:
0324:            /** 
0325:             * Java wrapper for Windows registry API RegEnumKeyEx()
0326:             */
0327:            private static native byte[] WindowsRegEnumKeyEx(int hKey,
0328:                    int subKeyIndex, int maxKeyLength);
0329:
0330:            /**
0331:             * Retries RegEnumKeyEx() MAX_ATTEMPTS times before giving up.
0332:             */
0333:            private static byte[] WindowsRegEnumKeyEx1(int hKey,
0334:                    int subKeyIndex, int maxKeyLength) {
0335:                byte[] result = WindowsRegEnumKeyEx(hKey, subKeyIndex,
0336:                        maxKeyLength);
0337:                if (result != null) {
0338:                    return result;
0339:                } else {
0340:                    long sleepTime = INIT_SLEEP_TIME;
0341:                    for (int i = 0; i < MAX_ATTEMPTS; i++) {
0342:                        try {
0343:                            Thread.sleep(sleepTime);
0344:                        } catch (InterruptedException e) {
0345:                            return result;
0346:                        }
0347:                        sleepTime *= 2;
0348:                        result = WindowsRegEnumKeyEx(hKey, subKeyIndex,
0349:                                maxKeyLength);
0350:                        if (result != null) {
0351:                            return result;
0352:                        }
0353:                    }
0354:                }
0355:                return result;
0356:            }
0357:
0358:            /** 
0359:             * Java wrapper for Windows registry API RegEnumValue()
0360:             */
0361:            private static native byte[] WindowsRegEnumValue(int hKey,
0362:                    int valueIndex, int maxValueNameLength);
0363:
0364:            /**
0365:             * Retries RegEnumValueEx() MAX_ATTEMPTS times before giving up.
0366:             */
0367:            private static byte[] WindowsRegEnumValue1(int hKey,
0368:                    int valueIndex, int maxValueNameLength) {
0369:                byte[] result = WindowsRegEnumValue(hKey, valueIndex,
0370:                        maxValueNameLength);
0371:                if (result != null) {
0372:                    return result;
0373:                } else {
0374:                    long sleepTime = INIT_SLEEP_TIME;
0375:                    for (int i = 0; i < MAX_ATTEMPTS; i++) {
0376:                        try {
0377:                            Thread.sleep(sleepTime);
0378:                        } catch (InterruptedException e) {
0379:                            return result;
0380:                        }
0381:                        sleepTime *= 2;
0382:                        result = WindowsRegEnumValue(hKey, valueIndex,
0383:                                maxValueNameLength);
0384:                        if (result != null) {
0385:                            return result;
0386:                        }
0387:                    }
0388:                }
0389:                return result;
0390:            }
0391:
0392:            /**
0393:             * Constructs a <tt>WindowsPreferences</tt> node, creating underlying
0394:             * Windows registry node and all its Windows parents, if they are not yet 
0395:             * created.
0396:             * Logs a warning message, if Windows Registry is unavailable.
0397:             */
0398:            private WindowsPreferences(WindowsPreferences parent, String name) {
0399:                super (parent, name);
0400:                int parentNativeHandle = parent.openKey(KEY_CREATE_SUB_KEY,
0401:                        KEY_READ);
0402:                if (parentNativeHandle == NULL_NATIVE_HANDLE) {
0403:                    // if here, openKey failed and logged 
0404:                    isBackingStoreAvailable = false;
0405:                    return;
0406:                }
0407:                int[] result = WindowsRegCreateKeyEx1(parentNativeHandle,
0408:                        toWindowsName(name));
0409:                if (result[ERROR_CODE] != ERROR_SUCCESS) {
0410:                    logger()
0411:                            .warning(
0412:                                    "Could not create windows registry "
0413:                                            + "node "
0414:                                            + byteArrayToString(windowsAbsolutePath())
0415:                                            + " at root 0x"
0416:                                            + Integer
0417:                                                    .toHexString(rootNativeHandle())
0418:                                            + ". Windows RegCreateKeyEx(...) returned error code "
0419:                                            + result[ERROR_CODE] + ".");
0420:                    isBackingStoreAvailable = false;
0421:                    return;
0422:                }
0423:                newNode = (result[DISPOSITION] == REG_CREATED_NEW_KEY);
0424:                closeKey(parentNativeHandle);
0425:                closeKey(result[NATIVE_HANDLE]);
0426:            }
0427:
0428:            /**
0429:             * Constructs a root node creating the underlying
0430:             * Windows registry node and all of its parents, if they have not yet been 
0431:             * created.
0432:             * Logs a warning message, if Windows Registry is unavailable.
0433:             * @param rootNativeHandle Native handle to one of Windows top level keys.
0434:             * @param rootDirectory Path to root directory, as a byte-encoded string.
0435:             */
0436:            private WindowsPreferences(int rootNativeHandle,
0437:                    byte[] rootDirectory) {
0438:                super (null, "");
0439:                int[] result = WindowsRegCreateKeyEx1(rootNativeHandle,
0440:                        rootDirectory);
0441:                if (result[ERROR_CODE] != ERROR_SUCCESS) {
0442:                    logger()
0443:                            .warning(
0444:                                    "Could not open/create prefs root node "
0445:                                            + byteArrayToString(windowsAbsolutePath())
0446:                                            + " at root 0x"
0447:                                            + Integer
0448:                                                    .toHexString(rootNativeHandle())
0449:                                            + ". Windows RegCreateKeyEx(...) returned error code "
0450:                                            + result[ERROR_CODE] + ".");
0451:                    isBackingStoreAvailable = false;
0452:                    return;
0453:                }
0454:                // Check if a new node
0455:                newNode = (result[DISPOSITION] == REG_CREATED_NEW_KEY);
0456:                closeKey(result[NATIVE_HANDLE]);
0457:            }
0458:
0459:            /**
0460:             * Returns Windows absolute path of the current node as a byte array.
0461:             * Java "/" separator is transformed into Windows "\".
0462:             * @see Preferences#absolutePath()
0463:             */
0464:            private byte[] windowsAbsolutePath() {
0465:                ByteArrayOutputStream bstream = new ByteArrayOutputStream();
0466:                bstream.write(WINDOWS_ROOT_PATH, 0,
0467:                        WINDOWS_ROOT_PATH.length - 1);
0468:                StringTokenizer tokenizer = new StringTokenizer(absolutePath(),
0469:                        "/");
0470:                while (tokenizer.hasMoreTokens()) {
0471:                    bstream.write((byte) '\\');
0472:                    String nextName = tokenizer.nextToken();
0473:                    byte[] windowsNextName = toWindowsName(nextName);
0474:                    bstream.write(windowsNextName, 0,
0475:                            windowsNextName.length - 1);
0476:                }
0477:                bstream.write(0);
0478:                return bstream.toByteArray();
0479:            }
0480:
0481:            /**
0482:             * Opens current node's underlying Windows registry key using a 
0483:             * given security mask.
0484:             * @param securityMask Windows security mask.
0485:             * @return Windows registry key's handle.
0486:             * @see #openKey(byte[], int)
0487:             * @see #openKey(int, byte[], int)    
0488:             * @see #closeKey(int)    
0489:             */
0490:            private int openKey(int securityMask) {
0491:                return openKey(securityMask, securityMask);
0492:            }
0493:
0494:            /**
0495:             * Opens current node's underlying Windows registry key using a 
0496:             * given security mask.
0497:             * @param mask1 Preferred Windows security mask.
0498:             * @param mask2 Alternate Windows security mask.
0499:             * @return Windows registry key's handle.
0500:             * @see #openKey(byte[], int)
0501:             * @see #openKey(int, byte[], int)    
0502:             * @see #closeKey(int)    
0503:             */
0504:            private int openKey(int mask1, int mask2) {
0505:                return openKey(windowsAbsolutePath(), mask1, mask2);
0506:            }
0507:
0508:            /**
0509:             * Opens Windows registry key at a given absolute path using a given
0510:             * security mask.
0511:             * @param windowsAbsolutePath Windows absolute path of the
0512:             *        key as a byte-encoded string.
0513:             * @param mask1 Preferred Windows security mask.
0514:             * @param mask2 Alternate Windows security mask.
0515:             * @return Windows registry key's handle.
0516:             * @see #openKey(int)
0517:             * @see #openKey(int, byte[],int)
0518:             * @see #closeKey(int)        
0519:             */
0520:            private int openKey(byte[] windowsAbsolutePath, int mask1, int mask2) {
0521:                /*  Check if key's path is short enough be opened at once
0522:                    otherwise use a path-splitting procedure */
0523:                if (windowsAbsolutePath.length <= MAX_WINDOWS_PATH_LENGTH + 1) {
0524:                    int[] result = WindowsRegOpenKey1(rootNativeHandle(),
0525:                            windowsAbsolutePath, mask1);
0526:                    if (result[ERROR_CODE] == ERROR_ACCESS_DENIED
0527:                            && mask2 != mask1)
0528:                        result = WindowsRegOpenKey1(rootNativeHandle(),
0529:                                windowsAbsolutePath, mask2);
0530:
0531:                    if (result[ERROR_CODE] != ERROR_SUCCESS) {
0532:                        logger()
0533:                                .warning(
0534:                                        "Could not open windows "
0535:                                                + "registry node "
0536:                                                + byteArrayToString(windowsAbsolutePath())
0537:                                                + " at root 0x"
0538:                                                + Integer
0539:                                                        .toHexString(rootNativeHandle())
0540:                                                + ". Windows RegOpenKey(...) returned error code "
0541:                                                + result[ERROR_CODE] + ".");
0542:                        result[NATIVE_HANDLE] = NULL_NATIVE_HANDLE;
0543:                        if (result[ERROR_CODE] == ERROR_ACCESS_DENIED) {
0544:                            throw new SecurityException(
0545:                                    "Could not open windows "
0546:                                            + "registry node "
0547:                                            + byteArrayToString(windowsAbsolutePath())
0548:                                            + " at root 0x"
0549:                                            + Integer
0550:                                                    .toHexString(rootNativeHandle())
0551:                                            + ": Access denied");
0552:                        }
0553:                    }
0554:                    return result[NATIVE_HANDLE];
0555:                } else {
0556:                    return openKey(rootNativeHandle(), windowsAbsolutePath,
0557:                            mask1, mask2);
0558:                }
0559:            }
0560:
0561:            /**
0562:             * Opens Windows registry key at a given relative path 
0563:             * with respect to a given Windows registry key.
0564:             * @param windowsAbsolutePath Windows relative path of the
0565:             *        key as a byte-encoded string.
0566:             * @param nativeHandle handle to the base Windows key.
0567:             * @param mask1 Preferred Windows security mask.
0568:             * @param mask2 Alternate Windows security mask.
0569:             * @return Windows registry key's handle.
0570:             * @see #openKey(int)
0571:             * @see #openKey(byte[],int)
0572:             * @see #closeKey(int)        
0573:             */
0574:            private int openKey(int nativeHandle, byte[] windowsRelativePath,
0575:                    int mask1, int mask2) {
0576:                /* If the path is short enough open at once. Otherwise split the path */
0577:                if (windowsRelativePath.length <= MAX_WINDOWS_PATH_LENGTH + 1) {
0578:                    int[] result = WindowsRegOpenKey1(nativeHandle,
0579:                            windowsRelativePath, mask1);
0580:                    if (result[ERROR_CODE] == ERROR_ACCESS_DENIED
0581:                            && mask2 != mask1)
0582:                        result = WindowsRegOpenKey1(nativeHandle,
0583:                                windowsRelativePath, mask2);
0584:
0585:                    if (result[ERROR_CODE] != ERROR_SUCCESS) {
0586:                        logger()
0587:                                .warning(
0588:                                        "Could not open windows "
0589:                                                + "registry node "
0590:                                                + byteArrayToString(windowsAbsolutePath())
0591:                                                + " at root 0x"
0592:                                                + Integer
0593:                                                        .toHexString(nativeHandle)
0594:                                                + ". Windows RegOpenKey(...) returned error code "
0595:                                                + result[ERROR_CODE] + ".");
0596:                        result[NATIVE_HANDLE] = NULL_NATIVE_HANDLE;
0597:                    }
0598:                    return result[NATIVE_HANDLE];
0599:                } else {
0600:                    int separatorPosition = -1;
0601:                    // Be greedy - open the longest possible path 
0602:                    for (int i = MAX_WINDOWS_PATH_LENGTH; i > 0; i--) {
0603:                        if (windowsRelativePath[i] == ((byte) '\\')) {
0604:                            separatorPosition = i;
0605:                            break;
0606:                        }
0607:                    }
0608:                    // Split the path and do the recursion
0609:                    byte[] nextRelativeRoot = new byte[separatorPosition + 1];
0610:                    System.arraycopy(windowsRelativePath, 0, nextRelativeRoot,
0611:                            0, separatorPosition);
0612:                    nextRelativeRoot[separatorPosition] = 0;
0613:                    byte[] nextRelativePath = new byte[windowsRelativePath.length
0614:                            - separatorPosition - 1];
0615:                    System.arraycopy(windowsRelativePath,
0616:                            separatorPosition + 1, nextRelativePath, 0,
0617:                            nextRelativePath.length);
0618:                    int nextNativeHandle = openKey(nativeHandle,
0619:                            nextRelativeRoot, mask1, mask2);
0620:                    if (nextNativeHandle == NULL_NATIVE_HANDLE) {
0621:                        return NULL_NATIVE_HANDLE;
0622:                    }
0623:                    int result = openKey(nextNativeHandle, nextRelativePath,
0624:                            mask1, mask2);
0625:                    closeKey(nextNativeHandle);
0626:                    return result;
0627:                }
0628:            }
0629:
0630:            /**
0631:             * Closes Windows registry key.
0632:             * Logs a warning if Windows registry is unavailable.
0633:             * @param key's Windows registry handle.
0634:             * @see #openKey(int)
0635:             * @see #openKey(byte[],int)
0636:             * @see #openKey(int, byte[],int)    
0637:             */
0638:            private void closeKey(int nativeHandle) {
0639:                int result = WindowsRegCloseKey(nativeHandle);
0640:                if (result != ERROR_SUCCESS) {
0641:                    logger()
0642:                            .warning(
0643:                                    "Could not close windows "
0644:                                            + "registry node "
0645:                                            + byteArrayToString(windowsAbsolutePath())
0646:                                            + " at root 0x"
0647:                                            + Integer
0648:                                                    .toHexString(rootNativeHandle())
0649:                                            + ". Windows RegCloseKey(...) returned error code "
0650:                                            + result + ".");
0651:                }
0652:            }
0653:
0654:            /**
0655:             * Implements <tt>AbstractPreferences</tt> <tt>putSpi()</tt> method.
0656:             * Puts name-value pair into the underlying Windows registry node.
0657:             * Logs a warning, if Windows registry is unavailable.
0658:             * @see #getSpi(String)
0659:             */
0660:            protected void putSpi(String javaName, String value) {
0661:                int nativeHandle = openKey(KEY_SET_VALUE);
0662:                if (nativeHandle == NULL_NATIVE_HANDLE) {
0663:                    isBackingStoreAvailable = false;
0664:                    return;
0665:                }
0666:                int result = WindowsRegSetValueEx1(nativeHandle,
0667:                        toWindowsName(javaName), toWindowsValueString(value));
0668:                if (result != ERROR_SUCCESS) {
0669:                    logger()
0670:                            .warning(
0671:                                    "Could not assign value to key "
0672:                                            + byteArrayToString(toWindowsName(javaName))
0673:                                            + " at Windows registry node "
0674:                                            + byteArrayToString(windowsAbsolutePath())
0675:                                            + " at root 0x"
0676:                                            + Integer
0677:                                                    .toHexString(rootNativeHandle())
0678:                                            + ". Windows RegSetValueEx(...) returned error code "
0679:                                            + result + ".");
0680:                    isBackingStoreAvailable = false;
0681:                }
0682:                closeKey(nativeHandle);
0683:            }
0684:
0685:            /**
0686:             * Implements <tt>AbstractPreferences</tt> <tt>getSpi()</tt> method.
0687:             * Gets a string value from the underlying Windows registry node.
0688:             * Logs a warning, if Windows registry is unavailable.
0689:             * @see #putSpi(String, String)
0690:             */
0691:            protected String getSpi(String javaName) {
0692:                int nativeHandle = openKey(KEY_QUERY_VALUE);
0693:                if (nativeHandle == NULL_NATIVE_HANDLE) {
0694:                    return null;
0695:                }
0696:                Object resultObject = WindowsRegQueryValueEx(nativeHandle,
0697:                        toWindowsName(javaName));
0698:                if (resultObject == null) {
0699:                    closeKey(nativeHandle);
0700:                    return null;
0701:                }
0702:                closeKey(nativeHandle);
0703:                return toJavaValueString((byte[]) resultObject);
0704:            }
0705:
0706:            /**
0707:             * Implements <tt>AbstractPreferences</tt> <tt>removeSpi()</tt> method.
0708:             * Deletes a string name-value pair from the underlying Windows registry 
0709:             * node, if this value still exists.
0710:             * Logs a warning, if Windows registry is unavailable or key has already
0711:             * been deleted.
0712:             */
0713:            protected void removeSpi(String key) {
0714:                int nativeHandle = openKey(KEY_SET_VALUE);
0715:                if (nativeHandle == NULL_NATIVE_HANDLE) {
0716:                    return;
0717:                }
0718:                int result = WindowsRegDeleteValue(nativeHandle,
0719:                        toWindowsName(key));
0720:                if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
0721:                    logger()
0722:                            .warning(
0723:                                    "Could not delete windows registry "
0724:                                            + "value "
0725:                                            + byteArrayToString(windowsAbsolutePath())
0726:                                            + "\\"
0727:                                            + toWindowsName(key)
0728:                                            + " at root 0x"
0729:                                            + Integer
0730:                                                    .toHexString(rootNativeHandle())
0731:                                            + ". Windows RegDeleteValue(...) returned error code "
0732:                                            + result + ".");
0733:                    isBackingStoreAvailable = false;
0734:                }
0735:                closeKey(nativeHandle);
0736:            }
0737:
0738:            /**
0739:             * Implements <tt>AbstractPreferences</tt> <tt>keysSpi()</tt> method.
0740:             * Gets value names from the underlying Windows registry node.
0741:             * Throws a BackingStoreException and logs a warning, if 
0742:             * Windows registry is unavailable.
0743:             */
0744:            protected String[] keysSpi() throws BackingStoreException {
0745:                // Find out the number of values
0746:                int nativeHandle = openKey(KEY_QUERY_VALUE);
0747:                if (nativeHandle == NULL_NATIVE_HANDLE) {
0748:                    throw new BackingStoreException("Could not open windows"
0749:                            + "registry node "
0750:                            + byteArrayToString(windowsAbsolutePath())
0751:                            + " at root 0x"
0752:                            + Integer.toHexString(rootNativeHandle()) + ".");
0753:                }
0754:                int[] result = WindowsRegQueryInfoKey1(nativeHandle);
0755:                if (result[ERROR_CODE] != ERROR_SUCCESS) {
0756:                    String info = "Could not query windows"
0757:                            + "registry node "
0758:                            + byteArrayToString(windowsAbsolutePath())
0759:                            + " at root 0x"
0760:                            + Integer.toHexString(rootNativeHandle())
0761:                            + ". Windows RegQueryInfoKeyEx(...) returned error code "
0762:                            + result[ERROR_CODE] + ".";
0763:                    logger().warning(info);
0764:                    throw new BackingStoreException(info);
0765:                }
0766:                int maxValueNameLength = result[MAX_VALUE_NAME_LENGTH];
0767:                int valuesNumber = result[VALUES_NUMBER];
0768:                if (valuesNumber == 0) {
0769:                    closeKey(nativeHandle);
0770:                    return new String[0];
0771:                }
0772:                // Get the values
0773:                String[] valueNames = new String[valuesNumber];
0774:                for (int i = 0; i < valuesNumber; i++) {
0775:                    byte[] windowsName = WindowsRegEnumValue1(nativeHandle, i,
0776:                            maxValueNameLength + 1);
0777:                    if (windowsName == null) {
0778:                        String info = "Could not enumerate value #" + i
0779:                                + "  of windows node "
0780:                                + byteArrayToString(windowsAbsolutePath())
0781:                                + " at root 0x"
0782:                                + Integer.toHexString(rootNativeHandle()) + ".";
0783:                        logger().warning(info);
0784:                        throw new BackingStoreException(info);
0785:                    }
0786:                    valueNames[i] = toJavaName(windowsName);
0787:                }
0788:                closeKey(nativeHandle);
0789:                return valueNames;
0790:            }
0791:
0792:            /**
0793:             * Implements <tt>AbstractPreferences</tt> <tt>childrenNamesSpi()</tt> method.
0794:             * Calls Windows registry to retrive children of this node.
0795:             * Throws a BackingStoreException and logs a warning message, 
0796:             * if Windows registry is not available.
0797:             */
0798:            protected String[] childrenNamesSpi() throws BackingStoreException {
0799:                // Open key
0800:                int nativeHandle = openKey(KEY_ENUMERATE_SUB_KEYS
0801:                        | KEY_QUERY_VALUE);
0802:                if (nativeHandle == NULL_NATIVE_HANDLE) {
0803:                    throw new BackingStoreException("Could not open windows"
0804:                            + "registry node "
0805:                            + byteArrayToString(windowsAbsolutePath())
0806:                            + " at root 0x"
0807:                            + Integer.toHexString(rootNativeHandle()) + ".");
0808:                }
0809:                // Get number of children
0810:                int[] result = WindowsRegQueryInfoKey1(nativeHandle);
0811:                if (result[ERROR_CODE] != ERROR_SUCCESS) {
0812:                    String info = "Could not query windows"
0813:                            + "registry node "
0814:                            + byteArrayToString(windowsAbsolutePath())
0815:                            + " at root 0x"
0816:                            + Integer.toHexString(rootNativeHandle())
0817:                            + ". Windows RegQueryInfoKeyEx(...) returned error code "
0818:                            + result[ERROR_CODE] + ".";
0819:                    logger().warning(info);
0820:                    throw new BackingStoreException(info);
0821:                }
0822:                int maxKeyLength = result[MAX_KEY_LENGTH];
0823:                int subKeysNumber = result[SUBKEYS_NUMBER];
0824:                if (subKeysNumber == 0) {
0825:                    closeKey(nativeHandle);
0826:                    return new String[0];
0827:                }
0828:                String[] subkeys = new String[subKeysNumber];
0829:                String[] children = new String[subKeysNumber];
0830:                // Get children
0831:                for (int i = 0; i < subKeysNumber; i++) {
0832:                    byte[] windowsName = WindowsRegEnumKeyEx1(nativeHandle, i,
0833:                            maxKeyLength + 1);
0834:                    if (windowsName == null) {
0835:                        String info = "Could not enumerate key #" + i
0836:                                + "  of windows node "
0837:                                + byteArrayToString(windowsAbsolutePath())
0838:                                + " at root 0x"
0839:                                + Integer.toHexString(rootNativeHandle())
0840:                                + ". ";
0841:                        logger().warning(info);
0842:                        throw new BackingStoreException(info);
0843:                    }
0844:                    String javaName = toJavaName(windowsName);
0845:                    children[i] = javaName;
0846:                }
0847:                closeKey(nativeHandle);
0848:                return children;
0849:            }
0850:
0851:            /**
0852:             * Implements <tt>Preferences</tt> <tt>flush()</tt> method.
0853:             * Flushes Windows registry changes to disk.
0854:             * Throws a BackingStoreException and logs a warning message if Windows
0855:             * registry is not available.
0856:             */
0857:            public void flush() throws BackingStoreException {
0858:
0859:                if (isRemoved()) {
0860:                    parent.flush();
0861:                    return;
0862:                }
0863:                if (!isBackingStoreAvailable) {
0864:                    throw new BackingStoreException(
0865:                            "flush(): Backing store not available.");
0866:                }
0867:                int nativeHandle = openKey(KEY_READ);
0868:                if (nativeHandle == NULL_NATIVE_HANDLE) {
0869:                    throw new BackingStoreException("Could not open windows"
0870:                            + "registry node "
0871:                            + byteArrayToString(windowsAbsolutePath())
0872:                            + " at root 0x"
0873:                            + Integer.toHexString(rootNativeHandle()) + ".");
0874:                }
0875:                int result = WindowsRegFlushKey1(nativeHandle);
0876:                if (result != ERROR_SUCCESS) {
0877:                    String info = "Could not flush windows " + "registry node "
0878:                            + byteArrayToString(windowsAbsolutePath())
0879:                            + " at root 0x"
0880:                            + Integer.toHexString(rootNativeHandle())
0881:                            + ". Windows RegFlushKey(...) returned error code "
0882:                            + result + ".";
0883:                    logger().warning(info);
0884:                    throw new BackingStoreException(info);
0885:                }
0886:                closeKey(nativeHandle);
0887:            }
0888:
0889:            /**
0890:             * Implements <tt>Preferences</tt> <tt>sync()</tt> method.
0891:             * Flushes Windows registry changes to disk. Equivalent to flush().
0892:             * @see flush()
0893:             */
0894:            public void sync() throws BackingStoreException {
0895:                if (isRemoved())
0896:                    throw new IllegalStateException("Node has been removed");
0897:                flush();
0898:            }
0899:
0900:            /**
0901:             * Implements <tt>AbstractPreferences</tt> <tt>childSpi()</tt> method.
0902:             * Constructs a child node with a 
0903:             * given name and creates its underlying Windows registry node, 
0904:             * if it does not exist.
0905:             * Logs a warning message, if Windows Registry is unavailable.
0906:             */
0907:            protected AbstractPreferences childSpi(String name) {
0908:                return new WindowsPreferences(this , name);
0909:            }
0910:
0911:            /**
0912:             * Implements <tt>AbstractPreferences</tt> <tt>removeNodeSpi()</tt> method.
0913:             * Deletes underlying Windows registry node.
0914:             * Throws a BackingStoreException and logs a warning, if Windows registry
0915:             * is not available.
0916:             */
0917:            public void removeNodeSpi() throws BackingStoreException {
0918:                int parentNativeHandle = ((WindowsPreferences) parent())
0919:                        .openKey(DELETE);
0920:                if (parentNativeHandle == NULL_NATIVE_HANDLE) {
0921:                    throw new BackingStoreException(
0922:                            "Could not open parent windows"
0923:                                    + "registry node of "
0924:                                    + byteArrayToString(windowsAbsolutePath())
0925:                                    + " at root 0x"
0926:                                    + Integer.toHexString(rootNativeHandle())
0927:                                    + ".");
0928:                }
0929:                int result = WindowsRegDeleteKey(parentNativeHandle,
0930:                        toWindowsName(name()));
0931:                if (result != ERROR_SUCCESS) {
0932:                    String info = "Could not delete windows "
0933:                            + "registry node "
0934:                            + byteArrayToString(windowsAbsolutePath())
0935:                            + " at root 0x"
0936:                            + Integer.toHexString(rootNativeHandle())
0937:                            + ". Windows RegDeleteKeyEx(...) returned error code "
0938:                            + result + ".";
0939:                    logger().warning(info);
0940:                    throw new BackingStoreException(info);
0941:                }
0942:                closeKey(parentNativeHandle);
0943:            }
0944:
0945:            /**
0946:             * Converts value's or node's name from its byte array representation to
0947:             * java string. Two encodings, simple and altBase64 are used. See
0948:             * {@link #toWindowsName(String) toWindowsName()} for a detailed 
0949:             * description of encoding conventions.
0950:             * @param windowsNameArray Null-terminated byte array.
0951:             */
0952:            private static String toJavaName(byte[] windowsNameArray) {
0953:                String windowsName = byteArrayToString(windowsNameArray);
0954:                // check if Alt64
0955:                if ((windowsName.length() > 1)
0956:                        && (windowsName.substring(0, 2).equals("/!"))) {
0957:                    return toJavaAlt64Name(windowsName);
0958:                }
0959:                StringBuffer javaName = new StringBuffer();
0960:                char ch;
0961:                // Decode from simple encoding
0962:                for (int i = 0; i < windowsName.length(); i++) {
0963:                    if ((ch = windowsName.charAt(i)) == '/') {
0964:                        char next = ' ';
0965:                        if ((windowsName.length() > i + 1)
0966:                                && ((next = windowsName.charAt(i + 1)) >= 'A')
0967:                                && (next <= 'Z')) {
0968:                            ch = next;
0969:                            i++;
0970:                        } else if ((windowsName.length() > i + 1)
0971:                                && (next == '/')) {
0972:                            ch = '\\';
0973:                            i++;
0974:                        }
0975:                    } else if (ch == '\\') {
0976:                        ch = '/';
0977:                    }
0978:                    javaName.append(ch);
0979:                }
0980:                return javaName.toString();
0981:            }
0982:
0983:            /**
0984:             * Converts value's or node's name from its Windows representation to java
0985:             * string, using altBase64 encoding. See
0986:             * {@link #toWindowsName(String) toWindowsName()} for a detailed 
0987:             * description of encoding conventions.
0988:             */
0989:
0990:            private static String toJavaAlt64Name(String windowsName) {
0991:                byte[] byteBuffer = Base64.altBase64ToByteArray(windowsName
0992:                        .substring(2));
0993:                StringBuffer result = new StringBuffer();
0994:                for (int i = 0; i < byteBuffer.length; i++) {
0995:                    int firstbyte = (byteBuffer[i++] & 0xff);
0996:                    int secondbyte = (byteBuffer[i] & 0xff);
0997:                    result.append((char) ((firstbyte << 8) + secondbyte));
0998:                }
0999:                return result.toString();
1000:            }
1001:
1002:            /**
1003:             * Converts value's or node's name to its Windows representation
1004:             * as a byte-encoded string.
1005:             * Two encodings, simple and altBase64 are used.
1006:             * <p>
1007:             * <i>Simple</i> encoding is used, if java string does not contain
1008:             * any characters less, than 0x0020, or greater, than 0x007f.
1009:             * Simple encoding adds "/" character to capital letters, i.e.
1010:             * "A" is encoded as "/A". Character '\' is encoded as '//', 
1011:             * '/' is encoded as '\'.
1012:             * The constructed string is converted to byte array by truncating the
1013:             * highest byte and adding the terminating <tt>null</tt> character.
1014:             * <p>
1015:             * <i>altBase64</i>  encoding is used, if java string does contain at least 
1016:             * one character less, than 0x0020, or greater, than 0x007f.
1017:             * This encoding is marked by setting first two bytes of the
1018:             * Windows string to '/!'. The java name is then encoded using 
1019:             * byteArrayToAltBase64() method from 
1020:             * Base64 class.
1021:             */
1022:            private static byte[] toWindowsName(String javaName) {
1023:                StringBuffer windowsName = new StringBuffer();
1024:                for (int i = 0; i < javaName.length(); i++) {
1025:                    char ch = javaName.charAt(i);
1026:                    if ((ch < 0x0020) || (ch > 0x007f)) {
1027:                        // If a non-trivial character encountered, use altBase64
1028:                        return toWindowsAlt64Name(javaName);
1029:                    }
1030:                    if (ch == '\\') {
1031:                        windowsName.append("//");
1032:                    } else if (ch == '/') {
1033:                        windowsName.append('\\');
1034:                    } else if ((ch >= 'A') && (ch <= 'Z')) {
1035:                        windowsName.append("/" + ch);
1036:                    } else {
1037:                        windowsName.append(ch);
1038:                    }
1039:                }
1040:                return stringToByteArray(windowsName.toString());
1041:            }
1042:
1043:            /**
1044:             * Converts value's or node's name to its Windows representation
1045:             * as a byte-encoded string, using altBase64 encoding. See
1046:             * {@link #toWindowsName(String) toWindowsName()} for a detailed 
1047:             * description of encoding conventions.
1048:             */
1049:            private static byte[] toWindowsAlt64Name(String javaName) {
1050:                byte[] javaNameArray = new byte[2 * javaName.length()];
1051:                // Convert to byte pairs
1052:                int counter = 0;
1053:                for (int i = 0; i < javaName.length(); i++) {
1054:                    int ch = javaName.charAt(i);
1055:                    javaNameArray[counter++] = (byte) (ch >>> 8);
1056:                    javaNameArray[counter++] = (byte) ch;
1057:                }
1058:
1059:                return stringToByteArray("/!"
1060:                        + Base64.byteArrayToAltBase64(javaNameArray));
1061:            }
1062:
1063:            /**
1064:             * Converts value string from its Windows representation
1065:             * to java string.  See
1066:             * {@link #toWindowsValueString(String) toWindowsValueString()} for the
1067:             * description of the encoding algorithm.
1068:             */
1069:            private static String toJavaValueString(byte[] windowsNameArray) {
1070:                // Use modified native2ascii algorithm
1071:                String windowsName = byteArrayToString(windowsNameArray);
1072:                StringBuffer javaName = new StringBuffer();
1073:                char ch;
1074:                for (int i = 0; i < windowsName.length(); i++) {
1075:                    if ((ch = windowsName.charAt(i)) == '/') {
1076:                        char next = ' ';
1077:
1078:                        if (windowsName.length() > i + 1
1079:                                && (next = windowsName.charAt(i + 1)) == 'u') {
1080:                            if (windowsName.length() < i + 6) {
1081:                                break;
1082:                            } else {
1083:                                ch = (char) Integer.parseInt(windowsName
1084:                                        .substring(i + 2, i + 6), 16);
1085:                                i += 5;
1086:                            }
1087:                        } else if ((windowsName.length() > i + 1)
1088:                                && ((windowsName.charAt(i + 1)) >= 'A')
1089:                                && (next <= 'Z')) {
1090:                            ch = next;
1091:                            i++;
1092:                        } else if ((windowsName.length() > i + 1)
1093:                                && (next == '/')) {
1094:                            ch = '\\';
1095:                            i++;
1096:                        }
1097:                    } else if (ch == '\\') {
1098:                        ch = '/';
1099:                    }
1100:                    javaName.append(ch);
1101:                }
1102:                return javaName.toString();
1103:            }
1104:
1105:            /**
1106:             * Converts value string to it Windows representation.
1107:             * as a byte-encoded string.
1108:             * Encoding algorithm adds "/" character to capital letters, i.e.
1109:             * "A" is encoded as "/A". Character '\' is encoded as '//', 
1110:             * '/' is encoded as  '\'.
1111:             * Then encoding scheme similar to jdk's native2ascii converter is used
1112:             * to convert java string to a byte array of ASCII characters.
1113:             */
1114:            private static byte[] toWindowsValueString(String javaName) {
1115:                StringBuffer windowsName = new StringBuffer();
1116:                for (int i = 0; i < javaName.length(); i++) {
1117:                    char ch = javaName.charAt(i);
1118:                    if ((ch < 0x0020) || (ch > 0x007f)) {
1119:                        // write \udddd
1120:                        windowsName.append("/u");
1121:                        String hex = Integer.toHexString(javaName.charAt(i));
1122:                        StringBuffer hex4 = new StringBuffer(hex);
1123:                        hex4.reverse();
1124:                        int len = 4 - hex4.length();
1125:                        for (int j = 0; j < len; j++) {
1126:                            hex4.append('0');
1127:                        }
1128:                        for (int j = 0; j < 4; j++) {
1129:                            windowsName.append(hex4.charAt(3 - j));
1130:                        }
1131:                    } else if (ch == '\\') {
1132:                        windowsName.append("//");
1133:                    } else if (ch == '/') {
1134:                        windowsName.append('\\');
1135:                    } else if ((ch >= 'A') && (ch <= 'Z')) {
1136:                        windowsName.append("/" + ch);
1137:                    } else {
1138:                        windowsName.append(ch);
1139:                    }
1140:                }
1141:                return stringToByteArray(windowsName.toString());
1142:            }
1143:
1144:            /**
1145:             * Returns native handle for the top Windows node for this node.
1146:             */
1147:            private int rootNativeHandle() {
1148:                return (isUserNode() ? USER_ROOT_NATIVE_HANDLE
1149:                        : SYSTEM_ROOT_NATIVE_HANDLE);
1150:            }
1151:
1152:            /**
1153:             * Returns this java string as a null-terminated byte array
1154:             */
1155:            private static byte[] stringToByteArray(String str) {
1156:                byte[] result = new byte[str.length() + 1];
1157:                for (int i = 0; i < str.length(); i++) {
1158:                    result[i] = (byte) str.charAt(i);
1159:                }
1160:                result[str.length()] = 0;
1161:                return result;
1162:            }
1163:
1164:            /** 
1165:             * Converts a null-terminated byte array to java string
1166:             */
1167:            private static String byteArrayToString(byte[] array) {
1168:                StringBuffer result = new StringBuffer();
1169:                for (int i = 0; i < array.length - 1; i++) {
1170:                    result.append((char) array[i]);
1171:                }
1172:                return result.toString();
1173:            }
1174:
1175:            /** 
1176:             * Empty, never used implementation  of AbstractPreferences.flushSpi(). 
1177:             */
1178:            protected void flushSpi() throws BackingStoreException {
1179:                // assert false;
1180:            }
1181:
1182:            /** 
1183:             * Empty, never used implementation  of AbstractPreferences.flushSpi(). 
1184:             */
1185:            protected void syncSpi() throws BackingStoreException {
1186:                // assert false;
1187:            }
1188:
1189:            private static synchronized Logger logger() {
1190:                if (logger == null) {
1191:                    logger = Logger.getLogger("java.util.prefs");
1192:                }
1193:                return logger;
1194:            }
1195:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.