Menu

#8 Using Jackcess Encrypt in OSGi fails due to not exported .impl

2.1.4
closed
nobody
None
1
2017-10-03
2017-04-10
M. le Rutte
No

The MS-Access library Jackcess is split into two bundles, a main jackcess and a jackcess-encrypt library. The last one is needed to read encrypted, and possibly password protected MS-Access files.

My code installs the crypto provider as

db = new DatabaseBuilder(new File(pathname))
.setCodecProvider(new CryptCodecProvider())
.open();

This results to having the OSGi bundle in having a dependency to com.healthmarketscience.jackcess.impl, according to the biz.aQute.bnd.builder BND plugin run by my Gradle script. Of course, the Jackcess bundle does not export this package. My assumption is that this is because the parameter from setCodecProvider is a com.healthmarketscience.jackcess.impl.CodecProvider. My own code does not reference the impl package in any way.

I'd prefer to use the two Jackcess bundles as they are, but am I right in assuming this is a packaging or reference error in Jackcess and to solve this I need to repackage the Jackcess bundle, exporting the impl package too?

Discussion

  • James Ahlborn

    James Ahlborn - 2017-04-10

    just so you are aware, you don't need jackcess-encrypt for simple password protection. you only need it for database formats which are actually encrypted in some form.

    otherwise, i've never used the osgi support myself, so i'm not surprised there are some issues. it would not be ideal to export the entire impl package, kind of defeats the purpose of the osgi exports (although i assume it would work). ideally, the CodecProvider interface should really be in a separate package.

     

    Last edit: James Ahlborn 2017-04-10
    • M. le Rutte

      M. le Rutte - 2017-04-10

      The database itself is not password protected, but the database is encrypted. Without the CryptCodecProvider it cannot be read, with it it can. Technically it would be enough to move the CodecProvider one package up, I guess.

      With the CodecProvider in an unexported package the using (my) bundle cannot be resolved by the OSGi framework.

      I don't want to export the impl package, as it indeed does defeat the purpose of the OSGi system.

       

      Last edit: M. le Rutte 2017-04-10
  • M. le Rutte

    M. le Rutte - 2017-04-11

    Besides having to add the .impl as Export-Package, the crypto implementation itself is in the same package. Eventually I ended up with creating an OSGi jar which includes Jackcess, Jackcess-Crypto and BouncyCastle, where none of the BouncyCastle stuff needs to be exported. I don't think the last part was needed as I had removed all Import-Package instructions.

     
  • James Ahlborn

    James Ahlborn - 2017-04-12

    are you saying that there is more that needs to be fixed, or just pointing out what you did to work around the issue?

     
  • M. le Rutte

    M. le Rutte - 2017-04-16

    Both.

    The crypto package should either be moved to a separate package, but more optimally it should be bundled as a bundle fragment, in which case it will augment the original bundle's classloader. The crypto package does not have a need for a standalone deployment, so it is a perfect candidate for a bundle fragment.

    The BouncyCastle bundling isn't necesssary as it was a result of too spurious manifest editing.

     
  • James Ahlborn

    James Ahlborn - 2017-04-17

    So, if i just reconfigured jackcess-entrypt into a bundle fragment, would it all "just work"? or do i still need to move some classes into different packages? do you have examples of manifests that work correctly?

     

    Last edit: James Ahlborn 2017-04-17
  • M. le Rutte

    M. le Rutte - 2017-04-22

    It appears that I was wrong, the problem is remains that the crypt provider does not have its own namespace.

    I made the encrypt bundle a fragment bundle by adding the header Fragment-Host: com.healthmarketscience.jackcess;bundle-version="[2.1.6,3)", and the kept the Export-Package header. Additionally I exported the .impl package from the regular Jackcess bundle.

    Unfortunately this doesn't make the CryptCodecProvider visible to my OSGi bundle, which is thus not capable of instantiating the CryptCodecProvider.

     
  • James Ahlborn

    James Ahlborn - 2017-05-03

    so, i was poking at this tonight to see if i could make it go, and it seems like there isn't an easy solution. i wanted to just move CodecProvider to an "spi" package, but i don't think that will work because it depends on PageChannel. since that is in impl, i assume it would still break the osgi mechanism?

     
  • James Ahlborn

    James Ahlborn - 2017-05-13

    So i'm running out ideas here. My latest thought is adding a utility class to jackcess-encrypt. If i added the following utility class to the "public" api of jackcess-encrypt, this should solve your problem, right? Since the public api of this class only depends on the public jackcess api?

    public class CryptCodecUtil
    {
      public static DatabaseBuilder setProvider(DatabaseBuilder db) {
        return db.setCodecProvider(new CryptCodecProvider());
      }
    
      public static DatabaseBuilder setProvider(DatabaseBuilder db, String pwd) {
        return db.setCodecProvider(new CryptCodecProvider(pwd));
      }
    }
    
     
  • James Ahlborn

    James Ahlborn - 2017-09-25

    Without a clear direction on this, i will probably close it in the near future.

     
  • M. le Rutte

    M. le Rutte - 2017-09-25

    Just noted your update, I guess it would not work as the CryptCodecProvider still would not be visible to the classloader of the bundle. In OSGi each bundle gets its own classloader and that classloader can only access public (exported) classes of another bundle.

    Whereas in 'plain' Java jars the entire path becomes a single namespace and multiple jars contributing to the same package become merged, this doesn't happen in OSGi,

     
    • James Ahlborn

      James Ahlborn - 2017-09-26

      but if the CryptCodecUtil class was in the public package of jackcess encrypt, then your code would only be interacting with classes in the public package. that seems like it should work.

       
      • M. le Rutte

        M. le Rutte - 2017-09-26

        I don't have the structure of Jackess in my head to be able to conclude that to be honest. As far as my OSGi knowledge goes the crypto bundle is best off as a fragment to the orignal bundle, as, like I wrote before, there is no need to run the crypto bundle on its own. In that case it will share a classloader, yet the consuming package must be able to access the class. If it can access the CryptCodecUtil then I guess it may work.

        Just a small checkup, will it run in Java 9's modular classpath? It seems to have a similar resolution process and doesn't allow split packages anymore.

         

        Last edit: M. le Rutte 2017-09-26
        • James Ahlborn

          James Ahlborn - 2017-10-03

          So here's my plan:

          • remove some of the unneeded cruft from the Export-Package (only needs the "main" package)
          • add a Fragment-Host with the value of "com.healthmarketscience.jackcess"
          • add the util class i described in an earlier comment to the com.healthmarketscience.jackcess package

          i have no idea how java 9 plays into all of this. a quck read of that link makes it sound like everything on the classpath is a single module, so no problems. i guess if you embrace modules, though, there could be problems. java 9 is going to be a migration nightmare for everyone.

           

          Last edit: James Ahlborn 2017-10-03
  • James Ahlborn

    James Ahlborn - 2017-10-02

    Ticket moved from /p/jackcess/bugs/140/

     
  • James Ahlborn

    James Ahlborn - 2017-10-03
    • status: open --> closed
    • Group: Unassigned --> 2.1.4
     
  • James Ahlborn

    James Ahlborn - 2017-10-03

    fixed in trunk, will be in the 2.1.4 release.

     

Log in to post a comment.

MongoDB Logo MongoDB
Gen AI apps are built with MongoDB Atlas
Atlas offers built-in vector search and global availability across 125+ regions. Start building AI apps faster, all in one place.