• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "java_client_proxy_code_emitter.h"
17 #include "util/logger.h"
18 
19 namespace OHOS {
20 namespace Idl {
ResolveDirectory(const std::string & targetDirectory)21 bool JavaClientProxyCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
22 {
23     if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
24         directory_ = GetFileParentPath(targetDirectory);
25     } else {
26         return false;
27     }
28 
29     if (!File::CreateParentDir(directory_)) {
30         Logger::E("CppClientInterfaceCodeEmitter", "Create '%s' failed!", directory_.c_str());
31         return false;
32     }
33 
34     return true;
35 }
36 
EmitCode()37 void JavaClientProxyCodeEmitter::EmitCode()
38 {
39     if (mode_ == GenMode::IPC) {
40         EmitProxyFile();
41     }
42 }
43 
EmitProxyFile()44 void JavaClientProxyCodeEmitter::EmitProxyFile()
45 {
46     std::string filePath =
47         File::AdapterPath(StringHelper::Format("%s/%s.java", directory_.c_str(), FileName(proxyName_).c_str()));
48     File file(filePath, File::WRITE);
49     StringBuilder sb;
50 
51     EmitLicense(sb);
52     EmitPackage(sb);
53     sb.Append("\n");
54     EmitProxyImports(sb);
55     sb.Append("\n");
56     EmitProxyImpl(sb);
57 
58     std::string data = sb.ToString();
59     file.WriteData(data.c_str(), data.size());
60     file.Flush();
61     file.Close();
62 }
63 
EmitProxyImports(StringBuilder & sb) const64 void JavaClientProxyCodeEmitter::EmitProxyImports(StringBuilder &sb) const
65 {
66     EmitProxyCorelibImports(sb);
67     EmitProxySelfDefinedTypeImports(sb);
68     EmitProxyDBinderImports(sb);
69 }
70 
EmitProxyCorelibImports(StringBuilder & sb) const71 void JavaClientProxyCodeEmitter::EmitProxyCorelibImports(StringBuilder &sb) const
72 {
73     bool includeList = false;
74     bool includeMap = false;
75     const AST::TypeStringMap &types = ast_->GetTypes();
76     for (const auto &pair : types) {
77         AutoPtr<ASTType> type = pair.second;
78         switch (type->GetTypeKind()) {
79             case TypeKind::TYPE_LIST: {
80                 if (!includeList) {
81                     sb.Append("import java.util.List;\n");
82                     includeList = true;
83                 }
84                 break;
85             }
86             case TypeKind::TYPE_MAP: {
87                 if (!includeMap) {
88                     sb.Append("import java.util.Map;\n");
89                     sb.Append("import java.util.HashMap;\n");
90                     includeMap = true;
91                 }
92                 break;
93             }
94             default:
95                 break;
96         }
97     }
98 }
99 
EmitProxySelfDefinedTypeImports(StringBuilder & sb) const100 void JavaClientProxyCodeEmitter::EmitProxySelfDefinedTypeImports(StringBuilder &sb) const
101 {
102     for (const auto &importPair : ast_->GetImports()) {
103         AutoPtr<AST> import = importPair.second;
104         sb.AppendFormat("import %s;\n", import->GetFullName().c_str());
105     }
106 }
107 
EmitProxyDBinderImports(StringBuilder & sb) const108 void JavaClientProxyCodeEmitter::EmitProxyDBinderImports(StringBuilder &sb) const
109 {
110     sb.Append("import ohos.hiviewdfx.HiLog;\n");
111     sb.Append("import ohos.hiviewdfx.HiLogLabel;\n");
112     sb.Append("import ohos.rpc.IRemoteObject;\n");
113     sb.Append("import ohos.rpc.RemoteException;\n");
114     sb.Append("import ohos.rpc.MessageParcel;\n");
115     sb.Append("import ohos.rpc.MessageOption;\n");
116 }
117 
EmitProxyImpl(StringBuilder & sb)118 void JavaClientProxyCodeEmitter::EmitProxyImpl(StringBuilder &sb)
119 {
120     sb.AppendFormat("public class %s implements %s {\n", proxyName_.c_str(), interfaceName_.c_str());
121     EmitProxyConstants(sb, TAB);
122     sb.Append("\n");
123     sb.Append(TAB).AppendFormat(
124         "private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_CORE, 0xD002510, \"%s\");\n",
125         interfaceFullName_.c_str());
126     sb.Append(TAB).Append("private final IRemoteObject remote;\n");
127     sb.Append(TAB).Append("private static final int ERR_OK = 0;\n");
128     sb.Append("\n");
129     EmitProxyConstructor(sb, TAB);
130     sb.Append("\n");
131     EmitProxyMethodImpls(sb, TAB);
132     sb.Append("};");
133 }
134 
EmitProxyConstants(StringBuilder & sb,const std::string & prefix)135 void JavaClientProxyCodeEmitter::EmitProxyConstants(StringBuilder &sb, const std::string &prefix)
136 {
137     sb.Append(prefix).AppendFormat(
138         "private static final std::string DESCRIPTOR = \"%s\";\n\n", interfaceFullName_.c_str());
139     EmitInterfaceMethodCommands(sb, prefix);
140 }
141 
EmitProxyConstructor(StringBuilder & sb,const std::string & prefix) const142 void JavaClientProxyCodeEmitter::EmitProxyConstructor(StringBuilder &sb, const std::string &prefix) const
143 {
144     sb.Append(prefix).AppendFormat("public %s(IRemoteObject remote) {\n", proxyName_.c_str());
145     sb.Append(prefix + TAB).Append("this.remote = remote;\n");
146     sb.Append(prefix).Append("}\n");
147     sb.Append("\n");
148     sb.Append(prefix).AppendFormat("@Override\n");
149     sb.Append(prefix).Append("public IRemoteObject asObject() {\n");
150     sb.Append(prefix + TAB).Append("return remote;\n");
151     sb.Append(prefix).Append("}\n");
152 }
153 
EmitProxyMethodImpls(StringBuilder & sb,const std::string & prefix) const154 void JavaClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder &sb, const std::string &prefix) const
155 {
156     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
157         EmitProxyMethodImpl(method, sb, prefix);
158         sb.Append("\n");
159     }
160 }
161 
EmitProxyMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const162 void JavaClientProxyCodeEmitter::EmitProxyMethodImpl(
163     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
164 {
165     sb.Append(prefix).Append("@Override\n");
166     if (method->GetParameterNumber() == 0) {
167         sb.Append(prefix).AppendFormat(
168             "public int %s() throws RemoteException ", MethodName(method->GetName()).c_str());
169     } else {
170         StringBuilder paramStr;
171         paramStr.Append(prefix).AppendFormat("public int %s(", MethodName(method->GetName()).c_str());
172         for (size_t i = 0; i < method->GetParameterNumber(); i++) {
173             AutoPtr<ASTParameter> param = method->GetParameter(i);
174             EmitInterfaceMethodParameter(param, paramStr, "");
175             if (i + 1 < method->GetParameterNumber()) {
176                 paramStr.Append(", ");
177             }
178         }
179         paramStr.Append(") throws RemoteException");
180 
181         sb.Append(SpecificationParam(paramStr, prefix + TAB));
182         sb.Append("\n");
183     }
184     EmitProxyMethodBody(method, sb, prefix);
185 }
186 
EmitProxyMethodBody(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const187 void JavaClientProxyCodeEmitter::EmitProxyMethodBody(
188     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
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         EmitParamWriteVar(param, "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         if (param->GetAttribute() == ASTParamAttr::PARAM_OUT) {
212             AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
213             if (typeEmitter == nullptr) {
214                 continue;
215             }
216             typeEmitter->EmitJavaReadVar("reply", param->GetName(), sb, prefix + TAB + TAB);
217         }
218     }
219 
220     sb.Append(prefix + TAB).Append("} finally {\n");
221     sb.Append(prefix + TAB + TAB).Append("data.reclaim();\n");
222     sb.Append(prefix + TAB + TAB).Append("reply.reclaim();\n");
223     sb.Append(prefix + TAB).Append("}\n");
224     sb.Append(prefix + TAB).Append("return 0;\n");
225     sb.Append(prefix).Append("}\n");
226 }
227 
EmitParamWriteVar(const AutoPtr<ASTParameter> & param,const std::string & parcelName,StringBuilder & sb,const std::string & prefix) const228 void JavaClientProxyCodeEmitter::EmitParamWriteVar(const AutoPtr<ASTParameter> &param,
229     const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
230 {
231     ASTParamAttr::ParamAttr attrAttr = param->GetAttribute();
232     AutoPtr<ASTType> type = param->GetType();
233     std::string name = param->GetName();
234     AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
235     if (typeEmitter == nullptr) {
236         return;
237     }
238     if (attrAttr == ASTParamAttr::PARAM_IN) {
239         typeEmitter->EmitJavaWriteVar(parcelName, name, sb, prefix);
240     }
241     if (attrAttr == ASTParamAttr::PARAM_OUT) {
242         if (type->GetTypeKind() == TypeKind::TYPE_ARRAY) {
243             typeEmitter->EmitJavaWriteVar(parcelName, name, sb, prefix, TypeMode::PARAM_OUT);
244         }
245     }
246 }
247 
EmitLocalVariable(const AutoPtr<ASTParameter> & param,StringBuilder & sb,const std::string & prefix) const248 void JavaClientProxyCodeEmitter::EmitLocalVariable(
249     const AutoPtr<ASTParameter> &param, StringBuilder &sb, const std::string &prefix) const
250 {
251     AutoPtr<ASTType> type = param->GetType();
252     AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
253     if (typeEmitter == nullptr) {
254         return;
255     }
256     if (type->IsSequenceableType()) {
257         sb.Append(prefix).AppendFormat("%s %s = new %s();\n", typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str(),
258             param->GetName().c_str(), typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str());
259     } else if (type->IsListType()) {
260         sb.Append(prefix).AppendFormat("%s %s = new Array%s();\n", typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str(),
261             param->GetName().c_str(), typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str());
262     } else if (type->IsMapType()) {
263         sb.Append(prefix).AppendFormat("%s %s = new Hash%s();\n", typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str(),
264             param->GetName().c_str(), typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str());
265     } else {
266         sb.Append(prefix).AppendFormat(
267             "%s %s;\n", typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str(), param->GetName().c_str());
268     }
269 }
270 } // namespace Idl
271 } // namespace OHOS