feat: 插件管理v0.01
This commit is contained in:
parent
ba6782663b
commit
2703e881eb
@ -13,6 +13,9 @@ import io.dataease.auth.util.RsaUtil;
|
||||
import io.dataease.commons.utils.BeanUtils;
|
||||
import io.dataease.commons.utils.CodingUtil;
|
||||
import io.dataease.commons.utils.ServletUtils;
|
||||
/*import io.dataease.plugins.config.SpringContextUtil;
|
||||
import io.dataease.plugins.xpack.dto.response.SysSettingDto;
|
||||
import io.dataease.plugins.xpack.service.DePluginXpackService;*/
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
@ -105,6 +108,14 @@ public class AuthServer implements AuthApi {
|
||||
SysUserEntity userById = authUserService.getUserById(4L);
|
||||
String nickName = userById.getNickName();
|
||||
System.out.println(nickName);
|
||||
/* Map<String, DePluginXpackService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType(DePluginXpackService.class);
|
||||
for (Map.Entry entry : beansOfType.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
DePluginXpackService value = (DePluginXpackService)entry.getValue();
|
||||
List<SysSettingDto> sysSettingDtos = value.systemSettings();
|
||||
String name = entry.getValue().getClass().getName();
|
||||
System.out.println("key: "+ key + ", value: "+ name);
|
||||
}*/
|
||||
return "apple";
|
||||
}
|
||||
}
|
||||
|
||||
35
backend/src/main/java/io/dataease/base/domain/MyPlugin.java
Normal file
35
backend/src/main/java/io/dataease/base/domain/MyPlugin.java
Normal file
@ -0,0 +1,35 @@
|
||||
package io.dataease.base.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class MyPlugin implements Serializable {
|
||||
private Long pluginId;
|
||||
|
||||
private String name;
|
||||
|
||||
private Boolean free;
|
||||
|
||||
private Integer cost;
|
||||
|
||||
private String descript;
|
||||
|
||||
private String version;
|
||||
|
||||
private Integer installType;
|
||||
|
||||
private String creator;
|
||||
|
||||
private Long releaseTime;
|
||||
|
||||
private Long installTime;
|
||||
|
||||
private String moduleName;
|
||||
|
||||
private String beanName;
|
||||
|
||||
private String icon;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
1050
backend/src/main/java/io/dataease/base/domain/MyPluginExample.java
Normal file
1050
backend/src/main/java/io/dataease/base/domain/MyPluginExample.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,30 @@
|
||||
package io.dataease.base.mapper;
|
||||
|
||||
import io.dataease.base.domain.MyPlugin;
|
||||
import io.dataease.base.domain.MyPluginExample;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
public interface MyPluginMapper {
|
||||
long countByExample(MyPluginExample example);
|
||||
|
||||
int deleteByExample(MyPluginExample example);
|
||||
|
||||
int deleteByPrimaryKey(Long pluginId);
|
||||
|
||||
int insert(MyPlugin record);
|
||||
|
||||
int insertSelective(MyPlugin record);
|
||||
|
||||
List<MyPlugin> selectByExample(MyPluginExample example);
|
||||
|
||||
MyPlugin selectByPrimaryKey(Long pluginId);
|
||||
|
||||
int updateByExampleSelective(@Param("record") MyPlugin record, @Param("example") MyPluginExample example);
|
||||
|
||||
int updateByExample(@Param("record") MyPlugin record, @Param("example") MyPluginExample example);
|
||||
|
||||
int updateByPrimaryKeySelective(MyPlugin record);
|
||||
|
||||
int updateByPrimaryKey(MyPlugin record);
|
||||
}
|
||||
338
backend/src/main/java/io/dataease/base/mapper/MyPluginMapper.xml
Normal file
338
backend/src/main/java/io/dataease/base/mapper/MyPluginMapper.xml
Normal file
@ -0,0 +1,338 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.dataease.base.mapper.MyPluginMapper">
|
||||
<resultMap id="BaseResultMap" type="io.dataease.base.domain.MyPlugin">
|
||||
<id column="plugin_id" jdbcType="BIGINT" property="pluginId" />
|
||||
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||
<result column="free" jdbcType="BIT" property="free" />
|
||||
<result column="cost" jdbcType="INTEGER" property="cost" />
|
||||
<result column="descript" jdbcType="VARCHAR" property="descript" />
|
||||
<result column="version" jdbcType="VARCHAR" property="version" />
|
||||
<result column="install_type" jdbcType="INTEGER" property="installType" />
|
||||
<result column="creator" jdbcType="VARCHAR" property="creator" />
|
||||
<result column="release_time" jdbcType="BIGINT" property="releaseTime" />
|
||||
<result column="install_time" jdbcType="BIGINT" property="installTime" />
|
||||
<result column="module_name" jdbcType="VARCHAR" property="moduleName" />
|
||||
<result column="bean_name" jdbcType="VARCHAR" property="beanName" />
|
||||
<result column="icon" jdbcType="VARCHAR" property="icon" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Update_By_Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="example.oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
plugin_id, `name`, `free`, cost, descript, version, install_type, creator, release_time,
|
||||
install_time, module_name, bean_name, icon
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.dataease.base.domain.MyPluginExample" resultMap="BaseResultMap">
|
||||
select
|
||||
<if test="distinct">
|
||||
distinct
|
||||
</if>
|
||||
<include refid="Base_Column_List" />
|
||||
from my_plugin
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
order by ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
|
||||
select
|
||||
<include refid="Base_Column_List" />
|
||||
from my_plugin
|
||||
where plugin_id = #{pluginId,jdbcType=BIGINT}
|
||||
</select>
|
||||
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
|
||||
delete from my_plugin
|
||||
where plugin_id = #{pluginId,jdbcType=BIGINT}
|
||||
</delete>
|
||||
<delete id="deleteByExample" parameterType="io.dataease.base.domain.MyPluginExample">
|
||||
delete from my_plugin
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</delete>
|
||||
<insert id="insert" parameterType="io.dataease.base.domain.MyPlugin">
|
||||
insert into my_plugin (plugin_id, `name`, `free`,
|
||||
cost, descript, version,
|
||||
install_type, creator, release_time,
|
||||
install_time, module_name, bean_name,
|
||||
icon)
|
||||
values (#{pluginId,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{free,jdbcType=BIT},
|
||||
#{cost,jdbcType=INTEGER}, #{descript,jdbcType=VARCHAR}, #{version,jdbcType=VARCHAR},
|
||||
#{installType,jdbcType=INTEGER}, #{creator,jdbcType=VARCHAR}, #{releaseTime,jdbcType=BIGINT},
|
||||
#{installTime,jdbcType=BIGINT}, #{moduleName,jdbcType=VARCHAR}, #{beanName,jdbcType=VARCHAR},
|
||||
#{icon,jdbcType=VARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.dataease.base.domain.MyPlugin">
|
||||
insert into my_plugin
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="pluginId != null">
|
||||
plugin_id,
|
||||
</if>
|
||||
<if test="name != null">
|
||||
`name`,
|
||||
</if>
|
||||
<if test="free != null">
|
||||
`free`,
|
||||
</if>
|
||||
<if test="cost != null">
|
||||
cost,
|
||||
</if>
|
||||
<if test="descript != null">
|
||||
descript,
|
||||
</if>
|
||||
<if test="version != null">
|
||||
version,
|
||||
</if>
|
||||
<if test="installType != null">
|
||||
install_type,
|
||||
</if>
|
||||
<if test="creator != null">
|
||||
creator,
|
||||
</if>
|
||||
<if test="releaseTime != null">
|
||||
release_time,
|
||||
</if>
|
||||
<if test="installTime != null">
|
||||
install_time,
|
||||
</if>
|
||||
<if test="moduleName != null">
|
||||
module_name,
|
||||
</if>
|
||||
<if test="beanName != null">
|
||||
bean_name,
|
||||
</if>
|
||||
<if test="icon != null">
|
||||
icon,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="pluginId != null">
|
||||
#{pluginId,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="name != null">
|
||||
#{name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="free != null">
|
||||
#{free,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="cost != null">
|
||||
#{cost,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="descript != null">
|
||||
#{descript,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="version != null">
|
||||
#{version,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="installType != null">
|
||||
#{installType,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="creator != null">
|
||||
#{creator,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="releaseTime != null">
|
||||
#{releaseTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="installTime != null">
|
||||
#{installTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="moduleName != null">
|
||||
#{moduleName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="beanName != null">
|
||||
#{beanName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="icon != null">
|
||||
#{icon,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.dataease.base.domain.MyPluginExample" resultType="java.lang.Long">
|
||||
select count(*) from my_plugin
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</select>
|
||||
<update id="updateByExampleSelective" parameterType="map">
|
||||
update my_plugin
|
||||
<set>
|
||||
<if test="record.pluginId != null">
|
||||
plugin_id = #{record.pluginId,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.name != null">
|
||||
`name` = #{record.name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.free != null">
|
||||
`free` = #{record.free,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="record.cost != null">
|
||||
cost = #{record.cost,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.descript != null">
|
||||
descript = #{record.descript,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.version != null">
|
||||
version = #{record.version,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.installType != null">
|
||||
install_type = #{record.installType,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.creator != null">
|
||||
creator = #{record.creator,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.releaseTime != null">
|
||||
release_time = #{record.releaseTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.installTime != null">
|
||||
install_time = #{record.installTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.moduleName != null">
|
||||
module_name = #{record.moduleName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.beanName != null">
|
||||
bean_name = #{record.beanName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.icon != null">
|
||||
icon = #{record.icon,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByExample" parameterType="map">
|
||||
update my_plugin
|
||||
set plugin_id = #{record.pluginId,jdbcType=BIGINT},
|
||||
`name` = #{record.name,jdbcType=VARCHAR},
|
||||
`free` = #{record.free,jdbcType=BIT},
|
||||
cost = #{record.cost,jdbcType=INTEGER},
|
||||
descript = #{record.descript,jdbcType=VARCHAR},
|
||||
version = #{record.version,jdbcType=VARCHAR},
|
||||
install_type = #{record.installType,jdbcType=INTEGER},
|
||||
creator = #{record.creator,jdbcType=VARCHAR},
|
||||
release_time = #{record.releaseTime,jdbcType=BIGINT},
|
||||
install_time = #{record.installTime,jdbcType=BIGINT},
|
||||
module_name = #{record.moduleName,jdbcType=VARCHAR},
|
||||
bean_name = #{record.beanName,jdbcType=VARCHAR},
|
||||
icon = #{record.icon,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByPrimaryKeySelective" parameterType="io.dataease.base.domain.MyPlugin">
|
||||
update my_plugin
|
||||
<set>
|
||||
<if test="name != null">
|
||||
`name` = #{name,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="free != null">
|
||||
`free` = #{free,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="cost != null">
|
||||
cost = #{cost,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="descript != null">
|
||||
descript = #{descript,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="version != null">
|
||||
version = #{version,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="installType != null">
|
||||
install_type = #{installType,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="creator != null">
|
||||
creator = #{creator,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="releaseTime != null">
|
||||
release_time = #{releaseTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="installTime != null">
|
||||
install_time = #{installTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="moduleName != null">
|
||||
module_name = #{moduleName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="beanName != null">
|
||||
bean_name = #{beanName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="icon != null">
|
||||
icon = #{icon,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where plugin_id = #{pluginId,jdbcType=BIGINT}
|
||||
</update>
|
||||
<update id="updateByPrimaryKey" parameterType="io.dataease.base.domain.MyPlugin">
|
||||
update my_plugin
|
||||
set `name` = #{name,jdbcType=VARCHAR},
|
||||
`free` = #{free,jdbcType=BIT},
|
||||
cost = #{cost,jdbcType=INTEGER},
|
||||
descript = #{descript,jdbcType=VARCHAR},
|
||||
version = #{version,jdbcType=VARCHAR},
|
||||
install_type = #{installType,jdbcType=INTEGER},
|
||||
creator = #{creator,jdbcType=VARCHAR},
|
||||
release_time = #{releaseTime,jdbcType=BIGINT},
|
||||
install_time = #{installTime,jdbcType=BIGINT},
|
||||
module_name = #{moduleName,jdbcType=VARCHAR},
|
||||
bean_name = #{beanName,jdbcType=VARCHAR},
|
||||
icon = #{icon,jdbcType=VARCHAR}
|
||||
where plugin_id = #{pluginId,jdbcType=BIGINT}
|
||||
</update>
|
||||
</mapper>
|
||||
@ -0,0 +1,11 @@
|
||||
package io.dataease.base.mapper.ext;
|
||||
|
||||
import io.dataease.base.domain.MyPlugin;
|
||||
import io.dataease.base.mapper.ext.query.GridExample;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtSysPluginMapper {
|
||||
|
||||
List<MyPlugin> query(GridExample example);
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="io.dataease.base.mapper.ext.ExtSysPluginMapper">
|
||||
|
||||
|
||||
|
||||
|
||||
<select id="query" parameterType="io.dataease.base.mapper.ext.query.GridExample" resultMap="io.dataease.base.mapper.MyPluginMapper.BaseResultMap">
|
||||
select *
|
||||
from my_plugin
|
||||
<if test="_parameter != null">
|
||||
<include refid="io.dataease.base.mapper.ext.query.GridSql.gridCondition" />
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
order by ${orderByClause}
|
||||
</if>
|
||||
<if test="orderByClause == null">
|
||||
order by install_time desc
|
||||
</if>
|
||||
|
||||
</select>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</mapper>
|
||||
115
backend/src/main/java/io/dataease/commons/utils/DeFileUtils.java
Normal file
115
backend/src/main/java/io/dataease/commons/utils/DeFileUtils.java
Normal file
@ -0,0 +1,115 @@
|
||||
package io.dataease.commons.utils;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
public class DeFileUtils {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Java文件操作 获取不带扩展名的文件名
|
||||
*/
|
||||
public static String getFileNameNoEx(String filename) {
|
||||
if ((filename != null) && (filename.length() > 0)) {
|
||||
int dot = filename.lastIndexOf('.');
|
||||
if ((dot > -1) && (dot < (filename.length()))) {
|
||||
return filename.substring(0, dot);
|
||||
}
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件扩展名,不带 .
|
||||
*/
|
||||
public static String getExtensionName(String filename) {
|
||||
if ((filename != null) && (filename.length() > 0)) {
|
||||
int dot = filename.lastIndexOf('.');
|
||||
if ((dot > -1) && (dot < (filename.length() - 1))) {
|
||||
return filename.substring(dot + 1);
|
||||
}
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
/**
|
||||
* 将文件名解析成文件的上传路径
|
||||
*/
|
||||
public static File upload(MultipartFile file, String filePath) {
|
||||
String name = getFileNameNoEx(file.getOriginalFilename());
|
||||
String suffix = getExtensionName(file.getOriginalFilename());
|
||||
try {
|
||||
String fileName = name + "." + suffix;
|
||||
String path = filePath + fileName;
|
||||
// getCanonicalFile 可解析正确各种路径
|
||||
File dest = new File(path).getCanonicalFile();
|
||||
// 检测是否存在目录
|
||||
if (!dest.getParentFile().exists()) {
|
||||
if (!dest.getParentFile().mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
}
|
||||
// 文件写入
|
||||
// file.transferTo(dest);
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(dest);
|
||||
fileOutputStream.write(file.getBytes());
|
||||
fileOutputStream.flush();
|
||||
fileOutputStream.close();
|
||||
return dest;
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String copy(File source, String targetDir) throws IOException{
|
||||
String name = source.getName();
|
||||
String destPath = null;
|
||||
if (targetDir.endsWith("/") || targetDir.endsWith("\\")){
|
||||
destPath = targetDir + name;
|
||||
}else{
|
||||
destPath = targetDir + "/" + name;
|
||||
}
|
||||
File DestFile = new File(destPath);
|
||||
if (!DestFile.getParentFile().exists()) {
|
||||
DestFile.getParentFile().mkdirs();
|
||||
}
|
||||
copyFileUsingFileChannels(source, DestFile);
|
||||
return destPath;
|
||||
}
|
||||
|
||||
private static void copyFileUsingFileChannels(File source, File dest) throws IOException {
|
||||
FileChannel inputChannel = null;
|
||||
FileChannel outputChannel = null;
|
||||
try {
|
||||
inputChannel = new FileInputStream(source).getChannel();
|
||||
outputChannel = new FileOutputStream(dest).getChannel();
|
||||
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
|
||||
} finally {
|
||||
inputChannel.close();
|
||||
outputChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static String readJson(File file) {
|
||||
String str = null;
|
||||
try {
|
||||
FileReader fileReader = new FileReader(file);
|
||||
Reader reader = new InputStreamReader(new FileInputStream(file), "utf-8");
|
||||
int ch=0;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while ((ch = reader.read()) != -1) {
|
||||
sb.append((char) ch);
|
||||
}
|
||||
fileReader.close();
|
||||
reader.close();
|
||||
str = sb.toString();
|
||||
return str;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
141
backend/src/main/java/io/dataease/commons/utils/ZipUtils.java
Normal file
141
backend/src/main/java/io/dataease/commons/utils/ZipUtils.java
Normal file
@ -0,0 +1,141 @@
|
||||
package io.dataease.commons.utils;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class ZipUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 解压文件
|
||||
*
|
||||
* @param zipFilePath 解压文件路径
|
||||
* @param outputFolder 输出解压文件路径
|
||||
*/
|
||||
public static void unZipIt(String zipFilePath, String outputFolder) {
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
File folder = new File(outputFolder);
|
||||
if (!folder.exists()) {
|
||||
folder.mkdir();
|
||||
}
|
||||
try {
|
||||
//get the zip file content
|
||||
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFilePath));
|
||||
ZipEntry ze = zis.getNextEntry();
|
||||
while (ze != null) {
|
||||
String fileName = ze.getName();
|
||||
File newFile = new File(outputFolder + File.separator + fileName);
|
||||
System.out.println("file unzip : " + newFile.getAbsoluteFile());
|
||||
//大部分网络上的源码,这里没有判断子目录
|
||||
if (ze.isDirectory()) {
|
||||
if (!newFile.mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
} else {
|
||||
if (!new File(newFile.getParent()).mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
FileOutputStream fos = new FileOutputStream(newFile);
|
||||
int len;
|
||||
while ((len = zis.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, len);
|
||||
}
|
||||
fos.close();
|
||||
}
|
||||
ze = zis.getNextEntry();
|
||||
}
|
||||
zis.closeEntry();
|
||||
zis.close();
|
||||
System.out.println("Done");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void unzip(File source, String out) throws IOException {
|
||||
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(source))) {
|
||||
|
||||
ZipEntry entry = zis.getNextEntry();
|
||||
|
||||
while (entry != null) {
|
||||
|
||||
File file = new File(out, entry.getName());
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
if (!file.mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
} else {
|
||||
File parent = file.getParentFile();
|
||||
|
||||
if (!parent.exists()) {
|
||||
if (!parent.mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
}
|
||||
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
|
||||
byte[] buffer = new byte[Math.toIntExact(entry.getSize())];
|
||||
|
||||
int location;
|
||||
|
||||
while ((location = zis.read(buffer)) != -1) {
|
||||
bos.write(buffer, 0, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
entry = zis.getNextEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把所有文件都直接解压到指定目录(忽略子文件夹)
|
||||
*
|
||||
* @param zipFile
|
||||
* @param folderPath
|
||||
* @throws ZipException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void upZipFile(File zipFile, String folderPath) throws ZipException, IOException {
|
||||
File desDir = new File(folderPath);
|
||||
if (!desDir.exists()) {
|
||||
if (!desDir.mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
}
|
||||
ZipFile zf = new ZipFile(zipFile);
|
||||
for (Enumeration<?> entries = zf.entries(); entries.hasMoreElements(); ) {
|
||||
ZipEntry entry = ((ZipEntry) entries.nextElement());
|
||||
InputStream in = zf.getInputStream(entry);
|
||||
File desFile = new File(folderPath, java.net.URLEncoder.encode(entry.getName(), "UTF-8"));
|
||||
|
||||
if (!desFile.exists()) {
|
||||
File fileParentDir = desFile.getParentFile();
|
||||
if (!fileParentDir.exists()) {
|
||||
if (!fileParentDir.mkdirs()) {
|
||||
System.out.println("was not successful.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OutputStream out = new FileOutputStream(desFile);
|
||||
byte[] buffer = new byte[1024 * 1024];
|
||||
int realLength = in.read(buffer);
|
||||
while (realLength != -1) {
|
||||
out.write(buffer, 0, realLength);
|
||||
realLength = in.read(buffer);
|
||||
}
|
||||
|
||||
out.close();
|
||||
in.close();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package io.dataease.controller.sys;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.dataease.base.domain.MyPlugin;
|
||||
import io.dataease.commons.utils.PageUtils;
|
||||
import io.dataease.commons.utils.Pager;
|
||||
import io.dataease.controller.sys.base.BaseGridRequest;
|
||||
import io.dataease.service.sys.PluginService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@RestController
|
||||
@Api(tags = "系统:插件管理")
|
||||
@RequestMapping("/api/plugin")
|
||||
public class SysPluginController {
|
||||
|
||||
@Autowired
|
||||
private PluginService pluginService;
|
||||
|
||||
@ApiOperation("查询已安装插件")
|
||||
@PostMapping("/pluginGrid/{goPage}/{pageSize}")
|
||||
public Pager<List<MyPlugin>> pluginGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody BaseGridRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||
return PageUtils.setPageInfo(page, pluginService.query(request));
|
||||
}
|
||||
|
||||
@PostMapping("upload")
|
||||
public Map<String, Object> localUpload(@RequestParam("file") MultipartFile file) throws Exception {
|
||||
return pluginService.localInstall(file);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package io.dataease.plugins.config;
|
||||
|
||||
import io.dataease.plugins.loader.ClassloaderResponsity;
|
||||
import io.dataease.plugins.loader.ModuleClassLoader;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class LoadjarUtil {
|
||||
|
||||
public List<?> loadJar(String jarPath){
|
||||
File jar = new File(jarPath);
|
||||
URI uri = jar.toURI();
|
||||
String moduleName = jarPath.substring(jarPath.lastIndexOf("/")+1,jarPath.lastIndexOf("."));
|
||||
try {
|
||||
|
||||
if(ClassloaderResponsity.getInstance().containsClassLoader(moduleName)){
|
||||
ClassloaderResponsity.getInstance().removeClassLoader(moduleName);
|
||||
}
|
||||
|
||||
ModuleClassLoader classLoader = new ModuleClassLoader(new URL[]{uri.toURL()}, Thread.currentThread().getContextClassLoader());
|
||||
SpringContextUtil.getBeanFactory().setBeanClassLoader(classLoader);
|
||||
Thread.currentThread().setContextClassLoader(classLoader);
|
||||
classLoader.initBean();
|
||||
ClassloaderResponsity.getInstance().addClassLoader(moduleName,classLoader);
|
||||
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return SpringContextUtil.getAllBean();
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> deleteModule(String moduleName){
|
||||
if(ClassloaderResponsity.getInstance().containsClassLoader(moduleName)){
|
||||
ClassloaderResponsity.getInstance().removeClassLoader(moduleName);
|
||||
}
|
||||
return beans();
|
||||
}
|
||||
public List<Map<String, Object>> beans(){
|
||||
return SpringContextUtil.getAllBean();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
package io.dataease.plugins.config;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class SpringContextUtil implements ApplicationContextAware {
|
||||
|
||||
//获取bean工厂,用来实现动态注入bean
|
||||
//不能使用其他类加载器加载bean
|
||||
//否则会出现异常:类未找到,类未定义
|
||||
public static DefaultListableBeanFactory getBeanFactory(){
|
||||
return (DefaultListableBeanFactory) getApplicationContext().getAutowireCapableBeanFactory();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static List<Map<String, Object>> getAllBean() {
|
||||
|
||||
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
|
||||
|
||||
String[] beans = getApplicationContext()
|
||||
.getBeanDefinitionNames();
|
||||
|
||||
for (String beanName : beans) {
|
||||
Class<?> beanType = getApplicationContext()
|
||||
.getType(beanName);
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
|
||||
map.put("BeanName", beanName);
|
||||
map.put("beanType", beanType);
|
||||
map.put("package", beanType.getPackage());
|
||||
list.add(map);
|
||||
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 上下文对象实例
|
||||
*/
|
||||
private static ApplicationContext applicationContext;
|
||||
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取applicationContext
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
|
||||
public static Object getBean(String name) {
|
||||
return getApplicationContext().getBean(name);
|
||||
}
|
||||
|
||||
public static <T> T getBean(Class<T> clazz) {
|
||||
return getApplicationContext().getBean(clazz);
|
||||
}
|
||||
|
||||
public static <T> T getBean(String name, Class<T> clazz) {
|
||||
return getApplicationContext().getBean(name, clazz);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package io.dataease.plugins.loader;
|
||||
|
||||
import io.dataease.plugins.config.SpringContextUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ClassloaderResponsity {
|
||||
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(ClassloaderResponsity.class);
|
||||
|
||||
private ClassloaderResponsity(){}
|
||||
|
||||
|
||||
private Map<String,ModuleClassLoader> responsityMap = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
|
||||
public void addClassLoader(String moduleName,ModuleClassLoader moduleClassLoader){
|
||||
responsityMap.put(moduleName,moduleClassLoader);
|
||||
}
|
||||
|
||||
public boolean containsClassLoader(String key){
|
||||
return responsityMap.containsKey(key);
|
||||
}
|
||||
|
||||
public ModuleClassLoader getClassLoader(String key){
|
||||
return responsityMap.get(key);
|
||||
}
|
||||
|
||||
public void removeClassLoader(String moduleName){
|
||||
ModuleClassLoader moduleClassLoader = responsityMap.get(moduleName);
|
||||
try {
|
||||
List<String> registeredBean = moduleClassLoader.getRegisteredBean();
|
||||
|
||||
for (String beanName : registeredBean) {
|
||||
logger.info("删除bean:"+beanName);
|
||||
SpringContextUtil.getBeanFactory().removeBeanDefinition(beanName);
|
||||
}
|
||||
|
||||
moduleClassLoader.close();
|
||||
responsityMap.remove(moduleName);
|
||||
|
||||
} catch (IOException e) {
|
||||
logger.error("删除"+moduleName+"模块发生错误");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static class ClassloaderResponsityHodler{
|
||||
private static ClassloaderResponsity instamce = new ClassloaderResponsity();
|
||||
}
|
||||
|
||||
public static ClassloaderResponsity getInstance(){
|
||||
return ClassloaderResponsityHodler.instamce;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,189 @@
|
||||
package io.dataease.plugins.loader;
|
||||
|
||||
import io.dataease.plugins.config.SpringContextUtil;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.*;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class ModuleClassLoader extends URLClassLoader {
|
||||
|
||||
//属于本类加载器加载的jar包
|
||||
private JarFile jarFile;
|
||||
|
||||
//保存已经加载过的Class对象
|
||||
private Map<String,Class> cacheClassMap = new HashMap<>();
|
||||
|
||||
//保存本类加载器加载的class字节码
|
||||
private Map<String,byte[]> classBytesMap = new HashMap<>();
|
||||
|
||||
//需要注册的spring bean的name集合
|
||||
private List<String> registeredBean = new ArrayList<>();
|
||||
|
||||
|
||||
//构造
|
||||
public ModuleClassLoader(URL[] urls, ClassLoader parent) {
|
||||
super(urls, parent);
|
||||
URL url = urls[0];
|
||||
String path = url.getPath();
|
||||
try {
|
||||
jarFile = new JarFile(path);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//初始化类加载器执行类加载
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//重写loadClass方法
|
||||
//改写loadClass方式
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
if(findLoadedClass(name)==null){
|
||||
return super.loadClass(name);
|
||||
}else{
|
||||
return cacheClassMap.get(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 方法描述 初始化类加载器,保存字节码
|
||||
* @method init
|
||||
*/
|
||||
private void init() {
|
||||
|
||||
//解析jar包每一项
|
||||
Enumeration<JarEntry> en = jarFile.entries();
|
||||
InputStream input = null;
|
||||
try{
|
||||
while (en.hasMoreElements()) {
|
||||
JarEntry je = en.nextElement();
|
||||
String name = je.getName();
|
||||
//这里添加了路径扫描限制
|
||||
if (name.endsWith(".class")) {
|
||||
String className = name.replace(".class", "").replaceAll("/", ".");
|
||||
input = jarFile.getInputStream(je);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
int bufferSize = 4096;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
int bytesNumRead = 0;
|
||||
while ((bytesNumRead = input.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, bytesNumRead);
|
||||
}
|
||||
byte[] classBytes = baos.toByteArray();
|
||||
classBytesMap.put(className,classBytes);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(input!=null){
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//将jar中的每一个class字节码进行Class载入
|
||||
for (Map.Entry<String, byte[]> entry : classBytesMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Class<?> aClass = null;
|
||||
try {
|
||||
aClass = loadClass(key);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
cacheClassMap.put(key,aClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 方法描述 初始化spring bean
|
||||
* @method initBean
|
||||
*/
|
||||
public void initBean(){
|
||||
for (Map.Entry<String, Class> entry : cacheClassMap.entrySet()) {
|
||||
String className = entry.getKey();
|
||||
Class<?> cla = entry.getValue();
|
||||
if(isSpringBeanClass(cla)){
|
||||
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(cla);
|
||||
BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
|
||||
//设置当前bean定义对象是单利的
|
||||
beanDefinition.setScope("singleton");
|
||||
|
||||
//将变量首字母置小写
|
||||
String beanName = StringUtils.uncapitalize(className);
|
||||
|
||||
beanName = beanName.substring(beanName.lastIndexOf(".")+1);
|
||||
beanName = StringUtils.uncapitalize(beanName);
|
||||
|
||||
SpringContextUtil.getBeanFactory().registerBeanDefinition(beanName,beanDefinition);
|
||||
registeredBean.add(beanName);
|
||||
System.out.println("注册bean:"+beanName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//获取当前类加载器注册的bean
|
||||
//在移除当前类加载器的时候需要手动删除这些注册的bean
|
||||
public List<String> getRegisteredBean() {
|
||||
return registeredBean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 方法描述 判断class对象是否带有spring的注解
|
||||
* @method isSpringBeanClass
|
||||
* @param cla jar中的每一个class
|
||||
* @return true 是spring bean false 不是spring bean
|
||||
*/
|
||||
public boolean isSpringBeanClass(Class<?> cla){
|
||||
if(cla==null){
|
||||
return false;
|
||||
}
|
||||
//是否是接口
|
||||
if(cla.isInterface()){
|
||||
return false;
|
||||
}
|
||||
|
||||
//是否是抽象类
|
||||
if( Modifier.isAbstract(cla.getModifiers())){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(cla.getAnnotation(Component.class)!=null){
|
||||
return true;
|
||||
}
|
||||
if(cla.getAnnotation(Repository.class)!=null){
|
||||
return true;
|
||||
}
|
||||
if(cla.getAnnotation(Service.class)!=null){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
134
backend/src/main/java/io/dataease/service/sys/PluginService.java
Normal file
134
backend/src/main/java/io/dataease/service/sys/PluginService.java
Normal file
@ -0,0 +1,134 @@
|
||||
package io.dataease.service.sys;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.dataease.base.domain.MyPlugin;
|
||||
import io.dataease.base.mapper.MyPluginMapper;
|
||||
import io.dataease.base.mapper.ext.ExtSysPluginMapper;
|
||||
import io.dataease.base.mapper.ext.query.GridExample;
|
||||
import io.dataease.commons.utils.BeanUtils;
|
||||
import io.dataease.commons.utils.DeFileUtils;
|
||||
import io.dataease.commons.utils.ZipUtils;
|
||||
import io.dataease.controller.sys.base.BaseGridRequest;
|
||||
import io.dataease.plugins.config.LoadjarUtil;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Service
|
||||
public class PluginService {
|
||||
|
||||
@Value("${dataease.plugin.dir:/opt/dataease/plugins/}")
|
||||
private String pluginDir;
|
||||
|
||||
private final static String pluginJsonName = "plugin.json";
|
||||
|
||||
@Resource
|
||||
private ExtSysPluginMapper extSysPluginMapper;
|
||||
|
||||
@Resource
|
||||
private MyPluginMapper myPluginMapper;
|
||||
|
||||
@Resource
|
||||
private LoadjarUtil loadjarUtil;
|
||||
|
||||
public List<MyPlugin> query(BaseGridRequest request) {
|
||||
GridExample gridExample = request.convertExample();
|
||||
List<MyPlugin> results = extSysPluginMapper.query(gridExample);
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从本地安装处插件
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Object> localInstall(MultipartFile file) {
|
||||
//1.上传文件到服务器pluginDir目录下
|
||||
File dest = DeFileUtils.upload(file, pluginDir+"temp/");
|
||||
//2.解压目标文件dest 得到plugin.json和jar
|
||||
String folder = pluginDir+"folder/";
|
||||
try {
|
||||
ZipUtils.upZipFile(dest, folder);
|
||||
} catch (IOException e) {
|
||||
// 需要删除文件
|
||||
e.printStackTrace();
|
||||
}
|
||||
//3.解析plugin.json 失败则 直接返回错误 删除文件
|
||||
File folderFile = new File(folder);
|
||||
File[] jsonFiles = folderFile.listFiles(this::isPluginJson);
|
||||
if (ArrayUtils.isEmpty(jsonFiles)) {
|
||||
throw new RuntimeException("缺少插件描述文件");
|
||||
}
|
||||
MyPlugin myPlugin = formatJsonFile(jsonFiles[0]);
|
||||
//4.加载jar包 失败则 直接返回错误 删除文件
|
||||
File[] jarFiles = folderFile.listFiles(this::isPluginJar);
|
||||
if (ArrayUtils.isEmpty(jarFiles)) {
|
||||
throw new RuntimeException("缺少插件jar文件");
|
||||
}
|
||||
File jarFile = jarFiles[0];
|
||||
String jarRoot = pluginDir+"jar/";
|
||||
String jarPath = null;
|
||||
try {
|
||||
jarPath = DeFileUtils.copy(jarFile, jarRoot);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
loadjarUtil.loadJar(jarPath);
|
||||
//5.写表到my_plugin
|
||||
myPlugin.setPluginId(0L);
|
||||
myPluginMapper.insert(myPlugin);
|
||||
return null;
|
||||
}
|
||||
|
||||
//判断当前文件是否实插件描述文件
|
||||
//文件名称必须plugin.json
|
||||
private boolean isPluginJson(File file) {
|
||||
return StringUtils.equals(file.getName(), pluginJsonName);
|
||||
}
|
||||
|
||||
private boolean isPluginJar(File file) {
|
||||
String name = file.getName();
|
||||
return StringUtils.equals(DeFileUtils.getExtensionName(name), "jar");
|
||||
}
|
||||
|
||||
/**
|
||||
* 从plugin.json文件反序列化为MyPlugin实例对象
|
||||
* @return
|
||||
*/
|
||||
private MyPlugin formatJsonFile(File file) {
|
||||
String str = DeFileUtils.readJson(file);
|
||||
Gson gson = new Gson();
|
||||
Map<String, Object> myPlugin = gson.fromJson(str, Map.class);
|
||||
myPlugin.put("free", (Double)myPlugin.get("free") > 0.0);
|
||||
MyPlugin result = new MyPlugin();
|
||||
try {
|
||||
org.apache.commons.beanutils.BeanUtils.populate(result, myPlugin);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//BeanUtils.copyBean(result, myPlugin);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从插件商城远程安装插件
|
||||
* 2.0版本实现
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Object> remoteInstall(Map<String, Object> params) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -239,3 +239,35 @@ INSERT INTO `sys_users_roles` VALUES (19, 4);
|
||||
COMMIT;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for my_plugin
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `my_plugin`;
|
||||
CREATE TABLE `my_plugin` (
|
||||
`plugin_id` bigint(20) NOT NULL COMMENT '主键',
|
||||
`name` varchar(255) DEFAULT NULL COMMENT '插件名称',
|
||||
`free` tinyint(1) DEFAULT NULL COMMENT '是否免费',
|
||||
`cost` int(10) DEFAULT NULL COMMENT '费用',
|
||||
`descript` varchar(255) DEFAULT NULL COMMENT '描述',
|
||||
`version` varchar(255) DEFAULT NULL COMMENT '版本号',
|
||||
`install_type` int(4) DEFAULT NULL COMMENT '安装类型',
|
||||
`creator` varchar(255) DEFAULT NULL COMMENT '开发者',
|
||||
`release_time` bigint(13) DEFAULT NULL COMMENT '发布时间',
|
||||
`install_time` bigint(13) DEFAULT NULL COMMENT '安装时间',
|
||||
`module_name` varchar(255) DEFAULT NULL COMMENT 'jar包名称',
|
||||
`bean_name` varchar(40) DEFAULT NULL COMMENT 'bean名称',
|
||||
`icon` varchar(255) DEFAULT NULL COMMENT '图标',
|
||||
PRIMARY KEY (`plugin_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of my_plugin
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
@ -67,7 +67,7 @@
|
||||
<!-- <table tableName="datasource"/>-->
|
||||
<!-- <table tableName="sys_dict"/>-->
|
||||
<!-- <table tableName="sys_dict_item"/>-->
|
||||
<table tableName="dataset_table_field"/>
|
||||
<table tableName="my_plugin"/>
|
||||
<!-- <table tableName="panel_design"/>-->
|
||||
|
||||
|
||||
|
||||
@ -887,5 +887,20 @@ export default {
|
||||
back: '返回',
|
||||
view: '视图',
|
||||
edit: '编辑'
|
||||
},
|
||||
plugin: {
|
||||
local_install: '本地安装',
|
||||
remote_install: '远程安装',
|
||||
name: '插件名称',
|
||||
free: '是否免费',
|
||||
cost: '费用',
|
||||
descript: '描述',
|
||||
version: '版本',
|
||||
creator: '作者',
|
||||
install_time: '安装时间',
|
||||
release_time: '时间',
|
||||
un_install: '卸载',
|
||||
uninstall_confirm: '确定卸载该插件',
|
||||
uninstall_cancel: '取消卸载插件'
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user