帆软报表设计器源代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

364 lines
14 KiB

package com.fr.design.mainframe.alphafine.search.helper;
import com.fr.base.login.ClientHelper;
import com.fr.design.DesignerEnvManager;
import com.fr.design.extra.PluginConstants;
import com.fr.design.mainframe.alphafine.download.FineMarketDownloadManager;
import com.fr.design.mainframe.alphafine.model.TemplateResource;
import com.fr.file.FileCommonUtils;
import com.fr.general.CloudCenter;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.market.key.FineMarketPublicKeyHolder;
import com.fr.security.SecurityToolbox;
import com.fr.stable.EncodeConstants;
import com.fr.stable.StableUtils;
import com.fr.third.org.apache.http.HttpEntity;
import com.fr.third.org.apache.http.HttpException;
import com.fr.third.org.apache.http.HttpStatus;
import com.fr.third.org.apache.http.client.config.CookieSpecs;
import com.fr.third.org.apache.http.client.config.RequestConfig;
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse;
import com.fr.third.org.apache.http.client.methods.HttpUriRequest;
import com.fr.third.org.apache.http.client.methods.RequestBuilder;
import com.fr.third.org.apache.http.impl.client.BasicCookieStore;
import com.fr.third.org.apache.http.impl.client.CloseableHttpClient;
import com.fr.third.org.apache.http.impl.client.HttpClients;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* alphafine - 帆软市场助手
*
* @author Link
* @version 10.0
* Created by Link on 2022/9/22
* */
public class FineMarketClientHelper {
private static final FineMarketClientHelper INSTANCE = new FineMarketClientHelper();
public static FineMarketClientHelper getInstance() {
return INSTANCE;
}
private static final String CERTIFICATE_PUBLIC_KEY = FineMarketPublicKeyHolder.getInstance().getDefaultKey();
public static final String FINE_MARKET_TEMPLATE_INFO = CloudCenter.getInstance().acquireUrlByKind("market.template.info");
public static final String FINE_MARKET_TEMPLATE_URL = CloudCenter.getInstance().acquireUrlByKind("market.template.url");
public static final String VERSION = "version";
public static final String CURRENT_VERSION = "10.0";
public static final String FILE_DOWNLOAD = "file/download/";
public static final String PACKAGE_DOWNLOAD = "package/download/";
public static final String TEMPLATES_PARENT_PACKAGE = "parent/";
public static final String TEMPLATES_TAGS = "filter";
public static final String NAME_SEARCH = "searchKeyword";
public static final String RESPONSE_STATE = "state";
public static final String RESPONSE_SUCCESS = "ok";
public static final String RESPONSE_RESULT = "result";
public static final String TAGS_KEY = "key";
public static final String TAGS_ITEMS = "items";
public static final String TAG_NAME = "name";
public static final String TAG_ID = "id";
private static final String FILENAME_FORMAT = ".+?(.zip|.rar|.cpt|.frm)";
private static final Pattern FILENAME_PATTERN = Pattern.compile(FILENAME_FORMAT);
// 缓存下所有tag标签
private Map<String, String> tags;
/**
* 获取模板资源的下载链接
* */
public String getResourceDownloadUrl(TemplateResource templateResource) {
if (TemplateResource.Type.SCENARIO_SOLUTION.equals(templateResource.getType())) {
return getPackageDownloadUrl();
} else {
return getFileDownLoadUrl();
}
}
private String getPackageDownloadUrl() {
return FINE_MARKET_TEMPLATE_INFO + PACKAGE_DOWNLOAD;
}
private String getFileDownLoadUrl() {
return FINE_MARKET_TEMPLATE_INFO + FILE_DOWNLOAD;
}
/**
* 下载
* */
public String download(TemplateResource resource, File destDir, com.fr.design.extra.Process<Double> process) throws Exception {
String resourceId = resource.getId();
CloseableHttpResponse fileRes = getFileResponse(resource, resourceId);
if (fileRes.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
File destFile = createDestFile(destDir, resource);
StableUtils.makesureFileExist(destFile);
InputStream content = null;
FileOutputStream writer = null;
try {
writer = new FileOutputStream(FileCommonUtils.getAbsolutePath(destFile));
HttpEntity entity = fileRes.getEntity();
long totalSize = entity.getContentLength();
content = entity.getContent();
byte[] data = new byte[PluginConstants.BYTES_NUM];
int bytesRead;
int totalBytesRead = 0;
while ((bytesRead = content.read(data)) > 0) {
writer.write(data, 0, bytesRead);
data = new byte[PluginConstants.BYTES_NUM];
totalBytesRead += bytesRead;
process.process(totalBytesRead / (double) totalSize);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
} finally {
content.close();
writer.flush();
writer.close();
}
FineLoggerFactory.getLogger().info("download resource{} success", resourceId);
process.process(FineMarketDownloadManager.PROCESS_SUCCESS);
return FileCommonUtils.getAbsolutePath(destFile);
} else {
FineLoggerFactory.getLogger().info("download resource{} failed", resourceId);
process.process(FineMarketDownloadManager.PROCESS_FAILED);
throw new HttpException();
}
}
private CloseableHttpResponse getFileResponse(TemplateResource resource, String resourceId) throws Exception {
CloseableHttpResponse fileRes = postDownloadHttpResponse(getResourceDownloadUrl(resource), resourceId);
if (fileRes.getStatusLine().getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY) {
fileRes = getDownloadHttpResponse(fileRes.getHeaders("Location")[0].getValue());
}
return fileRes;
}
/**
* 在目标路径下(destDir)创建与资源名称相同的文件夹 (finalDir)
* 将资源下载到 destDir/finalDir
* 如果文件重复,则在文件名前加自增id
* */
private File createDestFile(File destDir, TemplateResource resource) {
String fileName = resource.getName();
File finalDir = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(destDir), fileName));
try {
if (!finalDir.exists()) {
finalDir.mkdir();
}
fileName = resource.getFileName();
fileName = rename(fileName, finalDir);
File destFile = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(finalDir), fileName));
return destFile;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
fileName = UUID.randomUUID() + fileName;
File dest = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(finalDir), fileName));
return dest;
}
/**
* 处理下文件名,比如重复下载需要处理重名的情况
* */
String rename(String fileName, File parentDir) throws Exception {
if (!FILENAME_PATTERN.matcher(fileName).matches()) {
throw new Exception("fileName format error: " + fileName);
}
// 获取文件名(含后缀)
String prefix = fileName.substring(0, fileName.length() - 4);
String suffix = fileName.substring(fileName.length() - 4);
File file = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(parentDir), fileName));
// 处理重复文件名
if (file.exists()) {
String fileNameFormat = prefix + "(%d)" + suffix;
Pattern pattern = Pattern.compile(prefix + "\\((\\d)\\)" + suffix);
int cnt = 0;
File[] files = parentDir.listFiles();
for (File f : files) {
Matcher matcher = pattern.matcher(f.getName());
if (matcher.find()) {
cnt = Math.max(cnt, Integer.parseInt(matcher.group(1)));
}
}
cnt++;
fileName = String.format(fileNameFormat, cnt);
}
return fileName;
}
private static CloseableHttpResponse getDownloadHttpResponse(String url) throws Exception {
//先登录一下。不然可能失败
CloseableHttpClient client = createClient();
HttpUriRequest file = RequestBuilder.get()
.setUri(url)
.build();
return client.execute(file);
}
private static CloseableHttpResponse postDownloadHttpResponse(String url, String id) throws Exception {
return postDownloadHttpResponse(url, id, new HashMap<>());
}
private static CloseableHttpResponse postDownloadHttpResponse(String url, String id, Map<String, String> params) throws Exception {
//先登录一下。不然可能失败
CloseableHttpClient client = createClient();
FineLoggerFactory.getLogger().info("login fr-market");
FineLoggerFactory.getLogger().info("start download resource {}", id);
RequestBuilder builder = RequestBuilder.post()
.setHeader("User-Agent", "Mozilla/5.0")
.setUri(url)
.addParameter("id", SecurityToolbox.encrypt(id, CERTIFICATE_PUBLIC_KEY))
.addParameter("userId", String.valueOf(DesignerEnvManager.getEnvManager().getDesignerLoginUid()));
if (params != null) {
Set<String> keys = params.keySet();
for (String key: keys) {
builder.addParameter(key, params.get(key));
}
}
return client.execute(builder.build());
}
private static CloseableHttpClient createClient() {
BasicCookieStore cookieStore = new BasicCookieStore();
return HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.setDefaultCookieStore(cookieStore)
.build();
}
public @Nullable JSONObject getTemplateInfoById(String id) throws IOException {
String url = FINE_MARKET_TEMPLATE_INFO + id;
String jsonString = HttpToolbox.get(url);
JSONObject jsonObject = new JSONObject(jsonString);
String responseState = (String) jsonObject.get(RESPONSE_STATE);
if (RESPONSE_SUCCESS.equals(responseState)) {
return jsonObject.getJSONObject(RESPONSE_RESULT);
} else {
return null;
}
}
public @Nullable JSONArray getTemplateInfoByName(String name) throws IOException {
Map<String, String> params = new HashMap<>();
params.put(NAME_SEARCH, name);
params.put(VERSION, CURRENT_VERSION);
String jsonString = HttpToolbox.get(FINE_MARKET_TEMPLATE_INFO, params);
JSONObject jsonObject = new JSONObject(jsonString);
String responseState = (String) jsonObject.get(RESPONSE_STATE);
if (RESPONSE_SUCCESS.equals(responseState)) {
return jsonObject.getJSONArray(RESPONSE_RESULT);
}
return null;
}
public String getTemplateUrlById(String id) {
return FINE_MARKET_TEMPLATE_URL + id;
}
public @Nullable JSONObject getTemplateParentPackageByTemplateId(String id) throws IOException {
String url = FINE_MARKET_TEMPLATE_INFO + TEMPLATES_PARENT_PACKAGE + id;
String jsonString = HttpToolbox.get(url);
JSONObject jsonObject = new JSONObject(jsonString);
String responseState = (String) jsonObject.get(RESPONSE_STATE);
if (RESPONSE_SUCCESS.equals(responseState)) {
JSONArray jsonArray = jsonObject.getJSONArray(RESPONSE_RESULT);
if (!jsonArray.isEmpty()) {
return jsonObject.getJSONArray(RESPONSE_RESULT).getJSONObject(0);
}
}
return null;
}
/**
* 根据模板资源的tagid,获取tagName
* */
public List<String> getTemplateTagsByTemplateTagIds(String[] tagIds) throws IOException {
List<String> list = new ArrayList<>();
initTags();
if (tagIds != null) {
for (String tagId : tagIds) {
String tagName = tags.get(tagId);
if (tagName != null) {
list.add(tagName);
}
}
}
return list;
}
/**
* 请求帆软市场,获取所有tag信息,并构建tagid - tagname的map
* */
private void initTags() throws IOException {
tags = new HashMap<>();
String url = FINE_MARKET_TEMPLATE_INFO + ClientHelper.urlEncode(TEMPLATES_TAGS, EncodeConstants.ENCODING_UTF_8);
String jsonString = HttpToolbox.get(url);
JSONObject jsonObject = new JSONObject(jsonString);
String responseState = (String) jsonObject.get(RESPONSE_STATE);
if (RESPONSE_SUCCESS.equals(responseState)) {
JSONArray resultArray = jsonObject.getJSONArray(RESPONSE_RESULT);
for (int i = 1; i < resultArray.size(); i++) {
JSONObject result = resultArray.getJSONObject(i);
String key = result.getString(TAGS_KEY);
key = key.substring(key.indexOf('@') + 1);
JSONArray items = result.getJSONArray(TAGS_ITEMS);
for (int j = 0; j < items.length(); j++) {
JSONObject item = items.getJSONObject(j);
String id = item.getString(TAG_ID);
String name = item.getString(TAG_NAME);
tags.put(key + '-' + id, name);
}
}
}
}
}