I have this problem in Android/Eclipse.
I´m working in Android Project , this one has to be configured in different ways for different customers, this configurations are not similar(very different methods) between them.
The code is shared in 90%, but each customer has his own requirements.
Each customer has a package with diferent and multiple classes.
I would like only include package of choiced customer in the final compiled file.
But i have conditional object creation in my shared code, and i have to join all package for compiling.
More or less is this (Example)
//import every customer packages
import com.project.customer_1
import com.project.customer_2
import com.project.customer_3
…..
import com.project.customer_98
import com.project.customer_99
……..
final static int customer=2; //Define the customer for this compilation
………
if (customer==1) { //unreachable code
customerClass1 customer1=new customerClass1();
customer1.method1_1;
customer1.method1_2;
customer1.method1_3;
}
else if (customer==2) {
customerClass2 customer2=new customerClass2();
customer2.method2_1;
customer2.method2_2;
customer2.method2_3;
}
…….//unreachable code
else if (customer==98) {//unreachable code
customerClass98 customer98=new customerClass98();
customer98.method98_1;
customer98.method98_2;
customer98.method98_3;
}
else if (customer==99{//unreachable code
customerClass99 customer99=new customerClass99();
customer99.method99_1;
customer99.method99_2;
customer99.method99_3;
}
............
Is clear when customer=X, the other choices are unreachable code. I would like exclude other customer packages/classes than customer is choiced in compiled file. But exist dependency in code
Note: For me is not valid comment code, neither reflection.
You shouldn't do it in way you've described.
You should create additional level of abstraction to access data/logic specific to customers. And move that customer specific logic/data to separate libraries/projects.
To work with separated customer projects, your abstraction level should use dynamic class loading.
Edit. If you can't refactor your project, you can create Proguard config files for each customer to remove unreachable code.
Related
I'm wondering if there is a way to properly generate models so that the generated models can reference each other?
I have a file structure like this
# Project Structure
/common
- Name.json
/v1
- User.json
/v2
- User.json
My Open API Specification files, both v1 and v2 reference common's Name properly
However the generated code ends up like this:
import v1.Name //created another Name class in v1 package
public class User {
Name name;
//...
}
import v2.Name //created another Name class in v2 package
public class User {
Name name;
//...
}
Ideally I would like to have the generated classes to look something like this
package v1
import common.Name
public class User {
Name name;
}
I have tried the import mappings and type mappings flags but the code generator cannot seem to find the common.Name class during creation of User class.
Any workarounds for this or is this a known limitation of the generator?
Edit: Ah it seems like impossible to have different generated packages in a single generation. So I must break these packages into their projects with their own types then utilize .openapi-ignore or looking at the jar depdendencies that's generated. Darn.
I need to generate a jar library in three different versions. Some methods of the classes are marked with annotations that specify the version when they were added. For example:
public class A {
#SinceVersion(2)
public int getTotal() {
// do something...
}
#SinceVersion(5)
public int getMax() {
// do something...
}
#SinceVersion(4)
public int getAverage() {
// do something...
}
}
Then:
When I generate my-library-2.jar, only getTotal() should be included.
When I generate my-library-4.jar, only getTotal() and getAverage() should be included.
When I generate my-library-5.jar all three methods should be included.
This is a simplified example. The real problem spans 300 classes, 10 versions, with 6 subversions each.
You may wanna look into implementing an annotation processor.
Annotation processors run during compile time and are used to create and/or manipulate code, and I use them to create boilerplate code, as well as code that's otherwise tedious to maintain manually, but has a clear structure.
Why not use source control (git, etc.) to manage your releases? when you tag a release with v2.0, then code up to that point will have only getTotal(). Then v4.0 comes a long, and the code up to that point will have getTotal() and getAverage(), and so on.
Each release can be managed and built independently, and produce the specific jar file for that specific release.
Your client will then include whichever version of the jar it needs.
I wanted to post the solution I found in case is of help for someone else.
After researching for a week I finally found Apache Commons BCEL. This library allows you to inspect and modify a class loaded in the JVM; once modified it can be written to the file system as a .class file.
A piece of code like this produces a new class file without some methods:
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.AnnotationEntry;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ClassGen;
JavaClass clazz = Repository.lookupClass("test.House");
ClassGen cg = new ClassGen(clazz);
Method m = findMethod(clazz, "close");
AnnotationEntry ae = m.getAnnotationEntries(); // process annotations here...
cg.removeMethod(m); // remove the method you want to remove
JavaClass modifiedClazz = cg.getJavaClass();
modifiedClazz.dump("./gen/test/House.class"); // save to a new file
By walking the whole tree of classes (or a subpackage tree) it's possible to find all affected classes, process their methods, and remove them if the annotation values match some criteria.
I'm working with Google's Protocol Buffer (in combination with the Protocol Buffers maven plugin) which compiles a .proto file into a class. I can use the generated class in the default package perfectly, but not outside of it. I don't really know how to explain it any better so I'm going to show you some pictures.
I've tried subclassing the Hrp class but that doesn't work (the generated class is final). It is also not an option to move the class every time I re-generate the Hrp class.
I'm not sure if this is relevant, but the generated class is public final. It contains an empty, private constructor.
I have also tried setting the generated sources package prefix for the generated sources folder but that also does not work.
Any help would be greatly appreciated.
Try adding a package id to your Protocol Buffers definition. See Protocol Buffers Package
i.e.
syntax = "proto3";
package MyPackage;
option optimize_for = SPEED;
message Product {
repeated ASale sale = 1;
}
Then when you Generate the Java~Protocol~Buffers code (using protoc), it will be in package MyPackage and you will be able to import it into your java code in the normal way.
In java, you can not import anything from the Default package; which I believe is your problem. See How to access java-classes in the default-package?
I'm developing an android test app and i'm going to access all internal class of android.view package. android.view is a package that is present in jar file. I tried by loading package name but it doesn't display the classes if any one tried
this already, please help.
Here's what I tried so far:
public static void main() throws ClassNotFoundException{
Class o =Class.forName("android.view");
Class[] C=o.getDeclaredClasses();
for(int i=0;i<C.length;i++) {
Classname = C[i].getName();
ClassesDisplayActivity.your_array_list3.add(Classname);
Log.i("Ramu","classname "+ C[i].getName());
}
}
}
It is not possible to determine at runtime all of the classes that are in a package using a standard class loader.
You might have some luck with this library though:
https://code.google.com/p/reflections/
Package is not a class. You cannot call Class.forName() for package and access classes that belong to class using getDelcaredClasses().
I do not know what do you really need, so I'd recommend you to explain this in separate question. probably you will receive better solutions.
However if you really need this you have to do the following:
Get your classpath by calling System.getProperty(java.class.path)
split this property to its elements by colon
iterate over the list and read each resource. If resource is jar you can use ZipInputStream, if it is a directory use File class.
filter list of resources you got at #3.
Fortunately you can use 3rd party library named Reflections that helps you to do all this without writing code.
Currently my project developed using simple JSP and servlets has the following packages
1-Business package (Contains summed up methods from service package under a business rule)
2-Service package (Contains different services and their implementation - along with factory
method to call a specific implementation of each service)
3-Controller package (All the servlet controls ..)
3-Views (All the jsps)
4-CustomTags (Contain the Custom Tags)
5-Domain (Contains Domain objects)
Now I am planning to implement the same project using struts2 could you tell me what packages should i introduce. I know the service and business package will remain intact what about the controller package ? Should i place all the actions in the controller package ? Any suggestion will be appreciated.
Do not organise all your classes based on their type, they should be organised or grouped together with their immediate collaborators. If you can help it, place XAction and XController together in the same package. Its silly to place XAction in a separate package with 49 other actions that really have no relation while its controller is somewhere else.
If you group collaborators together in the same package its quite easy to know the working group and be reasonably more confident that changing one probably affects the other. With your original suggestion, who really knows what Action works with what Controller and so on.
Is possible!
Struts from 2.0 to 2.3.x (I used theses versions), if you use the annotations struts2-convention-plugin.jar dependency, you can do that:
The package default (generally is zx.yz.actions) mapped all Actions on the project and it is your package namespace from image above.
When you create a new package inner Actions package, zx.yz.actions.example for instance, you are creating a new namespace /servletContext/example in your application.
To disable it, you only need put a '/' before your "Action()" annotation method. For example:
public class ExampleAction {
#Action(value="/example",
#Result(name="ok", type="httpheader", params={"status", "200"})
public String execute() {
}
}
The '/' in '/example', will put in de namespace default.