Eclipse plug-in compiling (4) and eclipse plug-in compiling
Preface
As mentioned in the previous articles, if you compile a simple eclipse plug-in, such as creating a plug-in project, right-click the pop-up menu, and other functions, you can mainly write about how to generate code, this feature is not very relevant to the compilation of the plug-in itself, and mainly handles the business content after the plug-in. After the menu is displayed, click it and run the code generation function. Because the functions of this module are relatively independent, a separate project is created for management to be decoupled from the plug-in project, it is convenient for later maintenance. Because this part of content is relatively large and some content of other projects is referenced, a brief description of the content will not be demonstrated from the beginning. The source code of the project will be added later. You can run it on your own to see the effect.
By the way, it is important to note that this project has referenced and referenced other projects as a previous open-source koala project, and it should not be updated for a while, however, the idea is quite good. You can take a look at it later. Some directory structures and project code in this project refer to or reference the content of this project.
The core of the code generated in this article is the Form and receiver of the domain object. Form is the VO of the business at ordinary times, and the receiver is an assembly for the conversion from the domain object to the Form.
Reference jar package
protected String getPath() {
return MessageFormat.format("{0}/src/{1}/{2}.java", projectPath, //
getPackageName().replaceAll("\\.", "/"), getName());
}
FormNewFile:
This class is a subclass of NewFile, used to generate Form files. There are domain classes in the project development process, such as various models and some data transmission classes (VO ), the Form file to be generated here is VO. This class contains some member variables. It stores the name, field information, template path, and package to be imported of the Form class.
Member variables:FieldMap: stores information about the Form field to be generated. The key is the field name, and the value is the type. Modify the field to be initialized in the constructor, as shown in the following code:
private void initLoader() throws MalformedURLException{
if ("WEB".equals(webType)) {
String dir = webRootPath + "/web/WEB-INF/classes/";
String libs = webRootPath + "/web/WEB-INF/lib/";
loadeWeb(dir, libs);
} else {
String dir = webRootPath + "/bin";
loadJar(dir);
}
}
LoadWeb: This method stores the class path and all jar packages in the member variable urlList. Then, the constructor creates a new URLClassLoader, converts urlList into a URL array, and uses it as a parameter. You can use the URLClassLoader. loadClass (name) method to obtain the specified class.
private void loadeWeb(String dir, String libs) throws MalformedURLException {
urlList.add(new URL("file:" + dir));
File lib = new File(libs);
File[] jarFiles = lib.listFiles();
for (File jarFile : jarFiles) {
logger.info("addJar:" + jarFile.getAbsolutePath());
urlList.add(new URL("file:" + jarFile.getAbsolutePath()));
}
}
ForName: Use URLClassLoader. loadClass (name) to obtain the information of the loaded specified class.
CURDClassLoader: constructor that integrates the functions of the preceding methods. First, call initLoader to initialize the class and jar package paths, and then call loadWeb to obtain the class path and all jar package paths, finally, generate a URLClassLoader. Publish a public method forName to obtain the information of the specified class through URLClassLoader. loadClass.
private CURDClassLoader(String webRootPath) throws MalformedURLException{
this.webRootPath = webRootPath;
initLoader();
URL[] urls = new URL[] {};
classloader = new URLClassLoader(urlList.toArray(urls));
}
CURDCoreAnalysis:
This category is the core of Domain Modeling. It analyzes the class name and attribute information of domain objects,
Member variables:Classloader: this is an instance of the CURDClassLoader class just created. It is used to load the class to be analyzed.
Method:Analysis: This method is the entry method of this tool class. It passes in a project path, a java file to be analyzed, and then performs the analysis class attributes and related fields, the analysis class and attribute information are completed through the java reflection mechanism. The following is the complete code. If you do not understand anything, please study it with Baidu or leave a message.
/**
* Input the complete path of the selected JAVA file and perform Domain Modeling Analysis on the source file.
* @ Param srcJava full path of the java file, starting from the package name, for example, com. yunzaipiao. user. User
* @throws Exception
*/
public EntityModel analysis(String projectPath, String srcJava) throws Exception{
// String binPath = srcPath.replace("/src", "/bin");
// binPath = binPath.substring(0, binPath.lastIndexOf("/"));
// Compile
// new CURDClassCompilerAndLoad().compiler(srcPath, binPath);
classloader = CURDClassLoader.getInstance(projectPath);
// Analyze the object itself
EntityModel entity = analysisField(srcJava);
classloader.close();
return entity;
}
/**
* Analyze the ENTITY class selected by the user
* @param srcJava
*/
private EntityModel analysisField(String srcJava){
if(entityMap.containsKey(srcJava))return entityMap.get(srcJava);
Logger.info ("==================" + srcJava + "for modeling ================ ");
EntityModel entity = new EntityModel();
entityMap.put(srcJava, entity);
Class classEntity = null;
try {
classEntity = classloader.forName(srcJava);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
entity.setName(classEntity.getSimpleName());
entity.setClassName(classEntity.getName());
analysisField(classEntity,entity);
logger.info("entity.name: " + classEntity.getSimpleName());
logger.info("entity.className: " + classEntity.getName());
logger.info("entity.packageName: " + classEntity.getPackage().getName());
Logger.info ("================== complete modeling for" + srcJava + "==============" );
return entity;
}
/**
* Pass in a class to parse the attributes of this class.
* @param classEntity
*/
@SuppressWarnings("rawtypes")
private void analysisField(Class classEntity,EntityModel entity){
List<Class> classesForAnalysis = new ArrayList<Class>();
classesForAnalysis.add(classEntity);
Class supperClass = classEntity.getSuperclass();
while (supperClass != null) {
classesForAnalysis.add(supperClass);
supperClass = supperClass.getSuperclass();
}
for (int i = classesForAnalysis.size() -1; i >=0; i--) {
Class classForAnalysis = classesForAnalysis.get(i);
Field[] fields = classForAnalysis.getDeclaredFields();
Method[] methods = classForAnalysis.getDeclaredMethods();
Map<String,Method> methodMap = new HashMap<String,Method>();
for(Method method:methods){
methodMap.put(method.getName().toLowerCase(), method);
}
for(Field field:fields){
boolean isStatic = Modifier.isStatic(field.getModifiers());
if(isStatic)continue;
Logger.info ("analyzed attributes:" + field. getName () + "; Type: [" + field. getType (). getName () + "]");
// Analyze the FIELD
createModel(field,entity);
}
}
}
private void createModel(Field field,EntityModel entity){
FieldModel fieldModel = new FieldModel(field.getName(),field.getType().getName());
entity.getFields().add(fieldModel);
}
Utils
There are three classes under this package: ClassLoaderClear, CodeGenerator, and VelocityContextUtils. ClassLoaderClear is used to clear and release some resources when a project is loaded. For details, see the source code; velocityContextUtils is an instance of VelocityContext that generates a singleton mode. It is not easy to explain. The following describes the CodeGenerator class.
CodeGenerator:
First, let's take a look at the directory structure of our projects,
public static void generateCode(String javaPath) throws Exception {
try {
String projectPath = javaPath.substring(0,
javaPath.indexOf("/src") + 1);
projectPath = projectPath
.substring(0, projectPath.lastIndexOf("/"));
Logger.info ("project path:" + projectPath );
String srcPath = javaPath.substring(javaPath.indexOf("/src") + 4);
String srcJava = srcPath.substring(1, srcPath.lastIndexOf(".java"));
Logger.info ("the object class to be analyzed is:" + srcJava );
srcJava = srcJava.replaceAll("/", ".");
EntityModel entityModel = CURDCoreAnalysis.getInstance().analysis(
projectPath, srcJava);
VelocityContext context = VelocityContextUtils.getVelocityContext();
context.put("entity", entityModel);
FormNewFile formNewFile = createFormFile(projectPath, entityModel);
formNewFile.process();
AssemblerNewFile assemblerNewFile = createAssemblerFile(
projectPath, entityModel);
assemblerNewFile.process();
} catch (Exception e) {
throw e;
}
}
You can see that this method analyzes the full path of the input java source file and the full name of the project path and java class, and then analyzes the class name and attribute information through the CURDCoreAnalysis class described above, obtain an instance through VelocityContext, put the analyzed information into the velocity attribute, create a FormNewFile, create a Form file through the process method, and finally create a Explorer File.
In the above generateCode method, the createFormFile and createAssemblerFile methods are called to create the corresponding FormNewFile and assumernewfile. First, let's take a look at the createFormFile method:
private static FormNewFile createFormFile(String projectPath,
EntityModel entityModel) {
String className = entityModel.getClassName();
String formName = entityModel.getName();
if (formName.endsWith("Model")) {
formName = formName.substring(0, formName.indexOf("Model"));
}
formName += "Form";
String packageName = className.substring(0, className.lastIndexOf("."))
+ ".form";
packageName = packageName.replace(".model.", ".web.");
FormNewFile formNewFile = new FormNewFile(formName, projectPath,
packageName, NewFileType.Form, entityModel);
return formNewFile;
}
From the code, we can see that if the end of a domain object contains a Model, the Model is removed, a suffix Form is added to the end, and the path of the Form file to be stored is analyzed. under the form package, because of special project reasons, the path domain objects in our project are generally under the model package, while the form object is generally under the web package, so it is replaced later, replace model with web. create a FormNewFile object.
CreateAssemblerFile is similar to createFormFile.
Integration:
Well, the Form and aggreger files of the domain object have basically been generated. You can call CodeGenerator. generateCode (javaPath) method, pass in the full path name of a java file for testing. If there is no accident, two corresponding files will be generated, but this is definitely not our ultimate goal, this section describes how to create a plug-in. Therefore, we need to integrate this project into the plug-in projects created in the previous sections.
Step 1: first, package the created project into a jar package and export it. Right-click the project and choose Export> JAR file,
public Object execute(ExecutionEvent event) throws ExecutionException {
String path = getSelectPath();
if (null!=path) {
try {
CodeGenerator.generateCode(path);
MessageDialog.openInformation(
null,
"Generate code ",
"Code generated successfully !! ");
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
private String getSelectPath(){
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
ISelection selection = page.getSelection();
IStructuredSelection sel = (IStructuredSelection)selection;
Object element = sel.getFirstElement();
IResource resources = null;
if (element instanceof IResource) {
resources = (IResource) element;
}
if (!(element instanceof IAdaptable)) {
return null;
}
IAdaptable adaptable = (IAdaptable) element;
Object adapter = adaptable.getAdapter(IResource.class);
resources = (IResource) adapter;
String path = resources.getLocationURI().getPath();
if (null!=path) {
if (path.startsWith("/") && path.substring(2, 3).equals(":")) {
path = path.substring(1);
}
}
System.out.println(path);
return path;
}
Example:
Right-click the plug-in project and run as Eclipse Application. After the program runs successfully, create a web project and change the output path of the compilation class file of the project to: web/WEB-INF/classes path, for example:
After all, create a class and click Generate code. The generated directory and Code are as follows:
Well, the writing is a little hasty. If you have any questions that you don't understand or are incorrect, please correct them...
Attachment link: http://files.cnblogs.com/files/haifeng1990/TestPlugin.rar