1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
/*******************************************************************************
* Copyright (c) 2005, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.baseadaptor.bundlefile;
import java.io.File;
import java.io.IOException;
import java.util.*;
import org.eclipse.osgi.internal.baseadaptor.AdaptorMsg;
import org.eclipse.osgi.internal.baseadaptor.ListEntryPathsThreadLocal;
import org.eclipse.osgi.util.NLS;
/**
* A BundleFile that uses a directory as its base file.
* @since 3.2
*/
public class DirBundleFile extends BundleFile {
private static final String POINTER_SAME_DIRECTORY_1 = "/.";//$NON-NLS-1$
private static final String POINTER_SAME_DIRECTORY_2 = "//";//$NON-NLS-1$
private static final String POINTER_UPPER_DIRECTORY = "..";//$NON-NLS-1$
private final boolean enableStrictBundleEntryPath;
/**
* Constructs a DirBundleFile
* @param basefile the base file
* @throws IOException
*/
public DirBundleFile(File basefile, boolean enableStrictBundleEntryPath) throws IOException {
super(getBaseFile(basefile, enableStrictBundleEntryPath));
if (!BundleFile.secureAction.exists(basefile) || !BundleFile.secureAction.isDirectory(basefile)) {
throw new IOException(NLS.bind(AdaptorMsg.ADAPTOR_DIRECTORY_EXCEPTION, basefile));
}
this.enableStrictBundleEntryPath = enableStrictBundleEntryPath;
}
private static File getBaseFile(File basefile, boolean enableStrictBundleEntryPath) throws IOException {
return enableStrictBundleEntryPath ? secureAction.getCanonicalFile(basefile) : basefile;
}
public File getFile(String path, boolean nativeCode) {
final boolean checkInBundle = path != null && path.indexOf(POINTER_UPPER_DIRECTORY) >= 0;
File file = new File(this.basefile, path);
if (!BundleFile.secureAction.exists(file)) {
return null;
}
if (!enableStrictBundleEntryPath) {
// must do an extra check to make sure file is within the bundle (bug 320546)
if (checkInBundle) {
try {
if (!BundleFile.secureAction.getCanonicalPath(file).startsWith(BundleFile.secureAction.getCanonicalPath(basefile)))
return null;
} catch (IOException e) {
return null;
}
}
return file;
}
boolean normalize = false;
boolean isBundleRoot = false;
if (path != null) {
isBundleRoot = path.equals("/");//$NON-NLS-1$
if (!isBundleRoot) {
normalize = checkInBundle || path.indexOf(POINTER_SAME_DIRECTORY_1) >= 0 || path.indexOf(POINTER_SAME_DIRECTORY_2) >= 0;
}
}
File canonicalFile;
try {
canonicalFile = BundleFile.secureAction.getCanonicalFile(file);
if (!isBundleRoot) {
File absoluteFile = BundleFile.secureAction.getAbsoluteFile(file);
String canonicalPath;
String absolutePath;
if (normalize) {
canonicalPath = canonicalFile.toURI().getPath();
absolutePath = absoluteFile.toURI().normalize().getPath();
} else {
canonicalPath = canonicalFile.getPath();
absolutePath = absoluteFile.getPath();
}
if (!canonicalPath.equals(absolutePath)) {
return null;
}
}
// must do an extra check to make sure file is within the bundle (bug 320546)
if (checkInBundle) {
if (!canonicalFile.getPath().startsWith(basefile.getPath()))
return null;
}
} catch (IOException e) {
return null;
}
return file;
}
public BundleEntry getEntry(String path) {
File filePath = getFile(path, false);
if (filePath == null)
return null;
return new FileBundleEntry(filePath, path);
}
public boolean containsDir(String dir) {
File dirPath = getFile(dir, false);
return dirPath != null && BundleFile.secureAction.isDirectory(dirPath);
}
public Enumeration<String> getEntryPaths(String path) {
// Get entry paths. Recurse or not based on caller's thread local
// request.
Enumeration<String> result = getEntryPaths(path, ListEntryPathsThreadLocal.isRecursive());
// Always set the thread local back to its default value. If the caller
// requested recursion, this will indicate that recursion was done.
// Otherwise, no harm is done.
ListEntryPathsThreadLocal.setRecursive(false);
return result;
}
// Optimized method allowing this directory bundle file to recursively
// return entry paths when requested.
public Enumeration<String> getEntryPaths(String path, boolean recurse) {
if (path.length() > 0 && path.charAt(0) == '/')
path = path.substring(1);
File pathFile = getFile(path, false);
if (pathFile == null || !BundleFile.secureAction.isDirectory(pathFile))
return null;
String[] fileList = BundleFile.secureAction.list(pathFile);
if (fileList == null || fileList.length == 0)
return null;
String dirPath = path.length() == 0 || path.charAt(path.length() - 1) == '/' ? path : path + '/';
LinkedHashSet<String> entries = new LinkedHashSet<String>();
for (String s : fileList) {
java.io.File childFile = new java.io.File(pathFile, s);
StringBuilder sb = new StringBuilder(dirPath).append(s);
if (BundleFile.secureAction.isDirectory(childFile)) {
sb.append("/"); //$NON-NLS-1$
if (recurse) {
Enumeration<String> e = getEntryPaths(sb.toString(), true);
if (e != null)
entries.addAll(Collections.list(e));
}
}
entries.add(sb.toString());
}
return Collections.enumeration(entries);
}
public void close() {
// nothing to do.
}
public void open() {
// nothing to do.
}
}
|