Community
Participate
Working Groups
Build Identifier: org.eclipse.osgi-3.6.1.R36x.jar My project specifies the osgi.bundles property explicitly in an auto-generated config.ini with file:// URLs containing absolute paths to jars. This works fine. In development, we instead point at directories (the compile output folder for IntelliJ, specifically). This causes the exception below because "bundles\19\1\bundlefile" does not exist. If I change the entry in config.ini to be just a normal path instead of a file:// path (e.g. "C:\foo\bar@start" instead of "file:/C:/foo/bar@start") then it works great. I think the root cause is that a bundle specified by an URL triggers URL.openStream() in EclipseStarter.installBundles() whereas a simple file path is somehow different. java.util.zip.ZipException: Exception in opening zip file: C:\path\to\my\project\config\org.eclipse.osgi\bundles\19\1\bundlefile at org.eclipse.osgi.framework.util.SecureAction.getZipFile(SecureAction.java:264) at org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleFile.basicOpen(ZipBundleFile.java:88) at org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleFile.getZipFile(ZipBundleFile.java:101) at org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleFile.checkedOpen(ZipBundleFile.java:74) at org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleFile.getEntry(ZipBundleFile.java:246) at org.eclipse.osgi.baseadaptor.BaseData.getEntry0(BaseData.java:111) at org.eclipse.osgi.baseadaptor.BaseData$1.run(BaseData.java:105) at java.security.AccessController.doPrivileged(Native Method) at org.eclipse.osgi.baseadaptor.BaseData.getEntry(BaseData.java:103) at org.eclipse.osgi.internal.baseadaptor.AdaptorUtil.loadManifestFrom(AdaptorUtil.java:187) at org.eclipse.core.runtime.internal.adaptor.EclipseStorageHook.getGeneratedManifest0(EclipseStorageHook.java:406) at org.eclipse.core.runtime.internal.adaptor.EclipseStorageHook$1.run(EclipseStorageHook.java:397) at java.security.AccessController.doPrivileged(Native Method) at org.eclipse.core.runtime.internal.adaptor.EclipseStorageHook.getGeneratedManifest(EclipseStorageHook.java:395) at org.eclipse.core.runtime.internal.adaptor.EclipseStorageHook.createCachedManifest(EclipseStorageHook.java:388) at org.eclipse.core.runtime.internal.adaptor.EclipseStorageHook.getManifest(EclipseStorageHook.java:507) at org.eclipse.osgi.internal.baseadaptor.BaseStorage.loadManifest(BaseStorage.java:306) at org.eclipse.osgi.internal.baseadaptor.BundleInstall.begin(BundleInstall.java:82) at org.eclipse.osgi.framework.internal.core.Framework.installWorkerPrivileged(Framework.java:921) at org.eclipse.osgi.framework.internal.core.Framework$1.run(Framework.java:837) at java.security.AccessController.doPrivileged(Native Method) at org.eclipse.osgi.framework.internal.core.Framework.installWorker(Framework.java:888) at org.eclipse.osgi.framework.internal.core.Framework.installBundle(Framework.java:832) at org.eclipse.osgi.framework.internal.core.BundleContextImpl.installBundle(BundleContextImpl.java:167) at org.eclipse.core.runtime.adaptor.EclipseStarter.installBundles(EclipseStarter.java:1050) at org.eclipse.core.runtime.adaptor.EclipseStarter.loadBasicBundles(EclipseStarter.java:637) at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(EclipseStarter.java:301) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:175) at org.eclipse.core.runtime.adaptor.EclipseStarter.main(EclipseStarter.java:150) at com.avid.osgi.launcher.Main.start(Main.java:50) at com.avid.osgi.launcher.Main.main(Main.java:29) Caused by: java.util.zip.ZipException: error in opening zip file at java.util.zip.ZipFile.open(Native Method) at java.util.zip.ZipFile.<init>(ZipFile.java:114) at java.util.zip.ZipFile.<init>(ZipFile.java:131) at org.eclipse.osgi.framework.util.SecureAction$14.run(SecureAction.java:255) at java.security.AccessController.doPrivileged(Native Method) at org.eclipse.osgi.framework.util.SecureAction.getZipFile(SecureAction.java:253) ... 30 more Reproducible: Always Steps to Reproduce: 1. create a config.ini that has an osgi.bundles entry with a file:// URL pointing at a directory rather than a jar 2. launch Equinox, specifying that config.ini's parent folder via -configuration
Can you try a reference URL (e.g. reference:file:/C:/foo/bar@start). That better work because that is how we run from projects within an eclipse workspace. At any rate, we need to investigate why a normal file: URL to a directory is not working.
Using the reference URL works. I encountered the same issues while writing the ScopeAdmin tests. I just assumed I had been doing something wrong when it started working with the reference URL. I can take a look.
Specifying a file URL string within osgi.bundles results in a call to BundleContext.install(String, InputStream) from EclipseStarter.installBundles. The value of the first argument is the original file URL string with some customizations. The value of the second argument is created from new URL(file URL string).openStream(). When BundleInstall.begin() is reached, because an InputStream was specified that's not a ReferenceInputStream, the code copies the bundle data to a storage area (such as ...\org.eclipse.osgi\bundles\19\1\bundlefile, where bundlefile is a file not a directory). Because the InputStream points to a directory instead of a file, bundlefile ends up being nothing more than a plain-text file with some directory info as opposed to the expected archive file. Specifying a non-URL file path string within osgi.bundles works because of the legacy code in EclipseStarter.searchForBundle where a malformed URL is assumed to represent a file path and converted into a reference URL. Specifying a reference URL string within osgi.bundles works because the bundle data is never copied to a new location, and, consequently, a corrupt archive file is never created.
Note this condition can be easily reproduced with code similar to the following. String location = "file:/C:/workspaces/aries/org.apache.aries.scopeadmin.test/bundles/tb4/"; URL url = new URL(location); Bundle b = bundleContext.installBundle(location, url.openStream());
I'm not sure what can be done here. We are giving an input stream (FileInputStream?) to a directory. Unfortunately at that level of abstraction there is no way to determine if the contents of the stream points to a directory (or even a file) and therefore no way to know that we should do a directory copy instead of simply reading the stream and assume it is a valid jar. I think when you are running out of a directory you most likely want to use reference installs anyway to prevent the full copy. This works rather well in the dev environment if you have projects that look like bundles that can be run directly from your output folders in IntelliJ.
(In reply to comment #5) > We are giving an input stream (FileInputStream?) to a directory. The underlying stream from new URL(directory).openStream() is a ByteArrayInputStream.
(In reply to comment #4) > Note this condition can be easily reproduced with code similar to the > following. > String location = > "file:/C:/workspaces/aries/org.apache.aries.scopeadmin.test/bundles/tb4/"; > URL url = new URL(location); > Bundle b = bundleContext.installBundle(location, url.openStream()); The following code snippet works because, when the InputStream is null, the framework creates its own InputStream with new URL(location).openConnection().getInputStream() and, since it has access to the URL and can query the protocol, knows this represents a file directory and proceeds to do a directory copy instead of a file copy. String location = "file:/C:/workspaces/aries/org.apache.aries.scopeadmin.test/bundles/tb4/"; Bundle b = bundleContext.installBundle(location); This doesn't help the EclipseStarter, however, since it wants to customize the location strings which requires it to pass an InputStream.
(In reply to comment #5) > I think when you are running out of a directory you most likely want to use > reference installs anyway to prevent the full copy. This works rather well in > the dev environment if you have projects that look like bundles that can be run > directly from your output folders in IntelliJ. That certainly makes sense, and I'll change my project to do exactly that. But it's not at all obvious from the ZipException that I need to add "reference:" in front of my URLs. Perhaps the best solution for this defect should be simply a better failure behavior. That would have prevented me from filing this defect in the first place. Something like this: if ("file".equals(url.getProtocol()) && new File(url.getPath()).isDirectory()) { throw new IllegalArgumentException("use reference:file: instead of file: for URLs pointing at directories"); }
Created attachment 188640 [details] Automatically converts a file URL pointing to a directory into a reference URL. I'm wondering why we wouldn't instead automatically convert a file URL string pointing to a directory into a reference URL. This patch makes a simple modification to EclipseStarter.searchForBundle that does exactly that.
Created attachment 188641 [details] Automatically converts a file URL pointing to a directory into a reference URL. Added one additional check to the original patch to make sure the URL is using the file protocol.
(In reply to comment #9) > I'm wondering why we wouldn't instead automatically convert a file URL string > pointing to a directory into a reference URL. This patch makes a simple > modification to EclipseStarter.searchForBundle that does exactly that. That sounds good to me, as long as users aren't surprised that their directory is not copied to the osgi folder before running. If the file: URL is a remote filesystem and the network connection fails, that could be an unpleasant surprise. But I imagine that would be an extremely unlikely scenario.
(In reply to comment #11) > as long as users aren't surprised that their directory > is not copied to the osgi folder before running. Yes, it's a choice between being surprised the directory was not copied and being surprised a standard file URL does not work. > If the file: URL is a remote > filesystem and the network connection fails, that could be an unpleasant > surprise. There is no existing support for remote file URL connections with or without the modification.
Created attachment 188682 [details] Alternative: Detect directory and throw exception with a more meaningful error message. This alternate patch takes the approach suggested in comment 8. A file URL pointing to a directory is detected and an exception is thrown with a message suggesting to use a reference URL instead. I'll externalize the message if we decide to go this route.
Created attachment 191617 [details] throw meaningful exception The latest patch will not work for cases where a: reference:file:<path to directory> I think the code needs to be refactored to make sense of what is going on. Here is a patch that attempts to do that and adds a message for cases where file:<path to directory> is used incorrectly. Unfortunately this is more change than I had anticipated. I am attaching this patch to consider early next release.
I opened doc bug340574 to improve the osgi.bundles option documentation. It is sorely lacking.
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. -- The automated Eclipse Genie.
At this point there is no plans to address this issue.