Skip to content

Commit a20e749

Browse files
committed
(1)新增module-api的独立gradle plugin,不依赖于ArbitraryGen的gradle plugin,直接在插件内部集成ArbitraryGen生成代码逻辑;
(2)将api代码生成时机提前到gradle configuration阶段,用于生成跨module的接口; (3)解决在windows下路径识别失败的问题;
1 parent 14cb0e6 commit a20e749

File tree

5 files changed

+384
-54
lines changed

5 files changed

+384
-54
lines changed

module-api-ag-extension/src/main/groovy/cc/suitalk/gradle/plugin/ModuleApiAGExtensionPlugin.groovy

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,13 @@ class ModuleApiAGExtensionPlugin implements Plugin<Project> {
7575
File srcDir = this.project.file(moduleApi.srcDir)
7676
File destDir = this.project.file(moduleApi.destDir)
7777

78-
if (srcDir == null || !srcDir.exists() || destDir == null || !destDir.exists()) {
78+
if (srcDir == null || !srcDir.exists() || destDir == null) {
7979
println("project: ${this.project} do not exists moduleApi srcDir or destDir.")
8080
return
8181
}
82+
if (!destDir.exists()) {
83+
destDir.mkdirs()
84+
}
8285
copyFiles(srcDir, destDir)
8386
}
8487
}
@@ -122,8 +125,12 @@ class ModuleApiAGExtensionPlugin implements Plugin<Project> {
122125
collectFiles(list, srcDir)
123126
for (File file : list) {
124127
String path = file.getAbsolutePath()
125-
String destPath = path.replaceFirst(srcDir.getAbsolutePath(), destDir.getAbsolutePath())
126-
.replaceAll('^([^\\.]*)\\.api$', '$1.java')
128+
// String destPath = path.replaceFirst(srcDir.getAbsolutePath(), destDir.getAbsolutePath())
129+
// .replaceAll('^([^\\.]*)\\.api$', '$1.java')
130+
String destPath = (destDir.getAbsolutePath() + path.substring(srcDir.getAbsolutePath().length()))
131+
if (destPath.endsWith(".api")) {
132+
destPath = destPath.substring(0, destPath.length() - ".api".length()) + ".java"
133+
}
127134
copyFile(file, new File(destPath))
128135
println("copy file($path) to $destPath")
129136
}
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
/*
2+
* Copyright (C) 2016-present Albie Liang. All rights reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package cc.suitalk.gradle.plugin
19+
20+
import cc.suitalk.arbitrarygen.core.ArbitraryGenContext
21+
import cc.suitalk.arbitrarygen.core.ArgsConstants
22+
import cc.suitalk.arbitrarygen.core.Core
23+
import cc.suitalk.arbitrarygen.core.DefaultArbitraryGenInitializer
24+
import cc.suitalk.arbitrarygen.engine.JavaCodeAGEngine
25+
import cc.suitalk.arbitrarygen.extension.AGContext
26+
import cc.suitalk.arbitrarygen.extension.ArbitraryGenProcessor
27+
import cc.suitalk.arbitrarygen.impl.AGAnnotationWrapper
28+
import cc.suitalk.arbitrarygen.template.TemplateManager
29+
import cc.suitalk.arbitrarygen.tools.RuntimeContextHelper
30+
import cc.suitalk.arbitrarygen.utils.FileOperation
31+
import cc.suitalk.arbitrarygen.utils.JSONArgsUtils
32+
import cc.suitalk.arbitrarygen.utils.Log
33+
import cc.suitalk.moduleapi.ag.extension.ModuleApiAGContextExtension
34+
import cc.suitalk.moduleapi.ag.extension.ModuleApiTaskProcessor
35+
import groovy.json.JsonBuilder
36+
import net.sf.json.JSONArray
37+
import net.sf.json.JSONObject
38+
import org.gradle.api.Plugin
39+
import org.gradle.api.Project
40+
41+
/**
42+
*
43+
* Created by albieliang on 2018/2/1.
44+
*
45+
*/
46+
class ModuleApiPlugin implements Plugin<Project> {
47+
48+
static {
49+
loadTemplate("module-api-gentask", "/res/ag-template/ModuleApi.ag-template");
50+
}
51+
52+
private static void loadTemplate(String tag, String templatePath) {
53+
String template = "";
54+
InputStream is = ModuleApiAGContextExtension.class.getResourceAsStream(templatePath);
55+
// Log.i(TAG, "doGet(jarPath : %s)", ModuleApiAGContextExtension.class.getProtectionDomain().getCodeSource().getLocation().getPath());
56+
if (is != null) {
57+
template = FileOperation.read(is);
58+
try {
59+
is.close();
60+
} catch (IOException e) {
61+
}
62+
}
63+
if (template != null && template.length() > 0) {
64+
TemplateManager.getImpl().put(tag, template);
65+
}
66+
}
67+
68+
Project project;
69+
ModuleApiPluginExtension extension;
70+
71+
@Override
72+
void apply(Project project) {
73+
this.project = project
74+
println("project ${project.name} apply ModuleApiPlugin")
75+
76+
extension = project.extensions.create("moduleApi", ModuleApiPluginExtension)
77+
project.afterEvaluate {
78+
def moduleApiClosure = this.project["moduleApi"]
79+
if (moduleApiClosure == null) {
80+
println("closure moduleApi is null, skip")
81+
return
82+
}
83+
if (moduleApiClosure.srcDir == null || moduleApiClosure.destDir == null) {
84+
println("project(${project.name}), moduleApi.srcDir or moduleApi.destDir is null")
85+
return
86+
}
87+
JSONObject initArg = new JSONObject();
88+
initArg.put("srcDir", (moduleApiClosure.srcDir == null ? "" : moduleApiClosure.srcDir))
89+
initArg.put("destDir", (moduleApiClosure.destDir == null ? "" : moduleApiClosure.destDir))
90+
initArg.put("templateDir", (moduleApiClosure.templateDir == null ? "" : moduleApiClosure.templateDir))
91+
if (extension.makeApiRules != null && extension.makeApiRules.length > 0) {
92+
JSONArray jsonArray = new JSONArray();
93+
for (String rule : extension.makeApiRules) {
94+
jsonArray.add(rule)
95+
}
96+
initArg.put("makeApiRules", jsonArray)
97+
}
98+
if (extension.logger != null) {
99+
JsonBuilder jsonBuilder = new JsonBuilder()
100+
jsonBuilder {
101+
logger extension.logger
102+
}
103+
println("ModuleApi : ${jsonBuilder.toString()}")
104+
JSONObject loggerJson = JSONObject.fromObject(jsonBuilder.toString())
105+
if (!loggerJson.isNullObject() && !loggerJson.isEmpty()) {
106+
initArg.put("logger", loggerJson.get("logger"))
107+
}
108+
109+
}
110+
111+
println "moduleApi(${this.project.name}) srcDir : '${moduleApiClosure.srcDir}'"
112+
println "moduleApi(${this.project.name}) destDir : '${moduleApiClosure.destDir}'"
113+
println "moduleApi(${this.project.name}) makeApiRules : '${moduleApiClosure.makeApiRules}'"
114+
115+
File srcDir = this.project.file(moduleApiClosure.srcDir)
116+
File destDir = this.project.file(moduleApiClosure.destDir)
117+
118+
if (srcDir == null || !srcDir.exists() || destDir == null) {
119+
println("project: ${this.project} do not exists moduleApi srcDir or destDir.")
120+
return
121+
}
122+
if (!destDir.exists()) {
123+
destDir.mkdirs()
124+
}
125+
// copy and rename `*.api` files
126+
copyFiles(srcDir, destDir)
127+
128+
JSONObject envJson = new JSONObject();
129+
130+
envJson.put("buildDir", this.project.buildDir.getAbsolutePath())
131+
JSONObject projectJson = new JSONObject();
132+
projectJson.put("name", this.project.name)
133+
projectJson.put("projectDir", this.project.projectDir.getAbsolutePath())
134+
projectJson.put("rootDir", this.project.rootDir.getAbsolutePath())
135+
envJson.put("project", projectJson)
136+
137+
makeApi(initArg, envJson)
138+
}
139+
}
140+
141+
def copyFiles(JSONArray srcRules, File destDir) {
142+
println("copyFiles($srcRules, $destDir)")
143+
List<File> list = collectFiles(srcRules)
144+
for (File file : list) {
145+
String path = file.getAbsolutePath()
146+
String destPath = path.replaceFirst(srcDir.getAbsolutePath(), destDir.getAbsolutePath())
147+
.replaceAll('^([^\\.]*)\\.api$', '$1.java')
148+
copyFile(file, new File(destPath))
149+
println("copy file($path) to $destPath")
150+
}
151+
}
152+
153+
List<File> collectFiles(JSONArray srcRules) {
154+
List<File> list = new LinkedList();
155+
JSONObject args = new JSONObject();
156+
args.put(ArgsConstants.EXTERNAL_ARGS_KEY_RULE, srcRules)
157+
JSONObject result = Core.exec("rule-processor", args)
158+
JSONArray fileArray = result.getJSONArray("fileArray")
159+
if (fileArray.isEmpty()) {
160+
return list
161+
}
162+
for (int i = 0; i < fileArray.size(); i++) {
163+
String path = fileArray.getString(i)
164+
if (path == null) {
165+
continue
166+
}
167+
if (path.endsWith(".api")) {
168+
list.add(new File(path))
169+
}
170+
}
171+
return list
172+
}
173+
174+
def copyFiles(File srcDir, File destDir) {
175+
println("copyFiles($srcDir, $destDir)")
176+
List<File> list = new LinkedList();
177+
collectFiles(list, srcDir)
178+
for (File file : list) {
179+
String path = file.getAbsolutePath()
180+
String destPath = (destDir.getAbsolutePath() + path.substring(srcDir.getAbsolutePath().length()))
181+
if (destPath.endsWith(".api")) {
182+
destPath = destPath.substring(0, destPath.length() - ".api".length()) + ".java"
183+
}
184+
copyFile(file, new File(destPath))
185+
println("copy file($path) to $destPath")
186+
}
187+
}
188+
189+
def copyFile(File srcFile, File destFile) {
190+
InputStream is = null
191+
OutputStream os = null
192+
try {
193+
if (!destFile.getParentFile().exists()) {
194+
destFile.getParentFile().mkdirs()
195+
}
196+
is = new FileInputStream(srcFile)
197+
os = new FileOutputStream(destFile)
198+
final int bufferSize = 1024 * 64
199+
byte[] buffer = new byte[bufferSize]
200+
int ret = 0;
201+
while ((ret = is.read(buffer)) != -1) {
202+
os.write(buffer, 0, ret)
203+
}
204+
os.flush()
205+
return
206+
} catch (Exception e) {
207+
println("copyFile error : $e")
208+
} finally {
209+
if (is != null) {
210+
try {
211+
is.close()
212+
} catch (Exception e) {
213+
}
214+
}
215+
if (os != null) {
216+
try {
217+
os.close()
218+
} catch (Exception e) {
219+
}
220+
}
221+
}
222+
}
223+
224+
def collectFiles(List<File> list, File file) {
225+
if (file.isFile()) {
226+
if (file.name.endsWith(".api")) {
227+
list.add(file)
228+
}
229+
} else if (file.isDirectory()) {
230+
for (File f : file.listFiles()) {
231+
collectFiles(list, f)
232+
}
233+
}
234+
}
235+
236+
def makeApi(JSONObject initArgs, JSONObject envJson) {
237+
JSONArray makeApiRules = JSONArgsUtils.getJSONArray(initArgs, "makeApiRules", true);
238+
if (makeApiRules == null) {
239+
makeApiRules = new JSONArray();
240+
}
241+
if (makeApiRules.isEmpty()) {
242+
String srcDir = initArgs.getString("srcDir");
243+
if (srcDir == null || srcDir.length() == 0) {
244+
Log.e(TAG, "makeApi, neither moduleApi.srcDir nor moduleApi.makeApiRules is null or nil, skip.");
245+
return;
246+
}
247+
if (srcDir.endsWith("/")) {
248+
makeApiRules.add(srcDir + "*");
249+
} else {
250+
makeApiRules.add(srcDir + "/*");
251+
}
252+
}
253+
String destDir = initArgs.getString("destDir");
254+
if (destDir == null || destDir.length() == 0) {
255+
Log.e(TAG, "makeApi, moduleApi.destDir is null or nil, skip.");
256+
return;
257+
}
258+
259+
println("${initArgs.toString()}")
260+
println("${envJson.toString()}")
261+
262+
Core.initialize(DefaultArbitraryGenInitializer.INSTANCE);
263+
//
264+
// Initialize Environment arguments
265+
RuntimeContextHelper.initialize(envJson);
266+
// For new engine framework
267+
AGContext context = new ArbitraryGenContext();
268+
269+
ArbitraryGenProcessor processor = context.getProcessor("javaCodeEngine");
270+
if (processor instanceof JavaCodeAGEngine) {
271+
JavaCodeAGEngine engine = (JavaCodeAGEngine) processor;
272+
AGAnnotationWrapper annWrapper = new AGAnnotationWrapper();
273+
annWrapper.addAnnotationProcessor(new ModuleApiTaskProcessor());
274+
engine.addTypeDefWrapper(annWrapper);
275+
276+
JSONObject javaCodeEngine = new JSONObject();
277+
JSONArray ruleArray = new JSONArray();
278+
ruleArray.addAll(makeApiRules);
279+
javaCodeEngine.put("rule", ruleArray);
280+
initArgs.put("javaCodeEngine", javaCodeEngine);
281+
context.getKeyValueSet().put("apiDestPath", destDir);
282+
}
283+
context.initialize(initArgs);
284+
context.execute();
285+
Log.close();
286+
}
287+
}
288+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (C) 2017-present Albie Liang. All rights reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package cc.suitalk.gradle.plugin;
19+
20+
class ModuleApiPluginExtension {
21+
22+
String templateDir;
23+
String srcDir;
24+
String destDir;
25+
26+
String[] makeApiRules
27+
28+
Closure logger
29+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
implementation-class=cc.suitalk.gradle.plugin.ModuleApiPlugin

0 commit comments

Comments
 (0)