001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Anton Avtamonov, Rustem Rafikov
020: * @version $Revision$
021: */package org.apache.harmony.x.swing.filechooser.windows;
022:
023: import java.io.File;
024: import java.util.LinkedList;
025: import java.util.List;
026:
027: import org.apache.harmony.awt.nativebridge.Int16Pointer;
028: import org.apache.harmony.awt.nativebridge.Int32Pointer;
029: import org.apache.harmony.awt.nativebridge.Int8Pointer;
030: import org.apache.harmony.awt.nativebridge.NativeBridge;
031: import org.apache.harmony.awt.nativebridge.PointerPointer;
032: import org.apache.harmony.awt.nativebridge.windows.Win32;
033: import org.apache.harmony.awt.nativebridge.windows.WindowsDefs;
034: import org.apache.harmony.awt.nativebridge.windows.WindowsConsts;
035: import org.apache.harmony.x.swing.filechooser.PlatformFile;
036: import org.apache.harmony.x.swing.filechooser.PlatformFileManager;
037:
038: import org.apache.harmony.x.swing.internal.nls.Messages;
039:
040: public class WinFileManager implements PlatformFileManager {
041:
042: private static WinFileManager instance;
043:
044: private static final Win32 win32 = Win32.getInstance();
045: private static final NativeBridge nb = NativeBridge.getInstance();
046:
047: // REFIID for IShellFolder interface, see ComDefs.h
048: public static final Win32.GUID SHELL_FOLDER_GUID = getGUID("{000214E6-0000-0000-C000-000000000046}");
049:
050: private final Win32.IShellFolder DESKTOP_SHELL_FOLDER = createDesktopShellFolder();
051: private final WinFile DESKTOP_FOLDER = getWinFile(getAbsoluteItemID(WindowsDefs.CSIDL_DESKTOP));
052:
053: public static WinFileManager getManager() {
054: return instance;
055: }
056:
057: public WinFileManager() {
058: if (instance != null) {
059: throw new RuntimeException(Messages.getString("swing.6C")); //$NON-NLS-1$
060: }
061: instance = this ;
062: }
063:
064: public File getDefaultFolder() {
065: return getMyDocumentsFolder();
066: }
067:
068: public File getHomeFolder() {
069: return getDesktopFolder();
070: }
071:
072: public PlatformFile getPlatformFile(final File file) {
073: if (file instanceof WinFile) {
074: return (WinFile) file;
075: }
076:
077: Win32.ITEMIDLIST absoluteItemId = getAbsoluteItemID(file
078: .getAbsolutePath());
079: if (absoluteItemId == null) {
080: return null;
081: }
082:
083: return getWinFile(absoluteItemId);
084: }
085:
086: public WinFile getDesktopFolder() {
087: return DESKTOP_FOLDER;
088: }
089:
090: public Win32.IShellFolder getDesktopShellFolder() {
091: return DESKTOP_SHELL_FOLDER;
092: }
093:
094: public WinFile getMyDocumentsFolder() {
095: return getWinFileForSystemFolder(WindowsDefs.CSIDL_PERSONAL);
096: }
097:
098: public WinFile[] getDrives() {
099: WinFile myComputer = getWinFileForSystemFolder(WindowsDefs.CSIDL_DRIVES);
100: if (myComputer != null) {
101: List drives = myComputer
102: .getContent(WindowsConsts.SHCONTF_STORAGE);
103: return (WinFile[]) drives
104: .toArray(new WinFile[drives.size()]);
105: }
106:
107: return new WinFile[0];
108: }
109:
110: Win32.ITEMIDLIST[] getShellContent(
111: final Win32.ITEMIDLIST absoluteParentItemId, final int flags) {
112: Win32.IShellFolder parentFolder = getShellFolder(absoluteParentItemId);
113: List result = new LinkedList();
114: PointerPointer enumIDListPtrPtr = nb.createPointerPointer(1,
115: false);
116: if (parentFolder.EnumObjects(0, flags, enumIDListPtrPtr) == WindowsDefs.NOERROR) {
117: Win32.IEnumIDList idList = win32
118: .createIEnumIDList(enumIDListPtrPtr.getAddress(0));
119:
120: PointerPointer itemListPtr = nb.createPointerPointer(1,
121: false);
122:
123: while (true) {
124: if (idList.Next(1, itemListPtr, null) == WindowsDefs.NOERROR) {
125: Win32.ITEMIDLIST itemId = win32
126: .createITEMIDLIST(itemListPtr.getAddress(0));
127: result.add(ItemIdProcessor.getAbsoluteItemID(
128: absoluteParentItemId, itemId));
129: } else {
130: break;
131: }
132: }
133: idList.Release();
134: }
135: release(parentFolder);
136:
137: return (Win32.ITEMIDLIST[]) result
138: .toArray(new Win32.ITEMIDLIST[result.size()]);
139: }
140:
141: WinFile getWinFile(final Win32.ITEMIDLIST absoluteItemId) {
142: Object[] parentInfo = getParentShellInfo(absoluteItemId);
143: Win32.IShellFolder parentFolder = (Win32.IShellFolder) parentInfo[0];
144: String path = getPath(parentFolder,
145: (Win32.ITEMIDLIST) parentInfo[1]);
146: release(parentFolder);
147:
148: return new WinFile(path, absoluteItemId);
149: }
150:
151: String getChildFolderDisplayName(final Win32.IShellFolder parent,
152: final Win32.ITEMIDLIST itemId, final int flags) {
153: int bufLen = 2048;
154:
155: Win32.STRRET strret = win32.createSTRRET(false);
156:
157: if (parent.GetDisplayNameOf(itemId, flags, strret) != WindowsDefs.NOERROR) {
158: return null;
159: }
160:
161: Int16Pointer bufPtr = nb.createInt16Pointer(bufLen, false);
162: win32.StrRetToBufW(strret, null, bufPtr, bufLen);
163: return bufPtr.getString();
164: }
165:
166: void release(final Win32.IShellFolder folder) {
167: if (folder == null) {
168: return;
169: }
170: folder.Release();
171: }
172:
173: int getAttribute(final Win32.IShellFolder parent,
174: final Win32.ITEMIDLIST itemId, final int flags) {
175: PointerPointer itemIdPtrPtr = nb.createPointerPointer(1, false);
176: itemIdPtrPtr.set(0, itemId);
177:
178: Int32Pointer resultPtr = nb.createInt32Pointer(1, false);
179: resultPtr.set(0, flags);
180: if (parent.GetAttributesOf(1, itemIdPtrPtr, resultPtr) != WindowsDefs.NOERROR) {
181: return -1;
182: }
183: return resultPtr.get(0);
184: }
185:
186: Win32.SHFILEINFOW getFileInfo(final Win32.ITEMIDLIST itemId,
187: final int flags) {
188: Win32.SHFILEINFOW fileInfo = win32.createSHFILEINFOW(false);
189:
190: Win32.SHFILEINFOW result = null;
191: if (win32.SHGetFileInfoW(nb.createInt16Pointer(itemId), 0,
192: fileInfo, fileInfo.size(), WindowsDefs.SHGFI_PIDL
193: | flags) != 0) {
194: result = fileInfo;
195: }
196: return result;
197: }
198:
199: int getDescription(final Win32.IShellFolder parent,
200: final Win32.ITEMIDLIST itemId) {
201: Win32.SHDESCRIPTIONID res = win32.createSHDESCRIPTIONID(false);
202:
203: if (win32.SHGetDataFromIDListW(parent, itemId,
204: WindowsDefs.SHGDFIL_DESCRIPTIONID, res, res.size()) == WindowsDefs.NOERROR) {
205: return res.get_dwDescriptionId();
206: }
207: return 0;
208: }
209:
210: Win32.ITEMIDLIST getParentItemId(
211: final Win32.ITEMIDLIST absoluteItemId) {
212: return ItemIdProcessor.getAbsoluteParentItemID(absoluteItemId);
213: }
214:
215: Object[] getParentShellInfo(final Win32.ITEMIDLIST absoluteItemId) {
216:
217: PointerPointer relativeItemIdPrtPrt = nb.createPointerPointer(
218: 1, false);
219: PointerPointer shellFolderPtrPtr = nb.createPointerPointer(1,
220: false);
221: if (win32.SHBindToParent(absoluteItemId,
222: WinFileManager.SHELL_FOLDER_GUID, shellFolderPtrPtr,
223: relativeItemIdPrtPrt) != WindowsDefs.NOERROR) {
224: return new Object[2];
225: }
226: Win32.IShellFolder parentFolder = win32
227: .createIShellFolder(shellFolderPtrPtr.getAddress(0));
228: Win32.ITEMIDLIST relativeItemId = win32
229: .createITEMIDLIST(relativeItemIdPrtPrt.getAddress(0));
230: return new Object[] { parentFolder, relativeItemId };
231: }
232:
233: private String getPath(final Win32.IShellFolder parent,
234: final Win32.ITEMIDLIST itemId) {
235: return getChildFolderDisplayName(parent, itemId,
236: WindowsConsts.SHGDN_FORPARSING);
237: }
238:
239: private static Win32.GUID getGUID(final String name) {
240: Int16Pointer namePrt = nb.createInt16Pointer(name, false);
241: Win32.GUID result = win32.createGUID(false);
242: if (win32.CLSIDFromString(namePrt, result) != WindowsDefs.NOERROR) {
243: return null;
244: }
245: return result;
246: }
247:
248: private Win32.IShellFolder getShellFolder(
249: final Win32.ITEMIDLIST absoluteItemId) {
250: if (ItemIdProcessor.isRoot(absoluteItemId)) {
251: return getDesktopShellFolder();
252: }
253:
254: Object[] parentInfo = getParentShellInfo(absoluteItemId);
255: Win32.IShellFolder parentFolder = (Win32.IShellFolder) parentInfo[0];
256: Win32.IShellFolder result = getShellFolder(parentFolder,
257: (Win32.ITEMIDLIST) parentInfo[1]);
258: release(parentFolder);
259:
260: return result;
261: }
262:
263: private Win32.IShellFolder getShellFolder(
264: final Win32.IShellFolder parent,
265: final Win32.ITEMIDLIST itemId) {
266: if (parent == null) {
267: return null;
268: }
269:
270: PointerPointer childPtrPtr = nb.createPointerPointer(1, false);
271: if (parent.BindToObject(itemId, null,
272: WinFileManager.SHELL_FOLDER_GUID, childPtrPtr) != WindowsDefs.NOERROR) {
273: return null;
274: }
275: return win32.createIShellFolder(childPtrPtr.getAddress(0));
276: }
277:
278: private WinFile getWinFileForSystemFolder(final int folderID) {
279: Win32.ITEMIDLIST itemId = getAbsoluteItemID(folderID);
280: if (itemId != null) {
281: return getWinFile(itemId);
282: }
283: return null;
284: }
285:
286: private Win32.IShellFolder createDesktopShellFolder() {
287: PointerPointer shellDesktopPtrPtr = nb.createPointerPointer(1,
288: false);
289: if (win32.SHGetDesktopFolder(shellDesktopPtrPtr) != WindowsDefs.NOERROR) {
290: return null;
291: }
292: return win32.createIShellFolder(shellDesktopPtrPtr
293: .getAddress(0));
294: }
295:
296: private Win32.ITEMIDLIST getAbsoluteItemID(final int folderId) {
297: PointerPointer itemIdPtrPtr = nb.createPointerPointer(1, false);
298: if (win32.SHGetFolderLocation(0, folderId, null, 0,
299: itemIdPtrPtr) != WindowsDefs.NOERROR) {
300: return null;
301: }
302: return win32.createITEMIDLIST(itemIdPtrPtr.getAddress(0));
303: }
304:
305: private Win32.ITEMIDLIST getAbsoluteItemID(final String path) {
306: Win32.IShellFolder desktop = getDesktopShellFolder();
307:
308: Int16Pointer displayNamePtr = nb
309: .createInt16Pointer(path, false);
310: PointerPointer itemIdPtrPtr = nb.createPointerPointer(1, false);
311: if (desktop.ParseDisplayName(0, null, displayNamePtr, null,
312: itemIdPtrPtr, null) != WindowsDefs.NOERROR) {
313: return null;
314: }
315: return win32.createITEMIDLIST(itemIdPtrPtr.getAddress(0));
316: }
317:
318: private static class ItemIdProcessor {
319: public static Win32.ITEMIDLIST getAbsoluteItemID(
320: final Win32.ITEMIDLIST parentAbsoluteItemId,
321: final Win32.ITEMIDLIST itemId) {
322: final int parentSize = getItemIDListSize(parentAbsoluteItemId) - 2;
323: if (parentSize <= 0) {
324: return itemId;
325: }
326: final int childSize = getItemIDListSize(itemId);
327: Int8Pointer resPtr = nb.createInt8Pointer(parentSize
328: + childSize, true); //!!! should be in native mem
329:
330: resPtr.copy(parentAbsoluteItemId, 0, parentSize);
331: resPtr.copy(itemId, parentSize, childSize);
332:
333: return win32.createITEMIDLIST(resPtr);
334: }
335:
336: public static Win32.ITEMIDLIST getAbsoluteParentItemID(
337: final Win32.ITEMIDLIST absoluteItemId) {
338: Win32.ITEMIDLIST lastItemId = getLastItemIDList(absoluteItemId);
339: if (lastItemId == null) {
340: return null;
341: }
342:
343: final int parentSize = (int) (lastItemId.shortLockPointer() - absoluteItemId
344: .shortLockPointer());
345: lastItemId.unlock();
346: absoluteItemId.unlock();
347:
348: Int8Pointer resPtr = nb.createInt8Pointer(parentSize + 2,
349: true); // !!! should be in native mem
350: resPtr.copy(absoluteItemId, 0, parentSize);
351: resPtr
352: .copy(
353: lastItemId
354: .getElementPointer(getItemIDListSize(lastItemId) - 2),
355: parentSize, 2);
356: return win32.createITEMIDLIST(resPtr);
357: }
358:
359: public static boolean isRoot(final Win32.ITEMIDLIST itemId) {
360: return getFirstItemSize(itemId) == 0;
361: }
362:
363: private static int getFirstItemSize(
364: final Win32.ITEMIDLIST itemId) {
365: return itemId.get_mkid().get_cb();
366: }
367:
368: private static Win32.ITEMIDLIST getNextItemID(
369: final Win32.ITEMIDLIST itemId) {
370: if (itemId == null) {
371: return null;
372: }
373: final int size = getFirstItemSize(itemId);
374: if (size == 0) {
375: return null;
376: }
377:
378: Win32.ITEMIDLIST result = win32.createITEMIDLIST(itemId
379: .getElementPointer(size));
380:
381: final int nextSize = getFirstItemSize(result);
382: if (nextSize == 0) {
383: return null;
384: }
385: return result;
386: }
387:
388: private static int getItemIDListSize(
389: final Win32.ITEMIDLIST itemId) {
390: int size = getFirstItemSize(itemId);
391: if (size == 0) {
392: return 0;
393: }
394:
395: Win32.ITEMIDLIST child = getNextItemID(itemId);
396: while (child != null) {
397: size += getFirstItemSize(child);
398: child = getNextItemID(child);
399: }
400: return size + 2;
401: }
402:
403: private static Win32.ITEMIDLIST getLastItemIDList(
404: final Win32.ITEMIDLIST itemId) {
405: if (getFirstItemSize(itemId) == 0) {
406: return null;
407: }
408:
409: Win32.ITEMIDLIST prevChild = itemId;
410: Win32.ITEMIDLIST child = getNextItemID(prevChild);
411: while (child != null) {
412: prevChild = child;
413: child = getNextItemID(child);
414: }
415:
416: return prevChild;
417: }
418: }
419: }
|