diff options
author | Thomas Watson | 2016-10-24 20:00:55 +0000 |
---|---|---|
committer | Thomas Watson | 2016-11-07 20:19:26 +0000 |
commit | e71e4cbe7f8f7d813d890e522979a490d8f295ab (patch) | |
tree | e86ab2f1e71292b033ed687c3090ef4f73e97902 | |
parent | cc11dbcc759c5d04377bdb1a3b1c1ffe005f01ac (diff) | |
download | rt.equinox.framework-e71e4cbe7f8f7d813d890e522979a490d8f295ab.tar.gz rt.equinox.framework-e71e4cbe7f8f7d813d890e522979a490d8f295ab.tar.xz rt.equinox.framework-e71e4cbe7f8f7d813d890e522979a490d8f295ab.zip |
Bug 507178 - Issues with encoding/decoding file URLs in variousY20161110-1000I20161111-1220I20161111-0900I20161111-0740I20161111-0510I20161110-2030I20161110-1630I20161110-1225I20161110-1130I20161110-0710I20161110-0510I20161109-2000I20161108-1015I20161108-0800
scenarios
Change-Id: I2cf6b79d055eef7fb180f3f0f75032cbb84b7d51
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
13 files changed, 258 insertions, 112 deletions
diff --git a/bundles/org.eclipse.equinox.launcher/src/org/eclipse/equinox/launcher/Main.java b/bundles/org.eclipse.equinox.launcher/src/org/eclipse/equinox/launcher/Main.java index 34bcf44d3..bbec0b646 100644 --- a/bundles/org.eclipse.equinox.launcher/src/org/eclipse/equinox/launcher/Main.java +++ b/bundles/org.eclipse.equinox.launcher/src/org/eclipse/equinox/launcher/Main.java @@ -2137,7 +2137,7 @@ public class Main { Properties props = new Properties(); InputStream is = null; try { - is = url.openStream(); + is = getStream(url); props.load(is); } finally { if (is != null) @@ -2150,6 +2150,17 @@ public class Main { return props; } + private InputStream getStream(URL location) throws IOException { + if ("file".equalsIgnoreCase(location.getProtocol())) { //$NON-NLS-1$ + // this is done to handle URLs with invalid syntax in the path + File f = new File(location.getPath()); + if (f.exists()) { + return new FileInputStream(f); + } + } + return location.openStream(); + } + /* * Handle splash screen. * The splash screen is displayed natively. Whether or not the splash screen diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleInstallUpdateTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleInstallUpdateTests.java index 92048c5b4..029f856a6 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleInstallUpdateTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleInstallUpdateTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2015 IBM Corporation and others. + * Copyright (c) 2009, 2016 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 @@ -11,9 +11,8 @@ package org.eclipse.osgi.tests.bundles; import java.io.*; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Collection; +import java.net.*; +import java.util.*; import junit.framework.Test; import junit.framework.TestSuite; import org.eclipse.osgi.tests.OSGiTestsActivator; @@ -290,4 +289,82 @@ public class BundleInstallUpdateTests extends AbstractBundleTests { } } } + + public void testPercentLocation() throws BundleException, IOException { + doTestSpecialChars('%', false); + doTestSpecialChars('%', true); + } + + public void testSpaceLocation() throws BundleException, IOException { + doTestSpecialChars(' ', false); + doTestSpecialChars(' ', true); + } + + private void doTestSpecialChars(char c, boolean encode) throws BundleException, IOException { + File bundlesDirectory = OSGiTestsActivator.getContext().getDataFile("file_with_" + c + "_char"); + bundlesDirectory.mkdirs(); + + File testBundleJarFile = SystemBundleTests.createBundle(bundlesDirectory, getName() + 1, false, false); + @SuppressWarnings("deprecation") + String testBundleJarFileURL = encode ? testBundleJarFile.toURI().toString() : testBundleJarFile.toURL().toString(); + File testBundleDirFile = SystemBundleTests.createBundle(bundlesDirectory, getName() + 2, false, true); + @SuppressWarnings("deprecation") + String testBundleDirFileURL = encode ? testBundleDirFile.toURI().toString() : testBundleDirFile.toURL().toString(); + + // Test with reference URL to jar bundle + Bundle testBundleJarRef = getContext().installBundle("reference:" + testBundleJarFileURL); + testBundleJarRef.start(); + testBundleJarRef.uninstall(); + + // Test with reference URL to dir bundle + Bundle testBundleDirRef = getContext().installBundle("reference:" + testBundleDirFileURL); + testBundleDirRef.start(); + testBundleDirRef.uninstall(); + + // Test with jar bundle + Bundle testBundleJar = getContext().installBundle(testBundleJarFileURL); + testBundleJar.start(); + testBundleJar.uninstall(); + + // Test with dir bundle + Bundle testBundleDir = getContext().installBundle(testBundleDirFileURL); + testBundleDir.start(); + testBundleDir.uninstall(); + } + + public void testPercentCharBundleEntry() throws IOException, BundleException { + doTestSpaceCharsBundleEntry('%'); + } + + public void testSpaceCharBundleEntry() throws IOException, BundleException { + doTestSpaceCharsBundleEntry(' '); + } + + public void testPlusCharBundleEntry() throws IOException, BundleException { + doTestSpaceCharsBundleEntry('+'); + } + + public void doTestSpaceCharsBundleEntry(char c) throws IOException, BundleException { + String entryName = "file_with_" + c + "_char"; + File bundlesDirectory = OSGiTestsActivator.getContext().getDataFile(getName()); + bundlesDirectory.mkdirs(); + Map<String, String> headers = new HashMap<String, String>(); + headers.put(Constants.BUNDLE_MANIFESTVERSION, "2"); + headers.put(Constants.BUNDLE_SYMBOLICNAME, getName()); + Map<String, String> entry = Collections.singletonMap(entryName, "value"); + + File testBundleJarFile = SystemBundleTests.createBundle(bundlesDirectory, getName(), headers, entry); + Bundle testBundle = getContext().installBundle(getName(), new FileInputStream(testBundleJarFile)); + URL entryURL = testBundle.getEntry(entryName); + assertNotNull("Entry not found.", entryURL); + InputStream is = entryURL.openStream(); + is.close(); + + String encodeEntry = URLEncoder.encode(entryName, "UTF-8"); + String urlString = entryURL.toExternalForm(); + urlString = urlString.substring(0, urlString.indexOf(entryName)) + encodeEntry; + URL encodedURL = new URL(urlString); + is = encodedURL.openStream(); + is.close(); + } } diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java index 7ff00b52f..89d0aa376 100755 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java @@ -2737,7 +2737,7 @@ public class SystemBundleTests extends AbstractBundleTests { return bundles; } - private static File createBundle(File outputDir, String id, boolean emptyManifest, boolean dirBundle) throws IOException { + static File createBundle(File outputDir, String id, boolean emptyManifest, boolean dirBundle) throws IOException { File file = new File(outputDir, "bundle" + id + (dirBundle ? "" : ".jar")); //$NON-NLS-1$ //$NON-NLS-2$ if (!dirBundle) { JarOutputStream jos = new JarOutputStream(new FileOutputStream(file), createManifest(id, emptyManifest)); @@ -2987,6 +2987,45 @@ public class SystemBundleTests extends AbstractBundleTests { equinox.stop(); } + public void testConfigPercentChar() throws BundleException, IOException { + doTestConfigSpecialChar('%'); + } + + public void testConfigSpaceChar() throws BundleException, IOException { + doTestConfigSpecialChar(' '); + } + + public void testConfigPlusChar() throws BundleException, IOException { + doTestConfigSpecialChar('+'); + } + + private void doTestConfigSpecialChar(char c) throws BundleException, IOException { + File config = OSGiTestsActivator.getContext().getDataFile(getName() + c + "config"); + config.mkdirs(); + // create a config.ini with some system property substitutes + Properties configIni = new Properties(); + configIni.setProperty("test.config", getName()); + configIni.store(new FileOutputStream(new File(config, "config.ini")), "Test config.ini"); + + Map<String, Object> configuration = new HashMap<String, Object>(); + configuration.put(Constants.FRAMEWORK_STORAGE, config.getAbsolutePath()); + Equinox equinox = new Equinox(configuration); + equinox.init(); + + BundleContext systemContext = equinox.getBundleContext(); + // check for substitution + assertEquals("Wrong value for test.config", getName(), systemContext.getProperty("test.config")); + + equinox.stop(); + try { + equinox.waitForStop(5000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + fail("Unexpected interruption.", e); + } + + } + void checkActiveThreadType(Equinox equinox, boolean expectIsDeamon) { String uuid = equinox.getBundleContext().getProperty(Constants.FRAMEWORK_UUID); ThreadGroup topGroup = Thread.currentThread().getThreadGroup(); diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java index 60b24eb3c..068bf39fc 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java @@ -517,7 +517,7 @@ public class EclipseStarter { // if it is a reference URL then strip off the reference: and set base to the file:... if (url.getProtocol().equals(REFERENCE_PROTOCOL)) { reference = true; - String baseSpec = url.getFile(); + String baseSpec = url.getPath(); if (baseSpec.startsWith(FILE_SCHEME)) { File child = new File(baseSpec.substring(5)); baseURL = child.isAbsolute() ? child.toURL() : new File(parent, child.getPath()).toURL(); @@ -525,7 +525,7 @@ public class EclipseStarter { baseURL = createURL(baseSpec); } - fileLocation = new File(baseURL.getFile()); + fileLocation = new File(baseURL.getPath()); // if the location is relative, prefix it with the parent if (!fileLocation.isAbsolute()) fileLocation = new File(parent, fileLocation.toString()); @@ -542,7 +542,7 @@ public class EclipseStarter { // finally we have something worth trying try { - URLConnection result = url.openConnection(); + URLConnection result = LocationHelper.getConnection(url); result.connect(); return url; } catch (IOException e) { @@ -886,7 +886,7 @@ public class EclipseStarter { URL url = LocationHelper.buildURL(urlSpec, false); if (url == null) return null; - File fwkFile = new File(url.getFile()); + File fwkFile = LocationHelper.decodePath(new File(url.getPath())); fwkFile = new File(fwkFile.getAbsolutePath()); fwkFile = new File(fwkFile.getParent()); return fwkFile.getAbsolutePath(); @@ -902,7 +902,7 @@ public class EclipseStarter { URL url = cs.getLocation(); if (url == null) return null; - String result = url.getFile(); + String result = url.getPath(); if (File.separatorChar == '\\') { // in case on windows the \ is used result = result.replace('\\', '/'); @@ -969,7 +969,7 @@ public class EclipseStarter { try { // don't need to install if it is already installed if (osgiBundle == null) { - InputStream in = initialBundles[i].location.openStream(); + InputStream in = LocationHelper.getStream(initialBundles[i].location); try { osgiBundle = context.installBundle(initialBundles[i].locationString, in); } catch (BundleException e) { @@ -1202,14 +1202,7 @@ public class EclipseStarter { String[] candidates = searchCandidates.get(start); if (candidates == null) { File startFile = new File(start); - // Pre-check if file exists, if not, and it contains escape characters, - // try decoding the path - if (!startFile.exists() && start.indexOf('%') >= 0) { - String decodePath = EquinoxConfiguration.decode(start); - File f = new File(decodePath); - if (f.exists()) - startFile = f; - } + startFile = LocationHelper.decodePath(startFile); candidates = startFile.list(); if (candidates != null) searchCandidates.put(start, candidates); diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/debug/FrameworkDebugOptions.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/debug/FrameworkDebugOptions.java index e1f347be1..c81dcb666 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/debug/FrameworkDebugOptions.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/debug/FrameworkDebugOptions.java @@ -11,10 +11,10 @@ package org.eclipse.osgi.internal.debug; import java.io.*; -import java.net.MalformedURLException; import java.net.URL; import java.util.*; import org.eclipse.osgi.internal.framework.EquinoxConfiguration; +import org.eclipse.osgi.internal.location.LocationHelper; import org.eclipse.osgi.service.debug.*; import org.osgi.framework.*; import org.osgi.util.tracker.ServiceTracker; @@ -76,14 +76,14 @@ public class FrameworkDebugOptions implements DebugOptions, ServiceTrackerCustom userDir += "/"; //$NON-NLS-1$ debugOptionsFilename = new File(userDir, OPTIONS).toString(); } - optionsFile = buildURL(debugOptionsFilename, false); + optionsFile = LocationHelper.buildURL(debugOptionsFilename, false); if (optionsFile == null) { System.out.println("Unable to construct URL for options file: " + debugOptionsFilename); //$NON-NLS-1$ return; } System.out.print("Debug options:\n " + optionsFile.toExternalForm()); //$NON-NLS-1$ try { - InputStream input = optionsFile.openStream(); + InputStream input = LocationHelper.getStream(optionsFile); try { options.load(input); System.out.println(" loaded"); //$NON-NLS-1$ @@ -114,36 +114,6 @@ public class FrameworkDebugOptions implements DebugOptions, ServiceTrackerCustom this.context = null; } - @SuppressWarnings("deprecation") - private static URL buildURL(String spec, boolean trailingSlash) { - if (spec == null) - return null; - boolean isFile = spec.startsWith("file:"); //$NON-NLS-1$ - try { - if (isFile) - return adjustTrailingSlash(new File(spec.substring(5)).toURL(), trailingSlash); - return new URL(spec); - } catch (MalformedURLException e) { - // if we failed and it is a file spec, there is nothing more we can do - // otherwise, try to make the spec into a file URL. - if (isFile) - return null; - try { - return adjustTrailingSlash(new File(spec).toURL(), trailingSlash); - } catch (MalformedURLException e1) { - return null; - } - } - } - - private static URL adjustTrailingSlash(URL url, boolean trailingSlash) throws MalformedURLException { - String file = url.getFile(); - if (trailingSlash == (file.endsWith("/"))) //$NON-NLS-1$ - return url; - file = trailingSlash ? file + "/" : file.substring(0, file.length() - 1); //$NON-NLS-1$ - return new URL(url.getProtocol(), url.getHost(), file); - } - /** * @see DebugOptions#getBooleanOption(String, boolean) */ diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java index 54327d43c..7283c00c5 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java @@ -34,6 +34,7 @@ import org.eclipse.osgi.internal.debug.Debug; import org.eclipse.osgi.internal.debug.FrameworkDebugOptions; import org.eclipse.osgi.internal.hookregistry.HookRegistry; import org.eclipse.osgi.internal.location.EquinoxLocations; +import org.eclipse.osgi.internal.location.LocationHelper; import org.eclipse.osgi.internal.messages.Msg; import org.eclipse.osgi.service.datalocation.Location; import org.eclipse.osgi.service.debug.DebugOptions; @@ -322,7 +323,7 @@ public class EquinoxConfiguration implements EnvironmentInfo { if (location == null) return result; try { - InputStream in = location.openStream(); + InputStream in = LocationHelper.getStream(location); try { result.load(in); } finally { @@ -525,13 +526,13 @@ public class EquinoxConfiguration implements EnvironmentInfo { URL location = new URL(osgiDev); if ("file".equals(location.getProtocol())) { //$NON-NLS-1$ - f = new File(location.getFile()); + f = LocationHelper.decodePath(new File(location.getPath())); devLastModified = f.lastModified(); } // Check the osgi.dev property to see if dev classpath entries have been defined. try { - loadDevProperties(location.openStream()); + loadDevProperties(LocationHelper.getStream(location)); devMode = true; } catch (IOException e) { // TODO consider logging @@ -903,13 +904,13 @@ public class EquinoxConfiguration implements EnvironmentInfo { setConfiguration(PROP_FRAMEWORK, externalForm); } if (getConfiguration(EquinoxLocations.PROP_INSTALL_AREA) == null) { - String filePart = getFrameworkPath(url.getFile(), true); + String filePart = getFrameworkPath(url.getPath(), true); setConfiguration(EquinoxLocations.PROP_INSTALL_AREA, filePart); } } // always decode these properties - setConfiguration(PROP_FRAMEWORK, decode(getConfiguration(PROP_FRAMEWORK))); - setConfiguration(EquinoxLocations.PROP_INSTALL_AREA, decode(getConfiguration(EquinoxLocations.PROP_INSTALL_AREA))); + setConfiguration(PROP_FRAMEWORK, LocationHelper.decode(getConfiguration(PROP_FRAMEWORK), true)); + setConfiguration(EquinoxLocations.PROP_INSTALL_AREA, LocationHelper.decode(getConfiguration(EquinoxLocations.PROP_INSTALL_AREA), true)); setConfiguration(FRAMEWORK_VENDOR, ECLIPSE_FRAMEWORK_VENDOR); String value = getConfiguration(FRAMEWORK_PROCESSOR); @@ -1072,30 +1073,6 @@ public class EquinoxConfiguration implements EnvironmentInfo { } } - public static String decode(String urlString) { - //first encode '+' characters, because URLDecoder incorrectly converts - //them to spaces on certain class library implementations. - if (urlString.indexOf('+') >= 0) { - int len = urlString.length(); - StringBuffer buf = new StringBuffer(len); - for (int i = 0; i < len; i++) { - char c = urlString.charAt(i); - if (c == '+') - buf.append("%2B"); //$NON-NLS-1$ - else - buf.append(c); - } - urlString = buf.toString(); - } - try { - return URLDecoder.decode(urlString, "UTF-8"); //$NON-NLS-1$ - } catch (UnsupportedEncodingException e) { - // Tried but failed - // TODO should we throw runtime exception here? - return urlString; - } - } - public String substituteVars(String path) { return substituteVars(path, false); } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/BasicLocation.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/BasicLocation.java index d8519ac87..bd56fa4a2 100755 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/BasicLocation.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/BasicLocation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2015 IBM Corporation and others. + * Copyright (c) 2004, 2016 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 @@ -114,7 +114,8 @@ public class BasicLocation implements Location { File file = null; if (value.getProtocol().equalsIgnoreCase("file")) { //$NON-NLS-1$ try { - String basePath = new File(value.getFile()).getCanonicalPath(); + File f = LocationHelper.decodePath(new File(value.getPath())); + String basePath = f.getCanonicalPath(); value = LocationHelper.buildURL("file:" + basePath, true); //$NON-NLS-1$ } catch (IOException e) { // do nothing just use the original value @@ -124,10 +125,10 @@ public class BasicLocation implements Location { if (givenLockFile.isAbsolute()) { file = givenLockFile; } else { - file = new File(value.getFile(), lockFilePath); + file = new File(value.getPath(), lockFilePath); } } else { - file = new File(value.getFile(), DEFAULT_LOCK_FILENAME); + file = new File(value.getPath(), DEFAULT_LOCK_FILENAME); } } lock = lock && !isReadOnly; diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java index e5cf6db99..8d623a74a 100755 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2015 IBM Corporation and others. + * Copyright (c) 2004, 2016 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 @@ -251,7 +251,7 @@ public class EquinoxLocations { URL installURL = computeInstallConfigurationLocation(); if (installURL != null && "file".equals(installURL.getProtocol())) { //$NON-NLS-1$ - File installDir = new File(installURL.getFile()); + File installDir = new File(installURL.getPath()); File defaultConfigDir = new File(installDir, CONFIG_DIR); if (!defaultConfigDir.exists()) defaultConfigDir.mkdirs(); @@ -264,7 +264,7 @@ public class EquinoxLocations { private static boolean canWrite(URL location) { if (location != null && "file".equals(location.getProtocol())) { //$NON-NLS-1$ - File locationDir = new File(location.getFile()); + File locationDir = new File(location.getPath()); if (!locationDir.exists()) locationDir.mkdirs(); if (locationDir.exists() && StorageUtil.canWrite(locationDir)) @@ -282,7 +282,7 @@ public class EquinoxLocations { URL installURL = buildURL(installProperty, true); if (installURL == null) return null; - File installDir = new File(installURL.getFile()); + File installDir = new File(installURL.getPath()); String installDirHash = getInstallDirHash(); String appName = "." + ECLIPSE; //$NON-NLS-1$ @@ -322,7 +322,7 @@ public class EquinoxLocations { URL installURL = buildURL(installProperty, true); if (installURL == null) return ""; //$NON-NLS-1$ - File installDir = new File(installURL.getFile()); + File installDir = new File(installURL.getPath()); int hashCode; try { hashCode = installDir.getCanonicalPath().hashCode(); diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java index c97cdde0d..de64ca670 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java @@ -48,7 +48,7 @@ public class EquinoxLogServices { File configAreaDirectory = null; if (configuration != null) // TODO assumes the URL is a file: url - configAreaDirectory = new File(configuration.getURL().getFile()); + configAreaDirectory = new File(configuration.getURL().getPath()); if (configAreaDirectory != null) { logFile = new File(configAreaDirectory, logFilePath); diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java index 0bcbfdd7f..702c80073 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java @@ -115,7 +115,7 @@ public class Storage { osgiParentLocation = parentConfigLocation.createLocation(null, parentConfigLocation.getDataArea(EquinoxContainer.NAME), true); } this.osgiLocation = configLocation.createLocation(osgiParentLocation, configLocation.getDataArea(EquinoxContainer.NAME), configLocation.isReadOnly()); - this.childRoot = new File(osgiLocation.getURL().getFile()); + this.childRoot = new File(osgiLocation.getURL().getPath()); if (Boolean.valueOf(container.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_CLEAN)).booleanValue()) { cleanOSGiStorage(osgiLocation, childRoot); @@ -124,7 +124,7 @@ public class Storage { this.childRoot.mkdirs(); } Location parent = this.osgiLocation.getParentLocation(); - parentRoot = parent == null ? null : new File(parent.getURL().getFile()); + parentRoot = parent == null ? null : new File(parent.getURL().getPath()); if (container.getConfiguration().getConfiguration(Constants.FRAMEWORK_STORAGE) == null) { // Set the derived value if not already set as part of configuration. @@ -466,13 +466,13 @@ public class Storage { private URLConnection getContentConnection(final String spec) throws IOException { if (System.getSecurityManager() == null) { - return createURL(spec).openConnection(); + return LocationHelper.getConnection(createURL(spec)); } try { return AccessController.doPrivileged(new PrivilegedExceptionAction<URLConnection>() { @Override public URLConnection run() throws IOException { - return createURL(spec).openConnection(); + return LocationHelper.getConnection(createURL(spec)); } }); } catch (PrivilegedActionException e) { @@ -855,6 +855,7 @@ public class Storage { if ("file".equals(protocol)) { //$NON-NLS-1$ File inFile = new File(sourceURL.getPath()); + inFile = LocationHelper.decodePath(inFile); if (inFile.isDirectory()) { // need to delete the outFile because it is not a directory outFile.delete(); diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/bundleentry/Handler.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/bundleentry/Handler.java index aff50f1e4..3565735d9 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/bundleentry/Handler.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/bundleentry/Handler.java @@ -15,6 +15,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.net.URL; import org.eclipse.osgi.container.*; +import org.eclipse.osgi.internal.location.LocationHelper; import org.eclipse.osgi.storage.BundleInfo; import org.eclipse.osgi.storage.bundlefile.BundleEntry; import org.eclipse.osgi.storage.url.BundleResourceHandler; @@ -33,8 +34,20 @@ public class Handler extends BundleResourceHandler { ModuleRevision revision = module.getCurrentRevision(); BundleInfo.Generation revisionInfo = (BundleInfo.Generation) revision.getRevisionInfo(); BundleEntry entry = revisionInfo == null ? null : revisionInfo.getBundleFile().getEntry(url.getPath()); - if (entry == null) + if (entry == null) { + String path = url.getPath(); + if (revisionInfo != null && (path.indexOf('%') >= 0 || path.indexOf('+') >= 0)) { + entry = revisionInfo.getBundleFile().getEntry(LocationHelper.decode(path, true)); + if (entry != null) { + return entry; + } + entry = revisionInfo.getBundleFile().getEntry(LocationHelper.decode(path, false)); + if (entry != null) { + return entry; + } + } throw new FileNotFoundException(url.getPath()); + } return entry; } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceURLConnection.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceURLConnection.java index 82c847d4e..c776c8b0b 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceURLConnection.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/url/reference/ReferenceURLConnection.java @@ -15,7 +15,7 @@ import java.io.*; import java.net.URL; import java.net.URLConnection; import org.eclipse.osgi.framework.util.FilePath; -import org.eclipse.osgi.internal.framework.EquinoxConfiguration; +import org.eclipse.osgi.internal.location.LocationHelper; /** * URLConnection for the reference protocol. @@ -45,14 +45,7 @@ public class ReferenceURLConnection extends URLConnection { file = makeAbsolute(installPath, file); } - // Pre-check if file exists, if not, and it contains escape characters, - // try decoding the absolute path generated by makeAbsolute - if (!file.exists() && path.indexOf('%') >= 0) { - String decodePath = EquinoxConfiguration.decode(file.getAbsolutePath()); - File f = new File(decodePath); - if (f.exists()) - file = f; - } + file = LocationHelper.decodePath(file); ref = file.toURL(); checkRead(file); diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/LocationHelper.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/LocationHelper.java index 75da9a911..73050d44f 100644 --- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/LocationHelper.java +++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/internal/location/LocationHelper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2013 IBM Corporation and others. + * Copyright (c) 2006, 2016 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 @@ -10,9 +10,8 @@ *******************************************************************************/ package org.eclipse.osgi.internal.location; -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; +import java.io.*; +import java.net.*; import org.eclipse.osgi.internal.location.Locker.MockLocker; /** @@ -55,7 +54,7 @@ public class LocationHelper { } private static URL adjustTrailingSlash(URL url, boolean trailingSlash) throws MalformedURLException { - String file = url.getFile(); + String file = url.getPath(); if (trailingSlash == (file.endsWith("/"))) //$NON-NLS-1$ return url; file = trailingSlash ? file + "/" : file.substring(0, file.length() - 1); //$NON-NLS-1$ @@ -80,4 +79,76 @@ public class LocationHelper { // Backup case if an invalid value has been specified return new Locker_JavaNio(lock, debug); } + + public static InputStream getStream(URL location) throws IOException { + if ("file".equalsIgnoreCase(location.getProtocol())) { //$NON-NLS-1$ + // this is done to handle URLs with invalid syntax in the path + File f = new File(location.getPath()); + if (f.exists()) { + return new FileInputStream(f); + } + } + return location.openStream(); + } + + public static URLConnection getConnection(URL url) throws IOException { + if ("file".equalsIgnoreCase(url.getProtocol())) { //$NON-NLS-1$ + try { + return url.openConnection(); + } catch (IllegalArgumentException e) { + // this is done to handle URLs with invalid syntax in the path for URIs + File f = new File(url.getPath()); + if (f.exists()) { + return f.toURI().toURL().openConnection(); + } + } + } + return url.openConnection(); + } + + public static File decodePath(File file) { + // Pre-check if file exists, if not, and it contains escape characters, + // try decoding the absolute path generated by makeAbsolute + if (!file.exists() && (file.getPath().indexOf('%') >= 0 || file.getPath().indexOf('+') >= 0)) { + String absolute = file.getAbsolutePath(); + String decodePath = LocationHelper.decode(absolute, true); + File f = new File(decodePath); + if (f.exists()) { + return f; + } + decodePath = LocationHelper.decode(absolute, false); + f = new File(decodePath); + if (f.exists()) { + return f; + } + } + return file; + } + + public static String decode(String urlString, boolean plusEncoded) { + //first encode '+' characters, because URLDecoder incorrectly converts + //them to spaces on certain class library implementations. + if (plusEncoded && urlString.indexOf('+') >= 0) { + int len = urlString.length(); + StringBuffer buf = new StringBuffer(len); + for (int i = 0; i < len; i++) { + char c = urlString.charAt(i); + if (c == '+') + buf.append("%2B"); //$NON-NLS-1$ + else + buf.append(c); + } + urlString = buf.toString(); + } + try { + return URLDecoder.decode(urlString, "UTF-8"); //$NON-NLS-1$ + } catch (UnsupportedEncodingException e) { + // Tried but failed + // TODO should we throw runtime exception here? + return urlString; + } catch (RuntimeException e) { + // May have illegal characters for decoding + return urlString; + } + } } |