Question

This has been killing me all day. I am working on android / java in eclipse.

This is what I want to do

  • I want to embed one of my libraries - DatabaseLibrary

  • within another of my libraries - LogicLibrary

Crucially - without exposing any of the methods in DatabaseLibrary to a 3rd party who has access to the LogicLibrary.


I have tried including it using the proguard-maven-plugin like this

 <configuration>
                <assembly>
                 <inclusions>
                     <inclusion>
                         <groupId>xxx</groupId><artifactId>DatabaseLibrary</artifactId><library>true</library>
                     </inclusion>
                 </inclusions>
             </assembly> 

However this includes all methods into the DatabaseLibrary and exposed them to a 3rd party.

I want my LogicLibrary to be able to call against the DatabaseLibrary without the 3rd party ever seeing it.

I have searched all over the web and it seems like something called an uber jar is what i need to do. However I have tried a few methods such as maven-assembly-plugin mentioned here https://stackoverflow.com/a/1834905/1312937

maven embed dependency artifact code in jar

However I have got no where with this, it looks like it is a maven 2 answer so maybe there is something different i need to do for maven 3?

Can anyone tell me if uberjar is the correct way for me to achieve my aims? If there are alternate patterns please let me know, im not tied into maven.

Was it helpful?

Solution

I think the uber jar is the wrong route. Instead to accomplish your goal of hiding methods from the DatabaseLibrary but make them accessible to your Logic I would declare your methods as "protected" which limits its visibility to the package level. Given that you would make sure that any classes that needed to talk between jars were within the same package (though in seperate jars). This will force a 3rd party vendor only to use the public methods that are available to them.

- DatabaseLibrary
  |- com.mycompany
      |- DatabaseClass

-LogicLibrary
  |- com.mycompany
      |- LogicClass


 public class DatabaseClass{
    protected void doSomething(){
    }
 }

 public class LogicClass{
    public void doSomething(){
       DatabaseClass dbClass = new DatabaseClass();
       dbClass.doSomething();
    }
 }

Now you're 3rd party vendor will only see LogicClass.doSomething()

See also: http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

OTHER TIPS

The Java classpath just doesn't work the way you think it does. You can't 'hide' one of the jar files, and still have it accessible.

The 'uberjar' concept is to simply decompress all of the jar files, and then add all of the classes / resources to one big jar file.

Unfortunately, I'm not aware of any way to limit access to a jar file.

This might not apply to Android, because I am not 100% sure how classloaders in Android work. But this idea should work in Java in general.

So what you want to do it so create a a classloader that will allow your classes inside LogicLibrary to load the DatabaseLibrary. There are few solutions, One-Jar being one of them: http://one-jar.sourceforge.net/ This one allows you to pack one jar into another and then uses a custom classloader to load a jar within "uber" jar. In one of your links there's another link how to create this using maven assembly.

I did not use it, so I am not sure it will suit your needs. But what you can do is to create your own classloader that will decrypt encrypted JARs, or verify signature or use whatever mechanism you need. You can even put your library into a password-protected zip file and let the classloader uncompress it. Using the custom classloader is a way to go.

You can use maven assembly plugin to simply decompress one Jar, include another Jar and then package it back (and then use custom classloader). But it won't protect the Jar much...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top