From ad01a695b4846509c985a998ad2a08ad11b33d2f Mon Sep 17 00:00:00 2001 From: taojinlong Date: Fri, 20 May 2022 00:31:17 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=BA=90=E9=A9=B1=E5=8A=A8=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datasource/DriverMgmController.java | 91 ++++++ .../main/java/io/dataease/dto/DriverDTO.java | 9 + .../io/dataease/provider/ProviderFactory.java | 3 +- .../provider/datasource/JdbcProvider.java | 103 +++++- .../service/dataset/DataSetTableService.java | 2 +- .../service/datasource/DatasourceService.java | 11 +- .../service/datasource/DriverService.java | 175 +++++++++++ .../main/resources/db/migration/V35__1.11.sql | 21 ++ frontend/src/api/system/datasource.js | 55 ++++ frontend/src/lang/en.js | 15 + frontend/src/lang/tw.js | 15 + frontend/src/lang/zh.js | 15 + .../views/system/datasource/DriverForm.vue | 294 ++++++++++++++++++ .../system/datasource/DsConfiguration.vue | 98 ++++-- .../datasource/{form.vue => DsForm.vue} | 42 ++- .../src/views/system/datasource/DsMain.vue | 9 +- .../src/views/system/datasource/DsTree.vue | 178 +++++++++-- frontend/src/views/system/plugin/index.vue | 1 - 18 files changed, 1060 insertions(+), 77 deletions(-) create mode 100644 backend/src/main/java/io/dataease/controller/datasource/DriverMgmController.java create mode 100644 backend/src/main/java/io/dataease/dto/DriverDTO.java create mode 100644 backend/src/main/java/io/dataease/service/datasource/DriverService.java create mode 100644 frontend/src/views/system/datasource/DriverForm.vue rename frontend/src/views/system/datasource/{form.vue => DsForm.vue} (95%) diff --git a/backend/src/main/java/io/dataease/controller/datasource/DriverMgmController.java b/backend/src/main/java/io/dataease/controller/datasource/DriverMgmController.java new file mode 100644 index 0000000000..06abb58799 --- /dev/null +++ b/backend/src/main/java/io/dataease/controller/datasource/DriverMgmController.java @@ -0,0 +1,91 @@ +package io.dataease.controller.datasource; + + +import io.dataease.dto.DriverDTO; +import io.dataease.plugins.common.base.domain.DeDriver; +import io.dataease.plugins.common.base.domain.DeDriverDetails; +import io.dataease.service.datasource.DriverService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.security.core.parameters.P; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import springfox.documentation.annotations.ApiIgnore; + +import javax.annotation.Resource; +import java.util.List; +import java.util.stream.Collectors; + +@ApiIgnore +@RequestMapping("driver") +@RestController +public class DriverMgmController { + + @Resource + private DriverService driverService; + + @RequiresPermissions("datasource:read") + @ApiOperation("驱动列表") + @PostMapping("/list") + public List listDeDriver() throws Exception{ + return driverService.list(); + } + + @RequiresPermissions("datasource:read") + @ApiOperation("删除驱动") + @PostMapping("/delete/{id}") + public void delete(@PathVariable String id) throws Exception{ + driverService.delete(id); + } + + @RequiresPermissions("datasource:read") + @ApiOperation("驱动列表") + @GetMapping("/list/{type}") + public List listDeDriver(@PathVariable String type) throws Exception{ + return listDeDriver().stream().filter(driverDTO -> driverDTO.getType().equalsIgnoreCase(type)).collect(Collectors.toList()); + } + + @RequiresPermissions("datasource:read") + @ApiOperation("添加驱动") + @PostMapping("/save") + public DeDriver save(@RequestBody DeDriver deDriver) throws Exception{ + return driverService.save(deDriver); + } + + @RequiresPermissions("datasource:read") + @ApiOperation("更新驱动") + @PostMapping("/update") + public DeDriver update(@RequestBody DeDriver deDriver) throws Exception{ + return driverService.update(deDriver); + } + + @RequiresPermissions("datasource:read") + @ApiOperation("驱动文件列表") + @GetMapping("/listDriverDetails/{id}") + public List listDriverDetails(@PathVariable String id) throws Exception{ + return driverService.listDriverDetails(id); + } + + @RequiresPermissions("datasource:read") + @ApiOperation("删除驱动文件") + @PostMapping("/deleteDriverFile/{id}") + public void deleteDriverFile(@PathVariable String id) throws Exception{ + driverService.deleteDriverFile(id); + } + + @RequiresPermissions("datasource:read") + @ApiOperation("驱动文件上传") + @PostMapping("file/upload") + @ApiImplicitParams({ + @ApiImplicitParam(name = "file", value = "文件", required = true, dataType = "MultipartFile"), + @ApiImplicitParam(name = "id", value = "驱动D", required = true, dataType = "String") + }) + public void excelUpload(@RequestParam("file") MultipartFile file, @RequestParam("id") String id) throws Exception { + driverService.saveJar(file, id); + } + + + +} diff --git a/backend/src/main/java/io/dataease/dto/DriverDTO.java b/backend/src/main/java/io/dataease/dto/DriverDTO.java new file mode 100644 index 0000000000..774ecdbbd6 --- /dev/null +++ b/backend/src/main/java/io/dataease/dto/DriverDTO.java @@ -0,0 +1,9 @@ +package io.dataease.dto; + +import io.dataease.plugins.common.base.domain.DeDriver; +import lombok.Data; + +@Data +public class DriverDTO extends DeDriver { + private String typeDesc; +} diff --git a/backend/src/main/java/io/dataease/provider/ProviderFactory.java b/backend/src/main/java/io/dataease/provider/ProviderFactory.java index 1727d1a705..e5dcaf4ff9 100644 --- a/backend/src/main/java/io/dataease/provider/ProviderFactory.java +++ b/backend/src/main/java/io/dataease/provider/ProviderFactory.java @@ -1,6 +1,5 @@ package io.dataease.provider; -import com.google.gson.Gson; import io.dataease.plugins.common.constants.DatasourceTypes; import io.dataease.plugins.common.dto.datasource.DataSourceType; import io.dataease.plugins.config.SpringContextUtil; @@ -25,7 +24,7 @@ public class ProviderFactory implements ApplicationContextAware { for(final DatasourceTypes d: DatasourceTypes.values()) { final ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) context).getBeanFactory(); if(d.isDatasource()){ - DataSourceType dataSourceType = new DataSourceType(d.getType(), d.getName(), false, d.getExtraParams(), d.getCalculationMode()); + DataSourceType dataSourceType = new DataSourceType(d.getType(), d.getName(), false, d.getExtraParams(), d.getCalculationMode(), d.isJdbc()); if(dataSourceType.getType().equalsIgnoreCase("oracle")){ dataSourceType.setCharset(d.getCharset()); } diff --git a/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java b/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java index ddb7d3c58a..dc7204f859 100644 --- a/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java +++ b/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java @@ -6,16 +6,20 @@ import com.google.gson.Gson; import io.dataease.dto.datasource.*; import io.dataease.exception.DataEaseException; import io.dataease.i18n.Translator; +import io.dataease.plugins.common.base.domain.DeDriver; +import io.dataease.plugins.common.base.mapper.DeDriverMapper; import io.dataease.plugins.common.constants.DatasourceTypes; import io.dataease.plugins.common.dto.datasource.TableField; import io.dataease.plugins.common.request.datasource.DatasourceRequest; import io.dataease.plugins.datasource.entity.JdbcConfiguration; import io.dataease.plugins.datasource.provider.DefaultJdbcProvider; +import io.dataease.plugins.datasource.provider.ExtendedJdbcClassLoader; import io.dataease.plugins.datasource.query.QueryProvider; import io.dataease.provider.ProviderFactory; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import javax.annotation.Resource; import java.beans.PropertyVetoException; import java.lang.reflect.Method; import java.sql.*; @@ -25,6 +29,8 @@ import java.util.*; public class JdbcProvider extends DefaultJdbcProvider { + @Resource + private DeDriverMapper deDriverMapper; @Override public boolean isUseDatasourcePool(){ return true; @@ -294,10 +300,12 @@ public class JdbcProvider extends DefaultJdbcProvider { public Connection getConnection(DatasourceRequest datasourceRequest) throws Exception { String username = null; String password = null; - String driver = null; + String defaultDriver = null; String jdbcurl = null; + String customDriver = null; DatasourceTypes datasourceType = DatasourceTypes.valueOf(datasourceRequest.getDatasource().getType()); Properties props = new Properties(); + DeDriver deDriver = null; switch (datasourceType) { case mysql: case mariadb: @@ -309,21 +317,24 @@ public class JdbcProvider extends DefaultJdbcProvider { MysqlConfiguration mysqlConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), MysqlConfiguration.class); username = mysqlConfiguration.getUsername(); password = mysqlConfiguration.getPassword(); - driver = "com.mysql.jdbc.Driver"; + defaultDriver = "com.mysql.jdbc.Driver"; jdbcurl = mysqlConfiguration.getJdbc(); + customDriver = mysqlConfiguration.getCustomDriver(); break; case sqlServer: SqlServerConfiguration sqlServerConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), SqlServerConfiguration.class); username = sqlServerConfiguration.getUsername(); password = sqlServerConfiguration.getPassword(); - driver = sqlServerConfiguration.getDriver(); + defaultDriver = sqlServerConfiguration.getDriver(); + customDriver = sqlServerConfiguration.getCustomDriver(); jdbcurl = sqlServerConfiguration.getJdbc(); break; case oracle: OracleConfiguration oracleConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), OracleConfiguration.class); username = oracleConfiguration.getUsername(); password = oracleConfiguration.getPassword(); - driver = oracleConfiguration.getDriver(); + defaultDriver = oracleConfiguration.getDriver(); + customDriver = oracleConfiguration.getCustomDriver(); jdbcurl = oracleConfiguration.getJdbc(); props.put("oracle.net.CONNECT_TIMEOUT", "5000"); break; @@ -331,56 +342,84 @@ public class JdbcProvider extends DefaultJdbcProvider { PgConfiguration pgConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), PgConfiguration.class); username = pgConfiguration.getUsername(); password = pgConfiguration.getPassword(); - driver = pgConfiguration.getDriver(); + defaultDriver = pgConfiguration.getDriver(); + customDriver = pgConfiguration.getCustomDriver(); jdbcurl = pgConfiguration.getJdbc(); break; case ck: CHConfiguration chConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), CHConfiguration.class); username = chConfiguration.getUsername(); password = chConfiguration.getPassword(); - driver = chConfiguration.getDriver(); + defaultDriver = chConfiguration.getDriver(); + customDriver = chConfiguration.getCustomDriver(); jdbcurl = chConfiguration.getJdbc(); break; case mongo: MongodbConfiguration mongodbConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), MongodbConfiguration.class); username = mongodbConfiguration.getUsername(); password = mongodbConfiguration.getPassword(); - driver = mongodbConfiguration.getDriver(); + defaultDriver = mongodbConfiguration.getDriver(); + customDriver = mongodbConfiguration.getCustomDriver(); jdbcurl = mongodbConfiguration.getJdbc(datasourceRequest.getDatasource().getId()); break; case redshift: RedshiftConfigration redshiftConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), RedshiftConfigration.class); username = redshiftConfigration.getUsername(); password = redshiftConfigration.getPassword(); - driver = redshiftConfigration.getDriver(); + defaultDriver = redshiftConfigration.getDriver(); + customDriver = redshiftConfigration.getCustomDriver(); jdbcurl = redshiftConfigration.getJdbc(); break; case hive: HiveConfiguration hiveConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), HiveConfiguration.class); - username = hiveConfiguration.getUsername(); - password = hiveConfiguration.getPassword(); - driver = hiveConfiguration.getDriver(); + defaultDriver = hiveConfiguration.getDriver(); + customDriver = hiveConfiguration.getCustomDriver(); jdbcurl = hiveConfiguration.getJdbc(); + + if(StringUtils.isNotEmpty(hiveConfiguration.getAuthMethod()) && hiveConfiguration.getAuthMethod().equalsIgnoreCase("kerberos")){ + System.setProperty("java.security.krb5.conf", "/opt/dataease/conf/krb5.conf"); + ExtendedJdbcClassLoader classLoader; + if(isDefaultClassLoader(customDriver)){ + classLoader = extendedJdbcClassLoader; + }else { + deDriver = deDriverMapper.selectByPrimaryKey(customDriver); + classLoader = getCustomJdbcClassLoader(deDriver); + } + Class ConfigurationClass = classLoader.loadClass("org.apache.hadoop.conf.Configuration"); + Method set = ConfigurationClass.getMethod("set",String.class, String.class) ; + Object obj = ConfigurationClass.newInstance(); + set.invoke(obj, "hadoop.security.authentication", "Kerberos"); + + Class UserGroupInformationClass = classLoader.loadClass("org.apache.hadoop.security.UserGroupInformation"); + Method setConfiguration = UserGroupInformationClass.getMethod("setConfiguration",ConfigurationClass) ; + Method loginUserFromKeytab = UserGroupInformationClass.getMethod("loginUserFromKeytab",String.class, String.class) ; + setConfiguration.invoke(null, obj); + loginUserFromKeytab.invoke(null, hiveConfiguration.getUsername(), "/opt/dataease/conf/" + hiveConfiguration.getPassword()); + }else { + username = hiveConfiguration.getUsername(); + password = hiveConfiguration.getPassword(); + } break; case impala: ImpalaConfiguration impalaConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), ImpalaConfiguration.class); username = impalaConfiguration.getUsername(); password = impalaConfiguration.getPassword(); - driver = impalaConfiguration.getDriver(); + defaultDriver = impalaConfiguration.getDriver(); + customDriver = impalaConfiguration.getCustomDriver(); jdbcurl = impalaConfiguration.getJdbc(); break; case db2: Db2Configuration db2Configuration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), Db2Configuration.class); username = db2Configuration.getUsername(); password = db2Configuration.getPassword(); - driver = db2Configuration.getDriver(); + defaultDriver = db2Configuration.getDriver(); + customDriver = db2Configuration.getCustomDriver(); jdbcurl = db2Configuration.getJdbc(); break; default: break; } - Driver driverClass = (Driver) extendedJdbcClassLoader.loadClass(driver).newInstance(); if (StringUtils.isNotBlank(username)) { props.setProperty("user", username); if (StringUtils.isNotBlank(password)) { @@ -388,12 +427,34 @@ public class JdbcProvider extends DefaultJdbcProvider { } } - Connection conn = driverClass.connect(jdbcurl, props); + Connection conn; + String driverClassName ; + ExtendedJdbcClassLoader jdbcClassLoader; + if(isDefaultClassLoader(customDriver)){ + driverClassName = defaultDriver; + jdbcClassLoader = extendedJdbcClassLoader; + }else { + driverClassName = deDriver.getDriverClass(); + jdbcClassLoader = getCustomJdbcClassLoader(deDriver); + } + + Driver driverClass = (Driver) jdbcClassLoader.loadClass(driverClassName).newInstance(); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(jdbcClassLoader); + conn= driverClass.connect(jdbcurl, props); + }catch (Exception e){ + e.printStackTrace(); + throw e; + }finally { + Thread.currentThread().setContextClassLoader(classLoader); + } return conn; } + @Override - public JdbcConfiguration setCredential(DatasourceRequest datasourceRequest, DruidDataSource dataSource) throws PropertyVetoException { + public JdbcConfiguration setCredential(DatasourceRequest datasourceRequest, DruidDataSource dataSource) throws Exception{ DatasourceTypes datasourceType = DatasourceTypes.valueOf(datasourceRequest.getDatasource().getType()); JdbcConfiguration jdbcConfiguration = new JdbcConfiguration(); switch (datasourceType) { @@ -474,7 +535,15 @@ public class JdbcProvider extends DefaultJdbcProvider { } dataSource.setUsername(jdbcConfiguration.getUsername()); - dataSource.setDriverClassLoader(extendedJdbcClassLoader); + + ExtendedJdbcClassLoader classLoader; + if(isDefaultClassLoader(jdbcConfiguration.getCustomDriver())){ + classLoader = extendedJdbcClassLoader; + }else { + DeDriver deDriver = deDriverMapper.selectByPrimaryKey(jdbcConfiguration.getCustomDriver()); + classLoader = getCustomJdbcClassLoader(deDriver); + } + dataSource.setDriverClassLoader(classLoader); dataSource.setPassword(jdbcConfiguration.getPassword()); return jdbcConfiguration; diff --git a/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java b/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java index 227f06975c..a7339ea79c 100644 --- a/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java +++ b/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java @@ -2270,7 +2270,7 @@ public class DataSetTableService { record.setSyncStatus(JobStatus.Error.name()); example.clear(); example.createCriteria().andSyncStatusEqualTo(JobStatus.Underway.name()) - .andIdIn(datasetTableTasks.stream().map(DatasetTableTask::getTableId).collect(Collectors.toList())); + .andIdIn(jobStoppeddDatasetTables.stream().map(DatasetTable::getId).collect(Collectors.toList())); datasetTableMapper.updateByExampleSelective(record, example); //TaskLog diff --git a/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java b/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java index 58920ad4bc..f096eed2b9 100644 --- a/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java +++ b/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java @@ -27,11 +27,13 @@ import io.dataease.i18n.Translator; import io.dataease.plugins.common.base.domain.*; import io.dataease.plugins.common.base.mapper.DatasetTableMapper; import io.dataease.plugins.common.base.mapper.DatasourceMapper; +import io.dataease.plugins.common.constants.DatasourceCalculationMode; import io.dataease.plugins.common.constants.DatasourceTypes; import io.dataease.plugins.common.dto.datasource.DataSourceType; import io.dataease.plugins.common.dto.datasource.TableDesc; import io.dataease.plugins.common.request.datasource.DatasourceRequest; import io.dataease.plugins.config.SpringContextUtil; +import io.dataease.plugins.datasource.entity.JdbcConfiguration; import io.dataease.plugins.datasource.provider.Provider; import io.dataease.provider.ProviderFactory; import io.dataease.provider.datasource.ApiProvider; @@ -41,10 +43,8 @@ import io.dataease.service.sys.SysAuthService; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -131,6 +131,13 @@ public class DatasourceService { datasourceDTO.setCalculationMode(dataSourceType.getCalculationMode()); } }); + if(!datasourceDTO.getType().equalsIgnoreCase(DatasourceTypes.api.toString())){ + JdbcConfiguration configuration = new Gson().fromJson(datasourceDTO.getConfiguration(), JdbcConfiguration.class); + if(StringUtils.isNotEmpty(configuration.getCustomDriver()) && !configuration.getCustomDriver().equalsIgnoreCase("default")){ + datasourceDTO.setCalculationMode(DatasourceCalculationMode.DIRECT); + } + } + if(datasourceDTO.getType().equalsIgnoreCase(DatasourceTypes.mysql.toString())){ datasourceDTO.setConfiguration(JSONObject.toJSONString(new Gson().fromJson(datasourceDTO.getConfiguration(), MysqlConfiguration.class)) ); } diff --git a/backend/src/main/java/io/dataease/service/datasource/DriverService.java b/backend/src/main/java/io/dataease/service/datasource/DriverService.java new file mode 100644 index 0000000000..7934f92362 --- /dev/null +++ b/backend/src/main/java/io/dataease/service/datasource/DriverService.java @@ -0,0 +1,175 @@ +package io.dataease.service.datasource; + +import io.dataease.commons.utils.BeanUtils; +import io.dataease.commons.utils.DeFileUtils; +import io.dataease.dto.DriverDTO; +import io.dataease.plugins.common.base.domain.DeDriver; +import io.dataease.plugins.common.base.domain.DeDriverDetails; +import io.dataease.plugins.common.base.domain.DeDriverDetailsExample; +import io.dataease.plugins.common.base.mapper.DeDriverDetailsMapper; +import io.dataease.plugins.common.base.mapper.DeDriverMapper; +import io.dataease.plugins.datasource.provider.ExtendedJdbcClassLoader; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.UUID; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +@Transactional(rollbackFor = Exception.class) +@Service +public class DriverService { + + private static String DRIVER_PATH = "/opt/dataease/drivers/custom/"; + @Resource + private DeDriverMapper deDriverMapper; + @Resource + private DeDriverDetailsMapper deDriverDetailsMapper; + @Resource + private DatasourceService datasourceService; + + + public List list() throws Exception { + List driverDTOS = new ArrayList<>(); + deDriverMapper.selectByExample(null).forEach(deDriver -> { + DriverDTO driverDTO = new DriverDTO(); + BeanUtils.copyBean(driverDTO, deDriver); + datasourceService.types().forEach(dataSourceType -> { + if (dataSourceType.getType().equalsIgnoreCase(deDriver.getType())) { + driverDTO.setTypeDesc(dataSourceType.getName()); + } + + }); + driverDTOS.add(driverDTO); + }); + return driverDTOS; + } + + public void delete(String driverId) { + deDriverMapper.deleteByPrimaryKey(driverId); + + DeDriverDetailsExample example = new DeDriverDetailsExample(); + example.createCriteria().andDeDriverIdEqualTo(driverId); + deDriverDetailsMapper.deleteByExample(example); + DeFileUtils.deleteFile(DRIVER_PATH + driverId + "/"); + } + + public DeDriver save(DeDriver deDriver) { + deDriver.setCreateTime(System.currentTimeMillis()); + deDriver.setId(UUID.randomUUID().toString()); + deDriverMapper.insert(deDriver); + return deDriver; + } + + public DeDriver update(DeDriver deDriver) { + deDriverMapper.updateByPrimaryKey(deDriver); + return deDriver; + } + + + public List listDriverDetails(String driverId) { + DeDriverDetailsExample example = new DeDriverDetailsExample(); + example.createCriteria().andDeDriverIdEqualTo(driverId); + return deDriverDetailsMapper.selectByExampleWithBLOBs(example); + } + + public void deleteDriverFile(String driverFileId) { + DeDriverDetails deDriverDetails = deDriverDetailsMapper.selectByPrimaryKey(driverFileId); + DeFileUtils.deleteFile(DRIVER_PATH + deDriverDetails.getDeDriverId() + "/" + deDriverDetails.getFileName()); + deDriverDetailsMapper.deleteByPrimaryKey(driverFileId); + } + + public void saveJar(MultipartFile file, String driverId) throws Exception { + String filename = file.getOriginalFilename(); + String dirPath = DRIVER_PATH + driverId + "/"; + String filePath = dirPath + filename; + + saveFile(file, dirPath, filePath); + List jdbcList = new ArrayList<>(); + String version = ""; +// ExtendedJdbcClassLoader extendedJdbcClassLoader = new ExtendedJdbcClassLoader(new URL[]{new File(filePath).toURI().toURL()}, null); +// for (String className : getClassNameFrom(filePath)) { +// if (isChildClass(className, java.sql.Driver.class, extendedJdbcClassLoader)) { +// jdbcList.add(className); +// version = classVersion(extendedJdbcClassLoader, className); +// } +// } + + DeDriverDetails deDriverDetails = new DeDriverDetails(); + deDriverDetails.setId(UUID.randomUUID().toString()); + deDriverDetails.setDeDriverId(driverId); + deDriverDetails.setVersion(version); + deDriverDetails.setFileName(filename); + deDriverDetails.setDriverClass(String.join(",", jdbcList)); + deDriverDetailsMapper.insert(deDriverDetails); + } + + private List getClassNameFrom(String jarName) { + List fileList = new ArrayList(); + try { + JarFile jarFile = new JarFile(new File(jarName)); + Enumeration en = jarFile.entries(); // 枚举获得JAR文件内的实体,即相对路径 + while (en.hasMoreElements()) { + String name1 = en.nextElement().getName(); + if (!name1.endsWith(".class")) {//不是class文件 + continue; + } + String name2 = name1.substring(0, name1.lastIndexOf(".class")); + String name3 = name2.replaceAll("/", "."); + fileList.add(name3); + } + } catch (IOException e) { + e.printStackTrace(); + } + return fileList; + } + + public boolean isChildClass(String className, Class parentClazz, ExtendedJdbcClassLoader extendedJdbcClassLoader) { + if (className == null) return false; + + Class clazz = null; + try { + clazz = extendedJdbcClassLoader.loadClass(className); + if (Modifier.isAbstract(clazz.getModifiers())) {//抽象类忽略 + return false; + } + if (Modifier.isInterface(clazz.getModifiers())) {//接口忽略 + return false; + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return parentClazz.isAssignableFrom(clazz); + } + + private String classVersion(ExtendedJdbcClassLoader extendedJdbcClassLoader, String className) throws Exception { + Class clazz = extendedJdbcClassLoader.loadClass(className); + return clazz.getPackage().getImplementationVersion(); + } + + private String saveFile(MultipartFile file, String dirPath, String filePath) throws Exception { + File p = new File(dirPath); + if (!p.exists()) { + p.mkdirs(); + } + File f = new File(filePath); + FileOutputStream fileOutputStream = new FileOutputStream(f); + fileOutputStream.write(file.getBytes()); + fileOutputStream.flush(); + fileOutputStream.close(); + return filePath; + } + + +} diff --git a/backend/src/main/resources/db/migration/V35__1.11.sql b/backend/src/main/resources/db/migration/V35__1.11.sql index 8be983b423..8de594ecae 100644 --- a/backend/src/main/resources/db/migration/V35__1.11.sql +++ b/backend/src/main/resources/db/migration/V35__1.11.sql @@ -1,2 +1,23 @@ ALTER TABLE `panel_group` ADD COLUMN `status` varchar(255) NULL DEFAULT 'publish' COMMENT '1.publish--发布 2.unpublished--未发布' AFTER `mobile_layout`; + + +CREATE TABLE `de_driver` ( + `id` varchar(50) NOT NULL COMMENT '主键', + `name` varchar(50) NOT NULL COMMENT '用户ID', + `create_time` bigint(13) NOT NULL COMMENT '创健时间', + `type` varchar(255) DEFAULT NULL COMMENT '数据源类型', + `driver_class` varchar(255) DEFAULT NULL COMMENT '驱动类', + `desc` varchar(255) DEFAULT NULL COMMENT '描述', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='驱动'; + + +CREATE TABLE `de_driver_details` ( + `id` varchar(50) NOT NULL COMMENT '主键', + `de_driver_id` varchar(50) NOT NULL COMMENT '驱动主键', + `file_name` varchar(255) DEFAULT NULL COMMENT '名称', + `version` varchar(255) DEFAULT NULL COMMENT '版本', + `driver_class` longtext DEFAULT NULL COMMENT '驱动类', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='驱动详情'; \ No newline at end of file diff --git a/frontend/src/api/system/datasource.js b/frontend/src/api/system/datasource.js index ada40a1f3b..fb7f8ea3c6 100644 --- a/frontend/src/api/system/datasource.js +++ b/frontend/src/api/system/datasource.js @@ -15,6 +15,13 @@ export function listDatasource() { method: 'get' }) } +export function listDrivers() { + return request({ + url: '/driver/list', + loading: true, + method: 'post' + }) +} export function listDatasourceType() { return request({ url: '/datasource/types', @@ -29,6 +36,13 @@ export function listDatasourceByType(type) { method: 'get' }) } +export function listDriverByType(type) { + return request({ + url: '/driver/list/' + type, + loading: true, + method: 'get' + }) +} export function addDs(data) { return request({ url: 'datasource/add/', @@ -90,4 +104,45 @@ export function checkApiDatasource(data){ }) } +export function addDriver(data) { + return request({ + url: '/driver/save', + method: 'post', + loading: true, + data + }) +} + +export function listDriverDetails(id) { + return request({ + url: '/driver/listDriverDetails/' + id, + method: 'get', + loading: true + }) +} + +export function deleteDriverFile(id) { + return request({ + url: '/driver/deleteDriverFile/' + id, + method: 'post', + loading: true + }) +} + +export function delDriver(id) { + return request({ + url: 'driver/delete/' + id, + loading: true, + method: 'post' + }) +} +export function updateDriver(data) { + return request({ + url: 'driver/update/', + loading: true, + method: 'post', + data + }) +} + export default { dsGrid, addDs, editDs, delDs, validateDs, listDatasource, getSchema } diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index ee1cec1542..b6f3277817 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -1328,7 +1328,22 @@ export default { sql_ds_union_error: 'Direct connect SQL dataset can not be union', api_data: 'API dataset' }, + driver:{ + driver: 'Driver', + please_choose_driver: 'Please choose driver', + mgm: 'Driver', + add: 'ADD Driver', + modify: 'Modify', + show_info: 'Driver info', + file_name: 'File name', + version: 'version' + }, datasource: { + auth_method: 'Auth method', + passwd: 'UserName Password', + kerbers_info: 'Please make sure krb5 Conf, KeyTab key, added to path: /opt/dataease/conf', + client_principal: 'Client Principal', + keytab_Key_path: 'Keytab Key Path', datasource: 'Data Source', please_select_left: 'Please select the data source from the left', show_info: 'Data Source Info', diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js index 09da748a8a..77978c875a 100644 --- a/frontend/src/lang/tw.js +++ b/frontend/src/lang/tw.js @@ -1328,7 +1328,22 @@ export default { sql_ds_union_error: '直連模式下SQL數據集,不支持關聯', api_data: 'API 數據集' }, + driver:{ + driver: '驅動', + please_choose_driver: '青選擇驅動', + mgm: '驅動管理', + add: '添加驅動', + modify: '修改', + show_info: '驅動信息', + file_name: '文件名', + version: '版本' + }, datasource: { + auth_method: '認證方式', + passwd: '用户名密码', + kerbers_info: '请确保 krb5.Conf、Keytab Key,已经添加到路径:/opt/dataease/conf', + client_principal: 'Client Principal', + keytab_Key_path: 'Keytab Key Path', datasource: '數據源', please_select_left: '請從左側選擇數據源', show_info: '數據源信息', diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index 0ba1fa5899..1aa3191360 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -1330,7 +1330,22 @@ export default { sql_ds_union_error: '直连模式下SQL数据集,不支持关联', api_data: 'API 数据集' }, + driver:{ + driver: '驱动', + please_choose_driver: '请选择驱动', + mgm: '驱动管理', + add: '添加驱动', + modify: '修改', + show_info: '驱动信息', + file_name: '文件名', + version: '版本' + }, datasource: { + auth_method: '认证方式', + passwd: '用户名密码', + kerbers_info: '请确保 krb5.Conf、Keytab Key,已经添加到路径:/opt/dataease/conf', + client_principal: 'Client Principal', + keytab_Key_path: 'Keytab Key Path', datasource: '数据源', please_select_left: '请从左侧选择数据源', show_info: '数据源信息', diff --git a/frontend/src/views/system/datasource/DriverForm.vue b/frontend/src/views/system/datasource/DriverForm.vue new file mode 100644 index 0000000000..02a7ab99d9 --- /dev/null +++ b/frontend/src/views/system/datasource/DriverForm.vue @@ -0,0 +1,294 @@ + + + + diff --git a/frontend/src/views/system/datasource/DsConfiguration.vue b/frontend/src/views/system/datasource/DsConfiguration.vue index a7fe183691..4d2d421fbb 100644 --- a/frontend/src/views/system/datasource/DsConfiguration.vue +++ b/frontend/src/views/system/datasource/DsConfiguration.vue @@ -3,13 +3,13 @@ @@ -77,7 +77,8 @@ - + @@ -103,7 +104,10 @@ @@ -125,20 +129,55 @@ - - {{ $t('datasource.oracle_sid') }} + {{ + $t('datasource.oracle_sid') + }} + {{ $t('datasource.oracle_service_name') }} - + + + + + + + + + + + +

+ {{$t('datasource.kerbers_info')}} +

+
+ + + + + + - @@ -164,21 +203,26 @@ - {{ $t('datasource.get_schema') }} + v-if="form.type=='oracle' || form.type=='sqlServer' || form.type=='pg' || form.type=='redshift' || form.type=='db2'"> + {{ + $t('datasource.get_schema') + }} + - + - @@ -208,7 +252,6 @@ diff --git a/frontend/src/views/system/plugin/index.vue b/frontend/src/views/system/plugin/index.vue index 3713f245ee..59276e27c5 100644 --- a/frontend/src/views/system/plugin/index.vue +++ b/frontend/src/views/system/plugin/index.vue @@ -8,7 +8,6 @@ @search="search" >