importing a library as a package private - java

I know we can create a package private class in java. So the class is Internal and only accessible in the specified module:
class MyPackagePrivateClass
{
...
}
Now I am developing an android library which i named LibraryA and I wish to use an existing LibraryB in my own LibraryA. How is it possible to prevent user of LibraryA from using the LibraryB directly?
Is there any concept like package private library or anything like that?
Update (For those who ask 'why do I need this?')
In LibraryB there are methods like this:
public QueryBuilder select(String... columns);
But I strongly am of the view that we should use Type-Safe Enum pattern and prevent users from passing strings to these methods(Considering maintenance and refactoring issues). So I decided to wrap those methods in LibraryA:
public TypedQueryBuilder select(Column... columns) {
queryBuilder = queryBuilder.select(toString(columns));
return this;
}
Therefore users of my library should use the Typed methods I provided (Column is a type safe enum here). But if they have access to the original method they may use those instead and I tend to forbid this.

In Java, with polymorphism, you can't hide a public method of an extended class.
I think that you could archive your goal with Facade Pattern: hide all the complex logic and, in this case, control the access and, if needed, implements some interfaces.

Jigsaw project tries to reach the same goal. But it can take long enough to wait until it would be ported to Android. Until then the best solution IMO is to use package private methods. User will be able to understand that he shouldn't use these methods.
Anyway it's impossible to ultimately forbid library user to do certain things, because one can use reflection or substitute class to get rid of nasty restrictions. But it's possible to encourage user not to do certain things - that's what can be done.

Make a jar file out of library B and import it in library A.
https://stackoverflow.com/a/1051705/6897626

Related

What do i do if need to change a libraries functionality

I have a class in a Java Library(open-m3u) that I need to change just slightly.
The functionality is easy to implement on my own without using the library. The library is open-source so i have access to all of its code. The class is made in such a way that inheriting it or even changing that small part is not possible. My question is should I copy that class and all the classes that it depends on and put them in my own code base and change the functionality or should implement the functionality myself. Or is there another option?
The functionality is easy to implement on my own without using the
library.
IMHO, then that's the way to go. Your other options are:
Build the functionality around the library: you say that's not possible in your case.
Create a branch of the library in your own source control system. That means you'll have to keep that repository in sync with the library maintainers, which means a permanent burden. And you have to check what the library's license says about forking.
Copy the relevant parts into your code base and do the modifications there. Then you won't profit from future enhancements or bug fixes, but still have to maintain code that was created and architected by someone else, and doesn't exactly fit your requirements. And you have to check what the library's license says about copying parts into a foreign code base.
They all have their drawbacks.
As a general remark: in 25 years of professional software development, I've seen both successful usages of external libraries as well as complete failures. Some times, we invested more time into evaluating existing libraries (and then finding out that nothing matched) than we needed for implementing the project-specific solution on our own.
And every library you can do without, makes config management and rollout easier.
Decorator pattern allows you to add new functionality to existing object.
If java library you use has any class like this:
public class LibraryClass implement ILibraryInterface {
public void someMethod() {
...
}
}
Then you can create Decorator class:
public class LibraryClassDecorator implement ILibraryInterface {
private LibraryClass libObj;
public LibraryClassDecorator(LibraryClass libObj) {
this.libObj = libObj;
}
public void someMethod() {
libObj.someMethod();
// here you can do whatever you want.
// Add some additional logic
// transform result value if there is some
}
}
Note: you have to implement the same interface to follow Liskov substitution principle
A solution will be to make a class that extends the one you wanna change and overide the part you wanna change

How to prevent client from seeing internal private classes in Android library ?

I have a library with several packages-
lets say
package a;
package b;
inside package a I have public a_class
inside package b I have public b_class
a_class uses b_class.
I need to generate a library from this , but I do not want the Client to see b_class.
The only solution I know of is to flatten my beautifully understandable packages to single package and to use default package access for b_class.
Is there another way to do so ? maybe using interfaces or some form of design pattern ??
If you reject to move the code to an individual, controlled server, all you can do is to hinder the client programmer when trying to use your APIs. Let's begin applying good practices to your design:
Let your packages organized as they are now.
For every class you want to "hide":
Make it non-public.
Extract its public API to a new, public interface:
public interface MyInterface {...}
Create a public factory class to get an object of that interface type.
public class MyFactory
{
public MyInterface createObject();
}
So far, you have now your packages loosely coupled, and the implementation classes are now private (as good practices preach, and you already said). Still, they are yet available through the interfaces and factories.
So, how can you avoid that "stranger" clients execute your private APIs? What comes next is a creative, a little complicated, yet valid solution, based on hindering the client programmers:
Modify your factory classes: Add to every factory method a new parameter:
public class MyFactory
{
public MyInterface createObject(Macguffin parameter);
}
So, what is Macguffin? It is a new interface you must define in your application, with at least one method:
public interface Macguffin
{
public String dummyMethod();
}
But do not provide any usable implementation of this interface. In every place of your code you need to provide a Macguffin object, create it through an anonymous class:
MyFactory.getObject(new Macguffin(){
public String dummyMethod(){
return "x";
}
});
Or, even more advanced, through a dynamic proxy object, so no ".class" file of this implementation would be found even if the client programmer dares to decompile the code.
What do you get from this? Basically is to dissuade the programmer from using a factory which requires an unknown, undocumented, ununderstandable object. The factory classes should just care not to receive a null object, and to invoke the dummy method and check the return value it is not null either (or, if you want a higher security level, add an undocumented secret-key-rule).
So this solution relies upon a subtle obfuscation of your API, to discourage the client programmer to use it directly. The more obscure the names of the Macguffin interface and its methods, the better.
I need to generate a library from this , but I do not want the Client to see b_class. The only solution I know of is to flatten my beautifully understandable packages to single package and to use default package access for b_class. Is there another way to do so ?
Yes, make b_class package-private (default access) and instantiate it via reflection for use in a_class.
Since you know the full class name, reflectively load the class:
Class<?> clz = Class.forName("b.b_class")
Find the constructor you want to invoke:
Constructor<?> con = clz.getDeclaredConstructor();
Allow yourself to invoke the constructor by making it accessible:
con.setAccessible(true);
Invoke the constructor to obtain your b_class instance:
Object o = con.newInstance();
Hurrah, now you have an instance of b_class. However, you can't call b_class's methods on an instance of Object, so you have two options:
Use reflection to invoke b_class's methods (not much fun, but easy enough and may be ok if you only have a few methods with few parameters).
Have b_class implement an interface that you don't mind the client seeing and cast your instance of b_class to that interface (reading between the lines I suspect you may already have such an interface?).
You'll definitely want to go with option 2 to minimise your pain unless it gets you back to square one again (polluting the namespace with types you don't want to expose the client to).
For full disclosure, two notes:
1) There is a (small) overhead to using reflection vs direct instantiation and invocation. If you cast to an interface you'll only pay the cost of reflection on the instantiation. In any case it likely isn't a problem unless you make hundreds of thousands of invocations in a tight loop.
2) There is nothing to stop a determined client from finding out the class name and doing the same thing, but if I understand your motivation correctly you just want expose a clean API, so this isn't really a worry.
When using Kotlin, you can use the internal modifier for your library classes.
If I understand correctly you are asking about publishing your library for 3rd party usage without disclosing part of your source? If that's the case you can use proguard, which can obfuscate your library. By default everything will be excluded/obfuscated, unless you specify things you want to exclude from being obfuscated/excluded.
If you want to distribute [part of] your code without the client being able to access it at all, that means that the client won't be able to execute it either. :-O
Thus, you just have one option: Put the sensible part of your code into a public server and distribute a proxy to access it, so that your code would be kept and executed into your server and the client would still be able to execute it through the proxy but without accessing it directly.
You might use a servlet, a webservice, a RMI object, or a simple TCP server, depending on the complexity level of your code.
This is the safest approach I can think of, but it also deserves a price to pay: In addition to complexing your system, it would introduce a network delay for each remote operation, which might be big deal depending on the performance requirements. Also, you should securize the server itself, to avoid hacker intrussions. This could be a good solution if you already have a server that you could take advantage of.

Using shared class libraries internally, but not providing access to them in released SDK

After some research I cannot come across the best approach for this. There will be certain color classes that I would like to share amongst multiple projects. Let's call one of them EncryptedColor. Since it is used across multiple projects I don't want multiple copies of it in existence of course. Otherwise I would need to make sure that an update in one location would need to be updated everywhere. However, these classes are needed in some released SDKs that we provide to customers.
How could I design it such that I can use these classes but not provide them with the classes that they don't need access to from their SDK. I don't want useless classes to become visible and flood the smaller subset of classes that they really need to be seeing.
A couple approaches I have thought of so far but aren't quite ideal:
Try and use a doclet structure that hides the calls within the javadoc such as doclava. Javadoc has not fully implemented its own hiding mechanism yet. As I understand this doesn't keep the functions from being visible, but it was mentioned in one spot that you would need reflection to use the calls. I don't see how just the javadoc does that so I must have been missing something.
Android has designed themselves it seems to force reflection from some #hide attributes included in methods that they have in source code. But from the sounds of it, the system hides those and then uses a different jar when it is loading to make those visible at launch time. Probably not useful here.
If I were to keep shared classes in the same package name I could access default and protected members, but...then I am keeping all my classes that use these in the same package name. Not quite ideal either, but it could be done in that manner if I needed to. Might get out of hand with large quantities of shared resources.
What approaches are taken typically in situations such as these? I haven't liked my findings and thought process thus far.
Short answer : you can't hide/remove these classes as they are needed at runtime by your application.
In my opinon, you have 3 alternatives :
Change the classes access to "package private". Yes, doing that doesn't make it impossible to access them, but these classes won't be accessible directly.
Remove the classes and create an API. You want to hide the logic ? Remove it and provide it through a REST API for instance. Depending or your architecture, it could be difficult or impossible.
Create all the instance of these classes in a dynamic way, with Class.forName, using Spring or as in #Steve K answer, with Java's ServiceLoader. As a result, you will be able to remove these classes from the main jar and make them more private, in a way. Again, classes will be here but a little less accessible.
My suggestion that could work would be to implement your color classes as a service using the Java ServiceLoader
You make an interface for your color classes, and implementations can be called using the ServiceLoader class. Then you simply separate your color classes into two packages - a public package you can jar up and distribute with your SDK, and a private package for those classes you want to be internal. The ServiceLoader will find all the color classes available so long as the jar files are in your project's classpath.
For example, if your color classes (as an example) had a common interface like this:
public interface MyAppColor {
public int getRed();
public int getGreen();
public int getBlue();
public int getAlpha();
public void setRed(int red);
public void setGreen(int green);
public void setBlue(int blue);
public void setAlpha(int alpha);
public boolean isValid();
public void doSomething(Object arg);
}
Then you could have a bunch of implementing classes in a jar file, with a service descriptor file included in the jar at the path:
META-INF/services/com.my.app.MyAppColor
The text of that file is simply the list of classes in the jar that implement the interface - one per line:
com.my.app.MyPublicAppColor
com.my.app.MyEncryptedPublicAppColor
com.my.app.MyOtherPublicAppColor
etc. Then all you have to do is make a factory for instantiating the correct type, which could be as simple as this:
public class MyAppColorFactory {
private static ServiceLoader<MyAppColor> serviceLoader = ServiceLoader.load(MyAppColor.class, null);
public static MyAppColor get(String className){
if (className != null){
for (MyAppColor c : serviceLoader){
if (className.equals(c.getClass().getName())){
return c;
}
}
}
return null;
}
}
Deploying only needed code:
- Use Only The Needed Source In Development (1) (2)
Since you have an entire library and many deployments which each use different components, the easiest way to do what you suggest is to use only the sources that you need; not a single library. You can ignore the unused sources. This will only ship the needed code.
- Make The Library "Package Private"
This will allow the access only for the public components of the library and everything else will not be callable. But, it will still ship all the code.
- Create an API as a REST SDK
This will require web access, not desirable for performance code {any code really}. You will ship no sdk code with this method.
- Obfuscate the code
Easy with the correct tools. Obfuscation will change the class and method names in production code to gibberish. This will make the library basically unusable to anyone but you. This will ship all the code but it will be obfuscated
- Native API
You can compile java to machine code and use it in production or as the api. You can also create the api in a native language {not desirable}.

Best practice to hide a service implementation

I want to hide the implementation (concrete class) of a service (interface) from the API user. The implementation is provided to the user by a factory which uses the Java API ServiceLoader mechanism. This Loader requires the implementation class to have public visibility. This is OK as long as the implementation is hidden in a different JAR (apart from the API JAR) the user is not directly depending on.
However, for easy distribution the content of the JAR with the default implementation is packed into the API JAR. So effectively the user depends on this prepacked JAR where the default implementation class is available with public visibility. Nothing keeps people from directly instantiating the implementation. I don't want that to be possible.
My bad ideas:
implement an own version of ServiceLoader which allows to load package private implementations (btw, why does the Java API ServiceLoader doesn't allow this?)
ship separate API and implementation JARs
What do you think is the right way? Any compromise?
Using OSGi or other heavy machinery is out of question.
Disappointing maybe but:
Make a separate jar and put that with the other third party jars.
Let the installer/the deployment process handle nice packaging of all.
Do not make this jar available during compile time; maven: <scope>runtime</scope>.
The only other way would be the have #Deprecated in the javadoc, with as comment how to use the corresponding class using the java service API.
In C# you can create an internal interface that is visible only to relevant friend assemblies, and then explicitly implement the interface. I'm not sure how you would do this in Java, but conceptually this is how I've been able to work around this problem in the .NET world.
EDIT I just looked it up, from what I can tell Java doesn't have explicit implementation for interfaces. As an FYI, an explicit implementation of an interface requires you to make a function call through an interface member, you can't call it as a member of the implementing class. This is why my technique works for me, at least in the .NET world.
Alternatively, I would suggest putting the interface in another JAR, and don't distribute it with the API
You can't easily prevent people from instantiating/accessing any shipped class.
As such I would perhaps simply wrap the ServiceLoader mechanism that you're using and provide the instantiated class referenced through a Java interface (rather than as a concrete implementation reference).
I prefer your first approach, making the implementation class package private, and using a ServiceLoctor to retrieve a specific service. In my project, the package structure is like this:
-package
|-ServiceInterface(public)
|-ServiceImplementation(default,package private)
|-ServiceLocator(public)
The serviceLocator is like this:
public class ServiceLocator{
private static final Map<String,Service> services;
static {
services=new HashMap<String,Service>();
services.put("default",new ServiceImplementation());//hide implementation
}
public Service getService(String name){
return services.get(name);
}
public registerService(Service service, String name){
services.put(name,service)
}
}
The end user does not have access to the implementation class, and in later time, you can easily change to use a different implementation class.

Make a class extends another class at runtime

There is a library have a base class (let's call it CBase) that performs some tasks and one can create classes that extends this CBase class.
The behavior of the CBase is not enough for me, so I would like to create my own CBase class (let's call it MyCBase) that have the same methods and members but these methods don't do the same thing.
Until now everything is ok. But what blocks me is that I would like to replace CBase by MyCBase. However, I have a lot of classes that extend CBase and I don't want to change them all.
Is it possible to replace CBase by MyCBase at runtime ?
So that
public class A extends CBase {}
becomes
public class A extends MyCBase {}
Can I perform this using code enhancement ? (like we do to add methods to a class at runtime. Is it also possible to change inheritance this way ?)
Thank you for your help !
EDIT
I would like to write a plugin for a framework, this is why I would like to change inheritance at runtime. This way users of the framework can use my plugin without changing their source code (changing the inheritance of their classes from CBase to MyCBase)
EDIT 2
Is it possible to do like this: ?
CtClass cc = CtClass.forName("pkg.AClass");
cc.setSuperclass(CtClass.forName("mylib.MyCBase"));
cc.compile();
I'm not expert. Probably you could extend ClassLoader. But I highly recommend don't do it. The replacement will touch many of your classes but it will be clear in code reading and app execution.
I think there is also room for architecture improvement since you have so many classes extend CBase. People are trying to remove dependencies from other libraries or keep it really small. Because in this case you could easily switch to another library or add your own functionality.
I dont think you can change the extends of a class at runtime. I would suggest to change the extends of the objects or build an interface, which contains all the things your need
Changing all derived classes is a simple matter, provided you control their source code:
Create a new class in your project. Call it CBase, and put it in the same package as the library class.
Use the rename/move refactoring of your IDE to rename CBase to MyBase. This will have the IDE rename all references to the renamed/moved class ...
Write the code for MyBase, extending from CBase.
If you can not do this (for instance because some derived classes are in a library you do not control), you replace the implementation of CBase with your own. Simply create a class of the same package and name in your project (the classloader searches the classpath in order, and uses the first class of the proper package and name it finds). This approach however is very brittle, as the compiler can not check binary compability between the old and new version of CBase. The JVM will check this compatibility when classes are loaded, but since classes are only loaded when needed, its hard to test your changes. (Which is why I do not recommend this approach if there are other options).
You could also change the classes as they are loaded my manipulating the class file, that that's going to be even more brittle, and the compiler would allow you to use any additional features MyBase might have. ==> Definitely not a good idea.

Categories

Resources