/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package beans.service;
import beans.dbaccess.IDL;
import ngse.org.*;
import org.apache.log4j.Logger;
import javax.servlet.ServletOutputStream;
import java.io.*;
/**
* Created by Administrator on 2016/2/17.
* 根据某个IDL版本,生成代码并下载下去
*/
public class IDLGeneCodeAndDownload extends JsonRPCHandler {
private void copy3rdAPI(String destDir) throws Exception
{
Logger logger = Logger.getLogger(IDLGeneCodeAndDownload.class);
InputStream inputStream = this.getServlet().getServletContext().getResourceAsStream("/resource/3rd_API.tar.gz");
String destFile = destDir + File.separator + "3rd_API.tar.gz";
logger.info("copy 3rd API to " + destFile);
File f = null;
OutputStream outputStream = new FileOutputStream(destFile);
byte[] buf = new byte[10240];
int len;
while (true) {
len = inputStream.read(buf);
if (len <= 0) {
break;
}
outputStream.write(buf, 0, len);
}
outputStream.close();
inputStream.close();
}
private void genPhpCode(String protofile, String outputDir) throws Exception
{
Logger logger = Logger.getLogger(PackDevFile.class);
String rnd = ""+(int)(Math.random() * 1000000);
InputStream inputStream = getServlet().getServletContext().getResourceAsStream("/resource/spp_dev.tar");
String tmpTarFile = ServletConfig.fileServerRootDir + "/tmp/genPhpCode"+rnd+".tar";
String baseDir = ServletConfig.fileServerRootDir + "/tmp/genPhpCode"+rnd+"_basedir";
logger.info("copy php framework from resource to "+tmpTarFile);
File f = null;
//将资源文件拷贝到文件系统中的普通文件,并解压缩为目录baseDir
try
{
byte[] buf = new byte[10240];
int len;
OutputStream outputStream = new FileOutputStream(tmpTarFile);
while (true) {
len = inputStream.read(buf);
if (len <= 0) {
break;
}
outputStream.write(buf, 0, len);
}
outputStream.close();
inputStream.close();
//把普通文件解包到目录baseDir
TarUtil.dearchive(new File(tmpTarFile), new File(baseDir));
logger.info("dearchive tar to " + baseDir);
//执行python脚本产生php代码
String[] cmd = new String[5];
String pythonScript;
pythonScript = baseDir + "/rpc/php_template/create_rpc.py";
new File(pythonScript).setExecutable(true);
cmd[0] = pythonScript;
cmd[1] = protofile;
cmd[2] = baseDir;
cmd[3] = outputDir;
cmd[4] = "--protoc";
StringBuffer cmdResult = new StringBuffer();
if (Tools.runCommand(cmd, cmdResult, true) != 0)
{
throw new Exception("gene php code failed:"+cmdResult);
}
logger.info("run python script successfully.");
}
finally {
//删除普通文件
try {
new File(tmpTarFile).delete();
Tools.deleteDirectory(new File(baseDir));
}
catch (Exception e){}
}
}
public JsonRPCResponseBase exec(IDL request)
{
JsonRPCResponseBase response = new JsonRPCResponseBase();
Logger logger = Logger.getLogger(this.getClass());
String result = checkIdentity();
if (!result.equals("success"))
{
response.setStatus(99);
response.setMessage(result);
return response;
}
String flsn = request.getFirst_level_service_name();
String slsn = request.getSecond_level_service_name();
String tag = request.getTag_name();
if (flsn == null || flsn.length() < 1 ||
slsn == null || slsn.length() < 1||
tag == null || tag.length() < 1)
{
response.setMessage("service name/tag is empty!");
response.setStatus(100);
return response;
}
// 调用外部的protoc命令,生成代码保存到指定目录
logger.info("call protoc to generate code");
String rnd = String.format("%d", (int)( Math.random()*Integer.MAX_VALUE) );
String destDir = ServletConfig.fileServerRootDir+ File.separator+"tmp"+File.separator+"IDLGeneCode_"+slsn+"_"+rnd;
String cpp_out = destDir + File.separator+"cpp";
String java_out = destDir + File.separator+"java";
String php_out = destDir + File.separator+"php";
String py_out = destDir + File.separator+"python";
logger.info("code generation destDir="+destDir);
File f = new File(destDir);
if (f.isFile())
{
f.delete();
}
else if (f.isDirectory())
{
Tools.deleteDirectory(f);
}
f.mkdir();
new File(cpp_out).mkdir();
new File(java_out).mkdir();
new File(php_out).mkdir();
new File(py_out).mkdir();
//将第三方(例如cgi)要用到的库拷贝到目标目录
try
{
copy3rdAPI(destDir);
}
catch (Exception e)
{
e.printStackTrace();
response.setMessage("copy 3rd API failed"+e.getMessage());
response.setStatus(100);
return response;
}
String tarFileName = destDir +".tar";
try {
// protoc 命令生成代码
String idlFileName = IDL.getIDLFileName(flsn, slsn, tag);
String newIDLFileName = destDir + File.separator+ flsn+"_"+slsn+".proto";
Tools.copyFile(idlFileName, newIDLFileName);
String[] cmd = {"protoc", "--cpp_out=" + cpp_out, "--java_out=" + java_out,"--python_out="+py_out, "-I"+destDir, newIDLFileName};
StringBuffer sb = new StringBuffer();
int v = Tools.runCommand(cmd, sb, true);
if (v != 0)
{
throw new Exception("Cmd protoc failed!"+sb.toString());
}
logger.info(String.format("protoc compile:%d, %s", v, sb.toString()));
// pb这个版本不支持直接生成php的代码,只好自己实现
genPhpCode(newIDLFileName,php_out);
//打成tar包
logger.info("generate tar file...");
TarUtil.archive(destDir, tarFileName);
Tools.deleteDirectory(new File(destDir));
}
catch (Exception e)
{
e.printStackTrace();
response.setMessage(e.getMessage());
response.setStatus(100);
return response;
}
//把tar包下载下去
f = new File(tarFileName);
String length = String.format("%d", f.length());
logger.info("download tar file, file length:"+f.length());
getHttpResponse().setHeader("Content-disposition", "attachment;filename=" + f.getName());
// set the MIME type.
getHttpResponse().setContentType("application/x-tar");
getHttpResponse().setHeader("Content_Length", length);
try {
ServletOutputStream out = getHttpResponse().getOutputStream();
FileInputStream fileInputStream = new FileInputStream(f);
byte[] buf = new byte[10240];
while (true)
{
int len = fileInputStream.read(buf);
if (len <= 0)
{
break;
}
out.write(buf,0, len);
}
out.close();
fileInputStream.close();
f.delete();
return null;
}
catch (Exception e)
{
e.printStackTrace();
}
return response;
}
}