1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "codegen/java_client_proxy_code_emitter.h"
10 #include "util/logger.h"
11
12 namespace OHOS {
13 namespace HDI {
ResolveDirectory(const std::string & targetDirectory)14 bool JavaClientProxyCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
15 {
16 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
17 directory_ = GetFileParentPath(targetDirectory);
18 } else {
19 return false;
20 }
21
22 if (!File::CreateParentDir(directory_)) {
23 Logger::E("CppClientInterfaceCodeEmitter", "Create '%s' failed!", directory_.c_str());
24 return false;
25 }
26
27 return true;
28 }
29
EmitCode()30 void JavaClientProxyCodeEmitter::EmitCode()
31 {
32 EmitProxyFile();
33 }
34
EmitProxyFile()35 void JavaClientProxyCodeEmitter::EmitProxyFile()
36 {
37 std::string filePath =
38 File::AdapterPath(StringHelper::Format("%s/%s.java", directory_.c_str(), FileName(proxyName_).c_str()));
39 File file(filePath, File::WRITE);
40 StringBuilder sb;
41
42 EmitLicense(sb);
43 EmitPackage(sb);
44 sb.Append("\n");
45 EmitProxyImports(sb);
46 sb.Append("\n");
47 EmitProxyImpl(sb);
48
49 std::string data = sb.ToString();
50 file.WriteData(data.c_str(), data.size());
51 file.Flush();
52 file.Close();
53 }
54
EmitProxyImports(StringBuilder & sb)55 void JavaClientProxyCodeEmitter::EmitProxyImports(StringBuilder &sb)
56 {
57 EmitProxyCorelibImports(sb);
58 EmitProxySelfDefinedTypeImports(sb);
59 EmitProxyDBinderImports(sb);
60 }
61
EmitProxyCorelibImports(StringBuilder & sb)62 void JavaClientProxyCodeEmitter::EmitProxyCorelibImports(StringBuilder &sb)
63 {
64 bool includeList = false;
65 bool includeMap = false;
66 const AST::TypeStringMap &types = ast_->GetTypes();
67 for (const auto &pair : types) {
68 AutoPtr<ASTType> type = pair.second;
69 switch (type->GetTypeKind()) {
70 case TypeKind::TYPE_LIST: {
71 if (!includeList) {
72 sb.Append("import java.util.List;\n");
73 includeList = true;
74 }
75 break;
76 }
77 case TypeKind::TYPE_MAP: {
78 if (!includeMap) {
79 sb.Append("import java.util.Map;\n");
80 sb.Append("import java.util.HashMap;\n");
81 includeMap = true;
82 }
83 break;
84 }
85 default:
86 break;
87 }
88 }
89 }
90
EmitProxySelfDefinedTypeImports(StringBuilder & sb)91 void JavaClientProxyCodeEmitter::EmitProxySelfDefinedTypeImports(StringBuilder &sb)
92 {
93 for (const auto &importPair : ast_->GetImports()) {
94 AutoPtr<AST> import = importPair.second;
95 sb.AppendFormat("import %s;\n", import->GetFullName().c_str());
96 }
97 }
98
EmitProxyDBinderImports(StringBuilder & sb)99 void JavaClientProxyCodeEmitter::EmitProxyDBinderImports(StringBuilder &sb)
100 {
101 sb.Append("import ohos.hiviewdfx.HiLog;\n");
102 sb.Append("import ohos.hiviewdfx.HiLogLabel;\n");
103 sb.Append("import ohos.rpc.IRemoteObject;\n");
104 sb.Append("import ohos.rpc.RemoteException;\n");
105 sb.Append("import ohos.rpc.MessageParcel;\n");
106 sb.Append("import ohos.rpc.MessageOption;\n");
107 }
108
EmitProxyImpl(StringBuilder & sb)109 void JavaClientProxyCodeEmitter::EmitProxyImpl(StringBuilder &sb)
110 {
111 sb.AppendFormat("public class %s implements %s {\n", proxyName_.c_str(), interfaceName_.c_str());
112 EmitProxyConstants(sb, TAB);
113 sb.Append("\n");
114 sb.Append(TAB).AppendFormat(
115 "private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_CORE, 0xD001510, \"%s\");\n",
116 interfaceFullName_.c_str());
117 sb.Append(TAB).Append("private final IRemoteObject remote;\n");
118 sb.Append(TAB).Append("private static final int ERR_OK = 0;\n");
119 sb.Append("\n");
120 EmitProxyConstructor(sb, TAB);
121 sb.Append("\n");
122 EmitProxyMethodImpls(sb, TAB);
123 sb.Append("};");
124 }
125
EmitProxyConstants(StringBuilder & sb,const std::string & prefix)126 void JavaClientProxyCodeEmitter::EmitProxyConstants(StringBuilder &sb, const std::string &prefix)
127 {
128 sb.Append(prefix).AppendFormat(
129 "private static final std::string DESCRIPTOR = \"%s\";\n\n", interfaceFullName_.c_str());
130 EmitInterfaceMethodCommands(sb, prefix);
131 }
132
EmitProxyConstructor(StringBuilder & sb,const std::string & prefix)133 void JavaClientProxyCodeEmitter::EmitProxyConstructor(StringBuilder &sb, const std::string &prefix)
134 {
135 sb.Append(prefix).AppendFormat("public %s(IRemoteObject remote) {\n", proxyName_.c_str());
136 sb.Append(prefix + TAB).Append("this.remote = remote;\n");
137 sb.Append(prefix).Append("}\n");
138 sb.Append("\n");
139 sb.Append(prefix).AppendFormat("@Override\n");
140 sb.Append(prefix).Append("public IRemoteObject asObject() {\n");
141 sb.Append(prefix + TAB).Append("return remote;\n");
142 sb.Append(prefix).Append("}\n");
143 }
144
EmitProxyMethodImpls(StringBuilder & sb,const std::string & prefix)145 void JavaClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder &sb, const std::string &prefix)
146 {
147 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
148 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
149 EmitProxyMethodImpl(method, sb, prefix);
150 if (i + 1 < interface_->GetMethodNumber()) {
151 sb.Append("\n");
152 }
153 }
154 }
155
EmitProxyMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)156 void JavaClientProxyCodeEmitter::EmitProxyMethodImpl(
157 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
158 {
159 sb.Append(prefix).Append("@Override\n");
160 if (method->GetParameterNumber() == 0) {
161 sb.Append(prefix).AppendFormat(
162 "public int %s() throws RemoteException ", MethodName(method->GetName()).c_str());
163 } else {
164 StringBuilder paramStr;
165 paramStr.Append(prefix).AppendFormat("public int %s(", MethodName(method->GetName()).c_str());
166 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
167 AutoPtr<ASTParameter> param = method->GetParameter(i);
168 EmitInterfaceMethodParameter(param, paramStr, "");
169 if (i + 1 < method->GetParameterNumber()) {
170 paramStr.Append(", ");
171 }
172 }
173 paramStr.Append(") throws RemoteException");
174
175 sb.Append(SpecificationParam(paramStr, prefix + TAB));
176 sb.Append("\n");
177 }
178 EmitProxyMethodBody(method, sb, prefix);
179 }
180
EmitInterfaceMethodParameter(const AutoPtr<ASTParameter> & param,StringBuilder & sb,const std::string & prefix)181 void JavaClientProxyCodeEmitter::EmitInterfaceMethodParameter(
182 const AutoPtr<ASTParameter> ¶m, StringBuilder &sb, const std::string &prefix)
183 {
184 sb.Append(prefix).Append(param->EmitJavaParameter());
185 }
186
EmitProxyMethodBody(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)187 void JavaClientProxyCodeEmitter::EmitProxyMethodBody(
188 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
189 {
190 sb.Append(prefix).Append("{\n");
191 sb.Append(prefix + TAB).Append("MessageParcel data = MessageParcel.obtain();\n");
192 sb.Append(prefix + TAB).Append("MessageParcel reply = MessageParcel.obtain();\n");
193 sb.Append(prefix + TAB).AppendFormat("MessageOption option = new MessageOption(MessageOption.TF_SYNC);\n");
194 sb.Append("\n");
195 sb.Append(prefix).AppendFormat(" data.writeInterfaceToken(DESCRIPTOR);\n");
196
197 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
198 AutoPtr<ASTParameter> param = method->GetParameter(i);
199 param->EmitJavaWriteVar("data", sb, prefix + TAB);
200 }
201 sb.Append("\n");
202
203 sb.Append(prefix + TAB).Append("try {\n");
204 sb.Append(prefix + TAB + TAB).AppendFormat("if (remote.sendRequest(COMMAND_%s, data, reply, option)) {\n",
205 ConstantName(method->GetName()).c_str());
206 sb.Append(prefix + TAB + TAB + TAB).Append("return 1;\n");
207 sb.Append(prefix + TAB + TAB).Append("}\n");
208 sb.Append(prefix + TAB).Append(" reply.readException();\n");
209 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
210 AutoPtr<ASTParameter> param = method->GetParameter(i);
211 param->EmitJavaReadVar("reply", sb, prefix + TAB + TAB);
212 }
213
214 sb.Append(prefix + TAB).Append("} finally {\n");
215 sb.Append(prefix + TAB + TAB).Append("data.reclaim();\n");
216 sb.Append(prefix + TAB + TAB).Append("reply.reclaim();\n");
217 sb.Append(prefix + TAB).Append("}\n");
218 sb.Append(prefix + TAB).Append("return 0;\n");
219 sb.Append(prefix).Append("}\n");
220 }
221
EmitLocalVariable(const AutoPtr<ASTParameter> & param,StringBuilder & sb,const std::string & prefix)222 void JavaClientProxyCodeEmitter::EmitLocalVariable(
223 const AutoPtr<ASTParameter> ¶m, StringBuilder &sb, const std::string &prefix)
224 {
225 AutoPtr<ASTType> type = param->GetType();
226 if (type->GetTypeKind() == TypeKind::TYPE_SEQUENCEABLE) {
227 sb.Append(prefix).AppendFormat("%s %s = new %s();\n", type->EmitJavaType(TypeMode::NO_MODE).c_str(),
228 param->GetName().c_str(), type->EmitJavaType(TypeMode::NO_MODE).c_str());
229 } else if (type->GetTypeKind() == TypeKind::TYPE_LIST) {
230 sb.Append(prefix).AppendFormat("%s %s = new Array%s();\n", type->EmitJavaType(TypeMode::NO_MODE).c_str(),
231 param->GetName().c_str(), type->EmitJavaType(TypeMode::NO_MODE).c_str());
232 } else if (type->GetTypeKind() == TypeKind::TYPE_MAP) {
233 sb.Append(prefix).AppendFormat("%s %s = new Hash%s();\n", type->EmitJavaType(TypeMode::NO_MODE).c_str(),
234 param->GetName().c_str(), type->EmitJavaType(TypeMode::NO_MODE).c_str());
235 } else {
236 sb.Append(prefix).AppendFormat(
237 "%s %s;\n", type->EmitJavaType(TypeMode::NO_MODE).c_str(), param->GetName().c_str());
238 }
239 }
240 } // namespace HDI
241 } // namespace OHOS