diff --git a/.travis.yml b/.travis.yml index 601c2f558784f20cd346200a44cd2a08ecbdfa79..4bf0b9710fc504042e556775ab6d6024cdfa0d3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,9 +21,9 @@ before_script: script: - if [ "$TRAVIS_BRANCH" == "develop" ] && [ "$TRAVIS_PULL_REQUEST" == false ]; then - travis_wait 30 ./mvnw clean install -DskipTests=false -Dcheckstyle.skip=false -Dlicense.skip=false -q -P image -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; + travis_wait 30 ./mvnw clean install -DskipTests=false -Dcheckstyle.skip=false -Dlicense.skip=false -P image -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; else - travis_wait 30 ./mvnw clean install -DskipTests=false -Dcheckstyle.skip=false -Dlicense.skip=false -q -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; + travis_wait 30 ./mvnw clean install -DskipTests=false -Dcheckstyle.skip=false -Dlicense.skip=false -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn; fi after_success: - bash <(curl -s https://codecov.io/bash) diff --git a/README.md b/README.md index b2449e1155f6ce6a0c5d4c20e7cd0d27bbbd32aa..8b5c8e2890157194a18a385755c5a79a12f72b10 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ For more details about principle and design, please go to [Seata wiki page](http ## Maven dependency ```xml -<seata.version>1.2.0</seata.version> +<seata.version>1.3.0</seata.version> <dependency> <groupId>io.seata</groupId> @@ -117,7 +117,7 @@ Contributors are welcomed to join the Seata project. Please check [CONTRIBUTING] * dev-seata@googlegroups.com , for dev/user discussion. [subscribe](mailto:dev-seata+subscribe@googlegroups.com), [unsubscribe](mailto:dev-seata+unsubscribe@googlegroups.com), [archive](https://groups.google.com/forum/#!forum/dev-seata) -<img src="https://img.alicdn.com/tfs/TB1vuPqzXT7gK0jSZFpXXaTkpXa-1078-352.jpg" height="200" width="630"> +<img src="https://img.alicdn.com/tfs/TB1NvtaFrj1gK0jSZFOXXc7GpXa-1218-404.jpg" height="200" width="630"> ## Seata ecosystem @@ -156,7 +156,7 @@ here](https://github.com/seata/seata/issues/1246) to tell us your scenario to ma <img alt='政采云' height='40' src='https://img.alicdn.com/tfs/TB1DDiCorY1gK0jSZTEXXXDQVXa-440-114.jpg' /img> <img alt='浙江公安厅' height='40' src='https://img.alicdn.com/tfs/TB1SXGzoxn1gK0jSZKPXXXvUXXa-426-180.jpg' /img> <img alt='特步' height='40' src='https://www.xtep.com/images/logo.png' /img> - <img alt='中通快递' height='40' src='https://www.zto.com/imgs/logo.png' /img> + <img alt='中通快递' height='40' src='https://img.alicdn.com/tfs/TB1rCNSFxn1gK0jSZKPXXXvUXXa-172-31.png' /img> <img alt='美的集团' height='40' src='https://img.alicdn.com/tfs/TB1cgvjwYj1gK0jSZFOXXc7GpXa-1040-282.png' /img> <img alt='浙江烟草' height='40' src='https://img.alicdn.com/tfs/TB1e7Wiovb2gK0jSZK9XXaEgFXa-1028-160.jpg' /img> <img alt='韵达快递' height='40' src='http://www.yunda56.com/cn/images/ky_images/logo.png' /img> @@ -192,8 +192,8 @@ here](https://github.com/seata/seata/issues/1246) to tell us your scenario to ma <img alt='浙大睿医' height='40' src='https://img.alicdn.com/tfs/TB1kQThrFY7gK0jSZKzXXaikpXa-220-110.jpg' /img> <img alt='居然之家' height='40' src='https://img.alicdn.com/tfs/TB1LK6jrUT1gK0jSZFrXXcNCXXa-180-54.png' /img> <img alt='臻善科技' height='40' src='http://www.gisquest.com/static/web/img/img-1.png?v=v3' /img> - <img alt='中国支付通' height='40' src='http://www.chinasmartpay.com/img/index_logo.png' /img> - <img alt='众网小贷' height='40' src='http://imassbank.com/images/zw_logo.png' /img> + <img alt='中国支付通' height='40' src='https://img.alicdn.com/tfs/TB1VGpTFET1gK0jSZFrXXcNCXXa-193-55.png' /img> + <img alt='众网小贷' height='40' src='https://img.alicdn.com/tfs/TB19Y8XFEY1gK0jSZFMXXaWcVXa-160-60.png' /img> <img alt='谐云科技' height='40' src='https://img.alicdn.com/tfs/TB1V1YlrRv0gK0jSZKbXXbK2FXa-514-160.png' /img> <img alt='浙江甄品' height='40' src='https://img.alicdn.com/tfs/TB1oC2prND1gK0jSZFyXXciOVXa-246-124.jpg' /img> <img alt='深圳海豚网' height='40' src='https://img.alicdn.com/tfs/TB1defkrLb2gK0jSZK9XXaEgFXa-434-146.jpg' /img> @@ -209,18 +209,43 @@ here](https://github.com/seata/seata/issues/1246) to tell us your scenario to ma <img alt='维恩贝特' height='40' src='http://www.vivebest.com/templates/crs/images/vnb_logo.png' /img> <img alt='八库' height='40' src='https://img.alicdn.com/tfs/TB1hC5cwVY7gK0jSZKzXXaikpXa-318-134.png' /img> <img alt='大诚若谷' height='40' src='https://img.alicdn.com/tfs/TB1VuPhw4D1gK0jSZFyXXciOVXa-294-124.png' /img> - <img alt='成都数智索' height='40' src='https://img.alicdn.com/tfs/TB1oJKiw4D1gK0jSZFyXXciOVXa-2053-377.png' /img> + <img alt='成都数智索' height='40' src='https://img.alicdn.com/tfs/TB1oJKiw4D1gK0jSZFyXXciOVXa-2053-377.png' /img> + <img alt='北京超图' height='40' src='https://img.alicdn.com/tfs/TB1eKFXFEz1gK0jSZLeXXb9kVXa-163-54.png' /img> + <img alt='深圳易佰' height='40' src='https://img.alicdn.com/tfs/TB1gkXaFrr1gK0jSZR0XXbP8XXa-187-57.png' /img> <img alt='宿迁民丰农商银行' height='40' src='https://img.alicdn.com/tfs/TB1bH5fw7L0gK0jSZFAXXcA9pXa-442-39.png' /img> <img alt='杭州喜团科技' height='40' src='https://img.alicdn.com/tfs/TB1IXqgwYj1gK0jSZFuXXcrHpXa-197-58.png' /img> - <img alt='上海海智在线' height='40' src='https://user-images.githubusercontent.com/2938725/75735507-cbad3f00-5d35-11ea-9ce8-cad175948b7f.png' /img> + <img alt='上海海智在线' height='40' src='https://img.alicdn.com/tfs/TB1xAJUFy_1gK0jSZFqXXcpaXXa-320-80.jpg' /img> <img alt='丞家(上海)公寓管理' height='40' src='https://image.cjia.com/website/apartment/webresource/image/logo_8f2f47fe.png' /img> - <img alt='北京超图' height='40' src='https://user-images.githubusercontent.com/20411887/75741329-3a45c900-5d45-11ea-84db-aafed13bb8bc.png' /img> - <img alt='深圳易佰' height='40' src='https://user-images.githubusercontent.com/19617516/75748727-1beac800-5d5b-11ea-8ee1-71467e93c24f.png' /img> - <img alt='安徽国科新材科' height='40' src='https://user-images.githubusercontent.com/61726674/75748449-70da0e80-5d5a-11ea-8e4d-d22fe0442caf.png' /img> - <img alt='易点生活' height='40' src='https://user-images.githubusercontent.com/44664389/75748761-31f88880-5d5b-11ea-8223-d819b3430916.jpg' /img> + <img alt='安徽国科新材科' height='40' src='https://img.alicdn.com/tfs/TB1ICJfFuH2gK0jSZJnXXaT1FXa-654-232.png' /img> + <img alt='易点生活' height='40' src='https://img.alicdn.com/tfs/TB1AdI5FeL2gK0jSZPhXXahvXXa-1518-542.jpg' /img> <img alt='商银信支付' height='40' src='https://img.alicdn.com/tfs/TB1rxndw4n1gK0jSZKPXXXvUXXa-150-68.png' /img> <img alt='钛师傅云' height='40' src='https://www.tsfyun.com/images/logo.png' /img> - <img alt='广州力生信息' height='40' src='https://user-images.githubusercontent.com/21170967/75753185-30cc5900-5d65-11ea-8eba-cd24ee669c64.jpg' /img> -</div> + <img alt='广州力生信息' height='40' src='https://img.alicdn.com/tfs/TB1m0FcFuH2gK0jSZFEXXcqMpXa-139-48.png' /img> + <img alt='杭州启舰科技有限公司' height='40' src='http://www.qijian-tech.com/assets/onepage/img/logo/red.png' /img> + <img alt='上海美浮特' height='40' src='https://img.alicdn.com/tfs/TB1uUtaFuT2gK0jSZFvXXXnFXXa-370-45.jpg' /img> + <img alt='杭州中威慧云医疗科技有限公司' height='40' src='https://img.alicdn.com/tfs/TB1iqo_FaL7gK0jSZFBXXXZZpXa-361-54.jpg' /img> + <img alt='易族智汇(北京)' height='40' src='http://www.javamall.com.cn/images/logonew.jpg' /img> + <img alt='佛山宅无限' height='40' src='https://zwxnetwork.oss-cn-shenzhen.aliyuncs.com/static/temporary_official_website/logo.png' /img> + <img alt='F5未来商店' height='40' src='https://cdn.f5-store.cn/front_end/common_images/logo.png' /img> + <img alt='甄品信息科技' height='40' src='https://img.alicdn.com/tfs/TB1SxJWFEY1gK0jSZFCXXcwqXXa-185-65.png' /img> + <img alt='行云全球汇跨境电商(杭州分部)' height='40' src='http://www.xyb2b.com/_nuxt/img/5e5584f.png' /img> + <img alt='世纪加华' height='40' src='https://zhengxin-pub.bj.bcebos.com/logopic/a4ff4990e2ba2d57c90e8d16c649b952_fullsize.jpg?x-bce-process=image/resize,m_lfit,w_200' /img> + <img alt='海牛电子商务' height='40' src='http://www.hainiuec.com/public/assets/addons/cms/img/company-logo.png' /img> + <img alt='杭州华网信息' height='40' src='https://img.alicdn.com/tfs/TB1FFX6FqL7gK0jSZFBXXXZZpXa-288-101.png' /img> + <img alt='快陪练' height='40' src='https://img.alicdn.com/tfs/TB1rhNRFAL0gK0jSZFtXXXQCXXa-321-96.png' /img> + <img alt='西南石油大学' height='40' src='https://dss2.bdstatic.com/6Ot1bjeh1BF3odCf/it/u=829617221,290823158&fm=74&app=80&f=JPEG&size=f121,121?sec=1880279984&t=b0b603710dd0af061a278d11cfe327ae' /img> + <img alt='领课网络' height='40' src='https://img.alicdn.com/tfs/TB18TNRFEz1gK0jSZLeXXb9kVXa-244-60.jpg' /img> + <img alt='美通社' height='40' src='https://img.alicdn.com/tfs/TB1i1JTFCf2gK0jSZFPXXXsopXa-151-60.png' /img> + <img alt='睿维科技有限公司' height='40' src='https://img.alicdn.com/tfs/TB1ztXXFpY7gK0jSZKzXXaikpXa-179-60.png' /img> + <img alt='郑州信源信息技术' height='40' src='https://img.alicdn.com/tfs/TB1SkJ9FuT2gK0jSZFvXXXnFXXa-266-56.png' /img> + <img alt='荣怀集团' height='40' src='https://img.alicdn.com/tfs/TB1AzbWgZKfxu4jSZPfXXb3dXXa-1117-382.png' /img> + <img alt='浙江群集大数据科技有限公司' height='40' src='https://img.alicdn.com/tfs/TB1HtFZFq61gK0jSZFlXXXDKFXa-1375-214.png' /img> + <img alt='北京易点租有限公司' height='40' src='https://img.alicdn.com/tfs/TB1nax.FuH2gK0jSZFEXXcqMpXa-336-154.png' /img> + </div> + + + + + diff --git a/all/pom.xml b/all/pom.xml index 567482a27f1a3c3de36f30ec298a52be8892311f..9b18a59c978e9e84e14d7b772807cdfb3f187eb0 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -21,7 +21,7 @@ <groupId>io.seata</groupId> <artifactId>seata-all</artifactId> - <version>1.2.0</version> + <version>1.3.0</version> <name>Seata All-in-one ${project.version}</name> <url>http://seata.io</url> @@ -284,6 +284,11 @@ <artifactId>seata-compressor-zip</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>io.seata</groupId> + <artifactId>seata-compressor-lz4</artifactId> + <version>${project.version}</version> + </dependency> <!-- saga --> <dependency> @@ -456,7 +461,6 @@ <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> - <scope>provided</scope> </dependency> <dependency> <groupId>javax.inject</groupId> @@ -526,6 +530,7 @@ <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> + <scope>provided</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> @@ -552,6 +557,11 @@ <artifactId>kryo-serializers</artifactId> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.lz4</groupId> + <artifactId>lz4-java</artifactId> + <scope>provided</scope> + </dependency> </dependencies> <build> @@ -675,6 +685,7 @@ <include>io.seata:seata-compressor-7z</include> <include>io.seata:seata-compressor-bzip2</include> <include>io.seata:seata-compressor-zip</include> + <include>io.seata:seata-compressor-lz4</include> </includes> </artifactSet> <transformers> diff --git a/bom/pom.xml b/bom/pom.xml index f6ebdadc5ee68f475b384eb829883a190779a3f3..03759b0c8aef54221086ec224cfe33d2e17b4ee2 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -20,7 +20,7 @@ <groupId>io.seata</groupId> <artifactId>seata-bom</artifactId> - <version>1.2.0</version> + <version>1.3.0</version> <modelVersion>4.0.0</modelVersion> <packaging>pom</packaging> @@ -75,6 +75,7 @@ <commons-pool2.version>2.4.2</commons-pool2.version> <commons-pool.version>1.6</commons-pool.version> <commons-dbcp2.version>2.7.0</commons-dbcp2.version> + <hikari.version>3.4.3</hikari.version> <cglib.version>3.1</cglib.version> <aopalliance.version>1.0</aopalliance.version> <zkclient.version>0.11</zkclient.version> @@ -83,7 +84,8 @@ <spring-context-support.version>1.0.2</spring-context-support.version> <jacoco-maven-plugin.version>0.8.3</jacoco-maven-plugin.version> <apollo-client.version>1.1.0</apollo-client.version> - <redis-clients.version>2.9.0</redis-clients.version> + <redis-clients.version>3.2.0</redis-clients.version> + <mock-jedis.version>0.1.16</mock-jedis.version> <eureka-clients.version>1.9.5</eureka-clients.version> <consul-clients.version>1.4.2</consul-clients.version> <nacos-client.version>1.2.0</nacos-client.version> @@ -108,6 +110,7 @@ <xz.version>1.8</xz.version> <commons-compress.version>1.19</commons-compress.version> <ant.version>1.10.6</ant.version> + <lz4.version>1.7.1</lz4.version> <!-- Compiler settings properties --> <maven.compiler.source>1.8</maven.compiler.source> @@ -120,6 +123,7 @@ <kryo-serializers.version>0.42</kryo-serializers.version> <hessian.version>4.0.63</hessian.version> <fst.version>2.57</fst.version> + <groovy.version>2.4.4</groovy.version> </properties> <dependencyManagement> @@ -302,6 +306,12 @@ <artifactId>jedis</artifactId> <version>${redis-clients.version}</version> </dependency> + <dependency> + <groupId>com.github.fppt</groupId> + <artifactId>jedis-mock</artifactId> + <version>${mock-jedis.version}</version> + <scope>test</scope> + </dependency> <dependency> <groupId>com.netflix.eureka</groupId> <artifactId>eureka-client</artifactId> @@ -465,6 +475,11 @@ <artifactId>commons-dbcp2</artifactId> <version>${commons-dbcp2.version}</version> </dependency> + <dependency> + <groupId>com.zaxxer</groupId> + <artifactId>HikariCP</artifactId> + <version>${hikari.version}</version> + </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> @@ -491,6 +506,26 @@ <artifactId>ant</artifactId> <version>${ant.version}</version> </dependency> + <dependency> + <groupId>org.lz4</groupId> + <artifactId>lz4-java</artifactId> + <version>${lz4.version}</version> + </dependency> + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-all</artifactId> + <version>${groovy.version}</version> + <exclusions> + <exclusion> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + </exclusion> + <exclusion> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-launcher</artifactId> + </exclusion> + </exclusions> + </dependency> </dependencies> </dependencyManagement> diff --git a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java index 36cc6c846eff1daaaf0045da4b8eccb2247ac07a..cf815a6554426c9e66e05308176b6cd6223d4a23 100644 --- a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java +++ b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java @@ -24,6 +24,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; @@ -406,7 +408,6 @@ public class EnhancedServiceLoader { } private List<Class> loadAllExtensionClass(ClassLoader loader) { - List<Class> result; List<ExtensionDefinition> definitions = definitionsHolder.get(); if (definitions == null) { synchronized (definitionsHolder) { @@ -467,7 +468,7 @@ public class EnhancedServiceLoader { while (urls.hasMoreElements()) { java.net.URL url = urls.nextElement(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), Constants.DEFAULT_CHARSET))) { - String line = null; + String line; while ((line = reader.readLine()) != null) { final int ci = line.indexOf('#'); if (ci >= 0) { @@ -476,10 +477,11 @@ public class EnhancedServiceLoader { line = line.trim(); if (line.length() > 0) { try { - Class<?> clazz = Class.forName(line, true, loader); - ExtensionDefinition extensionDefinition = getUnloadedExtensionDefinition(clazz); + ExtensionDefinition extensionDefinition = getUnloadedExtensionDefinition(line, loader); if (extensionDefinition == null) { - LOGGER.warn("The same extension {} has already been loaded, skipped", line); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("The same extension {} has already been loaded, skipped", line); + } continue; } extensions.add(extensionDefinition); @@ -489,24 +491,26 @@ public class EnhancedServiceLoader { } } } catch (Throwable e) { - LOGGER.warn(e.getMessage()); + LOGGER.warn("load clazz instance error: {}", e.getMessage()); } } } } - private ExtensionDefinition getUnloadedExtensionDefinition(Class<?> clazz) { - String serviceName = null; - Integer priority = 0; - Scope scope = Scope.SINGLETON; - LoadLevel loadLevel = clazz.getAnnotation(LoadLevel.class); - if (loadLevel != null) { - serviceName = loadLevel.name(); - priority = loadLevel.order(); - scope = loadLevel.scope(); - } + private ExtensionDefinition getUnloadedExtensionDefinition(String className, ClassLoader loader) + throws ClassNotFoundException { //Check whether the definition has been loaded - if (!classToDefinitionMap.containsKey(clazz)) { + if (!isDefinitionContainsClazz(className, loader)) { + Class<?> clazz = Class.forName(className, true, loader); + String serviceName = null; + Integer priority = 0; + Scope scope = Scope.SINGLETON; + LoadLevel loadLevel = clazz.getAnnotation(LoadLevel.class); + if (loadLevel != null) { + serviceName = loadLevel.name(); + priority = loadLevel.order(); + scope = loadLevel.scope(); + } ExtensionDefinition result = new ExtensionDefinition(serviceName, priority, scope, clazz); classToDefinitionMap.put(clazz, result); if (serviceName != null) { @@ -517,6 +521,18 @@ public class EnhancedServiceLoader { return null; } + private boolean isDefinitionContainsClazz(String className, ClassLoader loader) { + for (Map.Entry<Class<?>, ExtensionDefinition> entry : classToDefinitionMap.entrySet()) { + if (!entry.getKey().getName().equals(className)) { + continue; + } + if (Objects.equals(entry.getValue().getServiceClass().getClassLoader(), loader)) { + return true; + } + } + return false; + } + private ExtensionDefinition getDefaultExtensionDefinition() { List<ExtensionDefinition> currentDefinitions = definitionsHolder.get(); if (currentDefinitions != null && currentDefinitions.size() > 0) { diff --git a/common/src/main/java/io/seata/common/thread/NamedThreadFactory.java b/common/src/main/java/io/seata/common/thread/NamedThreadFactory.java index 74420404105c8421aa766e4ebdb13d48cc160238..df8b940143e47d0c248a17c1b4ddf94183025705 100644 --- a/common/src/main/java/io/seata/common/thread/NamedThreadFactory.java +++ b/common/src/main/java/io/seata/common/thread/NamedThreadFactory.java @@ -30,6 +30,7 @@ import io.netty.util.concurrent.FastThreadLocalThread; */ public class NamedThreadFactory implements ThreadFactory { private final static Map<String, AtomicInteger> PREFIX_COUNTER = new ConcurrentHashMap<>(); + private AtomicInteger counter = new AtomicInteger(0); private final String prefix; private final int totalSize; private final boolean makeDaemons; @@ -71,7 +72,7 @@ public class NamedThreadFactory implements ThreadFactory { @Override public Thread newThread(Runnable r) { - String name = prefix; + String name = prefix + "_" + counter.incrementAndGet(); if (totalSize > 1) { name += "_" + totalSize; } diff --git a/common/src/main/java/io/seata/common/util/CollectionUtils.java b/common/src/main/java/io/seata/common/util/CollectionUtils.java index 69d06dd1d73609d3ab9f8bd4ff97ef8d732eb023..327f23c2bc4c48f274a0d87c368d6e960f60bedb 100644 --- a/common/src/main/java/io/seata/common/util/CollectionUtils.java +++ b/common/src/main/java/io/seata/common/util/CollectionUtils.java @@ -17,9 +17,9 @@ package io.seata.common.util; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; /** * The type Collection utils. @@ -146,7 +146,7 @@ public class CollectionUtils { if (data == null) { return null; } - Map<String, String> map = new ConcurrentHashMap<>(); + Map<String, String> map = new HashMap<>(); if (StringUtils.isBlank(data)) { return map; } @@ -177,7 +177,7 @@ public class CollectionUtils { if (isEmpty(sourceList)) { return sourceList; } List<String> destList = new ArrayList<>(sourceList.size()); for (String element : sourceList) { - if (null != element) { + if (element != null) { destList.add(element.toUpperCase()); } else { destList.add(null); diff --git a/common/src/main/java/io/seata/common/util/IdWorker.java b/common/src/main/java/io/seata/common/util/IdWorker.java new file mode 100644 index 0000000000000000000000000000000000000000..888f366c32fb8299dabe5f5838cf6280540b6bcb --- /dev/null +++ b/common/src/main/java/io/seata/common/util/IdWorker.java @@ -0,0 +1,175 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.common.util; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * @author funkye + */ +public class IdWorker { + + private volatile static IdWorker idWorker = null; + + /** + * Start time cut (2020-05-03) + */ + private final long twepoch = 1588435200000L; + + /** + * The number of bits occupied by the machine id + */ + private final long workerIdBits = 10L; + + /** + * Maximum supported machine id, the result is 1023 (this shift algorithm can quickly calculate the largest decimal + * number that can be represented by a few binary numbers) + */ + private final long maxWorkerId = -1L ^ (-1L << workerIdBits); + + /** + * The number of bits the sequence occupies in id + */ + private final long sequenceBits = 12L; + + /** + * Machine ID left 12 digits + */ + private final long workerIdShift = sequenceBits; + + /** + * Time truncated to the left by 22 bits (10 + 12) + */ + private final long timestampLeftShift = sequenceBits + workerIdBits; + + /** + * Generate sequence mask + */ + private final long sequenceMask = -1L ^ (-1L << sequenceBits); + + /** + * Machine ID (0 ~ 1023) + */ + private long workerId; + + /** + * Sequence in milliseconds (0 ~ 4095) + */ + private long sequence = 0L; + + /** + * Time of last ID generation + */ + private long lastTimestamp = -1L; + + /** + * Constructor + * + * @param workerId + * Job ID (0 ~ 1023) + */ + public IdWorker(long workerId) { + if (workerId > maxWorkerId || workerId < 0) { + throw new IllegalArgumentException( + String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); + } + this.workerId = workerId; + } + + /** + * Get the next ID (the method is thread-safe) + * + * @return SnowflakeId + */ + public long nextId() { + long timestamp = timeGen(); + + if (timestamp < lastTimestamp) { + throw new RuntimeException(String.format( + "clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); + } + + synchronized (this) { + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) { + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0L; + } + lastTimestamp = timestamp; + } + return ((timestamp - twepoch) << timestampLeftShift) | (workerId << workerIdShift) | sequence; + } + + /** + * Block until the next millisecond until a new timestamp is obtained + * + * @param lastTimestamp + * Time of last ID generation + * @return Current timestamp + */ + protected long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + /** + * Returns the current time in milliseconds + * + * @return Current time (ms) + */ + protected long timeGen() { + return System.currentTimeMillis(); + } + + public static IdWorker getInstance() { + if (idWorker == null) { + synchronized (IdWorker.class) { + if (idWorker == null) { + init(initWorkerId()); + } + } + } + return idWorker; + } + + public static long initWorkerId() { + InetAddress address; + try { + address = InetAddress.getLocalHost(); + } catch (final UnknownHostException e) { + throw new IllegalStateException("Cannot get LocalHost InetAddress, please check your network!",e); + } + byte[] ipAddressByteArray = address.getAddress(); + return ((ipAddressByteArray[ipAddressByteArray.length - 2] & 0B11) << Byte.SIZE) + (ipAddressByteArray[ipAddressByteArray.length - 1] & 0xFF); + } + + public static void init(Long serverNodeId) { + if (idWorker == null) { + synchronized (IdWorker.class) { + if (idWorker == null) { + idWorker = new IdWorker(serverNodeId); + } + } + } + } + +} diff --git a/common/src/main/java/io/seata/common/util/NetUtil.java b/common/src/main/java/io/seata/common/util/NetUtil.java index dd4ae9838c5763ac565d3a1439db07a95bca6b3d..724381392d3d58e23b9272c8e1e03d07bf72c6f2 100644 --- a/common/src/main/java/io/seata/common/util/NetUtil.java +++ b/common/src/main/java/io/seata/common/util/NetUtil.java @@ -47,7 +47,7 @@ public class NetUtil { * @return the string */ public static String toStringAddress(SocketAddress address) { - if (null == address) { + if (address == null) { return StringUtils.EMPTY; } return toStringAddress((InetSocketAddress) address); @@ -193,7 +193,7 @@ public class NetUtil { * @param address the address */ public static void validAddress(InetSocketAddress address) { - if (null == address.getHostName() || 0 == address.getPort()) { + if (address.getHostName() == null || 0 == address.getPort()) { throw new IllegalArgumentException("invalid address:" + address); } } diff --git a/common/src/main/java/io/seata/common/util/NumberUtils.java b/common/src/main/java/io/seata/common/util/NumberUtils.java index 5fb202fdfa3d17b3d6651a536fa6c2492e1f0adb..0724ef55928c3ed0baf80a2962b3c56c4b985abb 100644 --- a/common/src/main/java/io/seata/common/util/NumberUtils.java +++ b/common/src/main/java/io/seata/common/util/NumberUtils.java @@ -38,8 +38,26 @@ public class NumberUtils { } try { return Integer.parseInt(str); - } catch (final NumberFormatException nfe) { + } catch (NumberFormatException nfe) { return defaultValue; } } + + public static Long toLong(String str, final Long defaultValue) { + if (str == null) { + return defaultValue; + } + try { + return Long.valueOf(str); + } catch (NumberFormatException nfe) { + return defaultValue; + } + } + + public static Long toLong(String str) { + if (StringUtils.isNotBlank(str)) { + return Long.valueOf(str); + } + return null; + } } diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/util/StringFormatUtils.java b/common/src/main/java/io/seata/common/util/StringFormatUtils.java similarity index 98% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/util/StringFormatUtils.java rename to common/src/main/java/io/seata/common/util/StringFormatUtils.java index 68f7f77170c90a4b8da945dd05ac58a9ba17af9f..5f8d96b1f3ae41db08518f40f730bbb704c1e0ef 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/util/StringFormatUtils.java +++ b/common/src/main/java/io/seata/common/util/StringFormatUtils.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.util; +package io.seata.common.util; /** * @author xingfudeshi@gmail.com diff --git a/common/src/test/java/io/seata/common/exception/FrameworkExceptionTest.java b/common/src/test/java/io/seata/common/exception/FrameworkExceptionTest.java index 3fd7e9e9401f851cc86abbccdf4570a0d2af21c7..cbb014271c75cacc7cde658276de16de8110c717 100644 --- a/common/src/test/java/io/seata/common/exception/FrameworkExceptionTest.java +++ b/common/src/test/java/io/seata/common/exception/FrameworkExceptionTest.java @@ -143,7 +143,7 @@ public class FrameworkExceptionTest { } private static void exceptionAsserts(FrameworkException exception, String expectMessage) { - if (null == expectMessage) { + if (expectMessage == null) { expectMessage = FrameworkErrorCode.UnknownAppError.getErrMessage(); } assertThat(exception).isInstanceOf(FrameworkException.class).hasMessage(expectMessage); diff --git a/common/src/test/java/io/seata/common/thread/NamedThreadFactoryTest.java b/common/src/test/java/io/seata/common/thread/NamedThreadFactoryTest.java index d245319f784054a67545194d22b7db7250c74950..62240a6f35072094da7c607a12e012be20dcb8bf 100644 --- a/common/src/test/java/io/seata/common/thread/NamedThreadFactoryTest.java +++ b/common/src/test/java/io/seata/common/thread/NamedThreadFactoryTest.java @@ -24,6 +24,8 @@ import org.junit.jupiter.api.Test; * @author Otis.z */ public class NamedThreadFactoryTest { + private static final int THREAD_TOTAL_SIZE = 3; + private static final int DEFAULT_THREAD_PREFIX_COUNTER = 1; @Test public void testNewThread() { @@ -49,4 +51,18 @@ public class NamedThreadFactoryTest { assertThat(thread.getName()).startsWith("prefix"); assertThat(thread.isDaemon()).isTrue(); } + + + @Test + public void testThreadNameHasCounterWithPrefixCounter() { + NamedThreadFactory factory = new NamedThreadFactory("prefix", THREAD_TOTAL_SIZE, true); + for (int i = 0; i < THREAD_TOTAL_SIZE; i ++) { + Thread thread = factory.newThread(() -> {}); + + + // the first _DEFAULT_THREAD_PREFIX_COUNTER is meaning thread counter + assertThat("prefix_" + DEFAULT_THREAD_PREFIX_COUNTER + "_" + (i + 1) + "_" + THREAD_TOTAL_SIZE) + .isEqualTo(thread.getName()); + } + } } diff --git a/compressor/pom.xml b/compressor/pom.xml index c855f869bcb19e18fb74c6bb83df0d88f65b8001..7eb6dfd981eb307841daaa54e4cb348f768dfb73 100644 --- a/compressor/pom.xml +++ b/compressor/pom.xml @@ -33,6 +33,7 @@ <module>seata-compressor-zip</module> <module>seata-compressor-7z</module> <module>seata-compressor-bzip2</module> + <module>seata-compressor-lz4</module> </modules> diff --git a/compressor/seata-compressor-7z/src/main/java/io/seata/compressor/sevenz/SevenZUtil.java b/compressor/seata-compressor-7z/src/main/java/io/seata/compressor/sevenz/SevenZUtil.java index e6d2abc8c3d43efcfe30ef70f17a722b84873538..81d529a792d6cdb8b628a107bfaf9e21d93c9ae6 100644 --- a/compressor/seata-compressor-7z/src/main/java/io/seata/compressor/sevenz/SevenZUtil.java +++ b/compressor/seata-compressor-7z/src/main/java/io/seata/compressor/sevenz/SevenZUtil.java @@ -15,14 +15,14 @@ */ package io.seata.compressor.sevenz; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry; import org.apache.commons.compress.archivers.sevenz.SevenZFile; import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile; import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - /** * the SevenZ Util * diff --git a/compressor/seata-compressor-bzip2/src/main/java/io/seata/compressor/bzip2/BZip2Util.java b/compressor/seata-compressor-bzip2/src/main/java/io/seata/compressor/bzip2/BZip2Util.java index b03020429a7ba364b553e385afc8520423fa9147..0482b0a0930155b439065bd43384e7c5b039d225 100644 --- a/compressor/seata-compressor-bzip2/src/main/java/io/seata/compressor/bzip2/BZip2Util.java +++ b/compressor/seata-compressor-bzip2/src/main/java/io/seata/compressor/bzip2/BZip2Util.java @@ -15,13 +15,13 @@ */ package io.seata.compressor.bzip2; -import org.apache.tools.bzip2.CBZip2InputStream; -import org.apache.tools.bzip2.CBZip2OutputStream; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import org.apache.tools.bzip2.CBZip2InputStream; +import org.apache.tools.bzip2.CBZip2OutputStream; + /** * the BZip2 Util * diff --git a/compressor/seata-compressor-lz4/pom.xml b/compressor/seata-compressor-lz4/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..408ccc0cc1d8d311c6a4680a0091a7dd5b7d3c63 --- /dev/null +++ b/compressor/seata-compressor-lz4/pom.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright 1999-2019 Seata.io Group. + ~ + ~ Licensed under the Apache 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 + ~ + ~ http://www.apache.org/licenses/LICENSE-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. + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>io.seata</groupId> + <artifactId>seata-compressor</artifactId> + <version>${revision}</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>seata-compressor-lz4</artifactId> + <packaging>jar</packaging> + <name>seata-compressor-lz4 ${project.version}</name> + + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>seata-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.lz4</groupId> + <artifactId>lz4-java</artifactId> + </dependency> + </dependencies> + +</project> diff --git a/compressor/seata-compressor-lz4/src/main/java/io/seata/compressor/lz4/Lz4Compressor.java b/compressor/seata-compressor-lz4/src/main/java/io/seata/compressor/lz4/Lz4Compressor.java new file mode 100644 index 0000000000000000000000000000000000000000..dfac659ee911fd560cb9870976e9117671cdf2b1 --- /dev/null +++ b/compressor/seata-compressor-lz4/src/main/java/io/seata/compressor/lz4/Lz4Compressor.java @@ -0,0 +1,37 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.compressor.lz4; + +import io.seata.common.loader.LoadLevel; +import io.seata.core.compressor.Compressor; + +/** + * the Lz4 Compressor + * + * @author diguage + */ +@LoadLevel(name = "LZ4") +public class Lz4Compressor implements Compressor { + @Override + public byte[] compress(byte[] bytes) { + return Lz4Util.compress(bytes); + } + + @Override + public byte[] decompress(byte[] bytes) { + return Lz4Util.decompress(bytes); + } +} diff --git a/compressor/seata-compressor-lz4/src/main/java/io/seata/compressor/lz4/Lz4Util.java b/compressor/seata-compressor-lz4/src/main/java/io/seata/compressor/lz4/Lz4Util.java new file mode 100644 index 0000000000000000000000000000000000000000..4df9f3079b067042a5bc3c0ba62cf538cb77d216 --- /dev/null +++ b/compressor/seata-compressor-lz4/src/main/java/io/seata/compressor/lz4/Lz4Util.java @@ -0,0 +1,75 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.compressor.lz4; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import net.jpountz.lz4.LZ4BlockInputStream; +import net.jpountz.lz4.LZ4BlockOutputStream; +import net.jpountz.lz4.LZ4Compressor; +import net.jpountz.lz4.LZ4Factory; +import net.jpountz.lz4.LZ4FastDecompressor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * the Lz4 Util + * + * @author diguage + */ +public class Lz4Util { + private static final Logger LOGGER = LoggerFactory.getLogger(Lz4Util.class); + private static final int ARRAY_SIZE = 1024; + + public static byte[] compress(byte[] bytes) { + if (bytes == null) { + throw new NullPointerException("bytes is null"); + } + LZ4Compressor compressor = LZ4Factory.fastestInstance().fastCompressor(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try (LZ4BlockOutputStream lz4BlockOutputStream + = new LZ4BlockOutputStream(outputStream, ARRAY_SIZE, compressor)) { + lz4BlockOutputStream.write(bytes); + } catch (IOException e) { + LOGGER.error("compress bytes error", e); + } + return outputStream.toByteArray(); + } + + public static byte[] decompress(byte[] bytes) { + if (bytes == null) { + throw new NullPointerException("bytes is null"); + } + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(ARRAY_SIZE); + + LZ4FastDecompressor decompressor = LZ4Factory.fastestInstance().fastDecompressor(); + ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); + try (LZ4BlockInputStream decompressedInputStream + = new LZ4BlockInputStream(inputStream, decompressor)) { + int count; + byte[] buffer = new byte[ARRAY_SIZE]; + while ((count = decompressedInputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, count); + } + } catch (IOException e) { + LOGGER.error("decompress bytes error", e); + } + return outputStream.toByteArray(); + } +} diff --git a/compressor/seata-compressor-lz4/src/main/resources/META-INF/services/io.seata.core.compressor.Compressor b/compressor/seata-compressor-lz4/src/main/resources/META-INF/services/io.seata.core.compressor.Compressor new file mode 100644 index 0000000000000000000000000000000000000000..adadb02cdd60fd732a8fd749fe1450cbbac362b6 --- /dev/null +++ b/compressor/seata-compressor-lz4/src/main/resources/META-INF/services/io.seata.core.compressor.Compressor @@ -0,0 +1 @@ +io.seata.compressor.lz4.Lz4Compressor \ No newline at end of file diff --git a/compressor/seata-compressor-lz4/src/test/java/io/seata/compressor/lz4/Lz4CompressorTest.java b/compressor/seata-compressor-lz4/src/test/java/io/seata/compressor/lz4/Lz4CompressorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cbc9c7d7a70312c1024366a8482c7bc310c11cf4 --- /dev/null +++ b/compressor/seata-compressor-lz4/src/test/java/io/seata/compressor/lz4/Lz4CompressorTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.compressor.lz4; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * @author diguage + */ + +public class Lz4CompressorTest { + @Test + public void testCompressAndDecompress() { + Lz4Compressor compressor = new Lz4Compressor(); + String content = "a0123456789"; + byte[] bytes = content.getBytes(); + bytes = compressor.compress(bytes); + byte[] result = compressor.decompress(bytes); + Assertions.assertEquals(new String(result), content); + } +} \ No newline at end of file diff --git a/compressor/seata-compressor-lz4/src/test/java/io/seata/compressor/lz4/Lz4UtilTest.java b/compressor/seata-compressor-lz4/src/test/java/io/seata/compressor/lz4/Lz4UtilTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2f8497fd61197436c629560b24bb97e743ba01a7 --- /dev/null +++ b/compressor/seata-compressor-lz4/src/test/java/io/seata/compressor/lz4/Lz4UtilTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.compressor.lz4; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * @author diguage + */ +class Lz4UtilTest { + @Test + public void testCompress() { + Assertions.assertThrows(NullPointerException.class, () -> { + Lz4Util.compress(null); + }); + } + + @Test + public void testDecompress() { + Assertions.assertThrows(NullPointerException.class, () -> { + Lz4Util.decompress(null); + }); + } + +} \ No newline at end of file diff --git a/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfiguration.java b/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfiguration.java index 9001a7299d90ced522da8262be44d67ee5a987c7..ab8b699f450c262e6b9ba6fd4db783d8f2baa1c3 100644 --- a/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfiguration.java +++ b/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfiguration.java @@ -52,6 +52,8 @@ public class ApolloConfiguration extends AbstractConfiguration { private static final String REGISTRY_TYPE = "apollo"; private static final String APP_ID = "appId"; private static final String APOLLO_META = "apolloMeta"; + private static final String PROP_APP_ID = "app.id"; + private static final String PROP_APOLLO_META = "apollo.meta"; private static final String NAMESPACE = "namespace"; private static final String DEFAULT_NAMESPACE = "application"; private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; @@ -65,9 +67,9 @@ public class ApolloConfiguration extends AbstractConfiguration { private ApolloConfiguration() { readyApolloConfig(); - if (null == config) { + if (config == null) { synchronized (ApolloConfiguration.class) { - if (null == config) { + if (config == null) { config = ConfigService.getConfig(FILE_CONFIG.getConfig(getApolloNamespaceKey(), DEFAULT_NAMESPACE)); configOperateExecutor = new ThreadPoolExecutor(CORE_CONFIG_OPERATE_THREAD, MAX_CONFIG_OPERATE_THREAD, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, @@ -95,9 +97,9 @@ public class ApolloConfiguration extends AbstractConfiguration { * @return the instance */ public static ApolloConfiguration getInstance() { - if (null == instance) { + if (instance == null) { synchronized (ApolloConfiguration.class) { - if (null == instance) { + if (instance == null) { instance = new ApolloConfiguration(); } } @@ -106,7 +108,7 @@ public class ApolloConfiguration extends AbstractConfiguration { } @Override - public String getConfig(String dataId, String defaultValue, long timeoutMills) { + public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { String value; if ((value = getConfigFromSysPro(dataId)) != null) { return value; @@ -137,7 +139,7 @@ public class ApolloConfiguration extends AbstractConfiguration { @Override public void addConfigListener(String dataId, ConfigurationChangeListener listener) { - if (null == dataId || null == listener) { + if (dataId == null || listener == null) { return; } LISTENER_SERVICE_MAP.putIfAbsent(dataId, new ConcurrentSet<>()); @@ -159,11 +161,11 @@ public class ApolloConfiguration extends AbstractConfiguration { private void readyApolloConfig() { Properties properties = System.getProperties(); - if (!properties.containsKey(APP_ID)) { - System.setProperty(APP_ID, FILE_CONFIG.getConfig(getApolloAppIdFileKey())); + if (!properties.containsKey(PROP_APP_ID)) { + System.setProperty(PROP_APP_ID, FILE_CONFIG.getConfig(getApolloAppIdFileKey())); } - if (!properties.containsKey(APOLLO_META)) { - System.setProperty(APOLLO_META, FILE_CONFIG.getConfig(getApolloMetaFileKey())); + if (!properties.containsKey(PROP_APOLLO_META)) { + System.setProperty(PROP_APOLLO_META, FILE_CONFIG.getConfig(getApolloMetaFileKey())); } } diff --git a/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfiguration.java b/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfiguration.java index ca5b5391ab79bc540b577dabdbdab004aeef1549..15f67a8e2ef3d5198748dcbb336dca22941b9953 100644 --- a/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfiguration.java +++ b/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfiguration.java @@ -15,6 +15,7 @@ */ package io.seata.config.consul; +import java.net.InetSocketAddress; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -30,6 +31,7 @@ import com.ecwid.consul.v1.kv.model.GetValue; import com.ecwid.consul.v1.kv.model.PutParams; import io.netty.util.internal.ConcurrentSet; import io.seata.common.thread.NamedThreadFactory; +import io.seata.common.util.NetUtil; import io.seata.config.AbstractConfiguration; import io.seata.config.ConfigFuture; import io.seata.config.Configuration; @@ -78,9 +80,9 @@ public class ConsulConfiguration extends AbstractConfiguration { * @return instance */ public static ConsulConfiguration getInstance() { - if (null == instance) { + if (instance == null) { synchronized (ConsulConfiguration.class) { - if (null == instance) { + if (instance == null) { instance = new ConsulConfiguration(); } } @@ -89,7 +91,7 @@ public class ConsulConfiguration extends AbstractConfiguration { } @Override - public String getConfig(String dataId, String defaultValue, long timeoutMills) { + public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { String value; if ((value = getConfigFromSysPro(dataId)) != null) { return value; @@ -129,7 +131,7 @@ public class ConsulConfiguration extends AbstractConfiguration { @Override public void addConfigListener(String dataId, ConfigurationChangeListener listener) { - if (null == dataId || null == listener) { + if (dataId == null || listener == null) { return; } configListenersMap.putIfAbsent(dataId, new ConcurrentSet<>()); @@ -171,10 +173,12 @@ public class ConsulConfiguration extends AbstractConfiguration { * @return client */ private static ConsulClient getConsulClient() { - if (null == client) { + if (client == null) { synchronized (ConsulConfiguration.class) { - if (null == client) { - client = new ConsulClient(FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY)); + if (client == null) { + String serverAddr = FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY); + InetSocketAddress inetSocketAddress = NetUtil.toInetSocketAddress(serverAddr); + client = new ConsulClient(inetSocketAddress.getHostName(), inetSocketAddress.getPort()); } } } @@ -188,7 +192,7 @@ public class ConsulConfiguration extends AbstractConfiguration { * @param configFuture */ private void complete(Response response, ConfigFuture configFuture) { - if (null != response && null != response.getValue()) { + if (response != null && response.getValue() != null) { Object value = response.getValue(); if (value instanceof GetValue) { configFuture.setResult(((GetValue)value).getDecodedValue()); @@ -224,7 +228,7 @@ public class ConsulConfiguration extends AbstractConfiguration { @Override public void onChangeEvent(ConfigurationChangeEvent event) { - if (null != listener) { + if (listener != null) { while (true) { QueryParams queryParams = new QueryParams(DEFAULT_WATCH_TIMEOUT, consulIndex); Response<GetValue> response = getConsulClient().getKVValue(this.dataId, queryParams); diff --git a/config/seata-config-core/pom.xml b/config/seata-config-core/pom.xml index 1ebc1fbabeb776f48b8efe78138a47634fa4aa2d..dd147b13fd31c9202479be04beb49106afcb2afd 100644 --- a/config/seata-config-core/pom.xml +++ b/config/seata-config-core/pom.xml @@ -35,6 +35,10 @@ <groupId>com.typesafe</groupId> <artifactId>config</artifactId> </dependency> + <dependency> + <groupId>cglib</groupId> + <artifactId>cglib</artifactId> + </dependency> </dependencies> </project> diff --git a/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java b/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java index 71a5ce4bf7826efa2fe50c237e9c38558ca57cb6..858467fa922f58e366715958690d157c9b844859 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java +++ b/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java @@ -15,10 +15,8 @@ */ package io.seata.config; - -import io.seata.common.util.DurationUtil; - import java.time.Duration; +import io.seata.common.util.DurationUtil; /** * The type Abstract configuration. @@ -122,6 +120,11 @@ public abstract class AbstractConfiguration implements Configuration { return getConfig(dataId, null, timeoutMills); } + @Override + public String getConfig(String dataId, String content, long timeoutMills) { + return getLatestConfig(dataId, content, timeoutMills); + } + @Override public String getConfig(String dataId) { return getConfig(dataId, DEFAULT_CONFIG_TIMEOUT); diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java index 27fbd702d40331eae8d916d798835b5f2764a17e..326a1d47fcabe0e2c014a0953fb812fc29fa0907 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java @@ -66,6 +66,6 @@ public enum ConfigType { return configType; } } - throw new IllegalArgumentException("illegal type:" + name); + throw new IllegalArgumentException("not support config type: " + name); } } diff --git a/config/seata-config-core/src/main/java/io/seata/config/Configuration.java b/config/seata-config-core/src/main/java/io/seata/config/Configuration.java index b0210f11bfd2b4c127c15a91edf79e012258698a..1a5cc13e380de1b5ad116e6a6b6c4e417d2e74f7 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/Configuration.java +++ b/config/seata-config-core/src/main/java/io/seata/config/Configuration.java @@ -206,6 +206,15 @@ public interface Configuration { */ boolean putConfig(String dataId, String content, long timeoutMills); + /** + * + * @param dataId the data id + * @param defaultValue the default value + * @param timeoutMills the timeout mills + * @return the Latest config + */ + String getLatestConfig(String dataId, String defaultValue, long timeoutMills); + /** * Put config boolean. * diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java new file mode 100644 index 0000000000000000000000000000000000000000..913c90b446d63310e8f3984f718cc40d900e544e --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java @@ -0,0 +1,104 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.config; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import io.seata.common.util.StringUtils; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; + +/** + * @author funkye + */ +public class ConfigurationCache implements ConfigurationChangeListener { + + private static final String METHOD_PREFIX = "get"; + + private static final String METHOD_LATEST_CONFIG = METHOD_PREFIX + "LatestConfig"; + + private static final ConcurrentHashMap<String, Object> CONFIG_CACHE = new ConcurrentHashMap<>(); + + private Map<String, HashSet<ConfigurationChangeListener>> configListenersMap = + new HashMap<>(); + + public static void addConfigListener(String dataId, ConfigurationChangeListener... listeners) { + if (StringUtils.isBlank(dataId)) { + return; + } + synchronized (ConfigurationCache.class) { + HashSet<ConfigurationChangeListener> listenerHashSet = + getInstance().configListenersMap.computeIfAbsent(dataId, k -> new HashSet<>()); + if (!listenerHashSet.contains(getInstance())) { + ConfigurationFactory.getInstance().addConfigListener(dataId, getInstance()); + listenerHashSet.add(getInstance()); + } + if (null != listeners && listeners.length > 0) { + for (ConfigurationChangeListener listener : listeners) { + if (!listenerHashSet.contains(listener)) { + listenerHashSet.add(listener); + ConfigurationFactory.getInstance().addConfigListener(dataId, listener); + } + } + } + } + } + + public static ConfigurationCache getInstance() { + return ConfigurationCacheInstance.INSTANCE; + } + + @Override + public void onChangeEvent(ConfigurationChangeEvent event) { + Object oldValue = CONFIG_CACHE.get(event.getDataId()); + if (null == oldValue || !oldValue.equals(event.getNewValue())) { + if (StringUtils.isNotBlank(event.getNewValue())) { + CONFIG_CACHE.put(event.getDataId(), event.getNewValue()); + } else { + CONFIG_CACHE.remove(event.getDataId()); + } + } + } + + public Configuration proxy(Configuration originalConfiguration) { + return (Configuration)Enhancer.create(Configuration.class, + (MethodInterceptor)(proxy, method, args, methodProxy) -> { + if (method.getName().startsWith(METHOD_PREFIX) + && !method.getName().equalsIgnoreCase(METHOD_LATEST_CONFIG)) { + String rawDataId = (String)args[0]; + Object result = CONFIG_CACHE.get(rawDataId); + if (null == result) { + result = method.invoke(originalConfiguration, args); + if (result != null) { + CONFIG_CACHE.put(rawDataId, result); + } + } + if (method.getReturnType().equals(String.class)) { + return String.valueOf(result); + } + return result; + } + return method.invoke(originalConfiguration, args); + }); + } + + private static class ConfigurationCacheInstance { + private static final ConfigurationCache INSTANCE = new ConfigurationCache(); + } + +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java index 445d54859f20f16909a628839bf909ac52208fa5..b1ba6cedeb8fa0ebd871cef09fc99015c67953f9 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java @@ -16,10 +16,10 @@ package io.seata.config; import java.util.Objects; - import io.seata.common.exception.NotSupportYetException; import io.seata.common.loader.EnhancedServiceLoader; import io.seata.common.loader.EnhancedServiceNotFoundException; +import io.seata.common.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,17 +46,17 @@ public final class ConfigurationFactory { static { String seataConfigName = System.getProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME); - if (null == seataConfigName) { + if (seataConfigName == null) { seataConfigName = System.getenv(ENV_SEATA_CONFIG_NAME); } - if (null == seataConfigName) { + if (seataConfigName == null) { seataConfigName = REGISTRY_CONF_PREFIX; } String envValue = System.getProperty(ENV_PROPERTY_KEY); - if (null == envValue) { + if (envValue == null) { envValue = System.getenv(ENV_SYSTEM_KEY); } - Configuration configuration = (null == envValue) ? new FileConfiguration(seataConfigName + REGISTRY_CONF_SUFFIX, + Configuration configuration = (envValue == null) ? new FileConfiguration(seataConfigName + REGISTRY_CONF_SUFFIX, false) : new FileConfiguration(seataConfigName + "-" + envValue + REGISTRY_CONF_SUFFIX, false); Configuration extConfiguration = null; try { @@ -70,7 +70,7 @@ public final class ConfigurationFactory { } catch (Exception e) { LOGGER.error("failed to load extConfiguration:{}", e.getMessage(), e); } - CURRENT_FILE_INSTANCE = null == extConfiguration ? configuration : extConfiguration; + CURRENT_FILE_INSTANCE = extConfiguration == null ? configuration : extConfiguration; } private static final String NAME_KEY = "name"; @@ -96,36 +96,57 @@ public final class ConfigurationFactory { private static Configuration buildConfiguration() { ConfigType configType; - String configTypeName = null; + String configTypeName; try { configTypeName = CURRENT_FILE_INSTANCE.getConfig( ConfigurationKeys.FILE_ROOT_CONFIG + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR + ConfigurationKeys.FILE_ROOT_TYPE); + + if (StringUtils.isBlank(configTypeName)) { + throw new NotSupportYetException("config type can not be null"); + } + configType = ConfigType.getType(configTypeName); } catch (Exception e) { - throw new NotSupportYetException("not support register type: " + configTypeName, e); + throw e; } + Configuration extConfiguration = null; + Configuration configuration; if (ConfigType.File == configType) { - String pathDataId = String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, ConfigurationKeys.FILE_ROOT_CONFIG, FILE_TYPE, NAME_KEY); + String pathDataId = String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, + ConfigurationKeys.FILE_ROOT_CONFIG, FILE_TYPE, NAME_KEY); String name = CURRENT_FILE_INSTANCE.getConfig(pathDataId); - Configuration configuration = new FileConfiguration(name); - Configuration extConfiguration = null; + configuration = new FileConfiguration(name); try { extConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); if (LOGGER.isInfoEnabled()) { - LOGGER.info("load Configuration:{}", - extConfiguration == null ? configuration.getClass().getSimpleName() - : extConfiguration.getClass().getSimpleName()); + LOGGER.info("load Configuration:{}", extConfiguration == null + ? configuration.getClass().getSimpleName() : extConfiguration.getClass().getSimpleName()); } } catch (EnhancedServiceNotFoundException ignore) { } catch (Exception e) { LOGGER.error("failed to load extConfiguration:{}", e.getMessage(), e); } - return null == extConfiguration ? configuration : extConfiguration; } else { - return EnhancedServiceLoader.load(ConfigurationProvider.class, Objects.requireNonNull(configType).name()) - .provide(); + configuration = EnhancedServiceLoader + .load(ConfigurationProvider.class, Objects.requireNonNull(configType).name()).provide(); + } + try { + Configuration configurationCache; + if (null != extConfiguration) { + configurationCache = ConfigurationCache.getInstance().proxy(extConfiguration); + } else { + configurationCache = ConfigurationCache.getInstance().proxy(configuration); + } + if (null != configurationCache) { + extConfiguration = configurationCache; + } + } catch (EnhancedServiceNotFoundException ignore) { + + } catch (Exception e) { + LOGGER.error("failed to load configurationCacheProvider:{}", e.getMessage(), e); } + return null == extConfiguration ? configuration : extConfiguration; } } diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationKeys.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationKeys.java index 077a8cdc43c29d8137fdf5938275101632754c47..0a4b90ede1725a78b7a1285aeecb19955a0cffc2 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationKeys.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationKeys.java @@ -41,4 +41,5 @@ public final class ConfigurationKeys { * The constant FILE_ROOT_TYPE. */ public static final String FILE_ROOT_TYPE = "type"; + } diff --git a/config/seata-config-core/src/main/java/io/seata/config/FileConfiguration.java b/config/seata-config-core/src/main/java/io/seata/config/FileConfiguration.java index c8a5b827bb4d146e83f888b6265af50d7cb04f8e..8a5748ae76bd55da1e00b402b332179fbb906717 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/FileConfiguration.java +++ b/config/seata-config-core/src/main/java/io/seata/config/FileConfiguration.java @@ -98,7 +98,7 @@ public class FileConfiguration extends AbstractConfiguration { * @param allowDynamicRefresh the allow dynamic refresh */ public FileConfiguration(String name, boolean allowDynamicRefresh) { - if (null == name) { + if (name == null) { throw new IllegalArgumentException("name can't be null"); } else if (name.startsWith(SYS_FILE_RESOURCE_PREFIX)) { File targetFile = new File(name.substring(SYS_FILE_RESOURCE_PREFIX.length())); @@ -114,7 +114,7 @@ public class FileConfiguration extends AbstractConfiguration { } } else { URL resource = this.getClass().getClassLoader().getResource(name); - if (null != resource) { + if (resource != null) { targetFilePath = resource.getPath(); fileConfig = ConfigFactory.load(name); if (LOGGER.isInfoEnabled()) { @@ -129,7 +129,7 @@ public class FileConfiguration extends AbstractConfiguration { * For seata-server side the conf file should always exists. * For application(or client) side,conf file may not exists when using seata-spring-boot-starter */ - if (null == targetFilePath) { + if (targetFilePath == null) { fileConfig = ConfigFactory.load(); this.allowDynamicRefresh = false; } else { @@ -144,7 +144,7 @@ public class FileConfiguration extends AbstractConfiguration { } @Override - public String getConfig(String dataId, String defaultValue, long timeoutMills) { + public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { String value; if ((value = getConfigFromSysPro(dataId)) != null) { return value; @@ -177,7 +177,7 @@ public class FileConfiguration extends AbstractConfiguration { @Override public void addConfigListener(String dataId, ConfigurationChangeListener listener) { - if (null == dataId || null == listener) { + if (dataId == null || listener == null) { return; } configListenersMap.putIfAbsent(dataId, new ConcurrentSet<>()); @@ -231,7 +231,7 @@ public class FileConfiguration extends AbstractConfiguration { @Override public void run() { - if (null != configFuture) { + if (configFuture != null) { if (configFuture.isTimeout()) { setFailResult(configFuture); return; @@ -247,7 +247,7 @@ public class FileConfiguration extends AbstractConfiguration { } else { tempConfig = ConfigFactory.load(name); } - if (null != tempConfig) { + if (tempConfig != null) { fileConfig = tempConfig; targetFileLastModified = tempLastModified; } @@ -313,7 +313,8 @@ public class FileConfiguration extends AbstractConfiguration { public void onChangeEvent(ConfigurationChangeEvent event) { while (true) { try { - String currentConfig = ConfigurationFactory.getInstance().getConfig(dataId); + String currentConfig = + ConfigurationFactory.getInstance().getLatestConfig(dataId, null, DEFAULT_CONFIG_TIMEOUT); String oldConfig = listenedConfigMap.get(dataId); if (ObjectUtils.notEqual(currentConfig, oldConfig)) { listenedConfigMap.put(dataId, currentConfig); diff --git a/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationForTest.java b/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationForTest.java index e84ffcfd22293899c2200a3a46bd47087fd7b55f..577c195d12a3ad3c1031994c693a3042710cd2a1 100644 --- a/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationForTest.java +++ b/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationForTest.java @@ -38,7 +38,7 @@ public class CustomConfigurationForTest extends AbstractConfiguration { } @Override - public String getConfig(String dataId, String defaultValue, long timeoutMills) { + public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { return properties.getProperty(dataId, defaultValue); } diff --git a/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationTest.java b/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationTest.java index deba69b589bd1803543f9af33603e1b6962a5c7f..854ea185f72438aefa41d33cf20c88e900d1b5ca 100644 --- a/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationTest.java +++ b/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationTest.java @@ -15,11 +15,10 @@ */ package io.seata.config; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - import java.io.InputStream; import java.util.Properties; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; /** * @author ggndnn @@ -28,7 +27,7 @@ public class CustomConfigurationTest { @Test public void testCustomConfigLoad() throws Exception { Configuration configuration = ConfigurationFactory.getInstance(); - Assertions.assertTrue(configuration instanceof CustomConfigurationForTest); + Assertions.assertTrue(null != configuration); Properties properties; try (InputStream input = CustomConfigurationForTest.class.getClassLoader().getResourceAsStream("custom_for_test.properties")) { properties = new Properties(); diff --git a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfiguration.java b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfiguration.java index 36ea14e4a733eb937977d2f0400dfa9d13c4ffe4..9626a8b96325dc219d8dac5b41f974451368fabd 100644 --- a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfiguration.java +++ b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfiguration.java @@ -90,9 +90,9 @@ public class EtcdConfiguration extends AbstractConfiguration { * @return instance */ public static EtcdConfiguration getInstance() { - if (null == instance) { + if (instance == null) { synchronized (EtcdConfiguration.class) { - if (null == instance) { + if (instance == null) { instance = new EtcdConfiguration(); } } @@ -106,7 +106,7 @@ public class EtcdConfiguration extends AbstractConfiguration { } @Override - public String getConfig(String dataId, String defaultValue, long timeoutMills) { + public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { String value; if ((value = getConfigFromSysPro(dataId)) != null) { return value; @@ -152,7 +152,7 @@ public class EtcdConfiguration extends AbstractConfiguration { @Override public void addConfigListener(String dataId, ConfigurationChangeListener listener) { - if (null == dataId || null == listener) { + if (dataId == null || listener == null) { return; } configListenersMap.putIfAbsent(dataId, new ConcurrentSet<>()); @@ -188,9 +188,9 @@ public class EtcdConfiguration extends AbstractConfiguration { * @return client */ private static Client getClient() { - if (null == client) { + if (client == null) { synchronized (EtcdConfiguration.class) { - if (null == client) { + if (client == null) { client = Client.builder().endpoints(FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY)) .build(); } @@ -213,7 +213,7 @@ public class EtcdConfiguration extends AbstractConfiguration { List<KeyValue> keyValues = ((GetResponse)response).getKvs(); if (CollectionUtils.isNotEmpty(keyValues)) { ByteSequence value = keyValues.get(0).getValue(); - if (null != value) { + if (value != null) { configFuture.setResult(value.toString(UTF_8)); } } diff --git a/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfiguration.java b/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfiguration.java index 52970258d1767499e1e5dace81c89bc8ab0a2fc2..f2cf0c043da2698f2ffc26670c43ce9aeaf5f69d 100644 --- a/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfiguration.java +++ b/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfiguration.java @@ -15,6 +15,7 @@ */ package io.seata.config.nacos; +import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -36,6 +37,7 @@ import io.seata.config.ConfigurationKeys; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + /** * The type Nacos configuration. * @@ -48,11 +50,14 @@ public class NacosConfiguration extends AbstractConfiguration { private static final String DEFAULT_GROUP = "SEATA_GROUP"; private static final String GROUP_KEY = "group"; private static final String PRO_SERVER_ADDR_KEY = "serverAddr"; + private static final String ENDPOINT_KEY = "endpoint"; private static final String CONFIG_TYPE = "nacos"; private static final String DEFAULT_NAMESPACE = ""; private static final String PRO_NAMESPACE_KEY = "namespace"; private static final String USER_NAME = "username"; private static final String PASSWORD = "password"; + private static final String ACCESS_KEY = "accessKey"; + private static final String SECRET_KEY = "secretKey"; private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; private static volatile ConfigService configService; private static final int MAP_INITIAL_CAPACITY = 8; @@ -65,9 +70,9 @@ public class NacosConfiguration extends AbstractConfiguration { * @return instance */ public static NacosConfiguration getInstance() { - if (null == instance) { + if (instance == null) { synchronized (NacosConfiguration.class) { - if (null == instance) { + if (instance == null) { instance = new NacosConfiguration(); } } @@ -79,7 +84,7 @@ public class NacosConfiguration extends AbstractConfiguration { * Instantiates a new Nacos configuration. */ private NacosConfiguration() { - if (null == configService) { + if (configService == null) { try { configService = NacosFactory.createConfigService(getConfigProperties()); } catch (NacosException e) { @@ -89,7 +94,7 @@ public class NacosConfiguration extends AbstractConfiguration { } @Override - public String getConfig(String dataId, String defaultValue, long timeoutMills) { + public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { String value; if ((value = getConfigFromSysPro(dataId)) != null) { return value; @@ -131,7 +136,7 @@ public class NacosConfiguration extends AbstractConfiguration { @Override public void addConfigListener(String dataId, ConfigurationChangeListener listener) { - if (null == dataId || null == listener) { + if (dataId == null || listener == null) { return; } try { @@ -157,7 +162,7 @@ public class NacosConfiguration extends AbstractConfiguration { nacosListener = configListenersMap.get(dataId).get(listener); configListenersMap.get(dataId).remove(entry); } - if (null != nacosListener) { + if (nacosListener != null) { configService.removeListener(dataId, getNacosGroup(), nacosListener); } break; @@ -176,20 +181,24 @@ public class NacosConfiguration extends AbstractConfiguration { private static Properties getConfigProperties() { Properties properties = new Properties(); - if (null != System.getProperty(PRO_SERVER_ADDR_KEY)) { + if (System.getProperty(ENDPOINT_KEY) != null) { + properties.setProperty(ENDPOINT_KEY, System.getProperty(ENDPOINT_KEY)); + properties.put(ACCESS_KEY, Objects.toString(System.getProperty(ACCESS_KEY), "")); + properties.put(SECRET_KEY, Objects.toString(System.getProperty(SECRET_KEY), "")); + } else if (System.getProperty(PRO_SERVER_ADDR_KEY) != null) { properties.setProperty(PRO_SERVER_ADDR_KEY, System.getProperty(PRO_SERVER_ADDR_KEY)); } else { String address = FILE_CONFIG.getConfig(getNacosAddrFileKey()); - if (null != address) { + if (address != null) { properties.setProperty(PRO_SERVER_ADDR_KEY, address); } } - if (null != System.getProperty(PRO_NAMESPACE_KEY)) { + if (System.getProperty(PRO_NAMESPACE_KEY) != null) { properties.setProperty(PRO_NAMESPACE_KEY, System.getProperty(PRO_NAMESPACE_KEY)); } else { String namespace = FILE_CONFIG.getConfig(getNacosNameSpaceFileKey()); - if (null == namespace) { + if (namespace == null) { namespace = DEFAULT_NAMESPACE; } properties.setProperty(PRO_NAMESPACE_KEY, namespace); diff --git a/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfiguration.java b/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfiguration.java index 7c9f795eacd9026864ab2832f03cdd0806e3181e..c715dc4a2812dccfc95732b5c47b3820b5dbb741 100644 --- a/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfiguration.java +++ b/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfiguration.java @@ -32,9 +32,9 @@ public class SpringCloudConfiguration extends AbstractConfiguration { private static final String PREFIX = "seata."; public static SpringCloudConfiguration getInstance() { - if (null == instance) { + if (instance == null) { synchronized (SpringCloudConfiguration.class) { - if (null == instance) { + if (instance == null) { instance = new SpringCloudConfiguration(); } } @@ -52,9 +52,9 @@ public class SpringCloudConfiguration extends AbstractConfiguration { } @Override - public String getConfig(String dataId, String defaultValue, long timeoutMills) { + public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { ApplicationContext applicationContext = ObjectHolder.INSTANCE.getObject(ApplicationContext.class); - if (null == applicationContext || null == applicationContext.getEnvironment()) { + if (applicationContext == null || applicationContext.getEnvironment() == null) { return defaultValue; } String conf = applicationContext.getEnvironment().getProperty(PREFIX + dataId); diff --git a/config/seata-config-zk/src/main/java/io/seata/config/zk/DefaultZkSerializer.java b/config/seata-config-zk/src/main/java/io/seata/config/zk/DefaultZkSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..ae509a0ad7ef5394b1a5436334cbec3e48809277 --- /dev/null +++ b/config/seata-config-zk/src/main/java/io/seata/config/zk/DefaultZkSerializer.java @@ -0,0 +1,42 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.config.zk; + +import org.I0Itec.zkclient.exception.ZkMarshallingError; +import org.I0Itec.zkclient.serialize.ZkSerializer; + +import java.nio.charset.StandardCharsets; + +/** + * Default zk serializer. + * <p> + * If the user is not configured in config.zk.serializer configuration item, then use default serializer. + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class DefaultZkSerializer implements ZkSerializer { + + @Override + public byte[] serialize(Object data) throws ZkMarshallingError { + return String.valueOf(data).getBytes(StandardCharsets.UTF_8); + } + + @Override + public Object deserialize(byte[] bytes) throws ZkMarshallingError { + return new String(bytes, StandardCharsets.UTF_8); + } +} diff --git a/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfiguration.java b/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfiguration.java index 22b0ac414b0ed4c8cd1c81dad70c0db44a9bfd61..f798d9d1bdd0ccf9b8758a427ed587becfa93460 100644 --- a/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfiguration.java +++ b/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfiguration.java @@ -15,6 +15,7 @@ */ package io.seata.config.zk; +import java.lang.reflect.Constructor; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -35,6 +36,7 @@ import io.seata.config.ConfigurationChangeType; import io.seata.config.ConfigurationFactory; import org.I0Itec.zkclient.IZkDataListener; import org.I0Itec.zkclient.ZkClient; +import org.I0Itec.zkclient.serialize.ZkSerializer; import org.apache.zookeeper.CreateMode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,6 +62,7 @@ public class ZookeeperConfiguration extends AbstractConfiguration { private static final String CONNECT_TIMEOUT_KEY = "connectTimeout"; private static final String AUTH_USERNAME = "username"; private static final String AUTH_PASSWORD = "password"; + private static final String SERIALIZER_KEY = "serializer"; private static final int THREAD_POOL_NUM = 1; private static final int DEFAULT_SESSION_TIMEOUT = 6000; private static final int DEFAULT_CONNECT_TIMEOUT = 2000; @@ -79,10 +82,12 @@ public class ZookeeperConfiguration extends AbstractConfiguration { public ZookeeperConfiguration() { if (zkClient == null) { synchronized (ZookeeperConfiguration.class) { - if (null == zkClient) { - zkClient = new ZkClient(FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY), - FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + SESSION_TIMEOUT_KEY, DEFAULT_SESSION_TIMEOUT), - FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + CONNECT_TIMEOUT_KEY, DEFAULT_CONNECT_TIMEOUT)); + if (zkClient == null) { + ZkSerializer zkSerializer = getZkSerializer(); + String serverAddr = FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY); + int sessionTimeout = FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + SESSION_TIMEOUT_KEY, DEFAULT_SESSION_TIMEOUT); + int connectTimeout = FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + CONNECT_TIMEOUT_KEY, DEFAULT_CONNECT_TIMEOUT); + zkClient = new ZkClient(serverAddr, sessionTimeout, connectTimeout, zkSerializer); String username = FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + AUTH_USERNAME); String password = FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + AUTH_PASSWORD); if (!StringUtils.isBlank(username) && !StringUtils.isBlank(password)) { @@ -103,7 +108,7 @@ public class ZookeeperConfiguration extends AbstractConfiguration { } @Override - public String getConfig(String dataId, String defaultValue, long timeoutMills) { + public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { String value; if ((value = getConfigFromSysPro(dataId)) != null) { return value; @@ -167,7 +172,7 @@ public class ZookeeperConfiguration extends AbstractConfiguration { @Override public void addConfigListener(String dataId, ConfigurationChangeListener listener) { - if (null == dataId || null == listener) { + if (dataId == null || listener == null) { return; } String path = ROOT_PATH + ZK_PATH_SPLIT_CHAR + dataId; @@ -194,7 +199,7 @@ public class ZookeeperConfiguration extends AbstractConfiguration { zkListener = configListenersMap.get(dataId).get(listener); configListenersMap.get(dataId).remove(entry); } - if (null != zkListener) { + if (zkListener != null) { zkClient.unsubscribeDataChanges(path, zkListener); } break; @@ -247,4 +252,26 @@ public class ZookeeperConfiguration extends AbstractConfiguration { } } + private ZkSerializer getZkSerializer() { + ZkSerializer zkSerializer = null; + String serializer = FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERIALIZER_KEY); + if (StringUtils.isNotBlank(serializer)) { + try { + Class<?> clazz = Class.forName(serializer); + Constructor<?> constructor = clazz.getDeclaredConstructor(); + constructor.setAccessible(true); + zkSerializer = (ZkSerializer) constructor.newInstance(); + } catch (ClassNotFoundException cfe) { + LOGGER.warn("No zk serializer class found, serializer:{}", serializer, cfe); + } catch (Throwable cause) { + LOGGER.warn("found zk serializer encountered an unknown exception", cause); + } + } + if (zkSerializer == null) { + zkSerializer = new DefaultZkSerializer(); + LOGGER.info("Use default zk serializer: io.seata.config.zk.DefaultZkSerializer."); + } + return zkSerializer; + } + } diff --git a/core/pom.xml b/core/pom.xml index 6df31c217c52b8f01327302ac6e232d0bea897a5..9ab2dd3c095a07af5173aca734a93a8c6adbcadf 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -55,7 +55,6 @@ <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> - <optional>true</optional> </dependency> <dependency> <groupId>com.h2database</groupId> diff --git a/core/src/main/java/io/seata/core/README.md b/core/src/main/java/io/seata/core/README.md new file mode 100644 index 0000000000000000000000000000000000000000..44f2f5d4945c1e5d1b80d0e6a81e363260384bc6 --- /dev/null +++ b/core/src/main/java/io/seata/core/README.md @@ -0,0 +1,80 @@ +## request + +rm client -> server + +``` +RegisterRMRequest + +MergedWarpMessage + +BranchRegisterRequest +BranchReportRequest +GlobalLockQueryRequest +``` + +tm client -> server + +``` +RegisterTMRequest + +MergedWarpMessage + +GlobalBeginRequest +GlobalCommitRequest +GlobalRollbackRequest +GlobalStatusRequest +GlobalReportRequest +``` + +server -> rm client + +``` +BranchCommitRequest +BranchRollbackRequest +UndoLogDeleteRequest +``` + +server -> tm client + +``` +// null +``` + +## response + +Server -> rm client + +``` +RegisterRMResponse + +MergeResultMessage +BranchRegisterResponse +BranchReportResponse +GlobalLockQueryResponse +``` + +Server -> tm client + +``` +RegisterTMResponse + +MergeResultMessage +GlobalBeginResponse +GlobalCommitResponse +GlobalReportResponse +GlobalRollbackResponse +``` + +rm client -> server + +``` +BranchCommitResponse +BranchRollbackResponse +``` + +tm client -> server + +``` +// null +``` + diff --git a/core/src/main/java/io/seata/core/compressor/CompressorType.java b/core/src/main/java/io/seata/core/compressor/CompressorType.java index 1022517d10a5d71befe142eac5b7a66358e7df63..8ab1764b9c984389e03d4e9ec102c66c97dbeb61 100644 --- a/core/src/main/java/io/seata/core/compressor/CompressorType.java +++ b/core/src/main/java/io/seata/core/compressor/CompressorType.java @@ -43,7 +43,12 @@ public enum CompressorType { /** * The bzip2. */ - BZIP2((byte) 4); + BZIP2((byte) 4), + + /** + * The lz4. + */ + LZ4((byte) 5); private final byte code; diff --git a/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java b/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java index fc5c31e4db57cd8f84b9958c916315b3962e08d4..6f70f5730612eb637796b2d1797cddbbdd9a6068 100644 --- a/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java +++ b/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java @@ -123,6 +123,11 @@ public class ConfigurationKeys { */ public static final String CLIENT_SAGA_BRANCH_REGISTER_ENABLE = CLIENT_RM_PREFIX + "sagaBranchRegisterEnable"; + /** + * The constant CLIENT_SAGA_JSON_PARSER. + */ + public static final String CLIENT_SAGA_JSON_PARSER = CLIENT_RM_PREFIX + "sagaJsonParser"; + /** * The constant CLIENT_REPORT_RETRY_COUNT. */ @@ -164,6 +169,11 @@ public class ConfigurationKeys { */ public static final String STORE_DB_PREFIX = "store.db."; + /** + * The constant STORE_REDIS_PREFIX. + */ + public static final String STORE_REDIS_PREFIX = "store.redis."; + /** * The constant STORE_DB_GLOBAL_TABLE. */ @@ -229,6 +239,11 @@ public class ConfigurationKeys { */ public static final String LOCK_DB_TABLE = STORE_DB_PREFIX + "lockTable"; + /** + * The constant SERVER_PORT. + */ + public static final String SERVER_PORT = SERVER_PREFIX + "port"; + /** * The constant RECOVERY_PREFIX. */ @@ -267,6 +282,11 @@ public class ConfigurationKeys { */ public static final String TRANSACTION_UNDO_LOG_SERIALIZATION = CLIENT_UNDO_PREFIX + "logSerialization"; + /** + * The constant TRANSACTION_UNDO_ONLY_CARE_UPDATE_COLUMNS. + */ + public static final String TRANSACTION_UNDO_ONLY_CARE_UPDATE_COLUMNS = CLIENT_UNDO_PREFIX + "onlyCareUpdateColumns"; + /** * The constant METRICS_PREFIX. */ @@ -424,4 +444,68 @@ public class ConfigurationKeys { * The constant SQL_PARSER_TYPE. */ public static final String SQL_PARSER_TYPE = CLIENT_RM_PREFIX + "sqlParserType"; + + /** + * The constant STORE_REDIS_HOST. + */ + public static final String STORE_REDIS_HOST = STORE_REDIS_PREFIX + "host"; + + /** + * The constant STORE_MIN_Conn. + */ + public static final String STORE_REDIS_MIN_CONN = STORE_REDIS_PREFIX + "minConn"; + + /** + * The constant STORE_REDIS_PORT. + */ + public static final String STORE_REDIS_PORT = STORE_REDIS_PREFIX + "port"; + + /** + * The constant STORE_REDIS_MAX_CONN. + */ + public static final String STORE_REDIS_MAX_CONN = STORE_REDIS_PREFIX + "maxConn"; + + /** + * The constant STORE_REDIS_DATABASE. + */ + public static final String STORE_REDIS_DATABASE = STORE_REDIS_PREFIX + "database"; + + /** + * The constant STORE_REDIS_PASSWORD. + */ + public static final String STORE_REDIS_PASSWORD = STORE_REDIS_PREFIX + "password"; + + /** + * The constant STORE_REDIS_QUERY_LIMIT. + */ + public static final String STORE_REDIS_QUERY_LIMIT = STORE_REDIS_PREFIX + "queryLimit"; + + /** + * The constant CLIENT_DEGRADE_CHECK_PERIOD. + */ + public static final String CLIENT_DEGRADE_CHECK_PERIOD = CLIENT_TM_PREFIX + "degradeCheckPeriod"; + + /** + * The constant CLIENT_DEGRADE_CHECK. + */ + public static final String CLIENT_DEGRADE_CHECK = CLIENT_TM_PREFIX + "degradeCheck"; + /** + * The constant CLIENT_DEGRADE_CHECK_ALLOW_TIMES. + */ + public static final String CLIENT_DEGRADE_CHECK_ALLOW_TIMES = CLIENT_TM_PREFIX + "degradeCheckAllowTimes"; + + /** + * The constant SERVER_ENABLE_CHECK_AUTH. + */ + public static final String SERVER_ENABLE_CHECK_AUTH = SERVER_PREFIX + "enableCheckAuth"; + + /** + * The constant APPLICATION_ID. + */ + public static final String APPLICATION_ID = "applicationId"; + + /** + * The constant TX_SERVICE_GROUP. + */ + public static final String TX_SERVICE_GROUP = "txServiceGroup"; } diff --git a/core/src/main/java/io/seata/core/constants/DefaultValues.java b/core/src/main/java/io/seata/core/constants/DefaultValues.java index e289134ca99ae0c8023ff16ffa16340ae005e74c..d7225934bbb619b59bd32c3322d33b7475fd4b10 100644 --- a/core/src/main/java/io/seata/core/constants/DefaultValues.java +++ b/core/src/main/java/io/seata/core/constants/DefaultValues.java @@ -15,18 +15,23 @@ */ package io.seata.core.constants; +import java.util.concurrent.ThreadLocalRandom; + /** * @author xingfudeshi@gmail.com */ public class DefaultValues { public static final int DEFAULT_CLIENT_LOCK_RETRY_INTERVAL = 10; + public static final int DEFAULT_TM_DEGRADE_CHECK_ALLOW_TIMES = 10; public static final int DEFAULT_CLIENT_LOCK_RETRY_TIMES = 30; public static final boolean DEFAULT_CLIENT_LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT = true; public static final int DEFAULT_LOG_EXCEPTION_RATE = 100; public static final int DEFAULT_CLIENT_ASYNC_COMMIT_BUFFER_LIMIT = 10000; + public static final int DEFAULT_TM_DEGRADE_CHECK_PERIOD = 2000; public static final int DEFAULT_CLIENT_REPORT_RETRY_COUNT = 5; public static final boolean DEFAULT_CLIENT_REPORT_SUCCESS_ENABLE = false; public static final boolean DEFAULT_CLIENT_TABLE_META_CHECK_ENABLE = false; + public static final boolean DEFAULT_TM_DEGRADE_CHECK = false; public static final boolean DEFAULT_CLIENT_SAGA_BRANCH_REGISTER_ENABLE = false; /** * Shutdown timeout default 3s @@ -48,6 +53,7 @@ public class DefaultValues { public static final boolean DEFAULT_TRANSPORT_HEARTBEAT = true; public static final boolean DEFAULT_TRANSACTION_UNDO_DATA_VALIDATION = true; public static final String DEFAULT_TRANSACTION_UNDO_LOG_SERIALIZATION = "jackson"; + public static final boolean DEFAULT_ONLY_CARE_UPDATE_COLUMNS = true; /** * The constant DEFAULT_TRANSACTION_UNDO_LOG_TABLE. */ @@ -76,5 +82,11 @@ public class DefaultValues { public static final boolean DEFAULT_DISABLE_GLOBAL_TRANSACTION = false; + public static final int SERVER_DEFAULT_PORT = 8091; + public static final String SERVER_DEFAULT_STORE_MODE = "file"; + public static final long SERVER_DEFAULT_NODE = ThreadLocalRandom.current().nextLong(1024); + + public static final String DEFAULT_SAGA_JSON_PARSER = "fastjson"; + public static final boolean DEFAULT_SERVER_ENABLE_CHECK_AUTH = true; } diff --git a/core/src/main/java/io/seata/core/context/RootContext.java b/core/src/main/java/io/seata/core/context/RootContext.java index 97e5fc428c3d53010b0e46a1dd0a95f66f47206a..3c597b3228429431c723fb2ce88ce178341fb310 100644 --- a/core/src/main/java/io/seata/core/context/RootContext.java +++ b/core/src/main/java/io/seata/core/context/RootContext.java @@ -15,13 +15,14 @@ */ package io.seata.core.context; +import java.util.Map; + import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.util.StringUtils; import io.seata.core.model.BranchType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Map; /** * The type Root context. @@ -41,7 +42,10 @@ public class RootContext { */ public static final String KEY_XID = "TX_XID"; - public static final String KEY_XID_INTERCEPTOR_TYPE = "tx-xid-interceptor-type"; + /** + * The constant KEY_BRANCH_TYPE + */ + public static final String KEY_BRANCH_TYPE = "TX_BRANCH_TYPE"; public static final String KEY_GLOBAL_LOCK_FLAG = "TX_LOCK"; @@ -57,24 +61,9 @@ public class RootContext { if (StringUtils.isNotBlank(xid)) { return xid; } - - String xidType = CONTEXT_HOLDER.get(KEY_XID_INTERCEPTOR_TYPE); - if (StringUtils.isNotBlank(xidType) && xidType.contains("_")) { - return xidType.split("_")[0]; - } - return null; } - /** - * Gets xid. - * - * @return the xid - */ - public static String getXIDInterceptorType() { - return CONTEXT_HOLDER.get(KEY_XID_INTERCEPTOR_TYPE); - } - /** * Bind. * @@ -87,36 +76,6 @@ public class RootContext { CONTEXT_HOLDER.put(KEY_XID, xid); } - /** - * Bind interceptor type - * - * @param xidType - */ - public static void bindInterceptorType(String xidType) { - if (StringUtils.isNotBlank(xidType)) { - - String[] xidTypes = xidType.split("_"); - - if (xidTypes.length == 2) { - bindInterceptorType(xidTypes[0], BranchType.valueOf(xidTypes[1])); - } - } - } - - /** - * Bind interceptor type - * - * @param xid - * @param branchType - */ - public static void bindInterceptorType(String xid, BranchType branchType) { - String xidType = String.format("%s_%s", xid, branchType.name()); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("bind interceptor type xid={} branchType={}", xid, branchType); - } - CONTEXT_HOLDER.put(KEY_XID_INTERCEPTOR_TYPE, xidType); - } - /** * declare local transactions will use global lock check for update/delete/insert/selectForUpdate SQL */ @@ -143,19 +102,6 @@ public class RootContext { return xid; } - /** - * Unbind temporary string - * - * @return the string - */ - public static String unbindInterceptorType() { - String xidType = CONTEXT_HOLDER.remove(KEY_XID_INTERCEPTOR_TYPE); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("unbind inteceptor type {}", xidType); - } - return xidType; - } - public static void unbindGlobalLockFlag() { String lockFlag = CONTEXT_HOLDER.remove(KEY_GLOBAL_LOCK_FLAG); if (LOGGER.isDebugEnabled() && lockFlag != null) { @@ -172,6 +118,49 @@ public class RootContext { return CONTEXT_HOLDER.get(KEY_XID) != null; } + /** + * get the branch type + * + * @return the branch type String + */ + public static String getBranchType() { + if (inGlobalTransaction()) { + String branchType = CONTEXT_HOLDER.get(KEY_BRANCH_TYPE); + if (StringUtils.isNotBlank(branchType)) { + return branchType; + } + //default branchType is AT + return BranchType.AT.name(); + } + return null; + } + + /** + * bind branch type + * + * @param branchType the branch type + */ + public static void bindBranchType(BranchType branchType) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("bind branch type {}", branchType); + } + + CONTEXT_HOLDER.put(KEY_BRANCH_TYPE, branchType.name()); + } + + /** + * unbind branch type + * + * @return the previous branch type string + */ + public static String unbindBranchType() { + String unbindBranchType = CONTEXT_HOLDER.remove(KEY_BRANCH_TYPE); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("unbind branch type {}", unbindBranchType); + } + return unbindBranchType; + } + /** * requires global lock check * diff --git a/core/src/main/java/io/seata/core/event/GuavaEventBus.java b/core/src/main/java/io/seata/core/event/GuavaEventBus.java index bd9e470b87af0a5599dbc53bb361bd6d63908b80..8db0d8c0e39ef70e6c6485aeea5fce7c4252d571 100644 --- a/core/src/main/java/io/seata/core/event/GuavaEventBus.java +++ b/core/src/main/java/io/seata/core/event/GuavaEventBus.java @@ -15,16 +15,39 @@ */ package io.seata.core.event; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import io.seata.common.thread.NamedThreadFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Default event bus implement with Guava EventBus. * * @author zhengyangyong */ public class GuavaEventBus implements EventBus { + private static final Logger LOGGER = LoggerFactory.getLogger(GuavaEventBus.class); private final com.google.common.eventbus.EventBus eventBus; public GuavaEventBus(String identifier) { - this.eventBus = new com.google.common.eventbus.EventBus(identifier); + this(identifier, false); + } + + public GuavaEventBus(String identifier, boolean async) { + if (!async) { + this.eventBus = new com.google.common.eventbus.EventBus(identifier); + } else { + final ExecutorService eventExecutor = new ThreadPoolExecutor(1, 1, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(2048), new NamedThreadFactory(identifier, 1), (r, executor) -> { + + LOGGER.warn("eventBus executor queue is full, size:{}", executor.getQueue().size()); + }); + this.eventBus = new com.google.common.eventbus.AsyncEventBus(identifier, eventExecutor); + } } @Override diff --git a/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java b/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java index 4cc800ebef63fc5ddd011534867197b57ad67d91..98a27dd001ca4e1c483c3d3c9bd0e49d55a434c8 100644 --- a/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java +++ b/core/src/main/java/io/seata/core/exception/TransactionExceptionCode.java @@ -148,7 +148,7 @@ public enum TransactionExceptionCode { public static TransactionExceptionCode get(int ordinal) { TransactionExceptionCode code = MAP.get(ordinal); - if (null == code) { + if (code == null) { throw new IllegalArgumentException("Unknown TransactionExceptionCode[" + ordinal + "]"); } diff --git a/core/src/main/java/io/seata/core/logger/StackTraceLogger.java b/core/src/main/java/io/seata/core/logger/StackTraceLogger.java index 8ac473912f99bc68ff3d97d4c4540d15d4335a0f..1410777036660018aec1a4891a8b418414c966fb 100644 --- a/core/src/main/java/io/seata/core/logger/StackTraceLogger.java +++ b/core/src/main/java/io/seata/core/logger/StackTraceLogger.java @@ -19,6 +19,8 @@ import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; import org.slf4j.Logger; +import java.util.concurrent.ThreadLocalRandom; + import static io.seata.core.constants.DefaultValues.DEFAULT_LOG_EXCEPTION_RATE; /** @@ -33,7 +35,7 @@ public final class StackTraceLogger { public static void info(Logger logger, Throwable cause, String format, Object[] args) { if (logger.isInfoEnabled()) { int rate = getRate(); - if (System.currentTimeMillis() % rate == 0) { + if (ThreadLocalRandom.current().nextInt(rate) == 0) { logger.info(STACK_TRACE_LOGGER_PREFIX + format, args, cause); } else { logger.info(format, args); @@ -44,7 +46,7 @@ public final class StackTraceLogger { public static void warn(Logger logger, Throwable cause, String format, Object[] args) { if (logger.isWarnEnabled()) { int rate = getRate(); - if (System.currentTimeMillis() % rate == 0) { + if (ThreadLocalRandom.current().nextInt(rate) == 0) { logger.warn(STACK_TRACE_LOGGER_PREFIX + format, args, cause); } else { logger.warn(format, args); @@ -55,7 +57,7 @@ public final class StackTraceLogger { public static void error(Logger logger, Throwable cause, String format, Object[] args) { if (logger.isErrorEnabled()) { int rate = getRate(); - if (System.currentTimeMillis() % rate == 0) { + if (ThreadLocalRandom.current().nextInt(rate) == 0) { logger.error(STACK_TRACE_LOGGER_PREFIX + format, args, cause); } else { logger.error(format, args); diff --git a/core/src/main/java/io/seata/core/model/BranchStatus.java b/core/src/main/java/io/seata/core/model/BranchStatus.java index 610186a793df014ff4ecd4b97688643bd9f6e48e..70192c35c40682be68d130eabf11aacdb1db6b25 100644 --- a/core/src/main/java/io/seata/core/model/BranchStatus.java +++ b/core/src/main/java/io/seata/core/model/BranchStatus.java @@ -135,7 +135,7 @@ public enum BranchStatus { public static BranchStatus get(int code) { BranchStatus status = MAP.get(code); - if (null == status) { + if (status == null) { throw new ShouldNeverHappenException("Unknown BranchStatus[" + code + "]"); } diff --git a/core/src/main/java/io/seata/core/model/GlobalStatus.java b/core/src/main/java/io/seata/core/model/GlobalStatus.java index 037d1a64c8c478a3400d0ab4e559682a3d8fd394..5247ab7d34e0875f485ce3f08a05004f4bed8a76 100644 --- a/core/src/main/java/io/seata/core/model/GlobalStatus.java +++ b/core/src/main/java/io/seata/core/model/GlobalStatus.java @@ -166,7 +166,7 @@ public enum GlobalStatus { public static GlobalStatus get(int code) { GlobalStatus status = MAP.get(code); - if (null == status) { + if (status == null) { throw new IllegalArgumentException("Unknown GlobalStatus[" + code + "]"); } diff --git a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java index f38ff0ddeb9a28611af734a15314d55079b87a86..f11a10e307ddeb55bb6aa250f80960191eabd3bc 100644 --- a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java +++ b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java @@ -26,7 +26,7 @@ public abstract class AbstractIdentifyRequest extends AbstractMessage { /** * The Version. */ - protected String version = Version.CURRENT; + protected String version = Version.getCurrent(); /** * The Application id. diff --git a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java index e258e7a92f5d6a5f152c94245fcb8afd43e24e0a..564d8eab3d347bb6031173a3ef4942d5d060bcce 100644 --- a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java +++ b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java @@ -22,7 +22,7 @@ package io.seata.core.protocol; */ public abstract class AbstractIdentifyResponse extends AbstractResultMessage { - private String version = Version.CURRENT; + private String version = Version.getCurrent(); private String extraData; diff --git a/core/src/main/java/io/seata/core/protocol/HeartbeatMessage.java b/core/src/main/java/io/seata/core/protocol/HeartbeatMessage.java index 55ba7d28bc2e5b2e66aca0e3c300ff7e50d6af61..e3e8eb840c9002ee273959fe80c2ec3db7c6abf9 100644 --- a/core/src/main/java/io/seata/core/protocol/HeartbeatMessage.java +++ b/core/src/main/java/io/seata/core/protocol/HeartbeatMessage.java @@ -22,7 +22,7 @@ import java.io.Serializable; * * @author slievrly */ -public class HeartbeatMessage implements Serializable { +public class HeartbeatMessage implements MessageTypeAware, Serializable { private static final long serialVersionUID = -985316399527884899L; private boolean ping = true; /** @@ -38,6 +38,11 @@ public class HeartbeatMessage implements Serializable { this.ping = ping; } + @Override + public short getTypeCode() { + return MessageType.TYPE_HEARTBEAT_MSG; + } + @Override public String toString() { return this.ping ? "services ping" : "services pong"; diff --git a/core/src/main/java/io/seata/core/protocol/MessageType.java b/core/src/main/java/io/seata/core/protocol/MessageType.java index b686e9bf5e711aec80d163278994b578810801d3..5140e79f0330b6c6abc7e843415499381dd323ce 100644 --- a/core/src/main/java/io/seata/core/protocol/MessageType.java +++ b/core/src/main/java/io/seata/core/protocol/MessageType.java @@ -133,4 +133,9 @@ public class MessageType { * The constant TYPE_RM_DELETE_UNDOLOG. */ public static final short TYPE_RM_DELETE_UNDOLOG = 111; + + /** + * the constant TYPE_HEARTBEAT_MSG + */ + public static final short TYPE_HEARTBEAT_MSG = 120; } diff --git a/core/src/main/java/io/seata/core/protocol/ProtocolConstants.java b/core/src/main/java/io/seata/core/protocol/ProtocolConstants.java index fe45dee11745318a961d1d57662ae34d46e1f908..d08e096a1e5387262188fc78a263f60e2208b23c 100644 --- a/core/src/main/java/io/seata/core/protocol/ProtocolConstants.java +++ b/core/src/main/java/io/seata/core/protocol/ProtocolConstants.java @@ -49,7 +49,7 @@ public class ProtocolConstants { /** * Message type: Request */ - public static final byte MSGTYPE_RESQUEST = 0; + public static final byte MSGTYPE_RESQUEST_SYNC = 0; /** * Message type: Response */ diff --git a/core/src/main/java/io/seata/core/protocol/Version.java b/core/src/main/java/io/seata/core/protocol/Version.java index 942cd321a0a6098f0f458c37225ab49aa5e76105..2450c5a283485c2a0b443003fb293df908ba18ad 100644 --- a/core/src/main/java/io/seata/core/protocol/Version.java +++ b/core/src/main/java/io/seata/core/protocol/Version.java @@ -20,6 +20,7 @@ import java.util.concurrent.ConcurrentHashMap; import io.netty.channel.Channel; import io.seata.common.util.NetUtil; +import org.apache.commons.lang.StringUtils; /** * The type Version. @@ -31,7 +32,9 @@ public class Version { /** * The constant CURRENT. */ - public static final String CURRENT = "1.2.0"; + private static final String CURRENT = "1.3.0"; + private static final String VERSION_0_7_1 = "0.7.1"; + private static final int MAX_VERSION_DOT = 3; /** * The constant VERSION_MAP. @@ -42,6 +45,10 @@ public class Version { } + public static String getCurrent() { + return CURRENT; + } + /** * Put channel version. * @@ -69,8 +76,40 @@ public class Version { * @return the string * @throws IncompatibleVersionException the incompatible version exception */ - public static String checkVersion(String version) throws IncompatibleVersionException { - // TODO: check - return version; + public static void checkVersion(String version) throws IncompatibleVersionException { + long current = convertVersion(CURRENT); + long clientVersion = convertVersion(version); + long divideVersion = convertVersion(VERSION_0_7_1); + if ((current > divideVersion && clientVersion < divideVersion) || (current < divideVersion && clientVersion > divideVersion)) { + throw new IncompatibleVersionException("incompatible client version:" + version); + } + } + + private static long convertVersion(String version) throws IncompatibleVersionException { + String[] parts = StringUtils.split(version, '.'); + long result = 0L; + int i = 1; + int size = parts.length; + if (size > MAX_VERSION_DOT + 1) { + throw new IncompatibleVersionException("incompatible version format:" + version); + } + size = MAX_VERSION_DOT + 1; + for (String part : parts) { + if (StringUtils.isNumeric(part)) { + result += calculatePartValue(part, size, i); + } else { + String[] subParts = StringUtils.split(part, '-'); + if (StringUtils.isNumeric(subParts[0])) { + result += calculatePartValue(subParts[0], size, i); + } + } + + i++; + } + return result; + } + + private static long calculatePartValue(String partNumeric, int size, int index) { + return Long.parseLong(partNumeric) * Double.valueOf(Math.pow(100, size - index)).longValue(); } } diff --git a/core/src/main/java/io/seata/core/rpc/ClientMessageListener.java b/core/src/main/java/io/seata/core/rpc/ClientMessageListener.java index 0d3bf75a98e8e8909f444abcfc544fa7b8f695ab..2467e3ae7ea5eb2087ec8a4c2b31ebc51cbeb47b 100644 --- a/core/src/main/java/io/seata/core/rpc/ClientMessageListener.java +++ b/core/src/main/java/io/seata/core/rpc/ClientMessageListener.java @@ -22,6 +22,7 @@ import io.seata.core.protocol.RpcMessage; * * @author slievrly */ +@Deprecated public interface ClientMessageListener { /** * On message. diff --git a/core/src/main/java/io/seata/core/rpc/ClientMessageSender.java b/core/src/main/java/io/seata/core/rpc/ClientMessageSender.java index f3b5037b6f22a9c3ed7aef5ef3cca252e6fa3719..e1edc8708de8571ba41a8cbdc13d7fb20c63ed55 100644 --- a/core/src/main/java/io/seata/core/rpc/ClientMessageSender.java +++ b/core/src/main/java/io/seata/core/rpc/ClientMessageSender.java @@ -24,6 +24,7 @@ import java.util.concurrent.TimeoutException; * * @author slievrly */ +@Deprecated public interface ClientMessageSender { /** * Send msg with response object. diff --git a/core/src/main/java/io/seata/core/rpc/ClientType.java b/core/src/main/java/io/seata/core/rpc/ClientType.java index 82989d6931ff53b0257dc46848439621f3d65c89..658989a466e44c9bc0e272e0103eebf044b93bfc 100644 --- a/core/src/main/java/io/seata/core/rpc/ClientType.java +++ b/core/src/main/java/io/seata/core/rpc/ClientType.java @@ -20,6 +20,7 @@ package io.seata.core.rpc; * * @author slievrly */ +@Deprecated public enum ClientType { /** diff --git a/core/src/main/java/io/seata/core/rpc/DefaultServerMessageListenerImpl.java b/core/src/main/java/io/seata/core/rpc/DefaultServerMessageListenerImpl.java index a684a6dc1cb4a8f2bd21e1c096023bc3fac46092..c81f78fb5d483b1f8f94e6bb5de006c6a1075438 100644 --- a/core/src/main/java/io/seata/core/rpc/DefaultServerMessageListenerImpl.java +++ b/core/src/main/java/io/seata/core/rpc/DefaultServerMessageListenerImpl.java @@ -15,14 +15,6 @@ */ package io.seata.core.rpc; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - import io.netty.channel.ChannelHandlerContext; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.NetUtil; @@ -37,19 +29,29 @@ import io.seata.core.protocol.RegisterTMRequest; import io.seata.core.protocol.RegisterTMResponse; import io.seata.core.protocol.RpcMessage; import io.seata.core.protocol.Version; -import io.seata.core.rpc.netty.RegisterCheckAuthHandler; +import io.seata.core.rpc.netty.ChannelManager; +import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + /** * The type Default server message listener. * * @author slievrly */ +@Deprecated public class DefaultServerMessageListenerImpl implements ServerMessageListener { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultServerMessageListenerImpl.class); private static BlockingQueue<String> logQueue = new LinkedBlockingQueue<>(); - private ServerMessageSender serverMessageSender; + private RemotingServer remotingServer; private final TransactionMessageHandler transactionMessageHandler; private static final int MAX_LOG_SEND_THREAD = 1; private static final int MAX_LOG_TAKE_SIZE = 1024; @@ -92,14 +94,14 @@ public class DefaultServerMessageListenerImpl implements ServerMessageListener { } MergeResultMessage resultMessage = new MergeResultMessage(); resultMessage.setMsgs(results); - getServerMessageSender().sendResponse(request, ctx.channel(), resultMessage); + getServerMessageSender().sendAsyncResponse(request, ctx.channel(), resultMessage); } else if (message instanceof AbstractResultMessage) { transactionMessageHandler.onResponse((AbstractResultMessage) message, rpcContext); } else { // the single send request message final AbstractMessage msg = (AbstractMessage) message; AbstractResultMessage result = transactionMessageHandler.onRequest(msg, rpcContext); - getServerMessageSender().sendResponse(request, ctx.channel(), result); + getServerMessageSender().sendAsyncResponse(request, ctx.channel(), result); } } @@ -108,23 +110,29 @@ public class DefaultServerMessageListenerImpl implements ServerMessageListener { RegisterRMRequest message = (RegisterRMRequest)request.getBody(); String ipAndPort = NetUtil.toStringAddress(ctx.channel().remoteAddress()); boolean isSuccess = false; + String errorInfo = StringUtils.EMPTY; try { - if (null == checkAuthHandler || checkAuthHandler.regResourceManagerCheckAuth(message)) { + if (checkAuthHandler == null || checkAuthHandler.regResourceManagerCheckAuth(message)) { ChannelManager.registerRMChannel(message, ctx.channel()); Version.putChannelVersion(ctx.channel(), message.getVersion()); isSuccess = true; if (LOGGER.isDebugEnabled()) { - LOGGER.debug("checkAuth for client:{},vgroup:{},applicationId:{}", - ipAndPort,message.getTransactionServiceGroup(),message.getApplicationId()); + LOGGER.debug("checkAuth for client:{},vgroup:{},applicationId:{} is OK", ipAndPort, message.getTransactionServiceGroup(), message.getApplicationId()); } } } catch (Exception exx) { isSuccess = false; - LOGGER.error(exx.getMessage()); + errorInfo = exx.getMessage(); + LOGGER.error("RM register fail, error message:{}", errorInfo); } - getServerMessageSender().sendResponse(request, ctx.channel(), new RegisterRMResponse(isSuccess)); + RegisterRMResponse response = new RegisterRMResponse(isSuccess); + if (StringUtils.isNotEmpty(errorInfo)) { + response.setMsg(errorInfo); + } + getServerMessageSender().sendAsyncResponse(request, ctx.channel(), response); if (LOGGER.isInfoEnabled()) { - LOGGER.info("RM register success,message:{},channel:{}", message, ctx.channel()); + LOGGER.info("RM register success,message:{},channel:{},client version:{}", message, ctx.channel(), + message.getVersion()); } } @@ -134,30 +142,36 @@ public class DefaultServerMessageListenerImpl implements ServerMessageListener { String ipAndPort = NetUtil.toStringAddress(ctx.channel().remoteAddress()); Version.putChannelVersion(ctx.channel(), message.getVersion()); boolean isSuccess = false; + String errorInfo = StringUtils.EMPTY; try { - if (null == checkAuthHandler || checkAuthHandler.regTransactionManagerCheckAuth(message)) { + if (checkAuthHandler == null || checkAuthHandler.regTransactionManagerCheckAuth(message)) { ChannelManager.registerTMChannel(message, ctx.channel()); Version.putChannelVersion(ctx.channel(), message.getVersion()); isSuccess = true; if (LOGGER.isDebugEnabled()) { - LOGGER.debug("checkAuth for client:{},vgroup:{},applicationId:{}", - ipAndPort,message.getTransactionServiceGroup(),message.getApplicationId()); + LOGGER.debug("checkAuth for client:{},vgroup:{},applicationId:{} is OK", ipAndPort, message.getTransactionServiceGroup(), message.getApplicationId()); } } } catch (Exception exx) { isSuccess = false; - LOGGER.error(exx.getMessage()); + errorInfo = exx.getMessage(); + LOGGER.error("TM register fail, error message:{}", errorInfo); + } + RegisterTMResponse response = new RegisterTMResponse(isSuccess); + if (StringUtils.isNotEmpty(errorInfo)) { + response.setMsg(errorInfo); } - getServerMessageSender().sendResponse(request, ctx.channel(), new RegisterTMResponse(isSuccess)); + getServerMessageSender().sendAsyncResponse(request, ctx.channel(), response); if (LOGGER.isInfoEnabled()) { - LOGGER.info("TM register success,message:{},channel:{}", message, ctx.channel()); + LOGGER.info("TM register success,message:{},channel:{},client version:{}", message, ctx.channel(), + message.getVersion()); } } @Override public void onCheckMessage(RpcMessage request, ChannelHandlerContext ctx) { try { - getServerMessageSender().sendResponse(request, ctx.channel(), HeartbeatMessage.PONG); + getServerMessageSender().sendAsyncResponse(request, ctx.channel(), HeartbeatMessage.PONG); } catch (Throwable throwable) { LOGGER.error("send response error: {}", throwable.getMessage(), throwable); } @@ -181,20 +195,20 @@ public class DefaultServerMessageListenerImpl implements ServerMessageListener { * * @return the server message sender */ - public ServerMessageSender getServerMessageSender() { - if (serverMessageSender == null) { + public RemotingServer getServerMessageSender() { + if (remotingServer == null) { throw new IllegalArgumentException("serverMessageSender must not be null"); } - return serverMessageSender; + return remotingServer; } /** * Sets server message sender. * - * @param serverMessageSender the server message sender + * @param remotingServer the remoting server */ - public void setServerMessageSender(ServerMessageSender serverMessageSender) { - this.serverMessageSender = serverMessageSender; + public void setServerMessageSender(RemotingServer remotingServer) { + this.remotingServer = remotingServer; } /** diff --git a/core/src/main/java/io/seata/core/rpc/netty/RegisterCheckAuthHandler.java b/core/src/main/java/io/seata/core/rpc/RegisterCheckAuthHandler.java similarity index 97% rename from core/src/main/java/io/seata/core/rpc/netty/RegisterCheckAuthHandler.java rename to core/src/main/java/io/seata/core/rpc/RegisterCheckAuthHandler.java index 849531582be0deb099d2dd88281586df89d47259..a398f457a5810605b845ab9a00471828e2a40e44 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/RegisterCheckAuthHandler.java +++ b/core/src/main/java/io/seata/core/rpc/RegisterCheckAuthHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.core.rpc.netty; +package io.seata.core.rpc; import io.seata.core.protocol.RegisterRMRequest; import io.seata.core.protocol.RegisterTMRequest; diff --git a/core/src/main/java/io/seata/core/rpc/RemotingBootstrap.java b/core/src/main/java/io/seata/core/rpc/RemotingBootstrap.java new file mode 100644 index 0000000000000000000000000000000000000000..b280e6e1e08517a132c1112fa1eea4205859cfce --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/RemotingBootstrap.java @@ -0,0 +1,36 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc; + +/** + * The boot strap of the remoting process, generally there are client and server implementation classes + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public interface RemotingBootstrap { + + /** + * Start. + */ + void start(); + + /** + * Shutdown. + */ + void shutdown(); + +} diff --git a/core/src/main/java/io/seata/core/rpc/RemotingClient.java b/core/src/main/java/io/seata/core/rpc/RemotingClient.java index 2d44c16cb3e4acc709d4c4abeb0c74fbe4d266c8..0258b4e0f823647d23c2fbe6929e0167f1264cfc 100644 --- a/core/src/main/java/io/seata/core/rpc/RemotingClient.java +++ b/core/src/main/java/io/seata/core/rpc/RemotingClient.java @@ -15,10 +15,88 @@ */ package io.seata.core.rpc; +import io.netty.channel.Channel; +import io.seata.core.protocol.AbstractMessage; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.rpc.netty.NettyClientConfig; +import io.seata.core.rpc.processor.RemotingProcessor; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeoutException; + /** * The interface remoting client. * * @author zhaojun + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 */ -public interface RemotingClient extends RemotingService { +public interface RemotingClient { + + /** + * client send sync request. + * In this request, if {@link NettyClientConfig#isEnableClientBatchSendRequest} is enabled, + * the message will be sent in batches. + * + * @param msg transaction message {@link io.seata.core.protocol} + * @return server result message + * @throws TimeoutException + */ + Object sendSyncRequest(Object msg) throws TimeoutException; + + /** + * client send sync request. + * + * @param channel client channel + * @param msg transaction message {@link io.seata.core.protocol} + * @return server result message + * @throws TimeoutException + */ + Object sendSyncRequest(Channel channel, Object msg) throws TimeoutException; + + /** + * client send async request. + * + * @param channel client channel + * @param msg transaction message {@link io.seata.core.protocol} + */ + void sendAsyncRequest(Channel channel, Object msg); + + /** + * client send async response. + * + * @param serverAddress server address + * @param rpcMessage rpc message from server request + * @param msg transaction message {@link io.seata.core.protocol} + */ + void sendAsyncResponse(String serverAddress, RpcMessage rpcMessage, Object msg); + + /** + * On register msg success. + * + * @param serverAddress the server address + * @param channel the channel + * @param response the response + * @param requestMessage the request message + */ + void onRegisterMsgSuccess(String serverAddress, Channel channel, Object response, AbstractMessage requestMessage); + + /** + * On register msg fail. + * + * @param serverAddress the server address + * @param channel the channel + * @param response the response + * @param requestMessage the request message + */ + void onRegisterMsgFail(String serverAddress, Channel channel, Object response, AbstractMessage requestMessage); + + /** + * register processor + * + * @param messageType {@link io.seata.core.protocol.MessageType} + * @param processor {@link RemotingProcessor} + * @param executor thread pool + */ + void registerProcessor(final int messageType, final RemotingProcessor processor, final ExecutorService executor); } diff --git a/core/src/main/java/io/seata/core/rpc/RemotingServer.java b/core/src/main/java/io/seata/core/rpc/RemotingServer.java index 37003ce7b7b7b7f8232f6c86e2d7e0851ed070c3..1b1a3e3957999d36b32ad8e4bc460680c883a079 100644 --- a/core/src/main/java/io/seata/core/rpc/RemotingServer.java +++ b/core/src/main/java/io/seata/core/rpc/RemotingServer.java @@ -15,10 +15,67 @@ */ package io.seata.core.rpc; +import io.netty.channel.Channel; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.rpc.processor.RemotingProcessor; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeoutException; + /** * The interface Remoting server. * * @author slievrly + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 */ -public interface RemotingServer extends RemotingService { +public interface RemotingServer { + + /** + * server send sync request. + * + * @param resourceId rm client resourceId + * @param clientId rm client id + * @param msg transaction message {@link io.seata.core.protocol} + * @return client result message + * @throws TimeoutException + */ + Object sendSyncRequest(String resourceId, String clientId, Object msg) throws TimeoutException; + + /** + * server send sync request. + * + * @param channel client channel + * @param msg transaction message {@link io.seata.core.protocol} + * @return client result message + * @throws TimeoutException + */ + Object sendSyncRequest(Channel channel, Object msg) throws TimeoutException; + + /** + * server send async request. + * + * @param channel client channel + * @param msg transaction message {@link io.seata.core.protocol} + */ + void sendAsyncRequest(Channel channel, Object msg); + + /** + * server send async response. + * + * @param rpcMessage rpc message from client request + * @param channel client channel + * @param msg transaction message {@link io.seata.core.protocol} + */ + void sendAsyncResponse(RpcMessage rpcMessage, Channel channel, Object msg); + + /** + * register processor + * + * @param messageType {@link io.seata.core.protocol.MessageType} + * @param processor {@link RemotingProcessor} + * @param executor thread pool + */ + void registerProcessor(final int messageType, final RemotingProcessor processor, final ExecutorService executor); + } diff --git a/core/src/main/java/io/seata/core/rpc/RemotingService.java b/core/src/main/java/io/seata/core/rpc/RemotingService.java index 6d30a41a5a98bdb2b7801d704fa9db9cc2f3296a..b38df8a0b1277175c9d9e400251c5a93733e1a3f 100644 --- a/core/src/main/java/io/seata/core/rpc/RemotingService.java +++ b/core/src/main/java/io/seata/core/rpc/RemotingService.java @@ -20,6 +20,7 @@ package io.seata.core.rpc; * * @author slievrly */ +@Deprecated public interface RemotingService { /** * Start. diff --git a/core/src/main/java/io/seata/core/rpc/RpcContext.java b/core/src/main/java/io/seata/core/rpc/RpcContext.java index 8adae3974d6fd184a45d228516c8b969950141c7..c9d927d98865adabdd1e4be20626ca338f31d393 100644 --- a/core/src/main/java/io/seata/core/rpc/RpcContext.java +++ b/core/src/main/java/io/seata/core/rpc/RpcContext.java @@ -17,6 +17,7 @@ package io.seata.core.rpc; import io.netty.channel.Channel; import io.seata.common.util.StringUtils; +import io.seata.core.rpc.netty.ChannelUtil; import io.seata.core.rpc.netty.NettyPoolKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,7 +84,7 @@ public class RpcContext { } clientRMHolderMap = null; } - if (null != resourceSets) { + if (resourceSets != null) { resourceSets.clear(); } } @@ -122,7 +123,7 @@ public class RpcContext { * @param portMap the client rm holder map */ public void holdInResourceManagerChannels(String resourceId, ConcurrentMap<Integer, RpcContext> portMap) { - if (null == this.clientRMHolderMap) { + if (this.clientRMHolderMap == null) { this.clientRMHolderMap = new ConcurrentHashMap<String, ConcurrentMap<Integer, RpcContext>>(); } Integer clientPort = ChannelUtil.getClientPortFromChannel(channel); @@ -137,7 +138,7 @@ public class RpcContext { * @param clientPort the client port */ public void holdInResourceManagerChannels(String resourceId, Integer clientPort) { - if (null == this.clientRMHolderMap) { + if (this.clientRMHolderMap == null) { this.clientRMHolderMap = new ConcurrentHashMap<String, ConcurrentMap<Integer, RpcContext>>(); } clientRMHolderMap.putIfAbsent(resourceId, new ConcurrentHashMap<Integer, RpcContext>()); @@ -290,7 +291,7 @@ public class RpcContext { if (StringUtils.isBlank(resource)) { return; } - if (null == resourceSets) { + if (resourceSets == null) { this.resourceSets = new HashSet<String>(); } this.resourceSets.add(resource); @@ -302,8 +303,8 @@ public class RpcContext { * @param resources the resources */ public void addResources(Set<String> resources) { - if (null == resources) { return; } - if (null == resourceSets) { + if (resources == null) { return; } + if (resourceSets == null) { this.resourceSets = new HashSet<String>(); } this.resourceSets.addAll(resources); diff --git a/core/src/main/java/io/seata/core/rpc/ServerMessageListener.java b/core/src/main/java/io/seata/core/rpc/ServerMessageListener.java index d7d4ba124c5aa7327c1ddc3ec982a4917f548a41..efb3c4d3a868b837949fedb99bf20d4345ba8d1d 100644 --- a/core/src/main/java/io/seata/core/rpc/ServerMessageListener.java +++ b/core/src/main/java/io/seata/core/rpc/ServerMessageListener.java @@ -17,13 +17,13 @@ package io.seata.core.rpc; import io.netty.channel.ChannelHandlerContext; import io.seata.core.protocol.RpcMessage; -import io.seata.core.rpc.netty.RegisterCheckAuthHandler; /** * The interface Server message listener. * * @author slievrly */ +@Deprecated public interface ServerMessageListener { /** diff --git a/core/src/main/java/io/seata/core/rpc/ServerMessageSender.java b/core/src/main/java/io/seata/core/rpc/ServerMessageSender.java index a3f0e1d8987fe67adcc15a28475e4809938ae2cc..cb04f35aee813073f8a8e58044589e09656deb9b 100644 --- a/core/src/main/java/io/seata/core/rpc/ServerMessageSender.java +++ b/core/src/main/java/io/seata/core/rpc/ServerMessageSender.java @@ -16,17 +16,17 @@ package io.seata.core.rpc; import io.netty.channel.Channel; +import io.seata.core.protocol.RpcMessage; import java.io.IOException; import java.util.concurrent.TimeoutException; -import io.seata.core.protocol.RpcMessage; - /** * The interface Server message sender. * * @author slievrly */ +@Deprecated public interface ServerMessageSender { /** diff --git a/core/src/main/java/io/seata/core/rpc/netty/ShutdownHook.java b/core/src/main/java/io/seata/core/rpc/ShutdownHook.java similarity index 98% rename from core/src/main/java/io/seata/core/rpc/netty/ShutdownHook.java rename to core/src/main/java/io/seata/core/rpc/ShutdownHook.java index a9e14fa05a1c7287cdee7fa91a36cfbbe78187d5..899ed802198217fc53a6ca1876e9ec8eedf804d9 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/ShutdownHook.java +++ b/core/src/main/java/io/seata/core/rpc/ShutdownHook.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.core.rpc.netty; +package io.seata.core.rpc; import java.util.Objects; import java.util.Set; @@ -21,7 +21,6 @@ import java.util.TreeSet; import java.util.concurrent.atomic.AtomicBoolean; import io.seata.common.util.CollectionUtils; -import io.seata.core.rpc.Disposable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/core/src/main/java/io/seata/core/rpc/netty/TransportProtocolType.java b/core/src/main/java/io/seata/core/rpc/TransportProtocolType.java similarity index 97% rename from core/src/main/java/io/seata/core/rpc/netty/TransportProtocolType.java rename to core/src/main/java/io/seata/core/rpc/TransportProtocolType.java index 688064e62256fcb47b49764c3e61805360e5d9f3..42f88af043d95630cf779941a257f205dcacceb2 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/TransportProtocolType.java +++ b/core/src/main/java/io/seata/core/rpc/TransportProtocolType.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.core.rpc.netty; +package io.seata.core.rpc; /** * The enum Transport protocol type. diff --git a/core/src/main/java/io/seata/core/rpc/netty/TransportServerType.java b/core/src/main/java/io/seata/core/rpc/TransportServerType.java similarity index 96% rename from core/src/main/java/io/seata/core/rpc/netty/TransportServerType.java rename to core/src/main/java/io/seata/core/rpc/TransportServerType.java index 616b4e3dead16a0c77ecd11c3c8d840f5af2ee4d..d13f7dc46d0dca2d862f10d100054e45b611a65d 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/TransportServerType.java +++ b/core/src/main/java/io/seata/core/rpc/TransportServerType.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.core.rpc.netty; +package io.seata.core.rpc; /** * The enum Transport server type. diff --git a/core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemoting.java b/core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemoting.java new file mode 100644 index 0000000000000000000000000000000000000000..2452edab72ba05ac18f687604aecfee2895a20ac --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemoting.java @@ -0,0 +1,352 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.netty; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.seata.common.exception.FrameworkErrorCode; +import io.seata.common.exception.FrameworkException; +import io.seata.common.thread.NamedThreadFactory; +import io.seata.common.thread.PositiveAtomicCounter; +import io.seata.core.protocol.MessageFuture; +import io.seata.core.protocol.MessageType; +import io.seata.core.protocol.MessageTypeAware; +import io.seata.core.protocol.ProtocolConstants; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.rpc.Disposable; +import io.seata.core.rpc.processor.Pair; +import io.seata.core.rpc.processor.RemotingProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.net.SocketAddress; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +/** + * The abstract netty remoting. + * + * @author slievrly + * @author zhangchenghui.dev@gmail.com + */ +public abstract class AbstractNettyRemoting implements Disposable { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractNettyRemoting.class); + /** + * The Timer executor. + */ + protected final ScheduledExecutorService timerExecutor = new ScheduledThreadPoolExecutor(1, + new NamedThreadFactory("timeoutChecker", 1, true)); + /** + * The Message executor. + */ + protected final ThreadPoolExecutor messageExecutor; + + /** + * Id generator of this remoting + */ + protected final PositiveAtomicCounter idGenerator = new PositiveAtomicCounter(); + + /** + * Obtain the return result through MessageFuture blocking. + * + * @see AbstractNettyRemoting#sendSync + */ + protected final ConcurrentHashMap<Integer, MessageFuture> futures = new ConcurrentHashMap<>(); + + private static final long NOT_WRITEABLE_CHECK_MILLS = 10L; + + /** + * The Now mills. + */ + protected volatile long nowMills = 0; + private static final int TIMEOUT_CHECK_INTERNAL = 3000; + protected final Object lock = new Object(); + /** + * The Is sending. + */ + protected volatile boolean isSending = false; + private String group = "DEFAULT"; + + /** + * This container holds all processors. + * processor type {@link MessageType} + */ + protected final HashMap<Integer/*MessageType*/, Pair<RemotingProcessor, ExecutorService>> processorTable = new HashMap<>(32); + + public void init() { + timerExecutor.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + for (Map.Entry<Integer, MessageFuture> entry : futures.entrySet()) { + if (entry.getValue().isTimeout()) { + futures.remove(entry.getKey()); + entry.getValue().setResultMessage(null); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("timeout clear future: {}", entry.getValue().getRequestMessage().getBody()); + } + } + } + + nowMills = System.currentTimeMillis(); + } + }, TIMEOUT_CHECK_INTERNAL, TIMEOUT_CHECK_INTERNAL, TimeUnit.MILLISECONDS); + } + + public AbstractNettyRemoting(ThreadPoolExecutor messageExecutor) { + this.messageExecutor = messageExecutor; + } + + public int getNextMessageId() { + return idGenerator.incrementAndGet(); + } + + public ConcurrentHashMap<Integer, MessageFuture> getFutures() { + return futures; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public void destroyChannel(Channel channel) { + destroyChannel(getAddressFromChannel(channel), channel); + } + + @Override + public void destroy() { + timerExecutor.shutdown(); + messageExecutor.shutdown(); + } + + /** + * rpc sync request + * Obtain the return result through MessageFuture blocking. + * + * @param channel netty channel + * @param rpcMessage rpc message + * @param timeoutMillis rpc communication timeout + * @return response message + * @throws TimeoutException + */ + protected Object sendSync(Channel channel, RpcMessage rpcMessage, long timeoutMillis) throws TimeoutException { + if (timeoutMillis <= 0) { + throw new FrameworkException("timeout should more than 0ms"); + } + if (channel == null) { + LOGGER.warn("sendSync nothing, caused by null channel."); + return null; + } + + MessageFuture messageFuture = new MessageFuture(); + messageFuture.setRequestMessage(rpcMessage); + messageFuture.setTimeout(timeoutMillis); + futures.put(rpcMessage.getId(), messageFuture); + + channelWritableCheck(channel, rpcMessage.getBody()); + + channel.writeAndFlush(rpcMessage).addListener((ChannelFutureListener) future -> { + if (!future.isSuccess()) { + MessageFuture messageFuture1 = futures.remove(rpcMessage.getId()); + if (messageFuture1 != null) { + messageFuture1.setResultMessage(future.cause()); + } + destroyChannel(future.channel()); + } + }); + + try { + return messageFuture.get(timeoutMillis, TimeUnit.MILLISECONDS); + } catch (Exception exx) { + LOGGER.error("wait response error:{},ip:{},request:{}", exx.getMessage(), channel.remoteAddress(), + rpcMessage.getBody()); + if (exx instanceof TimeoutException) { + throw (TimeoutException) exx; + } else { + throw new RuntimeException(exx); + } + } + } + + /** + * rpc async request. + * + * @param channel netty channel + * @param rpcMessage rpc message + */ + protected void sendAsync(Channel channel, RpcMessage rpcMessage) { + channelWritableCheck(channel, rpcMessage.getBody()); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("write message:" + rpcMessage.getBody() + ", channel:" + channel + ",active?" + + channel.isActive() + ",writable?" + channel.isWritable() + ",isopen?" + channel.isOpen()); + } + channel.writeAndFlush(rpcMessage).addListener((ChannelFutureListener) future -> { + if (!future.isSuccess()) { + destroyChannel(future.channel()); + } + }); + } + + protected RpcMessage buildRequestMessage(Object msg, byte messageType) { + RpcMessage rpcMessage = new RpcMessage(); + rpcMessage.setId(getNextMessageId()); + rpcMessage.setMessageType(messageType); + rpcMessage.setCodec(ProtocolConstants.CONFIGURED_CODEC); + rpcMessage.setCompressor(ProtocolConstants.CONFIGURED_COMPRESSOR); + rpcMessage.setBody(msg); + return rpcMessage; + } + + protected RpcMessage buildResponseMessage(RpcMessage rpcMessage, Object msg, byte messageType) { + RpcMessage rpcMsg = new RpcMessage(); + rpcMsg.setMessageType(messageType); + rpcMsg.setCodec(rpcMessage.getCodec()); // same with request + rpcMsg.setCompressor(rpcMessage.getCompressor()); + rpcMsg.setBody(msg); + rpcMsg.setId(rpcMessage.getId()); + return rpcMsg; + } + + /** + * For testing. When the thread pool is full, you can change this variable and share the stack + */ + boolean allowDumpStack = false; + + /** + * Rpc message processing. + * + * @param ctx Channel handler context. + * @param rpcMessage rpc message. + * @throws Exception throws exception process message error. + * @since 1.3.0 + */ + protected void processMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(String.format("%s msgId:%s, body:%s", this, rpcMessage.getId(), rpcMessage.getBody())); + } + Object body = rpcMessage.getBody(); + if (body instanceof MessageTypeAware) { + MessageTypeAware messageTypeAware = (MessageTypeAware) body; + final Pair<RemotingProcessor, ExecutorService> pair = this.processorTable.get((int) messageTypeAware.getTypeCode()); + if (pair != null) { + if (pair.getSecond() != null) { + try { + pair.getSecond().execute(() -> { + try { + pair.getFirst().process(ctx, rpcMessage); + } catch (Throwable th) { + LOGGER.error(FrameworkErrorCode.NetDispatch.getErrCode(), th.getMessage(), th); + } + }); + } catch (RejectedExecutionException e) { + LOGGER.error(FrameworkErrorCode.ThreadPoolFull.getErrCode(), + "thread pool is full, current max pool size is " + messageExecutor.getActiveCount()); + if (allowDumpStack) { + String name = ManagementFactory.getRuntimeMXBean().getName(); + String pid = name.split("@")[0]; + int idx = new Random().nextInt(100); + try { + Runtime.getRuntime().exec("jstack " + pid + " >d:/" + idx + ".log"); + } catch (IOException exx) { + LOGGER.error(exx.getMessage()); + } + allowDumpStack = false; + } + } + } else { + try { + pair.getFirst().process(ctx, rpcMessage); + } catch (Throwable th) { + LOGGER.error(FrameworkErrorCode.NetDispatch.getErrCode(), th.getMessage(), th); + } + } + } else { + LOGGER.error("This message type [{}] has no processor.", messageTypeAware.getTypeCode()); + } + } else { + LOGGER.error("This rpcMessage body[{}] is not MessageTypeAware type.", body); + } + } + + /** + * Gets address from context. + * + * @param ctx the ctx + * @return the address from context + */ + protected String getAddressFromContext(ChannelHandlerContext ctx) { + return getAddressFromChannel(ctx.channel()); + } + + /** + * Gets address from channel. + * + * @param channel the channel + * @return the address from channel + */ + protected String getAddressFromChannel(Channel channel) { + SocketAddress socketAddress = channel.remoteAddress(); + String address = socketAddress.toString(); + if (socketAddress.toString().indexOf(NettyClientConfig.getSocketAddressStartChar()) == 0) { + address = socketAddress.toString().substring(NettyClientConfig.getSocketAddressStartChar().length()); + } + return address; + } + + private void channelWritableCheck(Channel channel, Object msg) { + int tryTimes = 0; + synchronized (lock) { + while (!channel.isWritable()) { + try { + tryTimes++; + if (tryTimes > NettyClientConfig.getMaxNotWriteableRetry()) { + destroyChannel(channel); + throw new FrameworkException("msg:" + ((msg == null) ? "null" : msg.toString()), + FrameworkErrorCode.ChannelIsNotWritable); + } + lock.wait(NOT_WRITEABLE_CHECK_MILLS); + } catch (InterruptedException exx) { + LOGGER.error(exx.getMessage()); + } + } + } + } + + /** + * Destroy channel. + * + * @param serverAddress the server address + * @param channel the channel + */ + public abstract void destroyChannel(String serverAddress, Channel channel); + +} diff --git a/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemotingClient.java b/core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemotingClient.java similarity index 61% rename from core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemotingClient.java rename to core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemotingClient.java index 6c9f9e221a21631a900f05add8ae324c3c5f6945..ae9782af2466037e4ab63ad85757c592d77d2b0c 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemotingClient.java +++ b/core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemotingClient.java @@ -15,19 +15,11 @@ */ package io.seata.core.rpc.netty; -import java.net.InetSocketAddress; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.function.Function; - import io.netty.channel.Channel; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import io.netty.util.concurrent.EventExecutorGroup; @@ -37,29 +29,44 @@ import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.NetUtil; import io.seata.core.protocol.AbstractMessage; import io.seata.core.protocol.HeartbeatMessage; -import io.seata.core.protocol.MergeResultMessage; +import io.seata.core.protocol.MergeMessage; import io.seata.core.protocol.MergedWarpMessage; import io.seata.core.protocol.MessageFuture; +import io.seata.core.protocol.ProtocolConstants; import io.seata.core.protocol.RpcMessage; -import io.seata.core.rpc.ClientMessageListener; -import io.seata.core.rpc.ClientMessageSender; +import io.seata.core.rpc.RemotingClient; +import io.seata.core.rpc.TransactionMessageHandler; +import io.seata.core.rpc.processor.Pair; +import io.seata.core.rpc.processor.RemotingProcessor; import io.seata.discovery.loadbalance.LoadBalanceFactory; import io.seata.discovery.registry.RegistryFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.net.InetSocketAddress; +import java.util.List; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Function; + import static io.seata.common.exception.FrameworkErrorCode.NoAvailableService; /** - * The type Rpc remoting client. + * The netty remoting client. * * @author slievrly * @author zhaojun + * @author zhangchenghui.dev@gmail.com */ -public abstract class AbstractRpcRemotingClient extends AbstractRpcRemoting - implements RegisterMsgListener, ClientMessageSender { +public abstract class AbstractNettyRemotingClient extends AbstractNettyRemoting implements RemotingClient { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRpcRemotingClient.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractNettyRemotingClient.class); private static final String MSG_ID_PREFIX = "msgId:"; private static final String FUTURES_PREFIX = "futures:"; private static final String SINGLE_LOG_POSTFIX = ";"; @@ -71,44 +78,28 @@ public abstract class AbstractRpcRemotingClient extends AbstractRpcRemoting private static final long SCHEDULE_DELAY_MILLS = 60 * 1000L; private static final long SCHEDULE_INTERVAL_MILLS = 10 * 1000L; private static final String MERGE_THREAD_PREFIX = "rpcMergeMessageSend"; - - private final RpcClientBootstrap clientBootstrap; - private NettyClientChannelManager clientChannelManager; - private ClientMessageListener clientMessageListener; - private final NettyPoolKey.TransactionRole transactionRole; - private ExecutorService mergeSendExecutorService; - - public AbstractRpcRemotingClient(NettyClientConfig nettyClientConfig, EventExecutorGroup eventExecutorGroup, - ThreadPoolExecutor messageExecutor, NettyPoolKey.TransactionRole transactionRole) { - super(messageExecutor); - this.transactionRole = transactionRole; - clientBootstrap = new RpcClientBootstrap(nettyClientConfig, eventExecutorGroup, transactionRole); - clientChannelManager = new NettyClientChannelManager( - new NettyPoolableFactory(this, clientBootstrap), getPoolKeyFunction(), nettyClientConfig); - } - - public NettyClientChannelManager getClientChannelManager() { - return clientChannelManager; - } + protected final Object mergeLock = new Object(); /** - * Get pool key function. - * - * @return lambda function + * When sending message type is {@link MergeMessage}, will be stored to mergeMsgMap. */ - protected abstract Function<String, NettyPoolKey> getPoolKeyFunction(); + protected final Map<Integer, MergeMessage> mergeMsgMap = new ConcurrentHashMap<>(); /** - * Get transaction service group. - * - * @return transaction service group + * When batch sending is enabled, the message will be stored to basketMap + * Send via asynchronous thread {@link MergedSendRunnable} + * {@link NettyClientConfig#isEnableClientBatchSendRequest} */ - protected abstract String getTransactionServiceGroup(); + protected final ConcurrentHashMap<String/*serverAddress*/, BlockingQueue<RpcMessage>> basketMap = new ConcurrentHashMap<>(); + + private final NettyClientBootstrap clientBootstrap; + private NettyClientChannelManager clientChannelManager; + private final NettyPoolKey.TransactionRole transactionRole; + private ExecutorService mergeSendExecutorService; + private TransactionMessageHandler transactionMessageHandler; @Override public void init() { - clientBootstrap.setChannelHandlers(new ClientHandler()); - clientBootstrap.start(); timerExecutor.scheduleAtFixedRate(new Runnable() { @Override public void run() { @@ -124,67 +115,139 @@ public abstract class AbstractRpcRemotingClient extends AbstractRpcRemoting mergeSendExecutorService.submit(new MergedSendRunnable()); } super.init(); + clientBootstrap.start(); + } + + public AbstractNettyRemotingClient(NettyClientConfig nettyClientConfig, EventExecutorGroup eventExecutorGroup, + ThreadPoolExecutor messageExecutor, NettyPoolKey.TransactionRole transactionRole) { + super(messageExecutor); + this.transactionRole = transactionRole; + clientBootstrap = new NettyClientBootstrap(nettyClientConfig, eventExecutorGroup, transactionRole); + clientBootstrap.setChannelHandlers(new ClientHandler()); + clientChannelManager = new NettyClientChannelManager( + new NettyPoolableFactory(this, clientBootstrap), getPoolKeyFunction(), nettyClientConfig); } @Override - public void destroy() { - clientBootstrap.shutdown(); - if (mergeSendExecutorService != null) { - mergeSendExecutorService.shutdown(); + public Object sendSyncRequest(Object msg) throws TimeoutException { + String serverAddress = loadBalance(getTransactionServiceGroup()); + int timeoutMillis = NettyClientConfig.getRpcRequestTimeout(); + RpcMessage rpcMessage = buildRequestMessage(msg, ProtocolConstants.MSGTYPE_RESQUEST_SYNC); + + // send batch message + // put message into basketMap, @see MergedSendRunnable + if (NettyClientConfig.isEnableClientBatchSendRequest()) { + + // send batch message is sync request, needs to create messageFuture and put it in futures. + MessageFuture messageFuture = new MessageFuture(); + messageFuture.setRequestMessage(rpcMessage); + messageFuture.setTimeout(timeoutMillis); + futures.put(rpcMessage.getId(), messageFuture); + + // put message into basketMap + ConcurrentHashMap<String, BlockingQueue<RpcMessage>> map = basketMap; + BlockingQueue<RpcMessage> basket = map.get(serverAddress); + if (basket == null) { + map.putIfAbsent(serverAddress, new LinkedBlockingQueue<>()); + basket = map.get(serverAddress); + } + basket.offer(rpcMessage); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("offer message: {}", rpcMessage.getBody()); + } + if (!isSending) { + synchronized (mergeLock) { + mergeLock.notifyAll(); + } + } + + try { + return messageFuture.get(timeoutMillis, TimeUnit.MILLISECONDS); + } catch (Exception exx) { + LOGGER.error("wait response error:{},ip:{},request:{}", + exx.getMessage(), serverAddress, rpcMessage.getBody()); + if (exx instanceof TimeoutException) { + throw (TimeoutException) exx; + } else { + throw new RuntimeException(exx); + } + } + + } else { + Channel channel = clientChannelManager.acquireChannel(serverAddress); + return super.sendSync(channel, rpcMessage, timeoutMillis); } - super.destroy(); + } @Override - public Object sendMsgWithResponse(Object msg, long timeout) throws TimeoutException { - String validAddress = loadBalance(getTransactionServiceGroup()); - Channel channel = clientChannelManager.acquireChannel(validAddress); - Object result = super.sendAsyncRequestWithResponse(validAddress, channel, msg, timeout); - return result; + public Object sendSyncRequest(Channel channel, Object msg) throws TimeoutException { + if (channel == null) { + LOGGER.warn("sendSyncRequest nothing, caused by null channel."); + return null; + } + RpcMessage rpcMessage = buildRequestMessage(msg, ProtocolConstants.MSGTYPE_RESQUEST_SYNC); + return super.sendSync(channel, rpcMessage, NettyClientConfig.getRpcRequestTimeout()); } @Override - public Object sendMsgWithResponse(Object msg) throws TimeoutException { - return sendMsgWithResponse(msg, NettyClientConfig.getRpcRequestTimeout()); + public void sendAsyncRequest(Channel channel, Object msg) { + if (channel == null) { + LOGGER.warn("sendAsyncRequest nothing, caused by null channel."); + return; + } + RpcMessage rpcMessage = buildRequestMessage(msg, msg instanceof HeartbeatMessage + ? ProtocolConstants.MSGTYPE_HEARTBEAT_REQUEST + : ProtocolConstants.MSGTYPE_RESQUEST_ONEWAY); + if (rpcMessage.getBody() instanceof MergeMessage) { + mergeMsgMap.put(rpcMessage.getId(), (MergeMessage) rpcMessage.getBody()); + } + super.sendAsync(channel, rpcMessage); } @Override - public Object sendMsgWithResponse(String serverAddress, Object msg, long timeout) - throws TimeoutException { - return super.sendAsyncRequestWithResponse(serverAddress, clientChannelManager.acquireChannel(serverAddress), msg, timeout); + public void sendAsyncResponse(String serverAddress, RpcMessage rpcMessage, Object msg) { + RpcMessage rpcMsg = buildResponseMessage(rpcMessage, msg, ProtocolConstants.MSGTYPE_RESPONSE); + Channel channel = clientChannelManager.acquireChannel(serverAddress); + super.sendAsync(channel, rpcMsg); } @Override - public void sendResponse(RpcMessage request, String serverAddress, Object msg) { - super.defaultSendResponse(request, clientChannelManager.acquireChannel(serverAddress), msg); + public void registerProcessor(int requestCode, RemotingProcessor processor, ExecutorService executor) { + Pair<RemotingProcessor, ExecutorService> pair = new Pair<>(processor, executor); + this.processorTable.put(requestCode, pair); } - /** - * Gets client message listener. - * - * @return the client message listener - */ - public ClientMessageListener getClientMessageListener() { - return clientMessageListener; + @Override + public void destroyChannel(String serverAddress, Channel channel) { + clientChannelManager.destroyChannel(serverAddress, channel); } - /** - * Sets client message listener. - * - * @param clientMessageListener the client message listener - */ - public void setClientMessageListener(ClientMessageListener clientMessageListener) { - this.clientMessageListener = clientMessageListener; + @Override + public void destroy() { + clientBootstrap.shutdown(); + if (mergeSendExecutorService != null) { + mergeSendExecutorService.shutdown(); + } + super.destroy(); } - @Override - public void destroyChannel(String serverAddress, Channel channel) { - clientChannelManager.destroyChannel(serverAddress, channel); + public void setTransactionMessageHandler(TransactionMessageHandler transactionMessageHandler) { + this.transactionMessageHandler = transactionMessageHandler; + } + + public TransactionMessageHandler getTransactionMessageHandler() { + return transactionMessageHandler; + } + + public NettyClientChannelManager getClientChannelManager() { + return clientChannelManager; } private String loadBalance(String transactionServiceGroup) { InetSocketAddress address = null; try { + @SuppressWarnings("unchecked") List<InetSocketAddress> inetSocketAddressList = RegistryFactory.getInstance().lookup(transactionServiceGroup); address = LoadBalanceFactory.getInstance().select(inetSocketAddressList); } catch (Exception ex) { @@ -197,9 +260,23 @@ public abstract class AbstractRpcRemotingClient extends AbstractRpcRemoting } private String getThreadPrefix() { - return AbstractRpcRemotingClient.MERGE_THREAD_PREFIX + THREAD_PREFIX_SPLIT_CHAR + transactionRole.name(); + return AbstractNettyRemotingClient.MERGE_THREAD_PREFIX + THREAD_PREFIX_SPLIT_CHAR + transactionRole.name(); } + /** + * Get pool key function. + * + * @return lambda function + */ + protected abstract Function<String, NettyPoolKey> getPoolKeyFunction(); + + /** + * Get transaction service group. + * + * @return transaction service group + */ + protected abstract String getTransactionServiceGroup(); + /** * The type Merged send runnable. */ @@ -232,8 +309,11 @@ public abstract class AbstractRpcRemotingClient extends AbstractRpcRemoting } Channel sendChannel = null; try { + // send batch message is sync request, but there is no need to get the return value. + // Since the messageFuture has been created before the message is placed in basketMap, + // the return value will be obtained in ClientOnResponseProcessor. sendChannel = clientChannelManager.acquireChannel(address); - AbstractRpcRemotingClient.super.defaultSendRequest(sendChannel, mergeMessage); + AbstractNettyRemotingClient.this.sendAsyncRequest(sendChannel, mergeMessage); } catch (FrameworkException e) { if (e.getErrcode() == FrameworkErrorCode.ChannelIsNotWritable && sendChannel != null) { destroyChannel(address, sendChannel); @@ -275,45 +355,24 @@ public abstract class AbstractRpcRemotingClient extends AbstractRpcRemoting * The type ClientHandler. */ @Sharable - class ClientHandler extends AbstractHandler { - - @Override - public void dispatch(RpcMessage request, ChannelHandlerContext ctx) { - if (clientMessageListener != null) { - String remoteAddress = NetUtil.toStringAddress(ctx.channel().remoteAddress()); - clientMessageListener.onMessage(request, remoteAddress); - } - } + class ClientHandler extends ChannelDuplexHandler { @Override public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception { if (!(msg instanceof RpcMessage)) { return; } - RpcMessage rpcMessage = (RpcMessage) msg; - if (rpcMessage.getBody() == HeartbeatMessage.PONG) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("received PONG from {}", ctx.channel().remoteAddress()); - } - return; - } - if (rpcMessage.getBody() instanceof MergeResultMessage) { - MergeResultMessage results = (MergeResultMessage) rpcMessage.getBody(); - MergedWarpMessage mergeMessage = (MergedWarpMessage) mergeMsgMap.remove(rpcMessage.getId()); - for (int i = 0; i < mergeMessage.msgs.size(); i++) { - int msgId = mergeMessage.msgIds.get(i); - MessageFuture future = futures.remove(msgId); - if (future == null) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("msg: {} is not found in futures.", msgId); - } - } else { - future.setResultMessage(results.getMsgs()[i]); - } + processMessage(ctx, (RpcMessage) msg); + } + + @Override + public void channelWritabilityChanged(ChannelHandlerContext ctx) { + synchronized (lock) { + if (ctx.channel().isWritable()) { + lock.notifyAll(); } - return; } - super.channelRead(ctx, msg); + ctx.fireChannelWritabilityChanged(); } @Override @@ -331,7 +390,7 @@ public abstract class AbstractRpcRemotingClient extends AbstractRpcRemoting @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { if (evt instanceof IdleStateEvent) { - IdleStateEvent idleStateEvent = (IdleStateEvent)evt; + IdleStateEvent idleStateEvent = (IdleStateEvent) evt; if (idleStateEvent.state() == IdleState.READER_IDLE) { if (LOGGER.isInfoEnabled()) { LOGGER.info("channel {} read idle.", ctx.channel()); @@ -350,7 +409,7 @@ public abstract class AbstractRpcRemotingClient extends AbstractRpcRemoting if (LOGGER.isDebugEnabled()) { LOGGER.debug("will send ping msg,channel {}", ctx.channel()); } - AbstractRpcRemotingClient.super.defaultSendRequest(ctx.channel(), HeartbeatMessage.PING); + AbstractNettyRemotingClient.this.sendAsyncRequest(ctx.channel(), HeartbeatMessage.PING); } catch (Throwable throwable) { LOGGER.error("send request error: {}", throwable.getMessage(), throwable); } @@ -368,6 +427,13 @@ public abstract class AbstractRpcRemotingClient extends AbstractRpcRemoting } super.exceptionCaught(ctx, cause); } - } + @Override + public void close(ChannelHandlerContext ctx, ChannelPromise future) throws Exception { + if (LOGGER.isInfoEnabled()) { + LOGGER.info(ctx + " will closed"); + } + super.close(ctx, future); + } + } } diff --git a/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemotingServer.java b/core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemotingServer.java similarity index 54% rename from core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemotingServer.java rename to core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemotingServer.java index 5241df5f560c3946573dc95c568554f7e66f25ad..8a26d37da4304ded380c71a8ab7e4e1e285526b0 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemotingServer.java +++ b/core/src/main/java/io/seata/core/rpc/netty/AbstractNettyRemotingServer.java @@ -16,104 +16,99 @@ package io.seata.core.rpc.netty; import io.netty.channel.Channel; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import io.seata.common.util.NetUtil; import io.seata.core.protocol.HeartbeatMessage; -import io.seata.core.protocol.RegisterRMRequest; -import io.seata.core.protocol.RegisterTMRequest; +import io.seata.core.protocol.ProtocolConstants; import io.seata.core.protocol.RpcMessage; -import io.seata.core.rpc.ChannelManager; +import io.seata.core.rpc.RemotingServer; import io.seata.core.rpc.RpcContext; -import io.seata.core.rpc.ServerMessageListener; -import io.seata.core.rpc.ServerMessageSender; -import io.seata.core.rpc.TransactionMessageHandler; +import io.seata.core.rpc.processor.Pair; +import io.seata.core.rpc.processor.RemotingProcessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeoutException; /** - * The type Rpc remoting server. + * The type abstract remoting server. * - * @author slievrly - * @author xingfudeshi@gmail.com + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 */ -public abstract class AbstractRpcRemotingServer extends AbstractRpcRemoting implements ServerMessageSender { +public abstract class AbstractNettyRemotingServer extends AbstractNettyRemoting implements RemotingServer { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRpcRemotingServer.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractNettyRemotingServer.class); - private final RpcServerBootstrap serverBootstrap; + private final NettyServerBootstrap serverBootstrap; - /** - * The Server message listener. - */ - private ServerMessageListener serverMessageListener; - - private TransactionMessageHandler transactionMessageHandler; - - private RegisterCheckAuthHandler checkAuthHandler; - - /** - * Instantiates a new Rpc remoting server. - * - * @param messageExecutor the message executor - * @param nettyServerConfig the netty server config - */ - public AbstractRpcRemotingServer(final ThreadPoolExecutor messageExecutor, NettyServerConfig nettyServerConfig) { - super(messageExecutor); - serverBootstrap = new RpcServerBootstrap(nettyServerConfig); - } - - /** - * Sets transactionMessageHandler. - * - * @param transactionMessageHandler the transactionMessageHandler - */ - public void setHandler(TransactionMessageHandler transactionMessageHandler) { - setHandler(transactionMessageHandler, null); + @Override + public void init() { + super.init(); + serverBootstrap.start(); } - private void setHandler(TransactionMessageHandler transactionMessageHandler, RegisterCheckAuthHandler checkAuthHandler) { - this.transactionMessageHandler = transactionMessageHandler; - this.checkAuthHandler = checkAuthHandler; + public AbstractNettyRemotingServer(ThreadPoolExecutor messageExecutor, NettyServerConfig nettyServerConfig) { + super(messageExecutor); + serverBootstrap = new NettyServerBootstrap(nettyServerConfig); + serverBootstrap.setChannelHandlers(new ServerHandler()); } - public TransactionMessageHandler getTransactionMessageHandler() { - return transactionMessageHandler; + @Override + public Object sendSyncRequest(String resourceId, String clientId, Object msg) throws TimeoutException { + Channel channel = ChannelManager.getChannel(resourceId, clientId); + if (channel == null) { + throw new RuntimeException("rm client is not connected. dbkey:" + resourceId + ",clientId:" + clientId); + } + RpcMessage rpcMessage = buildRequestMessage(msg, ProtocolConstants.MSGTYPE_RESQUEST_SYNC); + return super.sendSync(channel, rpcMessage, NettyServerConfig.getRpcRequestTimeout()); } - public RegisterCheckAuthHandler getCheckAuthHandler() { - return checkAuthHandler; + @Override + public Object sendSyncRequest(Channel channel, Object msg) throws TimeoutException { + if (channel == null) { + throw new RuntimeException("client is not connected"); + } + RpcMessage rpcMessage = buildRequestMessage(msg, ProtocolConstants.MSGTYPE_RESQUEST_SYNC); + return super.sendSync(channel, rpcMessage, NettyServerConfig.getRpcRequestTimeout()); } - /** - * Sets server message listener. - * - * @param serverMessageListener the server message listener - */ - public void setServerMessageListener(ServerMessageListener serverMessageListener) { - this.serverMessageListener = serverMessageListener; + @Override + public void sendAsyncRequest(Channel channel, Object msg) { + if (channel == null) { + throw new RuntimeException("client is not connected"); + } + RpcMessage rpcMessage = buildRequestMessage(msg, ProtocolConstants.MSGTYPE_RESQUEST_ONEWAY); + super.sendAsync(channel, rpcMessage); } - /** - * Gets server message listener. - * - * @return the server message listener - */ - public ServerMessageListener getServerMessageListener() { - return serverMessageListener; + @Override + public void sendAsyncResponse(RpcMessage rpcMessage, Channel channel, Object msg) { + Channel clientChannel = channel; + if (!(msg instanceof HeartbeatMessage)) { + clientChannel = ChannelManager.getSameClientChannel(channel); + } + if (clientChannel != null) { + RpcMessage rpcMsg = buildResponseMessage(rpcMessage, msg, msg instanceof HeartbeatMessage + ? ProtocolConstants.MSGTYPE_HEARTBEAT_RESPONSE + : ProtocolConstants.MSGTYPE_RESPONSE); + super.sendAsync(clientChannel, rpcMsg); + } else { + throw new RuntimeException("channel is error."); + } } - /** - * Sets channel handlers. - * - * @param handlers the handlers - */ - public void setChannelHandlers(ChannelHandler... handlers) { - serverBootstrap.setChannelHandlers(handlers); + @Override + public void registerProcessor(int messageType, RemotingProcessor processor, ExecutorService executor) { + Pair<RemotingProcessor, ExecutorService> pair = new Pair<>(processor, executor); + this.processorTable.put(messageType, pair); } /** @@ -134,12 +129,6 @@ public abstract class AbstractRpcRemotingServer extends AbstractRpcRemoting impl return serverBootstrap.getListenPort(); } - @Override - public void init() { - super.init(); - serverBootstrap.start(); - } - @Override public void destroy() { serverBootstrap.shutdown(); @@ -165,47 +154,11 @@ public abstract class AbstractRpcRemotingServer extends AbstractRpcRemoting impl ctx.close(); } - @Override - public void destroyChannel(String serverAddress, Channel channel) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("will destroy channel:{},address:{}", channel, serverAddress); - } - channel.disconnect(); - channel.close(); - } - /** * The type ServerHandler. */ @ChannelHandler.Sharable - class ServerHandler extends AbstractHandler { - - /** - * Dispatch. - * - * @param request the request - * @param ctx the ctx - */ - @Override - public void dispatch(RpcMessage request, ChannelHandlerContext ctx) { - Object msg = request.getBody(); - if (msg instanceof RegisterRMRequest) { - serverMessageListener.onRegRmMessage(request, ctx, checkAuthHandler); - } else { - if (ChannelManager.isRegistered(ctx.channel())) { - serverMessageListener.onTrxMessage(request, ctx); - } else { - try { - closeChannelHandlerContext(ctx); - } catch (Exception exx) { - LOGGER.error(exx.getMessage()); - } - if (LOGGER.isInfoEnabled()) { - LOGGER.info(String.format("close a unhandled connection! [%s]", ctx.channel().toString())); - } - } - } - } + class ServerHandler extends ChannelDuplexHandler { /** * Channel read. @@ -216,19 +169,20 @@ public abstract class AbstractRpcRemotingServer extends AbstractRpcRemoting impl */ @Override public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof RpcMessage) { - RpcMessage rpcMessage = (RpcMessage) msg; - debugLog("read:" + rpcMessage.getBody()); - if (rpcMessage.getBody() instanceof RegisterTMRequest) { - serverMessageListener.onRegTmMessage(rpcMessage, ctx, checkAuthHandler); - return; - } - if (rpcMessage.getBody() == HeartbeatMessage.PING) { - serverMessageListener.onCheckMessage(rpcMessage, ctx); - return; + if (!(msg instanceof RpcMessage)) { + return; + } + processMessage(ctx, (RpcMessage) msg); + } + + @Override + public void channelWritabilityChanged(ChannelHandlerContext ctx) { + synchronized (lock) { + if (ctx.channel().isWritable()) { + lock.notifyAll(); } } - super.channelRead(ctx, msg); + ctx.fireChannelWritabilityChanged(); } /** @@ -253,7 +207,7 @@ public abstract class AbstractRpcRemotingServer extends AbstractRpcRemoting impl if (LOGGER.isInfoEnabled()) { LOGGER.info(ipAndPort + " to server channel inactive."); } - if (null != rpcContext && null != rpcContext.getClientRole()) { + if (rpcContext != null && rpcContext.getClientRole() != null) { rpcContext.release(); if (LOGGER.isInfoEnabled()) { LOGGER.info("remove channel:" + ctx.channel() + "context:" + rpcContext); @@ -307,6 +261,13 @@ public abstract class AbstractRpcRemotingServer extends AbstractRpcRemoting impl } } - } + @Override + public void close(ChannelHandlerContext ctx, ChannelPromise future) throws Exception { + if (LOGGER.isInfoEnabled()) { + LOGGER.info(ctx + " will closed"); + } + super.close(ctx, future); + } + } } diff --git a/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemoting.java b/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemoting.java deleted file mode 100644 index cdbca423bdf7a3d85fe5edf17f56c74a03487283..0000000000000000000000000000000000000000 --- a/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemoting.java +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache 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 - * - * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.netty; - -import io.netty.channel.Channel; -import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.seata.common.exception.FrameworkErrorCode; -import io.seata.common.exception.FrameworkException; -import io.seata.common.thread.NamedThreadFactory; -import io.seata.common.thread.PositiveAtomicCounter; -import io.seata.core.protocol.HeartbeatMessage; -import io.seata.core.protocol.MergeMessage; -import io.seata.core.protocol.MessageFuture; -import io.seata.core.protocol.ProtocolConstants; -import io.seata.core.protocol.RpcMessage; -import io.seata.core.rpc.Disposable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.net.SocketAddress; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * The type Abstract rpc remoting. - * - * @author slievrly - */ -public abstract class AbstractRpcRemoting implements Disposable { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRpcRemoting.class); - /** - * The Timer executor. - */ - protected final ScheduledExecutorService timerExecutor = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("timeoutChecker", 1, true)); - /** - * The Message executor. - */ - protected final ThreadPoolExecutor messageExecutor; - - /** - * Id generator of this remoting - */ - protected final PositiveAtomicCounter idGenerator = new PositiveAtomicCounter(); - - /** - * The Futures. - */ - protected final ConcurrentHashMap<Integer, MessageFuture> futures = new ConcurrentHashMap<>(); - /** - * The Basket map. - */ - protected final ConcurrentHashMap<String, BlockingQueue<RpcMessage>> basketMap = new ConcurrentHashMap<>(); - - private static final long NOT_WRITEABLE_CHECK_MILLS = 10L; - /** - * The Merge lock. - */ - protected final Object mergeLock = new Object(); - /** - * The Now mills. - */ - protected volatile long nowMills = 0; - private static final int TIMEOUT_CHECK_INTERNAL = 3000; - private final Object lock = new Object(); - /** - * The Is sending. - */ - protected volatile boolean isSending = false; - private String group = "DEFAULT"; - /** - * The Merge msg map. - */ - protected final Map<Integer, MergeMessage> mergeMsgMap = new ConcurrentHashMap<>(); - - /** - * Instantiates a new Abstract rpc remoting. - * - * @param messageExecutor the message executor - */ - public AbstractRpcRemoting(ThreadPoolExecutor messageExecutor) { - this.messageExecutor = messageExecutor; - } - - /** - * Gets next message id. - * - * @return the next message id - */ - public int getNextMessageId() { - return idGenerator.incrementAndGet(); - } - - /** - * Init. - */ - public void init() { - timerExecutor.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - for (Map.Entry<Integer, MessageFuture> entry : futures.entrySet()) { - if (entry.getValue().isTimeout()) { - futures.remove(entry.getKey()); - entry.getValue().setResultMessage(null); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("timeout clear future: {}", entry.getValue().getRequestMessage().getBody()); - } - } - } - - nowMills = System.currentTimeMillis(); - } - }, TIMEOUT_CHECK_INTERNAL, TIMEOUT_CHECK_INTERNAL, TimeUnit.MILLISECONDS); - } - - /** - * Destroy. - */ - @Override - public void destroy() { - timerExecutor.shutdown(); - messageExecutor.shutdown(); - } - - /** - * Send async request with response object. - * - * @param channel the channel - * @param msg the msg - * @return the object - * @throws TimeoutException the timeout exception - */ - protected Object sendAsyncRequestWithResponse(Channel channel, Object msg) throws TimeoutException { - return sendAsyncRequestWithResponse(null, channel, msg, NettyClientConfig.getRpcRequestTimeout()); - } - - /** - * Send async request with response object. - * - * @param address the address - * @param channel the channel - * @param msg the msg - * @param timeout the timeout - * @return the object - * @throws TimeoutException the timeout exception - */ - protected Object sendAsyncRequestWithResponse(String address, Channel channel, Object msg, long timeout) throws - TimeoutException { - if (timeout <= 0) { - throw new FrameworkException("timeout should more than 0ms"); - } - return sendAsyncRequest(address, channel, msg, timeout); - } - - /** - * Send async request without response object. - * - * @param channel the channel - * @param msg the msg - * @return the object - * @throws TimeoutException the timeout exception - */ - protected Object sendAsyncRequestWithoutResponse(Channel channel, Object msg) throws - TimeoutException { - return sendAsyncRequest(null, channel, msg, 0); - } - - private Object sendAsyncRequest(String address, Channel channel, Object msg, long timeout) - throws TimeoutException { - if (channel == null) { - LOGGER.warn("sendAsyncRequestWithResponse nothing, caused by null channel."); - return null; - } - final RpcMessage rpcMessage = new RpcMessage(); - rpcMessage.setId(getNextMessageId()); - rpcMessage.setMessageType(ProtocolConstants.MSGTYPE_RESQUEST_ONEWAY); - rpcMessage.setCodec(ProtocolConstants.CONFIGURED_CODEC); - rpcMessage.setCompressor(ProtocolConstants.CONFIGURED_COMPRESSOR); - rpcMessage.setBody(msg); - - final MessageFuture messageFuture = new MessageFuture(); - messageFuture.setRequestMessage(rpcMessage); - messageFuture.setTimeout(timeout); - futures.put(rpcMessage.getId(), messageFuture); - - if (address != null) { - /* - The batch send. - Object From big to small: RpcMessage -> MergedWarpMessage -> AbstractMessage - @see AbstractRpcRemotingClient.MergedSendRunnable - */ - if (NettyClientConfig.isEnableClientBatchSendRequest()) { - ConcurrentHashMap<String, BlockingQueue<RpcMessage>> map = basketMap; - BlockingQueue<RpcMessage> basket = map.get(address); - if (basket == null) { - map.putIfAbsent(address, new LinkedBlockingQueue<>()); - basket = map.get(address); - } - basket.offer(rpcMessage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("offer message: {}", rpcMessage.getBody()); - } - if (!isSending) { - synchronized (mergeLock) { - mergeLock.notifyAll(); - } - } - } else { - // the single send. - sendSingleRequest(channel, msg, rpcMessage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("send this msg[{}] by single send.", msg); - } - } - } else { - sendSingleRequest(channel, msg, rpcMessage); - } - if (timeout > 0) { - try { - return messageFuture.get(timeout, TimeUnit.MILLISECONDS); - } catch (Exception exx) { - LOGGER.error("wait response error:{},ip:{},request:{}", exx.getMessage(), address, msg); - if (exx instanceof TimeoutException) { - throw (TimeoutException) exx; - } else { - throw new RuntimeException(exx); - } - } - } else { - return null; - } - } - - private void sendSingleRequest(Channel channel, Object msg, RpcMessage rpcMessage) { - ChannelFuture future; - channelWritableCheck(channel, msg); - future = channel.writeAndFlush(rpcMessage); - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) { - if (!future.isSuccess()) { - MessageFuture messageFuture = futures.remove(rpcMessage.getId()); - if (messageFuture != null) { - messageFuture.setResultMessage(future.cause()); - } - destroyChannel(future.channel()); - } - } - }); - } - - /** - * Default Send request. - * - * @param channel the channel - * @param msg the msg - */ - protected void defaultSendRequest(Channel channel, Object msg) { - RpcMessage rpcMessage = new RpcMessage(); - rpcMessage.setMessageType(msg instanceof HeartbeatMessage ? - ProtocolConstants.MSGTYPE_HEARTBEAT_REQUEST - : ProtocolConstants.MSGTYPE_RESQUEST); - rpcMessage.setCodec(ProtocolConstants.CONFIGURED_CODEC); - rpcMessage.setCompressor(ProtocolConstants.CONFIGURED_COMPRESSOR); - rpcMessage.setBody(msg); - rpcMessage.setId(getNextMessageId()); - if (msg instanceof MergeMessage) { - mergeMsgMap.put(rpcMessage.getId(), (MergeMessage) msg); - } - channelWritableCheck(channel, msg); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("write message:" + rpcMessage.getBody() + ", channel:" + channel + ",active?" - + channel.isActive() + ",writable?" + channel.isWritable() + ",isopen?" + channel.isOpen()); - } - channel.writeAndFlush(rpcMessage); - } - - /** - * Default Send response. - * - * @param request the msg id - * @param channel the channel - * @param msg the msg - */ - protected void defaultSendResponse(RpcMessage request, Channel channel, Object msg) { - RpcMessage rpcMessage = new RpcMessage(); - rpcMessage.setMessageType(msg instanceof HeartbeatMessage ? - ProtocolConstants.MSGTYPE_HEARTBEAT_RESPONSE : - ProtocolConstants.MSGTYPE_RESPONSE); - rpcMessage.setCodec(request.getCodec()); // same with request - rpcMessage.setCompressor(request.getCompressor()); - rpcMessage.setBody(msg); - rpcMessage.setId(request.getId()); - channelWritableCheck(channel, msg); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("send response:" + rpcMessage.getBody() + ",channel:" + channel); - } - channel.writeAndFlush(rpcMessage); - } - - private void channelWritableCheck(Channel channel, Object msg) { - int tryTimes = 0; - synchronized (lock) { - while (!channel.isWritable()) { - try { - tryTimes++; - if (tryTimes > NettyClientConfig.getMaxNotWriteableRetry()) { - destroyChannel(channel); - throw new FrameworkException("msg:" + ((msg == null) ? "null" : msg.toString()), - FrameworkErrorCode.ChannelIsNotWritable); - } - lock.wait(NOT_WRITEABLE_CHECK_MILLS); - } catch (InterruptedException exx) { - LOGGER.error(exx.getMessage()); - } - } - } - } - - /** - * Gets group. - * - * @return the group - */ - public String getGroup() { - return group; - } - - /** - * Sets group. - * - * @param group the group - */ - public void setGroup(String group) { - this.group = group; - } - - /** - * Destroy channel. - * - * @param channel the channel - */ - public void destroyChannel(Channel channel) { - destroyChannel(getAddressFromChannel(channel), channel); - } - - /** - * Destroy channel. - * - * @param serverAddress the server address - * @param channel the channel - */ - public abstract void destroyChannel(String serverAddress, Channel channel); - - /** - * Gets address from context. - * - * @param ctx the ctx - * @return the address from context - */ - protected String getAddressFromContext(ChannelHandlerContext ctx) { - return getAddressFromChannel(ctx.channel()); - } - - /** - * Gets address from channel. - * - * @param channel the channel - * @return the address from channel - */ - protected String getAddressFromChannel(Channel channel) { - SocketAddress socketAddress = channel.remoteAddress(); - String address = socketAddress.toString(); - if (socketAddress.toString().indexOf(NettyClientConfig.getSocketAddressStartChar()) == 0) { - address = socketAddress.toString().substring(NettyClientConfig.getSocketAddressStartChar().length()); - } - return address; - } - - /** - * For testing. When the thread pool is full, you can change this variable and share the stack - */ - boolean allowDumpStack = false; - - /** - * The type AbstractHandler. - */ - abstract class AbstractHandler extends ChannelDuplexHandler { - - /** - * Dispatch. - * - * @param request the request - * @param ctx the ctx - */ - public abstract void dispatch(RpcMessage request, ChannelHandlerContext ctx); - - @Override - public void channelWritabilityChanged(ChannelHandlerContext ctx) { - synchronized (lock) { - if (ctx.channel().isWritable()) { - lock.notifyAll(); - } - } - - ctx.fireChannelWritabilityChanged(); - } - - @Override - public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof RpcMessage) { - final RpcMessage rpcMessage = (RpcMessage) msg; - if (rpcMessage.getMessageType() == ProtocolConstants.MSGTYPE_RESQUEST - || rpcMessage.getMessageType() == ProtocolConstants.MSGTYPE_RESQUEST_ONEWAY) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("%s msgId:%s, body:%s", this, rpcMessage.getId(), rpcMessage.getBody())); - } - try { - messageExecutor.execute(new Runnable() { - @Override - public void run() { - try { - dispatch(rpcMessage, ctx); - } catch (Throwable th) { - LOGGER.error(FrameworkErrorCode.NetDispatch.getErrCode(), th.getMessage(), th); - } - } - }); - } catch (RejectedExecutionException e) { - LOGGER.error(FrameworkErrorCode.ThreadPoolFull.getErrCode(), - "thread pool is full, current max pool size is " + messageExecutor.getActiveCount()); - if (allowDumpStack) { - String name = ManagementFactory.getRuntimeMXBean().getName(); - String pid = name.split("@")[0]; - int idx = new Random().nextInt(100); - try { - Runtime.getRuntime().exec("jstack " + pid + " >d:/" + idx + ".log"); - } catch (IOException exx) { - LOGGER.error(exx.getMessage()); - } - allowDumpStack = false; - } - } - } else { - MessageFuture messageFuture = futures.remove(rpcMessage.getId()); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String - .format("%s msgId:%s, future :%s, body:%s", this, rpcMessage.getId(), messageFuture, - rpcMessage.getBody())); - } - if (messageFuture != null) { - messageFuture.setResultMessage(rpcMessage.getBody()); - } else { - try { - messageExecutor.execute(new Runnable() { - @Override - public void run() { - try { - dispatch(rpcMessage, ctx); - } catch (Throwable th) { - LOGGER.error(FrameworkErrorCode.NetDispatch.getErrCode(), th.getMessage(), th); - } - } - }); - } catch (RejectedExecutionException e) { - LOGGER.error(FrameworkErrorCode.ThreadPoolFull.getErrCode(), - "thread pool is full, current max pool size is " + messageExecutor.getActiveCount()); - } - } - } - } - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - LOGGER.error(FrameworkErrorCode.ExceptionCaught.getErrCode(), - ctx.channel() + " connect exception. " + cause.getMessage(), - cause); - try { - destroyChannel(ctx.channel()); - } catch (Exception e) { - LOGGER.error("failed to close channel {}: {}", ctx.channel(), e.getMessage(), e); - } - } - - @Override - public void close(ChannelHandlerContext ctx, ChannelPromise future) throws Exception { - if (LOGGER.isInfoEnabled()) { - LOGGER.info(ctx + " will closed"); - } - super.close(ctx, future); - } - - } -} diff --git a/core/src/main/java/io/seata/core/rpc/netty/ChannelAuthHealthChecker.java b/core/src/main/java/io/seata/core/rpc/netty/ChannelAuthHealthChecker.java index e21e1600c9fa3a0c848e165dd8a389d9f3092ba0..5008aaa6a481dfe056bc59e32cf11bf9dcf355f5 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/ChannelAuthHealthChecker.java +++ b/core/src/main/java/io/seata/core/rpc/netty/ChannelAuthHealthChecker.java @@ -25,6 +25,7 @@ import io.netty.util.concurrent.Future; * * @author slievrly */ +@Deprecated public interface ChannelAuthHealthChecker extends ChannelHealthChecker { /** * The constant ACTIVE. diff --git a/core/src/main/java/io/seata/core/rpc/netty/ChannelEventListener.java b/core/src/main/java/io/seata/core/rpc/netty/ChannelEventListener.java index df6d876cafdde8f4eb8201af66fb23d9de22a720..19868ef027ed7ac52164ad852dff6108bcd0a981 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/ChannelEventListener.java +++ b/core/src/main/java/io/seata/core/rpc/netty/ChannelEventListener.java @@ -22,6 +22,7 @@ import io.netty.channel.Channel; * * @author slievrly */ +@Deprecated public interface ChannelEventListener { /** * On channel connect. diff --git a/core/src/main/java/io/seata/core/rpc/ChannelManager.java b/core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java similarity index 98% rename from core/src/main/java/io/seata/core/rpc/ChannelManager.java rename to core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java index 07ef5640c09ac8967d659db8ba5f8752ca376f65..9c011611e4dbdbd3277eb58a84bd2100f6268136 100644 --- a/core/src/main/java/io/seata/core/rpc/ChannelManager.java +++ b/core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.core.rpc; +package io.seata.core.rpc.netty; import io.netty.channel.Channel; import io.seata.common.Constants; @@ -23,7 +23,7 @@ import io.seata.core.protocol.IncompatibleVersionException; import io.seata.core.protocol.RegisterRMRequest; import io.seata.core.protocol.RegisterTMRequest; import io.seata.core.protocol.Version; -import io.seata.core.rpc.netty.NettyPoolKey; +import io.seata.core.rpc.RpcContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -157,7 +157,7 @@ public class ChannelManager { rpcContext = IDENTIFIED_CHANNELS.get(channel); rpcContext.addResources(dbkeySet); } - if (null == dbkeySet || dbkeySet.isEmpty()) { return; } + if (dbkeySet == null || dbkeySet.isEmpty()) { return; } for (String resourceId : dbkeySet) { String clientIp; ConcurrentMap<Integer, RpcContext> portMap = RM_CHANNELS.computeIfAbsent(resourceId, resourceIdKey -> new ConcurrentHashMap<>()) @@ -223,7 +223,7 @@ public class ChannelManager { return channel; } RpcContext rpcContext = getContextFromIdentified(channel); - if (null == rpcContext) { + if (rpcContext == null) { LOGGER.error("rpcContext is null,channel:{},active:{}", channel, channel.isActive()); return null; } @@ -244,7 +244,7 @@ public class ChannelManager { } else if (clientRole == NettyPoolKey.TransactionRole.RMROLE) { for (Map<Integer, RpcContext> clientRmMap : rpcContext.getClientRMHolderMap().values()) { Channel sameClientChannel = getChannelFromSameClientMap(clientRmMap, clientPort); - if (null != sameClientChannel) { + if (sameClientChannel != null) { return sameClientChannel; } } @@ -254,7 +254,7 @@ public class ChannelManager { } private static Channel getChannelFromSameClientMap(Map<Integer, RpcContext> clientChannelMap, int exclusivePort) { - if (null != clientChannelMap && !clientChannelMap.isEmpty()) { + if (clientChannelMap != null && !clientChannelMap.isEmpty()) { for (ConcurrentMap.Entry<Integer, RpcContext> entry : clientChannelMap.entrySet()) { if (entry.getKey() == exclusivePort) { clientChannelMap.remove(entry.getKey()); @@ -300,7 +300,7 @@ public class ChannelManager { ConcurrentMap<String, ConcurrentMap<Integer, RpcContext>> ipMap = applicationIdMap.get(targetApplicationId); - if (null != ipMap && !ipMap.isEmpty()) { + if (ipMap != null && !ipMap.isEmpty()) { // Firstly, try to find the original channel through which the branch was registered. ConcurrentMap<Integer, RpcContext> portMapOnTargetIP = ipMap.get(targetIP); diff --git a/core/src/main/java/io/seata/core/rpc/ChannelUtil.java b/core/src/main/java/io/seata/core/rpc/netty/ChannelUtil.java similarity index 98% rename from core/src/main/java/io/seata/core/rpc/ChannelUtil.java rename to core/src/main/java/io/seata/core/rpc/netty/ChannelUtil.java index 1bbc8089fcaeb428c0de767955c7d3e5f7ac7506..ca26a43700d0b1f877ead16ccf8ff8749c8f3c98 100644 --- a/core/src/main/java/io/seata/core/rpc/ChannelUtil.java +++ b/core/src/main/java/io/seata/core/rpc/netty/ChannelUtil.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.core.rpc; +package io.seata.core.rpc.netty; import io.netty.channel.Channel; import io.seata.common.Constants; diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyBaseConfig.java b/core/src/main/java/io/seata/core/rpc/netty/NettyBaseConfig.java index ccee8ec8faabb8ba1c954361aeb1b8e8ff336ca4..3f125047481d0f0aee67adff5d51b4ef8ac89e3f 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyBaseConfig.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyBaseConfig.java @@ -32,6 +32,8 @@ import io.netty.util.internal.PlatformDependent; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.rpc.TransportProtocolType; +import io.seata.core.rpc.TransportServerType; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -114,7 +116,7 @@ public class NettyBaseConfig { String workerThreadSize = CONFIG.getConfig(ConfigurationKeys.WORKER_THREAD_SIZE); if (StringUtils.isNotBlank(workerThreadSize) && StringUtils.isNumeric(workerThreadSize)) { WORKER_THREAD_SIZE = Integer.parseInt(workerThreadSize); - } else if (null != WorkThreadMode.getModeByName(workerThreadSize)) { + } else if (WorkThreadMode.getModeByName(workerThreadSize) != null) { WORKER_THREAD_SIZE = WorkThreadMode.getModeByName(workerThreadSize).getValue(); } else { WORKER_THREAD_SIZE = WorkThreadMode.Default.getValue(); diff --git a/core/src/main/java/io/seata/core/rpc/netty/RpcClientBootstrap.java b/core/src/main/java/io/seata/core/rpc/netty/NettyClientBootstrap.java similarity index 92% rename from core/src/main/java/io/seata/core/rpc/netty/RpcClientBootstrap.java rename to core/src/main/java/io/seata/core/rpc/netty/NettyClientBootstrap.java index 7cba4ff437404c77c27e4efbcdfdb77268b19ea9..2d52bb51b94786234d03a3e49cb438390cb66c67 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/RpcClientBootstrap.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyClientBootstrap.java @@ -33,7 +33,7 @@ import io.netty.util.concurrent.EventExecutorGroup; import io.netty.util.internal.PlatformDependent; import io.seata.common.exception.FrameworkException; import io.seata.common.thread.NamedThreadFactory; -import io.seata.core.rpc.RemotingClient; +import io.seata.core.rpc.RemotingBootstrap; import io.seata.core.rpc.netty.v1.ProtocolV1Decoder; import io.seata.core.rpc.netty.v1.ProtocolV1Encoder; import org.slf4j.Logger; @@ -49,9 +49,9 @@ import java.util.concurrent.atomic.AtomicBoolean; * @author slievrly * @author zhaojun */ -public class RpcClientBootstrap implements RemotingClient { +public class NettyClientBootstrap implements RemotingBootstrap { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRpcRemotingClient.class); + private static final Logger LOGGER = LoggerFactory.getLogger(NettyClientBootstrap.class); private final NettyClientConfig nettyClientConfig; private final Bootstrap bootstrap = new Bootstrap(); private final EventLoopGroup eventLoopGroupWorker; @@ -61,9 +61,9 @@ public class RpcClientBootstrap implements RemotingClient { private final NettyPoolKey.TransactionRole transactionRole; private ChannelHandler[] channelHandlers; - public RpcClientBootstrap(NettyClientConfig nettyClientConfig, final EventExecutorGroup eventExecutorGroup, - NettyPoolKey.TransactionRole transactionRole) { - if (null == nettyClientConfig) { + public NettyClientBootstrap(NettyClientConfig nettyClientConfig, final EventExecutorGroup eventExecutorGroup, + NettyPoolKey.TransactionRole transactionRole) { + if (nettyClientConfig == null) { nettyClientConfig = new NettyClientConfig(); if (LOGGER.isInfoEnabled()) { LOGGER.info("use default netty client config."); @@ -84,7 +84,7 @@ public class RpcClientBootstrap implements RemotingClient { * @param handlers the handlers */ protected void setChannelHandlers(final ChannelHandler... handlers) { - if (null != handlers) { + if (handlers != null) { channelHandlers = handlers; } } @@ -96,7 +96,7 @@ public class RpcClientBootstrap implements RemotingClient { * @param handlers the handlers */ private void addChannelPipelineLast(Channel channel, ChannelHandler... handlers) { - if (null != channel && null != handlers) { + if (channel != null && handlers != null) { channel.pipeline().addLast(handlers); } } @@ -137,14 +137,14 @@ public class RpcClientBootstrap implements RemotingClient { nettyClientConfig.getChannelMaxAllIdleSeconds())) .addLast(new ProtocolV1Decoder()) .addLast(new ProtocolV1Encoder()); - if (null != channelHandlers) { + if (channelHandlers != null) { addChannelPipelineLast(ch, channelHandlers); } } }); if (initialized.compareAndSet(false, true) && LOGGER.isInfoEnabled()) { - LOGGER.info("RpcClientBootstrap has started"); + LOGGER.info("NettyClientBootstrap has started"); } } diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java b/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java index de20cf4084312ebd3f1f2e6e7f1964af48072e63..3c062451e684032b4ddb831b6fb4b7a90d3e93d2 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java @@ -91,7 +91,7 @@ class NettyClientChannelManager { Channel channelToServer = channels.get(serverAddress); if (channelToServer != null) { channelToServer = getExistAliveChannel(channelToServer, serverAddress); - if (null != channelToServer) { + if (channelToServer != null) { return channelToServer; } } @@ -111,11 +111,11 @@ class NettyClientChannelManager { * @param serverAddress server address */ void releaseChannel(Channel channel, String serverAddress) { - if (null == channel || null == serverAddress) { return; } + if (channel == null || serverAddress == null) { return; } try { synchronized (channelLocks.get(serverAddress)) { Channel ch = channels.get(serverAddress); - if (null == ch) { + if (ch == null) { nettyClientKeyPool.returnObject(poolKeyMap.get(serverAddress), channel); return; } @@ -140,7 +140,7 @@ class NettyClientChannelManager { * @param channel channel */ void destroyChannel(String serverAddress, Channel channel) { - if (null == channel) { return; } + if (channel == null) { return; } try { if (channel.equals(channels.get(serverAddress))) { channels.remove(serverAddress); @@ -184,7 +184,7 @@ class NettyClientChannelManager { } void registerChannel(final String serverAddress, final Channel channel) { - if (null != channels.get(serverAddress) && channels.get(serverAddress).isActive()) { + if (channels.get(serverAddress) != null && channels.get(serverAddress).isActive()) { return; } channels.put(serverAddress, channel); @@ -199,7 +199,7 @@ class NettyClientChannelManager { try { NettyPoolKey currentPoolKey = poolKeyFunction.apply(serverAddress); NettyPoolKey previousPoolKey = poolKeyMap.putIfAbsent(serverAddress, currentPoolKey); - if (null != previousPoolKey && previousPoolKey.getMessage() instanceof RegisterRMRequest) { + if (previousPoolKey != null && previousPoolKey.getMessage() instanceof RegisterRMRequest) { RegisterRMRequest registerRMRequest = (RegisterRMRequest) currentPoolKey.getMessage(); ((RegisterRMRequest) previousPoolKey.getMessage()).setResourceIds(registerRMRequest.getResourceIds()); } @@ -236,7 +236,7 @@ class NettyClientChannelManager { LOGGER.error(exx.getMessage()); } rmChannel = channels.get(serverAddress); - if (null != rmChannel && rmChannel.isActive()) { + if (rmChannel != null && rmChannel.isActive()) { return rmChannel; } } diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java b/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java index 772a050578fc13ebcd8f64a9623ffd4f6a17e823..685f901533238191ad7706fd6666779820a85c6e 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java @@ -17,6 +17,7 @@ package io.seata.core.rpc.netty; import io.netty.channel.Channel; import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.rpc.TransportServerType; import static io.seata.core.constants.DefaultValues.DEFAULT_ENABLE_CLIENT_BATCH_SEND_REQUEST; import static io.seata.core.constants.DefaultValues.DEFAULT_SELECTOR_THREAD_PREFIX; diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java b/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java index c18eae131b2846781eca84557e8bbce3c67c1da6..795a4e4452a87bc734feb25cf5ee5f24ac48c15c 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java @@ -15,6 +15,8 @@ */ package io.seata.core.rpc.netty; +import java.net.InetSocketAddress; + import io.netty.channel.Channel; import io.seata.common.exception.FrameworkException; import io.seata.common.util.NetUtil; @@ -24,8 +26,6 @@ import org.apache.commons.pool.KeyedPoolableObjectFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.net.InetSocketAddress; - /** * The type Netty key poolable factory. * @@ -35,16 +35,16 @@ public class NettyPoolableFactory implements KeyedPoolableObjectFactory<NettyPoo private static final Logger LOGGER = LoggerFactory.getLogger(NettyPoolableFactory.class); - private final AbstractRpcRemotingClient rpcRemotingClient; + private final AbstractNettyRemotingClient rpcRemotingClient; - private final RpcClientBootstrap clientBootstrap; + private final NettyClientBootstrap clientBootstrap; /** * Instantiates a new Netty key poolable factory. * * @param rpcRemotingClient the rpc remoting client */ - public NettyPoolableFactory(AbstractRpcRemotingClient rpcRemotingClient, RpcClientBootstrap clientBootstrap) { + public NettyPoolableFactory(AbstractNettyRemotingClient rpcRemotingClient, NettyClientBootstrap clientBootstrap) { this.rpcRemotingClient = rpcRemotingClient; this.clientBootstrap = clientBootstrap; } @@ -59,12 +59,12 @@ public class NettyPoolableFactory implements KeyedPoolableObjectFactory<NettyPoo long start = System.currentTimeMillis(); Object response; Channel channelToServer = null; - if (null == key.getMessage()) { + if (key.getMessage() == null) { throw new FrameworkException("register msg is null, role:" + key.getTransactionRole().name()); } try { - response = rpcRemotingClient.sendAsyncRequestWithResponse(tmpChannel, key.getMessage()); - if (!isResponseSuccess(response, key.getTransactionRole())) { + response = rpcRemotingClient.sendSyncRequest(tmpChannel, key.getMessage()); + if (!isRegisterSuccess(response, key.getTransactionRole())) { rpcRemotingClient.onRegisterMsgFail(key.getAddress(), tmpChannel, response, key.getMessage()); } else { channelToServer = tmpChannel; @@ -75,7 +75,7 @@ public class NettyPoolableFactory implements KeyedPoolableObjectFactory<NettyPoo tmpChannel.close(); } throw new FrameworkException( - "register error,role:" + key.getTransactionRole().name() + ",err:" + exx.getMessage()); + "register " + key.getTransactionRole().name() + " error, errMsg:" + exx.getMessage()); } if (LOGGER.isInfoEnabled()) { LOGGER.info("register success, cost " + (System.currentTimeMillis() - start) + " ms, version:" + getVersion( @@ -85,35 +85,37 @@ public class NettyPoolableFactory implements KeyedPoolableObjectFactory<NettyPoo return channelToServer; } - private boolean isResponseSuccess(Object response, NettyPoolKey.TransactionRole transactionRole) { - if (null == response) { + private boolean isRegisterSuccess(Object response, NettyPoolKey.TransactionRole transactionRole) { + if (response == null) { return false; } if (transactionRole.equals(NettyPoolKey.TransactionRole.TMROLE)) { if (!(response instanceof RegisterTMResponse)) { return false; } - return ((RegisterTMResponse)response).isIdentified(); + RegisterTMResponse registerTMResponse = (RegisterTMResponse)response; + return registerTMResponse.isIdentified(); } else if (transactionRole.equals(NettyPoolKey.TransactionRole.RMROLE)) { if (!(response instanceof RegisterRMResponse)) { return false; } - return ((RegisterRMResponse)response).isIdentified(); + RegisterRMResponse registerRMResponse = (RegisterRMResponse)response; + return registerRMResponse.isIdentified(); } return false; } private String getVersion(Object response, NettyPoolKey.TransactionRole transactionRole) { if (transactionRole.equals(NettyPoolKey.TransactionRole.TMROLE)) { - return ((RegisterTMResponse)response).getVersion(); + return ((RegisterTMResponse) response).getVersion(); } else { - return ((RegisterRMResponse)response).getVersion(); + return ((RegisterRMResponse) response).getVersion(); } } @Override public void destroyObject(NettyPoolKey key, Channel channel) throws Exception { - if (null != channel) { + if (channel != null) { if (LOGGER.isInfoEnabled()) { LOGGER.info("will destroy channel:" + channel); } @@ -124,7 +126,7 @@ public class NettyPoolableFactory implements KeyedPoolableObjectFactory<NettyPoo @Override public boolean validateObject(NettyPoolKey key, Channel obj) { - if (null != obj && obj.isActive()) { + if (obj != null && obj.isActive()) { return true; } if (LOGGER.isInfoEnabled()) { diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyRemotingServer.java b/core/src/main/java/io/seata/core/rpc/netty/NettyRemotingServer.java new file mode 100644 index 0000000000000000000000000000000000000000..0940c0b20b7bd5b38a3888d4d8c5b088c6759a60 --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyRemotingServer.java @@ -0,0 +1,116 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.netty; + +import io.netty.channel.Channel; +import io.seata.core.protocol.MessageType; +import io.seata.core.rpc.TransactionMessageHandler; +import io.seata.core.rpc.processor.server.RegRmProcessor; +import io.seata.core.rpc.processor.server.RegTmProcessor; +import io.seata.core.rpc.processor.server.ServerHeartbeatProcessor; +import io.seata.core.rpc.processor.server.ServerOnRequestProcessor; +import io.seata.core.rpc.processor.server.ServerOnResponseProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * The netty remoting server. + * + * @author slievrly + * @author xingfudeshi@gmail.com + * @author zhangchenghui.dev@gmail.com + */ +public class NettyRemotingServer extends AbstractNettyRemotingServer { + + private static final Logger LOGGER = LoggerFactory.getLogger(NettyRemotingServer.class); + + private TransactionMessageHandler transactionMessageHandler; + + private final AtomicBoolean initialized = new AtomicBoolean(false); + + @Override + public void init() { + // registry processor + registerProcessor(); + if (initialized.compareAndSet(false, true)) { + super.init(); + } + } + + /** + * Instantiates a new Rpc remoting server. + * + * @param messageExecutor the message executor + */ + public NettyRemotingServer(ThreadPoolExecutor messageExecutor) { + super(messageExecutor, new NettyServerConfig()); + } + + /** + * Sets transactionMessageHandler. + * + * @param transactionMessageHandler the transactionMessageHandler + */ + public void setHandler(TransactionMessageHandler transactionMessageHandler) { + this.transactionMessageHandler = transactionMessageHandler; + } + + public TransactionMessageHandler getHandler() { + return transactionMessageHandler; + } + + @Override + public void destroyChannel(String serverAddress, Channel channel) { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("will destroy channel:{},address:{}", channel, serverAddress); + } + channel.disconnect(); + channel.close(); + } + + private void registerProcessor() { + // 1. registry on request message processor + ServerOnRequestProcessor onRequestProcessor = + new ServerOnRequestProcessor(this, getHandler()); + super.registerProcessor(MessageType.TYPE_BRANCH_REGISTER, onRequestProcessor, messageExecutor); + super.registerProcessor(MessageType.TYPE_BRANCH_STATUS_REPORT, onRequestProcessor, messageExecutor); + super.registerProcessor(MessageType.TYPE_GLOBAL_BEGIN, onRequestProcessor, messageExecutor); + super.registerProcessor(MessageType.TYPE_GLOBAL_COMMIT, onRequestProcessor, messageExecutor); + super.registerProcessor(MessageType.TYPE_GLOBAL_LOCK_QUERY, onRequestProcessor, messageExecutor); + super.registerProcessor(MessageType.TYPE_GLOBAL_REPORT, onRequestProcessor, messageExecutor); + super.registerProcessor(MessageType.TYPE_GLOBAL_ROLLBACK, onRequestProcessor, messageExecutor); + super.registerProcessor(MessageType.TYPE_GLOBAL_STATUS, onRequestProcessor, messageExecutor); + super.registerProcessor(MessageType.TYPE_SEATA_MERGE, onRequestProcessor, messageExecutor); + // 2. registry on response message processor + ServerOnResponseProcessor onResponseProcessor = + new ServerOnResponseProcessor(getHandler(), getFutures()); + super.registerProcessor(MessageType.TYPE_BRANCH_COMMIT_RESULT, onResponseProcessor, messageExecutor); + super.registerProcessor(MessageType.TYPE_BRANCH_ROLLBACK_RESULT, onResponseProcessor, messageExecutor); + // 3. registry rm message processor + RegRmProcessor regRmProcessor = new RegRmProcessor(this); + super.registerProcessor(MessageType.TYPE_REG_RM, regRmProcessor, messageExecutor); + // 4. registry tm message processor + RegTmProcessor regTmProcessor = new RegTmProcessor(this); + super.registerProcessor(MessageType.TYPE_REG_CLT, regTmProcessor, null); + // 5. registry heartbeat message processor + ServerHeartbeatProcessor heartbeatMessageProcessor = new ServerHeartbeatProcessor(this); + super.registerProcessor(MessageType.TYPE_HEARTBEAT_MSG, heartbeatMessageProcessor, null); + } + +} diff --git a/core/src/main/java/io/seata/core/rpc/netty/RpcServerBootstrap.java b/core/src/main/java/io/seata/core/rpc/netty/NettyServerBootstrap.java similarity index 93% rename from core/src/main/java/io/seata/core/rpc/netty/RpcServerBootstrap.java rename to core/src/main/java/io/seata/core/rpc/netty/NettyServerBootstrap.java index f4cd2ae05dce0adaa260d806444d418d7a19d031..9a0de2bea19cb365acf5126fab5dfe03a9c0fb7b 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/RpcServerBootstrap.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyServerBootstrap.java @@ -29,7 +29,7 @@ import io.netty.channel.socket.SocketChannel; import io.netty.handler.timeout.IdleStateHandler; import io.seata.common.XID; import io.seata.common.thread.NamedThreadFactory; -import io.seata.core.rpc.RemotingServer; +import io.seata.core.rpc.RemotingBootstrap; import io.seata.core.rpc.netty.v1.ProtocolV1Decoder; import io.seata.core.rpc.netty.v1.ProtocolV1Encoder; import io.seata.discovery.registry.RegistryFactory; @@ -46,9 +46,9 @@ import java.util.concurrent.atomic.AtomicBoolean; * @author zhangchenghui.dev@gmail.com * @since 1.1.0 */ -public class RpcServerBootstrap implements RemotingServer { +public class NettyServerBootstrap implements RemotingBootstrap { - private static final Logger LOGGER = LoggerFactory.getLogger(RpcServerBootstrap.class); + private static final Logger LOGGER = LoggerFactory.getLogger(NettyServerBootstrap.class); private final ServerBootstrap serverBootstrap = new ServerBootstrap(); private final EventLoopGroup eventLoopGroupWorker; private final EventLoopGroup eventLoopGroupBoss; @@ -57,7 +57,7 @@ public class RpcServerBootstrap implements RemotingServer { private int listenPort; private final AtomicBoolean initialized = new AtomicBoolean(false); - public RpcServerBootstrap(NettyServerConfig nettyServerConfig) { + public NettyServerBootstrap(NettyServerConfig nettyServerConfig) { this.nettyServerConfig = nettyServerConfig; if (NettyServerConfig.enableEpoll()) { @@ -84,7 +84,7 @@ public class RpcServerBootstrap implements RemotingServer { * @param handlers the handlers */ protected void setChannelHandlers(final ChannelHandler... handlers) { - if (null != handlers) { + if (handlers != null) { channelHandlers = handlers; } } @@ -96,7 +96,7 @@ public class RpcServerBootstrap implements RemotingServer { * @param handlers the handlers */ private void addChannelPipelineLast(Channel channel, ChannelHandler... handlers) { - if (null != channel && null != handlers) { + if (channel != null && handlers != null) { channel.pipeline().addLast(handlers); } } @@ -126,7 +126,7 @@ public class RpcServerBootstrap implements RemotingServer { @Override public void start() { this.serverBootstrap.group(this.eventLoopGroupBoss, this.eventLoopGroupWorker) - .channel(nettyServerConfig.SERVER_CHANNEL_CLAZZ) + .channel(NettyServerConfig.SERVER_CHANNEL_CLAZZ) .option(ChannelOption.SO_BACKLOG, nettyServerConfig.getSoBackLogSize()) .option(ChannelOption.SO_REUSEADDR, true) .childOption(ChannelOption.SO_KEEPALIVE, true) @@ -143,7 +143,7 @@ public class RpcServerBootstrap implements RemotingServer { ch.pipeline().addLast(new IdleStateHandler(nettyServerConfig.getChannelMaxReadIdleSeconds(), 0, 0)) .addLast(new ProtocolV1Decoder()) .addLast(new ProtocolV1Encoder()); - if (null != channelHandlers) { + if (channelHandlers != null) { addChannelPipelineLast(ch, channelHandlers); } @@ -152,7 +152,7 @@ public class RpcServerBootstrap implements RemotingServer { try { ChannelFuture future = this.serverBootstrap.bind(listenPort).sync(); - LOGGER.info("Server started ... "); + LOGGER.info("Server started, listen port: {}", listenPort); RegistryFactory.getInstance().register(new InetSocketAddress(XID.getIpAddress(), XID.getPort())); initialized.set(true); future.channel().closeFuture().sync(); diff --git a/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java b/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java index 6f78e93c42a2c6dea632d16995e270eb1ac0e0b4..f1fb4f1cf2e8d3e41b461eaaeb5bbac113cc8898 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java +++ b/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java @@ -23,6 +23,7 @@ import io.seata.core.protocol.AbstractMessage; * * @author slievrly */ +@Deprecated public interface RegisterMsgListener { /** diff --git a/core/src/main/java/io/seata/core/rpc/netty/RmMessageListener.java b/core/src/main/java/io/seata/core/rpc/netty/RmMessageListener.java deleted file mode 100644 index bf6a7b38549e2427e0d6ea1b3c3b706ab6bf7e99..0000000000000000000000000000000000000000 --- a/core/src/main/java/io/seata/core/rpc/netty/RmMessageListener.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache 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 - * - * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.netty; - -import io.seata.common.exception.FrameworkErrorCode; -import io.seata.core.protocol.ResultCode; -import io.seata.core.protocol.RpcMessage; -import io.seata.core.protocol.transaction.BranchCommitRequest; -import io.seata.core.protocol.transaction.BranchCommitResponse; -import io.seata.core.protocol.transaction.BranchRollbackRequest; -import io.seata.core.protocol.transaction.BranchRollbackResponse; -import io.seata.core.protocol.transaction.UndoLogDeleteRequest; -import io.seata.core.rpc.ClientMessageListener; -import io.seata.core.rpc.ClientMessageSender; -import io.seata.core.rpc.TransactionMessageHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The type Rm message listener. - * - * @author slievrly - */ -public class RmMessageListener implements ClientMessageListener { - - private static final Logger LOGGER = LoggerFactory.getLogger(RmMessageListener.class); - - private TransactionMessageHandler handler; - - private ClientMessageSender sender; - - /** - * Instantiates a new Rm message listener. - * - * @param handler the handler - */ - public RmMessageListener(TransactionMessageHandler handler, ClientMessageSender sender) { - this.handler = handler; - this.sender = sender; - } - - public void setSender(ClientMessageSender sender) { - this.sender = sender; - } - - public ClientMessageSender getSender() { - if (sender == null) { - throw new IllegalArgumentException("clientMessageSender must not be null"); - } - return sender; - } - - /** - * Sets handler. - * - * @param handler the handler - */ - public void setHandler(TransactionMessageHandler handler) { - this.handler = handler; - } - - @Override - public void onMessage(RpcMessage request, String serverAddress) { - Object msg = request.getBody(); - if (LOGGER.isInfoEnabled()) { - LOGGER.info("onMessage:" + msg); - } - if (msg instanceof BranchCommitRequest) { - handleBranchCommit(request, serverAddress, (BranchCommitRequest)msg); - } else if (msg instanceof BranchRollbackRequest) { - handleBranchRollback(request, serverAddress, (BranchRollbackRequest)msg); - } else if (msg instanceof UndoLogDeleteRequest) { - handleUndoLogDelete((UndoLogDeleteRequest) msg); - } - } - - private void handleBranchRollback(RpcMessage request, String serverAddress, - BranchRollbackRequest branchRollbackRequest) { - BranchRollbackResponse resultMessage = null; - resultMessage = (BranchRollbackResponse)handler.onRequest(branchRollbackRequest, null); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("branch rollback result:" + resultMessage); - } - try { - sender.sendResponse(request, serverAddress, resultMessage); - } catch (Throwable throwable) { - LOGGER.error("send response error: {}", throwable.getMessage(), throwable); - } - } - - private void handleBranchCommit(RpcMessage request, String serverAddress, BranchCommitRequest branchCommitRequest) { - - BranchCommitResponse resultMessage = null; - try { - resultMessage = (BranchCommitResponse)handler.onRequest(branchCommitRequest, null); - getSender().sendResponse(request, serverAddress, resultMessage); - } catch (Exception e) { - LOGGER.error(FrameworkErrorCode.NetOnMessage.getErrCode(), e.getMessage(), e); - if (resultMessage == null) { - resultMessage = new BranchCommitResponse(); - } - resultMessage.setResultCode(ResultCode.Failed); - resultMessage.setMsg(e.getMessage()); - getSender().sendResponse(request, serverAddress, resultMessage); - } - } - - private void handleUndoLogDelete(UndoLogDeleteRequest undoLogDeleteRequest) { - try { - handler.onRequest(undoLogDeleteRequest, null); - } catch (Exception e) { - LOGGER.error("Failed to delete undo log by undoLogDeleteRequest on" + undoLogDeleteRequest.getResourceId()); - } - } -} diff --git a/core/src/main/java/io/seata/core/rpc/netty/RmRpcClient.java b/core/src/main/java/io/seata/core/rpc/netty/RmNettyRemotingClient.java similarity index 63% rename from core/src/main/java/io/seata/core/rpc/netty/RmRpcClient.java rename to core/src/main/java/io/seata/core/rpc/netty/RmNettyRemotingClient.java index 8661c6b84946c94ffcea700d52d9b0bd33259288..e72eb45fe1f75670b28689f7b52fd29af78e9294 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/RmRpcClient.java +++ b/core/src/main/java/io/seata/core/rpc/netty/RmNettyRemotingClient.java @@ -15,15 +15,6 @@ */ package io.seata.core.rpc.netty; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; - import io.netty.channel.Channel; import io.netty.channel.ChannelHandler.Sharable; import io.netty.util.concurrent.EventExecutorGroup; @@ -33,34 +24,58 @@ import io.seata.common.thread.NamedThreadFactory; import io.seata.core.model.Resource; import io.seata.core.model.ResourceManager; import io.seata.core.protocol.AbstractMessage; +import io.seata.core.protocol.MessageType; import io.seata.core.protocol.RegisterRMRequest; import io.seata.core.protocol.RegisterRMResponse; import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole; +import io.seata.core.rpc.processor.client.ClientHeartbeatProcessor; +import io.seata.core.rpc.processor.client.ClientOnResponseProcessor; +import io.seata.core.rpc.processor.client.RmBranchCommitProcessor; +import io.seata.core.rpc.processor.client.RmBranchRollbackProcessor; +import io.seata.core.rpc.processor.client.RmUndoLogProcessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; + import static io.seata.common.Constants.DBKEYS_SPLIT_CHAR; /** - * The type Rm rpc client. + * The Rm netty client. * * @author slievrly * @author zhaojun + * @author zhangchenghui.dev@gmail.com */ @Sharable -public final class RmRpcClient extends AbstractRpcRemotingClient { +public final class RmNettyRemotingClient extends AbstractNettyRemotingClient { - private static final Logger LOGGER = LoggerFactory.getLogger(RmRpcClient.class); + private static final Logger LOGGER = LoggerFactory.getLogger(RmNettyRemotingClient.class); private ResourceManager resourceManager; - private static volatile RmRpcClient instance; + private static volatile RmNettyRemotingClient instance; private final AtomicBoolean initialized = new AtomicBoolean(false); private static final long KEEP_ALIVE_TIME = Integer.MAX_VALUE; private static final int MAX_QUEUE_SIZE = 20000; private String applicationId; private String transactionServiceGroup; - - private RmRpcClient(NettyClientConfig nettyClientConfig, EventExecutorGroup eventExecutorGroup, - ThreadPoolExecutor messageExecutor) { + + @Override + public void init() { + // registry processor + registerProcessor(); + if (initialized.compareAndSet(false, true)) { + super.init(); + } + } + + private RmNettyRemotingClient(NettyClientConfig nettyClientConfig, EventExecutorGroup eventExecutorGroup, + ThreadPoolExecutor messageExecutor) { super(nettyClientConfig, eventExecutorGroup, messageExecutor, TransactionRole.RMROLE); } @@ -71,11 +86,11 @@ public final class RmRpcClient extends AbstractRpcRemotingClient { * @param transactionServiceGroup the transaction service group * @return the instance */ - public static RmRpcClient getInstance(String applicationId, String transactionServiceGroup) { - RmRpcClient rmRpcClient = getInstance(); - rmRpcClient.setApplicationId(applicationId); - rmRpcClient.setTransactionServiceGroup(transactionServiceGroup); - return rmRpcClient; + public static RmNettyRemotingClient getInstance(String applicationId, String transactionServiceGroup) { + RmNettyRemotingClient rmNettyRemotingClient = getInstance(); + rmNettyRemotingClient.setApplicationId(applicationId); + rmNettyRemotingClient.setTransactionServiceGroup(transactionServiceGroup); + return rmNettyRemotingClient; } /** @@ -83,23 +98,23 @@ public final class RmRpcClient extends AbstractRpcRemotingClient { * * @return the instance */ - public static RmRpcClient getInstance() { - if (null == instance) { - synchronized (RmRpcClient.class) { - if (null == instance) { + public static RmNettyRemotingClient getInstance() { + if (instance == null) { + synchronized (RmNettyRemotingClient.class) { + if (instance == null) { NettyClientConfig nettyClientConfig = new NettyClientConfig(); final ThreadPoolExecutor messageExecutor = new ThreadPoolExecutor( nettyClientConfig.getClientWorkerThreads(), nettyClientConfig.getClientWorkerThreads(), KEEP_ALIVE_TIME, TimeUnit.SECONDS, new LinkedBlockingQueue<>(MAX_QUEUE_SIZE), new NamedThreadFactory(nettyClientConfig.getRmDispatchThreadPrefix(), nettyClientConfig.getClientWorkerThreads()), new ThreadPoolExecutor.CallerRunsPolicy()); - instance = new RmRpcClient(nettyClientConfig, null, messageExecutor); + instance = new RmNettyRemotingClient(nettyClientConfig, null, messageExecutor); } } } return instance; } - + /** * Sets application id. * @@ -108,7 +123,7 @@ public final class RmRpcClient extends AbstractRpcRemotingClient { public void setApplicationId(String applicationId) { this.applicationId = applicationId; } - + /** * Sets transaction service group. * @@ -117,7 +132,7 @@ public final class RmRpcClient extends AbstractRpcRemotingClient { public void setTransactionServiceGroup(String transactionServiceGroup) { this.transactionServiceGroup = transactionServiceGroup; } - + /** * Sets resource manager. * @@ -127,50 +142,18 @@ public final class RmRpcClient extends AbstractRpcRemotingClient { this.resourceManager = resourceManager; } - @Override - public void init() { - if (initialized.compareAndSet(false, true)) { - super.init(); - } - } - - @Override - public void destroy() { - super.destroy(); - initialized.getAndSet(false); - instance = null; - } - - @Override - protected Function<String, NettyPoolKey> getPoolKeyFunction() { - return (serverAddress) -> { - String resourceIds = getMergedResourceKeys(); - if (null != resourceIds && LOGGER.isInfoEnabled()) { - LOGGER.info("RM will register :{}", resourceIds); - } - RegisterRMRequest message = new RegisterRMRequest(applicationId, transactionServiceGroup); - message.setResourceIds(resourceIds); - return new NettyPoolKey(NettyPoolKey.TransactionRole.RMROLE, serverAddress, message); - }; - } - - - @Override - protected String getTransactionServiceGroup() { - return transactionServiceGroup; - } - @Override public void onRegisterMsgSuccess(String serverAddress, Channel channel, Object response, AbstractMessage requestMessage) { + RegisterRMRequest registerRMRequest = (RegisterRMRequest)requestMessage; + RegisterRMResponse registerRMResponse = (RegisterRMResponse)response; if (LOGGER.isInfoEnabled()) { - LOGGER.info("register RM success. server version:{},channel:{}", ((RegisterRMResponse)response).getVersion(), channel); + LOGGER.info("register RM success. client version:{}, server version:{},channel:{}", registerRMRequest.getVersion(), registerRMResponse.getVersion(), channel); } getClientChannelManager().registerChannel(serverAddress, channel); String dbKey = getMergedResourceKeys(); - RegisterRMRequest message = (RegisterRMRequest)requestMessage; - if (message.getResourceIds() != null) { - if (!message.getResourceIds().equals(dbKey)) { + if (registerRMRequest.getResourceIds() != null) { + if (!registerRMRequest.getResourceIds().equals(dbKey)) { sendRegisterMessage(serverAddress, channel, dbKey); } } @@ -180,11 +163,11 @@ public final class RmRpcClient extends AbstractRpcRemotingClient { @Override public void onRegisterMsgFail(String serverAddress, Channel channel, Object response, AbstractMessage requestMessage) { - - if (response instanceof RegisterRMResponse && LOGGER.isInfoEnabled()) { - LOGGER.info("register RM failed. server version:{}", ((RegisterRMResponse)response).getVersion()); - } - throw new FrameworkException("register RM failed, channel:" + channel); + RegisterRMRequest registerRMRequest = (RegisterRMRequest)requestMessage; + RegisterRMResponse registerRMResponse = (RegisterRMResponse)response; + String errMsg = String.format( + "register RM failed. client version: %s,server version: %s, errorMsg: %s, " + "channel: %s", registerRMRequest.getVersion(), registerRMResponse.getVersion(), registerRMResponse.getMsg(), channel); + throw new FrameworkException(errMsg); } /** @@ -214,7 +197,7 @@ public final class RmRpcClient extends AbstractRpcRemotingClient { RegisterRMRequest message = new RegisterRMRequest(applicationId, transactionServiceGroup); message.setResourceIds(resourceId); try { - super.sendAsyncRequestWithoutResponse(channel, message); + super.sendAsyncRequest(channel, message); } catch (FrameworkException e) { if (e.getErrcode() == FrameworkErrorCode.ChannelIsNotWritable && serverAddress != null) { getClientChannelManager().releaseChannel(channel, serverAddress); @@ -224,8 +207,6 @@ public final class RmRpcClient extends AbstractRpcRemotingClient { } else { LOGGER.error("register resource failed, channel:{},resourceId:{}", channel, resourceId, e); } - } catch (TimeoutException e) { - LOGGER.error(e.getMessage()); } } @@ -247,4 +228,52 @@ public final class RmRpcClient extends AbstractRpcRemotingClient { } return null; } + + @Override + public void destroy() { + super.destroy(); + initialized.getAndSet(false); + instance = null; + } + + @Override + protected Function<String, NettyPoolKey> getPoolKeyFunction() { + return (serverAddress) -> { + String resourceIds = getMergedResourceKeys(); + if (resourceIds != null && LOGGER.isInfoEnabled()) { + LOGGER.info("RM will register :{}", resourceIds); + } + RegisterRMRequest message = new RegisterRMRequest(applicationId, transactionServiceGroup); + message.setResourceIds(resourceIds); + return new NettyPoolKey(NettyPoolKey.TransactionRole.RMROLE, serverAddress, message); + }; + } + + @Override + protected String getTransactionServiceGroup() { + return transactionServiceGroup; + } + + private void registerProcessor() { + // 1.registry rm client handle branch commit processor + RmBranchCommitProcessor rmBranchCommitProcessor = new RmBranchCommitProcessor(getTransactionMessageHandler(), this); + super.registerProcessor(MessageType.TYPE_BRANCH_COMMIT, rmBranchCommitProcessor, messageExecutor); + // 2.registry rm client handle branch commit processor + RmBranchRollbackProcessor rmBranchRollbackProcessor = new RmBranchRollbackProcessor(getTransactionMessageHandler(), this); + super.registerProcessor(MessageType.TYPE_BRANCH_ROLLBACK, rmBranchRollbackProcessor, messageExecutor); + // 3.registry rm handler undo log processor + RmUndoLogProcessor rmUndoLogProcessor = new RmUndoLogProcessor(getTransactionMessageHandler()); + super.registerProcessor(MessageType.TYPE_RM_DELETE_UNDOLOG, rmUndoLogProcessor, messageExecutor); + // 4.registry TC response processor + ClientOnResponseProcessor onResponseProcessor = + new ClientOnResponseProcessor(mergeMsgMap, super.getFutures(), getTransactionMessageHandler()); + super.registerProcessor(MessageType.TYPE_SEATA_MERGE_RESULT, onResponseProcessor, null); + super.registerProcessor(MessageType.TYPE_BRANCH_REGISTER_RESULT, onResponseProcessor, null); + super.registerProcessor(MessageType.TYPE_BRANCH_STATUS_REPORT_RESULT, onResponseProcessor, null); + super.registerProcessor(MessageType.TYPE_GLOBAL_LOCK_QUERY_RESULT, onResponseProcessor, null); + super.registerProcessor(MessageType.TYPE_REG_RM_RESULT, onResponseProcessor, null); + // 5.registry heartbeat message processor + ClientHeartbeatProcessor clientHeartbeatProcessor = new ClientHeartbeatProcessor(); + super.registerProcessor(MessageType.TYPE_HEARTBEAT_MSG, clientHeartbeatProcessor, null); + } } diff --git a/core/src/main/java/io/seata/core/rpc/netty/RpcEventLoopGroup.java b/core/src/main/java/io/seata/core/rpc/netty/RpcEventLoopGroup.java index f20d8dc08fd971922a3650b5ed14c3a535a9f6d3..0ef16a802700cd82b0b89e46ec58b0c0d38401d0 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/RpcEventLoopGroup.java +++ b/core/src/main/java/io/seata/core/rpc/netty/RpcEventLoopGroup.java @@ -15,15 +15,16 @@ */ package io.seata.core.rpc.netty; -import java.util.concurrent.ThreadFactory; - import io.netty.channel.EventLoopGroup; +import java.util.concurrent.ThreadFactory; + /** * The interface Rpc event loop group. * * @author slievrly */ +@Deprecated public interface RpcEventLoopGroup { // EventLoopGroup WORKER_GROUP = new RpcEventLoopGroup() { diff --git a/core/src/main/java/io/seata/core/rpc/netty/RpcServer.java b/core/src/main/java/io/seata/core/rpc/netty/RpcServer.java deleted file mode 100644 index d94033d01cac4e8a2e070b65319cfb8d5f56f697..0000000000000000000000000000000000000000 --- a/core/src/main/java/io/seata/core/rpc/netty/RpcServer.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache 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 - * - * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.netty; - -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeoutException; - -import io.netty.channel.Channel; -import io.seata.core.protocol.HeartbeatMessage; -import io.seata.core.protocol.RpcMessage; -import io.seata.core.rpc.ChannelManager; -import io.seata.core.rpc.DefaultServerMessageListenerImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The type Abstract rpc server. - * - * @author slievrly - */ -public class RpcServer extends AbstractRpcRemotingServer { - - private static final Logger LOGGER = LoggerFactory.getLogger(RpcServer.class); - - - /** - * Instantiates a new Abstract rpc server. - * - * @param messageExecutor the message executor - */ - public RpcServer(ThreadPoolExecutor messageExecutor) { - super(messageExecutor, new NettyServerConfig()); - } - - /** - * Init. - */ - @Override - public void init() { - DefaultServerMessageListenerImpl defaultServerMessageListenerImpl = - new DefaultServerMessageListenerImpl(getTransactionMessageHandler()); - defaultServerMessageListenerImpl.init(); - defaultServerMessageListenerImpl.setServerMessageSender(this); - super.setServerMessageListener(defaultServerMessageListenerImpl); - super.setChannelHandlers(new ServerHandler()); - super.init(); - } - - /** - * Destroy. - */ - @Override - public void destroy() { - super.destroy(); - if (LOGGER.isInfoEnabled()) { - LOGGER.info("destroyed rpcServer"); - } - } - - - - /** - * Send response. - * rm reg,rpc reg,inner response - * - * @param request the request - * @param channel the channel - * @param msg the msg - */ - @Override - public void sendResponse(RpcMessage request, Channel channel, Object msg) { - Channel clientChannel = channel; - if (!(msg instanceof HeartbeatMessage)) { - clientChannel = ChannelManager.getSameClientChannel(channel); - } - if (clientChannel != null) { - super.defaultSendResponse(request, clientChannel, msg); - } else { - throw new RuntimeException("channel is error. channel:" + clientChannel); - } - } - - /** - * Send request with response object. - * send syn request for rm - * - * @param resourceId the db key - * @param clientId the client ip - * @param message the message - * @param timeout the timeout - * @return the object - * @throws TimeoutException the timeout exception - */ - @Override - public Object sendSyncRequest(String resourceId, String clientId, Object message, - long timeout) throws TimeoutException { - Channel clientChannel = ChannelManager.getChannel(resourceId, clientId); - if (clientChannel == null) { - throw new RuntimeException("rm client is not connected. dbkey:" + resourceId - + ",clientId:" + clientId); - - } - return sendAsyncRequestWithResponse(null, clientChannel, message, timeout); - } - - /** - * Send request with response object. - * send syn request for rm - * - * @param clientChannel the client channel - * @param message the message - * @return the object - * @throws TimeoutException the timeout exception - */ - @Override - public Object sendSyncRequest(Channel clientChannel, Object message) throws TimeoutException { - return sendSyncRequest(clientChannel, message, NettyServerConfig.getRpcRequestTimeout()); - } - - /** - * Send request with response object. - * send syn request for rm - * - * @param clientChannel the client channel - * @param message the message - * @param timeout the timeout - * @return the object - * @throws TimeoutException the timeout exception - */ - @Override - public Object sendSyncRequest(Channel clientChannel, Object message, long timeout) throws TimeoutException { - if (clientChannel == null) { - throw new RuntimeException("rm client is not connected"); - - } - return sendAsyncRequestWithResponse(null, clientChannel, message, timeout); - } - - /** - * Send request with response object. - * - * @param resourceId the db key - * @param clientId the client ip - * @param message the msg - * @return the object - * @throws TimeoutException the timeout exception - */ - @Override - public Object sendSyncRequest(String resourceId, String clientId, Object message) - throws TimeoutException { - return sendSyncRequest(resourceId, clientId, message, NettyServerConfig.getRpcRequestTimeout()); - } - - /** - * Send request with response object. - * - * @param channel the channel - * @param message the msg - * @return the object - * @throws TimeoutException the timeout exception - */ - @Override - public Object sendASyncRequest(Channel channel, Object message) throws TimeoutException { - return sendAsyncRequestWithoutResponse(channel, message); - } -} \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/rpc/netty/TmRpcClient.java b/core/src/main/java/io/seata/core/rpc/netty/TmNettyRemotingClient.java similarity index 57% rename from core/src/main/java/io/seata/core/rpc/netty/TmRpcClient.java rename to core/src/main/java/io/seata/core/rpc/netty/TmNettyRemotingClient.java index 9c68f8d9f4bf0d6e58d82747c8ddbbd8ad724b44..45b811c51b0b8ac82ae4b4a122cc3973dfaaae7c 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/TmRpcClient.java +++ b/core/src/main/java/io/seata/core/rpc/netty/TmNettyRemotingClient.java @@ -15,52 +15,56 @@ */ package io.seata.core.rpc.netty; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; + import io.netty.channel.Channel; import io.netty.channel.ChannelHandler.Sharable; import io.netty.util.concurrent.EventExecutorGroup; import io.seata.common.exception.FrameworkException; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.thread.RejectedPolicies; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; import io.seata.core.protocol.AbstractMessage; +import io.seata.core.protocol.MessageType; import io.seata.core.protocol.RegisterTMRequest; import io.seata.core.protocol.RegisterTMResponse; +import io.seata.core.rpc.processor.client.ClientHeartbeatProcessor; +import io.seata.core.rpc.processor.client.ClientOnResponseProcessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; - /** - * The type Rpc client. + * The rm netty client. * * @author slievrly * @author zhaojun + * @author zhangchenghui.dev@gmail.com */ @Sharable -public final class TmRpcClient extends AbstractRpcRemotingClient { - private static final Logger LOGGER = LoggerFactory.getLogger(TmRpcClient.class); - private static volatile TmRpcClient instance; - private static final Configuration CONFIG = ConfigurationFactory.getInstance(); +public final class TmNettyRemotingClient extends AbstractNettyRemotingClient { + private static final Logger LOGGER = LoggerFactory.getLogger(TmNettyRemotingClient.class); + private static volatile TmNettyRemotingClient instance; private static final long KEEP_ALIVE_TIME = Integer.MAX_VALUE; private static final int MAX_QUEUE_SIZE = 2000; private final AtomicBoolean initialized = new AtomicBoolean(false); private String applicationId; private String transactionServiceGroup; - - /** - * The constant enableDegrade. - */ - public static boolean enableDegrade = false; - private TmRpcClient(NettyClientConfig nettyClientConfig, - EventExecutorGroup eventExecutorGroup, - ThreadPoolExecutor messageExecutor) { + @Override + public void init() { + // registry processor + registerProcessor(); + if (initialized.compareAndSet(false, true)) { + super.init(); + } + } + + private TmNettyRemotingClient(NettyClientConfig nettyClientConfig, + EventExecutorGroup eventExecutorGroup, + ThreadPoolExecutor messageExecutor) { super(nettyClientConfig, eventExecutorGroup, messageExecutor, NettyPoolKey.TransactionRole.TMROLE); } @@ -71,11 +75,11 @@ public final class TmRpcClient extends AbstractRpcRemotingClient { * @param transactionServiceGroup the transaction service group * @return the instance */ - public static TmRpcClient getInstance(String applicationId, String transactionServiceGroup) { - TmRpcClient tmRpcClient = getInstance(); - tmRpcClient.setApplicationId(applicationId); - tmRpcClient.setTransactionServiceGroup(transactionServiceGroup); - return tmRpcClient; + public static TmNettyRemotingClient getInstance(String applicationId, String transactionServiceGroup) { + TmNettyRemotingClient tmNettyRemotingClient = getInstance(); + tmNettyRemotingClient.setApplicationId(applicationId); + tmNettyRemotingClient.setTransactionServiceGroup(transactionServiceGroup); + return tmNettyRemotingClient; } /** @@ -83,10 +87,10 @@ public final class TmRpcClient extends AbstractRpcRemotingClient { * * @return the instance */ - public static TmRpcClient getInstance() { - if (null == instance) { - synchronized (TmRpcClient.class) { - if (null == instance) { + public static TmNettyRemotingClient getInstance() { + if (instance == null) { + synchronized (TmNettyRemotingClient.class) { + if (instance == null) { NettyClientConfig nettyClientConfig = new NettyClientConfig(); final ThreadPoolExecutor messageExecutor = new ThreadPoolExecutor( nettyClientConfig.getClientWorkerThreads(), nettyClientConfig.getClientWorkerThreads(), @@ -95,13 +99,13 @@ public final class TmRpcClient extends AbstractRpcRemotingClient { new NamedThreadFactory(nettyClientConfig.getTmDispatchThreadPrefix(), nettyClientConfig.getClientWorkerThreads()), RejectedPolicies.runsOldestTaskPolicy()); - instance = new TmRpcClient(nettyClientConfig, null, messageExecutor); + instance = new TmNettyRemotingClient(nettyClientConfig, null, messageExecutor); } } } return instance; } - + /** * Sets application id. * @@ -110,7 +114,7 @@ public final class TmRpcClient extends AbstractRpcRemotingClient { public void setApplicationId(String applicationId) { this.applicationId = applicationId; } - + /** * Sets transaction service group. * @@ -119,22 +123,40 @@ public final class TmRpcClient extends AbstractRpcRemotingClient { public void setTransactionServiceGroup(String transactionServiceGroup) { this.transactionServiceGroup = transactionServiceGroup; } - + @Override - public void init() { - if (initialized.compareAndSet(false, true)) { - enableDegrade = CONFIG.getBoolean(ConfigurationKeys.SERVICE_PREFIX + ConfigurationKeys.ENABLE_DEGRADE_POSTFIX); - super.init(); + public String getTransactionServiceGroup() { + return transactionServiceGroup; + } + + @Override + public void onRegisterMsgSuccess(String serverAddress, Channel channel, Object response, + AbstractMessage requestMessage) { + RegisterTMRequest registerTMRequest = (RegisterTMRequest)requestMessage; + RegisterTMResponse registerTMResponse = (RegisterTMResponse)response; + if (LOGGER.isInfoEnabled()) { + LOGGER.info("register TM success. client version:{}, server version:{},channel:{}", registerTMRequest.getVersion(), registerTMResponse.getVersion(), channel); } + getClientChannelManager().registerChannel(serverAddress, channel); } - + + @Override + public void onRegisterMsgFail(String serverAddress, Channel channel, Object response, + AbstractMessage requestMessage) { + RegisterTMRequest registerTMRequest = (RegisterTMRequest)requestMessage; + RegisterTMResponse registerTMResponse = (RegisterTMResponse)response; + String errMsg = String.format( + "register TM failed. client version: %s,server version: %s, errorMsg: %s, " + "channel: %s", registerTMRequest.getVersion(), registerTMResponse.getVersion(), registerTMResponse.getMsg(), channel); + throw new FrameworkException(errMsg); + } + @Override public void destroy() { super.destroy(); initialized.getAndSet(false); instance = null; } - + @Override protected Function<String, NettyPoolKey> getPoolKeyFunction() { return (severAddress) -> { @@ -142,28 +164,20 @@ public final class TmRpcClient extends AbstractRpcRemotingClient { return new NettyPoolKey(NettyPoolKey.TransactionRole.TMROLE, severAddress, message); }; } - - @Override - public String getTransactionServiceGroup() { - return transactionServiceGroup; - } - - @Override - public void onRegisterMsgSuccess(String serverAddress, Channel channel, Object response, - AbstractMessage requestMessage) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("register TM success. server version:{},channel:{}", ((RegisterTMResponse)response).getVersion(), channel); - } - getClientChannelManager().registerChannel(serverAddress, channel); - } - @Override - public void onRegisterMsgFail(String serverAddress, Channel channel, Object response, - AbstractMessage requestMessage) { - if (response instanceof RegisterTMResponse && LOGGER.isInfoEnabled()) { - LOGGER.info("register client failed, server version:" - + ((RegisterTMResponse)response).getVersion()); - } - throw new FrameworkException("register client app failed."); + private void registerProcessor() { + // 1.registry TC response processor + ClientOnResponseProcessor onResponseProcessor = + new ClientOnResponseProcessor(mergeMsgMap, super.getFutures(), getTransactionMessageHandler()); + super.registerProcessor(MessageType.TYPE_SEATA_MERGE_RESULT, onResponseProcessor, null); + super.registerProcessor(MessageType.TYPE_GLOBAL_BEGIN_RESULT, onResponseProcessor, null); + super.registerProcessor(MessageType.TYPE_GLOBAL_COMMIT_RESULT, onResponseProcessor, null); + super.registerProcessor(MessageType.TYPE_GLOBAL_REPORT_RESULT, onResponseProcessor, null); + super.registerProcessor(MessageType.TYPE_GLOBAL_ROLLBACK_RESULT, onResponseProcessor, null); + super.registerProcessor(MessageType.TYPE_GLOBAL_STATUS_RESULT, onResponseProcessor, null); + super.registerProcessor(MessageType.TYPE_REG_CLT_RESULT, onResponseProcessor, null); + // 2.registry heartbeat message processor + ClientHeartbeatProcessor clientHeartbeatProcessor = new ClientHeartbeatProcessor(); + super.registerProcessor(MessageType.TYPE_HEARTBEAT_MSG, clientHeartbeatProcessor, null); } } diff --git a/core/src/main/java/io/seata/core/rpc/processor/Pair.java b/core/src/main/java/io/seata/core/rpc/processor/Pair.java new file mode 100644 index 0000000000000000000000000000000000000000..67396ae033031eb5450135e6d6a7b3be2ae37743 --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/Pair.java @@ -0,0 +1,40 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor; + +/** + * Currently used to associate first and second object. + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public final class Pair<T1, T2> { + private final T1 first; + private final T2 second; + + public Pair(T1 first, T2 second) { + this.first = first; + this.second = second; + } + + public T1 getFirst() { + return first; + } + + public T2 getSecond() { + return second; + } +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/RemotingProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/RemotingProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..77bf9a8b9931a7ee8c7c9c5be174df0c921b700b --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/RemotingProcessor.java @@ -0,0 +1,42 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor; + +import io.netty.channel.ChannelHandlerContext; +import io.seata.core.protocol.RpcMessage; + +/** + * The remoting processor + * <p> + * Used to encapsulate remote interaction logic. + * In order to separate the processing business from netty. + * When netty starts, it will register processors to abstractNettyRemoting#processorTable. + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public interface RemotingProcessor { + + /** + * Process message + * + * @param ctx Channel handler context. + * @param rpcMessage rpc message. + * @throws Exception throws exception process message error. + */ + void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception; + +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/client/ClientHeartbeatProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/client/ClientHeartbeatProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..3af164e36a8dde76516cb1349e0e83e120eab8f2 --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/client/ClientHeartbeatProcessor.java @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor.client; + +import io.netty.channel.ChannelHandlerContext; +import io.seata.core.protocol.HeartbeatMessage; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.rpc.processor.RemotingProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * process TC heartbeat message request(PONG) + * <p> + * process message type: + * {@link HeartbeatMessage} + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class ClientHeartbeatProcessor implements RemotingProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(ClientHeartbeatProcessor.class); + + @Override + public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { + if (rpcMessage.getBody() == HeartbeatMessage.PONG) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("received PONG from {}", ctx.channel().remoteAddress()); + } + } + } +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/client/ClientOnResponseProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/client/ClientOnResponseProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..0a528f88cf334c3d6a6ae451229371702aa8838c --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/client/ClientOnResponseProcessor.java @@ -0,0 +1,120 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor.client; + +import io.netty.channel.ChannelHandlerContext; +import io.seata.core.protocol.AbstractResultMessage; +import io.seata.core.protocol.MergeMessage; +import io.seata.core.protocol.MergeResultMessage; +import io.seata.core.protocol.MergedWarpMessage; +import io.seata.core.protocol.MessageFuture; +import io.seata.core.protocol.RegisterRMResponse; +import io.seata.core.protocol.RegisterTMResponse; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.protocol.transaction.BranchRegisterResponse; +import io.seata.core.protocol.transaction.BranchReportResponse; +import io.seata.core.protocol.transaction.GlobalBeginResponse; +import io.seata.core.protocol.transaction.GlobalCommitResponse; +import io.seata.core.protocol.transaction.GlobalLockQueryResponse; +import io.seata.core.protocol.transaction.GlobalReportResponse; +import io.seata.core.protocol.transaction.GlobalRollbackResponse; +import io.seata.core.rpc.TransactionMessageHandler; +import io.seata.core.rpc.processor.RemotingProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * process TC response message. + * <p> + * process message type: + * RM: + * 1) {@link MergeResultMessage} + * 2) {@link RegisterRMResponse} + * 3) {@link BranchRegisterResponse} + * 4) {@link BranchReportResponse} + * 5) {@link GlobalLockQueryResponse} + * TM: + * 1) {@link MergeResultMessage} + * 2) {@link RegisterTMResponse} + * 3) {@link GlobalBeginResponse} + * 4) {@link GlobalCommitResponse} + * 5) {@link GlobalReportResponse} + * 6) {@link GlobalRollbackResponse} + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class ClientOnResponseProcessor implements RemotingProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(ClientOnResponseProcessor.class); + + /** + * The Merge msg map from io.seata.core.rpc.netty.AbstractNettyRemotingClient#mergeMsgMap. + */ + private Map<Integer, MergeMessage> mergeMsgMap; + + /** + * The Futures from io.seata.core.rpc.netty.AbstractNettyRemoting#futures + */ + private ConcurrentMap<Integer, MessageFuture> futures; + + /** + * To handle the received RPC message on upper level. + */ + private TransactionMessageHandler transactionMessageHandler; + + public ClientOnResponseProcessor(Map<Integer, MergeMessage> mergeMsgMap, + ConcurrentHashMap<Integer, MessageFuture> futures, + TransactionMessageHandler transactionMessageHandler) { + this.mergeMsgMap = mergeMsgMap; + this.futures = futures; + this.transactionMessageHandler = transactionMessageHandler; + } + + @Override + public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { + if (rpcMessage.getBody() instanceof MergeResultMessage) { + MergeResultMessage results = (MergeResultMessage) rpcMessage.getBody(); + MergedWarpMessage mergeMessage = (MergedWarpMessage) mergeMsgMap.remove(rpcMessage.getId()); + for (int i = 0; i < mergeMessage.msgs.size(); i++) { + int msgId = mergeMessage.msgIds.get(i); + MessageFuture future = futures.remove(msgId); + if (future == null) { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("msg: {} is not found in futures.", msgId); + } + } else { + future.setResultMessage(results.getMsgs()[i]); + } + } + } else { + MessageFuture messageFuture = futures.remove(rpcMessage.getId()); + if (messageFuture != null) { + messageFuture.setResultMessage(rpcMessage.getBody()); + } else { + if (rpcMessage.getBody() instanceof AbstractResultMessage) { + if (transactionMessageHandler != null) { + transactionMessageHandler.onResponse((AbstractResultMessage) rpcMessage.getBody(), null); + } + } + } + } + } +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/client/RmBranchCommitProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/client/RmBranchCommitProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..6aed69ace30927891b13b1070f8264f18e903639 --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/client/RmBranchCommitProcessor.java @@ -0,0 +1,73 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor.client; + +import io.netty.channel.ChannelHandlerContext; +import io.seata.common.util.NetUtil; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.protocol.transaction.BranchCommitRequest; +import io.seata.core.protocol.transaction.BranchCommitResponse; +import io.seata.core.rpc.RemotingClient; +import io.seata.core.rpc.TransactionMessageHandler; +import io.seata.core.rpc.processor.RemotingProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * process TC global commit command. + * <p> + * process message type: + * {@link BranchCommitRequest} + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class RmBranchCommitProcessor implements RemotingProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(RmBranchCommitProcessor.class); + + private TransactionMessageHandler handler; + + private RemotingClient remotingClient; + + public RmBranchCommitProcessor(TransactionMessageHandler handler, RemotingClient remotingClient) { + this.handler = handler; + this.remotingClient = remotingClient; + } + + @Override + public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { + String remoteAddress = NetUtil.toStringAddress(ctx.channel().remoteAddress()); + Object msg = rpcMessage.getBody(); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("rm client handle branch commit process:" + msg); + } + handleBranchCommit(rpcMessage, remoteAddress, (BranchCommitRequest) msg); + } + + private void handleBranchCommit(RpcMessage request, String serverAddress, BranchCommitRequest branchCommitRequest) { + BranchCommitResponse resultMessage; + resultMessage = (BranchCommitResponse) handler.onRequest(branchCommitRequest, null); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("branch commit result:" + resultMessage); + } + try { + this.remotingClient.sendAsyncResponse(serverAddress, request, resultMessage); + } catch (Throwable throwable) { + LOGGER.error("branch commit error: {}", throwable.getMessage(), throwable); + } + } +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/client/RmBranchRollbackProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/client/RmBranchRollbackProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..fd3cf6514f3c60056c89e4fd5673c761b621da25 --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/client/RmBranchRollbackProcessor.java @@ -0,0 +1,73 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor.client; + +import io.netty.channel.ChannelHandlerContext; +import io.seata.common.util.NetUtil; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.protocol.transaction.BranchRollbackRequest; +import io.seata.core.protocol.transaction.BranchRollbackResponse; +import io.seata.core.rpc.RemotingClient; +import io.seata.core.rpc.TransactionMessageHandler; +import io.seata.core.rpc.processor.RemotingProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * process TC do global rollback command. + * <p> + * process message type: + * {@link BranchRollbackRequest} + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class RmBranchRollbackProcessor implements RemotingProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(RmBranchRollbackProcessor.class); + + private TransactionMessageHandler handler; + + private RemotingClient remotingClient; + + public RmBranchRollbackProcessor(TransactionMessageHandler handler, RemotingClient remotingClient) { + this.handler = handler; + this.remotingClient = remotingClient; + } + + @Override + public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { + String remoteAddress = NetUtil.toStringAddress(ctx.channel().remoteAddress()); + Object msg = rpcMessage.getBody(); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("rm handle branch rollback process:" + msg); + } + handleBranchRollback(rpcMessage, remoteAddress, (BranchRollbackRequest) msg); + } + + private void handleBranchRollback(RpcMessage request, String serverAddress, BranchRollbackRequest branchRollbackRequest) { + BranchRollbackResponse resultMessage; + resultMessage = (BranchRollbackResponse) handler.onRequest(branchRollbackRequest, null); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("branch rollback result:" + resultMessage); + } + try { + this.remotingClient.sendAsyncResponse(serverAddress, request, resultMessage); + } catch (Throwable throwable) { + LOGGER.error("send response error: {}", throwable.getMessage(), throwable); + } + } +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/client/RmUndoLogProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/client/RmUndoLogProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..7500caf01acd546e6e48f27de13a5881b264523f --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/client/RmUndoLogProcessor.java @@ -0,0 +1,61 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor.client; + +import io.netty.channel.ChannelHandlerContext; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.protocol.transaction.UndoLogDeleteRequest; +import io.seata.core.rpc.TransactionMessageHandler; +import io.seata.core.rpc.processor.RemotingProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * process TC undo log delete command. + * <p> + * process message type: + * {@link UndoLogDeleteRequest} + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class RmUndoLogProcessor implements RemotingProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(RmUndoLogProcessor.class); + + private TransactionMessageHandler handler; + + public RmUndoLogProcessor(TransactionMessageHandler handler) { + this.handler = handler; + } + + @Override + public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { + Object msg = rpcMessage.getBody(); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("rm handle undo log process:" + msg); + } + handleUndoLogDelete((UndoLogDeleteRequest) msg); + } + + private void handleUndoLogDelete(UndoLogDeleteRequest undoLogDeleteRequest) { + try { + handler.onRequest(undoLogDeleteRequest, null); + } catch (Exception e) { + LOGGER.error("Failed to delete undo log by undoLogDeleteRequest on" + undoLogDeleteRequest.getResourceId()); + } + } +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/server/BatchLogHandler.java b/core/src/main/java/io/seata/core/rpc/processor/server/BatchLogHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..616126c539beabd9eb6a4d5e710d6e2030a72efa --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/server/BatchLogHandler.java @@ -0,0 +1,89 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor.server; + +import io.seata.common.thread.NamedThreadFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * handle ServerOnRequestProcessor and ServerOnResponseProcessor log print. + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class BatchLogHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(BatchLogHandler.class); + + private static final BlockingQueue<String> LOG_QUEUE = new LinkedBlockingQueue<>(); + + public static final BatchLogHandler INSTANCE = new BatchLogHandler(); + + private static final int MAX_LOG_SEND_THREAD = 1; + private static final int MAX_LOG_TAKE_SIZE = 1024; + private static final long KEEP_ALIVE_TIME = 0L; + private static final String THREAD_PREFIX = "batchLoggerPrint"; + private static final long BUSY_SLEEP_MILLS = 5L; + + static { + ExecutorService mergeSendExecutorService = new ThreadPoolExecutor(MAX_LOG_SEND_THREAD, MAX_LOG_SEND_THREAD, + KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), + new NamedThreadFactory(THREAD_PREFIX, MAX_LOG_SEND_THREAD, true)); + mergeSendExecutorService.submit(new BatchLogRunnable()); + } + + public BlockingQueue<String> getLogQueue() { + return LOG_QUEUE; + } + + /** + * The type Batch log runnable. + */ + static class BatchLogRunnable implements Runnable { + + @Override + public void run() { + List<String> logList = new ArrayList<>(); + while (true) { + try { + logList.add(LOG_QUEUE.take()); + LOG_QUEUE.drainTo(logList, MAX_LOG_TAKE_SIZE); + if (LOGGER.isInfoEnabled()) { + for (String str : logList) { + LOGGER.info(str); + } + } + logList.clear(); + TimeUnit.MILLISECONDS.sleep(BUSY_SLEEP_MILLS); + } catch (InterruptedException exx) { + LOGGER.error("batch log busy sleep error:{}", exx.getMessage(), exx); + } + + } + } + } + +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/server/RegRmProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/server/RegRmProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..17f0d423d57bee6fbee08ba45481101ba9dd3aa9 --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/server/RegRmProcessor.java @@ -0,0 +1,90 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor.server; + +import io.netty.channel.ChannelHandlerContext; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.util.NetUtil; +import io.seata.core.protocol.RegisterRMRequest; +import io.seata.core.protocol.RegisterRMResponse; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.protocol.Version; +import io.seata.core.rpc.netty.ChannelManager; +import io.seata.core.rpc.RemotingServer; +import io.seata.core.rpc.RegisterCheckAuthHandler; +import io.seata.core.rpc.processor.RemotingProcessor; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * process RM client registry message. + * <p> + * process message type: + * {@link RegisterRMRequest} + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class RegRmProcessor implements RemotingProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(RegRmProcessor.class); + + private RemotingServer remotingServer; + + private RegisterCheckAuthHandler checkAuthHandler; + + public RegRmProcessor(RemotingServer remotingServer) { + this.remotingServer = remotingServer; + this.checkAuthHandler = EnhancedServiceLoader.load(RegisterCheckAuthHandler.class); + } + + @Override + public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { + onRegRmMessage(ctx, rpcMessage); + } + + private void onRegRmMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) { + RegisterRMRequest message = (RegisterRMRequest) rpcMessage.getBody(); + String ipAndPort = NetUtil.toStringAddress(ctx.channel().remoteAddress()); + boolean isSuccess = false; + String errorInfo = StringUtils.EMPTY; + try { + if (null == checkAuthHandler || checkAuthHandler.regResourceManagerCheckAuth(message)) { + ChannelManager.registerRMChannel(message, ctx.channel()); + Version.putChannelVersion(ctx.channel(), message.getVersion()); + isSuccess = true; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("checkAuth for client:{},vgroup:{},applicationId:{} is OK", ipAndPort, message.getTransactionServiceGroup(), message.getApplicationId()); + } + } + } catch (Exception exx) { + isSuccess = false; + errorInfo = exx.getMessage(); + LOGGER.error("RM register fail, error message:{}", errorInfo); + } + RegisterRMResponse response = new RegisterRMResponse(isSuccess); + if (StringUtils.isNotEmpty(errorInfo)) { + response.setMsg(errorInfo); + } + remotingServer.sendAsyncResponse(rpcMessage, ctx.channel(), response); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("RM register success,message:{},channel:{},client version:{}", message, ctx.channel(), + message.getVersion()); + } + } + +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/server/RegTmProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/server/RegTmProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..04a34a76c673c3c23eb7481fee552dcb63325876 --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/server/RegTmProcessor.java @@ -0,0 +1,92 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor.server; + +import io.netty.channel.ChannelHandlerContext; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.util.NetUtil; +import io.seata.core.protocol.RegisterTMRequest; +import io.seata.core.protocol.RegisterTMResponse; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.protocol.Version; +import io.seata.core.rpc.netty.ChannelManager; +import io.seata.core.rpc.RemotingServer; +import io.seata.core.rpc.RegisterCheckAuthHandler; +import io.seata.core.rpc.processor.RemotingProcessor; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * process TM client registry message. + * <p> + * process message type: + * {@link RegisterTMRequest} + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class RegTmProcessor implements RemotingProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(RegTmProcessor.class); + + private RemotingServer remotingServer; + + private RegisterCheckAuthHandler checkAuthHandler; + + public RegTmProcessor(RemotingServer remotingServer) { + this.remotingServer = remotingServer; + this.checkAuthHandler = EnhancedServiceLoader.load(RegisterCheckAuthHandler.class); + } + + @Override + public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { + onRegTmMessage(ctx, rpcMessage); + } + + private void onRegTmMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) { + RegisterTMRequest message = (RegisterTMRequest) rpcMessage.getBody(); + String ipAndPort = NetUtil.toStringAddress(ctx.channel().remoteAddress()); + Version.putChannelVersion(ctx.channel(), message.getVersion()); + boolean isSuccess = false; + String errorInfo = StringUtils.EMPTY; + try { + if (null == checkAuthHandler || checkAuthHandler.regTransactionManagerCheckAuth(message)) { + ChannelManager.registerTMChannel(message, ctx.channel()); + Version.putChannelVersion(ctx.channel(), message.getVersion()); + isSuccess = true; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("checkAuth for client:{},vgroup:{},applicationId:{}", + ipAndPort, message.getTransactionServiceGroup(), message.getApplicationId()); + } + } + } catch (Exception exx) { + isSuccess = false; + errorInfo = exx.getMessage(); + LOGGER.error("TM register fail, error message:{}", errorInfo); + } + RegisterTMResponse response = new RegisterTMResponse(isSuccess); + if (StringUtils.isNotEmpty(errorInfo)) { + response.setMsg(errorInfo); + } + remotingServer.sendAsyncResponse(rpcMessage, ctx.channel(), response); + if (LOGGER.isInfoEnabled()) { + LOGGER.info("TM register success,message:{},channel:{},client version:{}", message, ctx.channel(), + message.getVersion()); + } + } + +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/server/ServerHeartbeatProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/server/ServerHeartbeatProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..c4ac853ee318475ae0e9a8dfd97a394f2ed8db8b --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/server/ServerHeartbeatProcessor.java @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor.server; + +import io.netty.channel.ChannelHandlerContext; +import io.seata.core.protocol.HeartbeatMessage; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.rpc.RemotingServer; +import io.seata.core.rpc.processor.RemotingProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * process client heartbeat message request(PING). + * <p> + * process message type: + * {@link HeartbeatMessage} + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class ServerHeartbeatProcessor implements RemotingProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServerHeartbeatProcessor.class); + + private RemotingServer remotingServer; + + public ServerHeartbeatProcessor(RemotingServer remotingServer) { + this.remotingServer = remotingServer; + } + + @Override + public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { + try { + remotingServer.sendAsyncResponse(rpcMessage, ctx.channel(), HeartbeatMessage.PONG); + } catch (Throwable throwable) { + LOGGER.error("send response error: {}", throwable.getMessage(), throwable); + } + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("received PING from {}", ctx.channel().remoteAddress()); + } + } + +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnRequestProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnRequestProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..63405752f0144fddf1c7af6679e19ef948e0266d --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnRequestProcessor.java @@ -0,0 +1,129 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor.server; + +import io.netty.channel.ChannelHandlerContext; +import io.seata.common.util.NetUtil; +import io.seata.core.protocol.AbstractMessage; +import io.seata.core.protocol.AbstractResultMessage; +import io.seata.core.protocol.MergeResultMessage; +import io.seata.core.protocol.MergedWarpMessage; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.protocol.transaction.BranchRegisterRequest; +import io.seata.core.protocol.transaction.BranchReportRequest; +import io.seata.core.protocol.transaction.GlobalBeginRequest; +import io.seata.core.protocol.transaction.GlobalCommitRequest; +import io.seata.core.protocol.transaction.GlobalLockQueryRequest; +import io.seata.core.protocol.transaction.GlobalReportRequest; +import io.seata.core.protocol.transaction.GlobalRollbackRequest; +import io.seata.core.protocol.transaction.GlobalStatusRequest; +import io.seata.core.rpc.netty.ChannelManager; +import io.seata.core.rpc.RemotingServer; +import io.seata.core.rpc.RpcContext; +import io.seata.core.rpc.TransactionMessageHandler; +import io.seata.core.rpc.processor.RemotingProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * process RM/TM client request message. + * <p> + * message type: + * RM: + * 1) {@link MergedWarpMessage} + * 2) {@link BranchRegisterRequest} + * 3) {@link BranchReportRequest} + * 4) {@link GlobalLockQueryRequest} + * TM: + * 1) {@link MergedWarpMessage} + * 2) {@link GlobalBeginRequest} + * 3) {@link GlobalCommitRequest} + * 4) {@link GlobalReportRequest} + * 5) {@link GlobalRollbackRequest} + * 6) {@link GlobalStatusRequest} + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class ServerOnRequestProcessor implements RemotingProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServerOnRequestProcessor.class); + + private RemotingServer remotingServer; + + private TransactionMessageHandler transactionMessageHandler; + + public ServerOnRequestProcessor(RemotingServer remotingServer, TransactionMessageHandler transactionMessageHandler) { + this.remotingServer = remotingServer; + this.transactionMessageHandler = transactionMessageHandler; + } + + @Override + public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { + if (ChannelManager.isRegistered(ctx.channel())) { + onRequestMessage(ctx, rpcMessage); + } else { + try { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("closeChannelHandlerContext channel:" + ctx.channel()); + } + ctx.disconnect(); + ctx.close(); + } catch (Exception exx) { + LOGGER.error(exx.getMessage()); + } + if (LOGGER.isInfoEnabled()) { + LOGGER.info(String.format("close a unhandled connection! [%s]", ctx.channel().toString())); + } + } + } + + private void onRequestMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) { + Object message = rpcMessage.getBody(); + RpcContext rpcContext = ChannelManager.getContextFromIdentified(ctx.channel()); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("server received:{},clientIp:{},vgroup:{}", message, + NetUtil.toIpAddress(ctx.channel().remoteAddress()), rpcContext.getTransactionServiceGroup()); + } else { + try { + BatchLogHandler.INSTANCE.getLogQueue() + .put(message + ",clientIp:" + NetUtil.toIpAddress(ctx.channel().remoteAddress()) + ",vgroup:" + + rpcContext.getTransactionServiceGroup()); + } catch (InterruptedException e) { + LOGGER.error("put message to logQueue error: {}", e.getMessage(), e); + } + } + if (!(message instanceof AbstractMessage)) { + return; + } + if (message instanceof MergedWarpMessage) { + AbstractResultMessage[] results = new AbstractResultMessage[((MergedWarpMessage) message).msgs.size()]; + for (int i = 0; i < results.length; i++) { + final AbstractMessage subMessage = ((MergedWarpMessage) message).msgs.get(i); + results[i] = transactionMessageHandler.onRequest(subMessage, rpcContext); + } + MergeResultMessage resultMessage = new MergeResultMessage(); + resultMessage.setMsgs(results); + remotingServer.sendAsyncResponse(rpcMessage, ctx.channel(), resultMessage); + } else { + // the single send request message + final AbstractMessage msg = (AbstractMessage) message; + AbstractResultMessage result = transactionMessageHandler.onRequest(msg, rpcContext); + remotingServer.sendAsyncResponse(rpcMessage, ctx.channel(), result); + } + } + +} diff --git a/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnResponseProcessor.java b/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnResponseProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..705b83a73a0dd24966ef220c70540ab63373cf89 --- /dev/null +++ b/core/src/main/java/io/seata/core/rpc/processor/server/ServerOnResponseProcessor.java @@ -0,0 +1,110 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.core.rpc.processor.server; + +import io.netty.channel.ChannelHandlerContext; +import io.seata.common.util.NetUtil; +import io.seata.core.protocol.AbstractResultMessage; +import io.seata.core.protocol.MessageFuture; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.protocol.transaction.BranchCommitResponse; +import io.seata.core.protocol.transaction.BranchRollbackResponse; +import io.seata.core.rpc.RpcContext; +import io.seata.core.rpc.TransactionMessageHandler; +import io.seata.core.rpc.netty.ChannelManager; +import io.seata.core.rpc.processor.RemotingProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * handle RM/TM response message. + * <p> + * process message type: + * RM: + * 1) {@link BranchCommitResponse} + * 2) {@link BranchRollbackResponse} + * + * @author zhangchenghui.dev@gmail.com + * @since 1.3.0 + */ +public class ServerOnResponseProcessor implements RemotingProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServerOnRequestProcessor.class); + + /** + * To handle the received RPC message on upper level. + */ + private TransactionMessageHandler transactionMessageHandler; + + /** + * The Futures from io.seata.core.rpc.netty.AbstractNettyRemoting#futures + */ + private ConcurrentMap<Integer, MessageFuture> futures; + + public ServerOnResponseProcessor(TransactionMessageHandler transactionMessageHandler, + ConcurrentHashMap<Integer, MessageFuture> futures) { + this.transactionMessageHandler = transactionMessageHandler; + this.futures = futures; + } + + @Override + public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception { + MessageFuture messageFuture = futures.remove(rpcMessage.getId()); + if (messageFuture != null) { + messageFuture.setResultMessage(rpcMessage.getBody()); + } else { + if (ChannelManager.isRegistered(ctx.channel())) { + onResponseMessage(ctx, rpcMessage); + } else { + try { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("closeChannelHandlerContext channel:" + ctx.channel()); + } + ctx.disconnect(); + ctx.close(); + } catch (Exception exx) { + LOGGER.error(exx.getMessage()); + } + if (LOGGER.isInfoEnabled()) { + LOGGER.info(String.format("close a unhandled connection! [%s]", ctx.channel().toString())); + } + } + } + } + + private void onResponseMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("server received:{},clientIp:{},vgroup:{}", rpcMessage.getBody(), + NetUtil.toIpAddress(ctx.channel().remoteAddress()), + ChannelManager.getContextFromIdentified(ctx.channel()).getTransactionServiceGroup()); + } else { + try { + BatchLogHandler.INSTANCE.getLogQueue() + .put(rpcMessage.getBody() + ",clientIp:" + NetUtil.toIpAddress(ctx.channel().remoteAddress()) + ",vgroup:" + + ChannelManager.getContextFromIdentified(ctx.channel()).getTransactionServiceGroup()); + } catch (InterruptedException e) { + LOGGER.error("put message to logQueue error: {}", e.getMessage(), e); + } + } + if (rpcMessage.getBody() instanceof AbstractResultMessage) { + RpcContext rpcContext = ChannelManager.getContextFromIdentified(ctx.channel()); + transactionMessageHandler.onResponse((AbstractResultMessage) rpcMessage.getBody(), rpcContext); + } + } +} diff --git a/core/src/main/java/io/seata/core/store/BranchTransactionDO.java b/core/src/main/java/io/seata/core/store/BranchTransactionDO.java index 19990bf7bda9b6fca661ce3a4a54540d9bf04913..d38717e9967459ff2fc396207de6081923df5ebb 100644 --- a/core/src/main/java/io/seata/core/store/BranchTransactionDO.java +++ b/core/src/main/java/io/seata/core/store/BranchTransactionDO.java @@ -29,9 +29,9 @@ public class BranchTransactionDO { private String xid; - private long transactionId; + private Long transactionId; - private long branchId; + private Long branchId; private String resourceGroupId; @@ -39,7 +39,7 @@ public class BranchTransactionDO { private String branchType; - private int status = BranchStatus.Unknown.getCode(); + private Integer status = BranchStatus.Unknown.getCode(); private String clientId; diff --git a/core/src/main/java/io/seata/core/store/GlobalTransactionDO.java b/core/src/main/java/io/seata/core/store/GlobalTransactionDO.java index 2db38cb6e8f1286494094d5e1a39535e906100e3..d1103d93149a2cfcd8636897bd6311ec25ea046e 100644 --- a/core/src/main/java/io/seata/core/store/GlobalTransactionDO.java +++ b/core/src/main/java/io/seata/core/store/GlobalTransactionDO.java @@ -28,9 +28,9 @@ public class GlobalTransactionDO { private String xid; - private long transactionId; + private Long transactionId; - private int status; + private Integer status; private String applicationId; @@ -38,9 +38,9 @@ public class GlobalTransactionDO { private String transactionName; - private int timeout; + private Integer timeout; - private long beginTime; + private Long beginTime; private String applicationData; diff --git a/core/src/main/java/io/seata/core/store/StoreMode.java b/core/src/main/java/io/seata/core/store/StoreMode.java index 6fe559676569532acf2f06cc86195c55e57920bd..6cdef200aac24852e1cd8103af716e759715cbe4 100644 --- a/core/src/main/java/io/seata/core/store/StoreMode.java +++ b/core/src/main/java/io/seata/core/store/StoreMode.java @@ -30,7 +30,12 @@ public enum StoreMode { /** * database store */ - DB("db"); + DB("db"), + + /** + * redis store + */ + REDIS("redis"); private String name; diff --git a/core/src/main/java/io/seata/core/store/db/AbstractDataSourceGenerator.java b/core/src/main/java/io/seata/core/store/db/AbstractDataSourceProvider.java similarity index 91% rename from core/src/main/java/io/seata/core/store/db/AbstractDataSourceGenerator.java rename to core/src/main/java/io/seata/core/store/db/AbstractDataSourceProvider.java index 0cedd49fe2a10917bbde4db8e9faa6f6e69e9b76..dce50799180d91ace7df224117e000ee0d616b55 100644 --- a/core/src/main/java/io/seata/core/store/db/AbstractDataSourceGenerator.java +++ b/core/src/main/java/io/seata/core/store/db/AbstractDataSourceProvider.java @@ -15,6 +15,15 @@ */ package io.seata.core.store.db; +import io.seata.common.exception.StoreException; +import io.seata.common.executor.Initialize; +import io.seata.common.util.StringUtils; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.constants.DBType; + +import javax.sql.DataSource; import java.io.File; import java.net.MalformedURLException; import java.net.URL; @@ -24,19 +33,21 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Stream; -import io.seata.common.exception.StoreException; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.constants.DBType; - /** - * The type Abstract data source generator. - * + * The abstract datasource provider + * * @author zhangsen + * @author will */ -public abstract class AbstractDataSourceGenerator implements DataSourceGenerator { +public abstract class AbstractDataSourceProvider implements DataSourceProvider, Initialize { + + private DataSource dataSource; + + /** + * The constant CONFIG. + */ + protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); + private final static String MYSQL_DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver"; private final static String MYSQL8_DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver"; @@ -45,20 +56,31 @@ public abstract class AbstractDataSourceGenerator implements DataSourceGenerator private final static Map<String, ClassLoader> MYSQL_DRIVER_LOADERS; + private static final int DEFAULT_DB_MAX_CONN = 20; + + private static final int DEFAULT_DB_MIN_CONN = 1; + + private static final long DEFAULT_DB_MAX_WAIT = 5000; + static { MYSQL_DRIVER_LOADERS = createMysqlDriverClassLoaders(); } - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - private static final int DEFAULT_DB_MAX_CONN = 10; + @Override + public void init() { + this.dataSource = generate(); + } - private static final int DEFAULT_DB_MIN_CONN = 1; + @Override + public DataSource provide() { + return this.dataSource; + } - private static final long DEFAULT_DB_MAX_WAIT = 5000; + /** + * generate the datasource + * @return datasource + */ + public abstract DataSource generate(); /** * Get db type db type. diff --git a/core/src/main/java/io/seata/core/store/db/DataSourceGenerator.java b/core/src/main/java/io/seata/core/store/db/DataSourceProvider.java similarity index 76% rename from core/src/main/java/io/seata/core/store/db/DataSourceGenerator.java rename to core/src/main/java/io/seata/core/store/db/DataSourceProvider.java index cad6d3ea55a8b45c95fcd5a509d37127b070320c..2d2d439ceca273cba4e5c8062695d8e59f88f80d 100644 --- a/core/src/main/java/io/seata/core/store/db/DataSourceGenerator.java +++ b/core/src/main/java/io/seata/core/store/db/DataSourceProvider.java @@ -18,17 +18,14 @@ package io.seata.core.store.db; import javax.sql.DataSource; /** - * The interface Data source generator. - * - * @author zhangsen + * The datasource provider + * @author will */ -public interface DataSourceGenerator { +public interface DataSourceProvider { /** - * create DataSource from config - * - * @return data source + * provide the datasource + * @return datasource */ - DataSource generateDataSource(); - + DataSource provide(); } diff --git a/core/src/main/java/io/seata/core/store/db/sql/log/AbstractLogStoreSqls.java b/core/src/main/java/io/seata/core/store/db/sql/log/AbstractLogStoreSqls.java index e823024368e1cd9ec1df50889254e33c96ce20a9..fb0ceaf0d8f99ad02a48303658fea5989e2b9646 100644 --- a/core/src/main/java/io/seata/core/store/db/sql/log/AbstractLogStoreSqls.java +++ b/core/src/main/java/io/seata/core/store/db/sql/log/AbstractLogStoreSqls.java @@ -36,6 +36,7 @@ public abstract class AbstractLogStoreSqls implements LogStoreSqls { /** * The constant PRAMETER_PLACEHOLD. + * format: ?, ?, ? */ public static final String PRAMETER_PLACEHOLD = " #PRAMETER_PLACEHOLD# "; @@ -48,8 +49,8 @@ public abstract class AbstractLogStoreSqls implements LogStoreSqls { + ServerTableColumnsName.GLOBAL_TABLE_STATUS + ", " + ServerTableColumnsName.GLOBAL_TABLE_APPLICATION_ID + ", " + ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_SERVICE_GROUP + ", " + ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_NAME + ", " + ServerTableColumnsName.GLOBAL_TABLE_TIMEOUT + ", " + ServerTableColumnsName.GLOBAL_TABLE_BEGIN_TIME + ", " - + ServerTableColumnsName.GLOBAL_TABLE_APPLICATION_DATA + ", " + ServerTableColumnsName.GLOBAL_TABLE_GMT_CREATE + ", " - + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED; + + ServerTableColumnsName.GLOBAL_TABLE_APPLICATION_DATA + ", " + + ServerTableColumnsName.GLOBAL_TABLE_GMT_CREATE + ", " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED; /** * The constant ALL_BRANCH_COLUMNS. @@ -66,26 +67,29 @@ public abstract class AbstractLogStoreSqls implements LogStoreSqls { /** * The constant DELETE_GLOBAL_TRANSACTION. */ - public static final String DELETE_GLOBAL_TRANSACTION = "delete from " + GLOBAL_TABLE_PLACEHOLD + " where " + ServerTableColumnsName.GLOBAL_TABLE_XID + " = ?"; + public static final String DELETE_GLOBAL_TRANSACTION = "delete from " + GLOBAL_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.GLOBAL_TABLE_XID + " = ?"; /** * The constant QUERY_GLOBAL_TRANSACTION. */ - public static final String QUERY_GLOBAL_TRANSACTION = "select " + ALL_GLOBAL_COLUMNS + " from " - + GLOBAL_TABLE_PLACEHOLD + " where " + ServerTableColumnsName.GLOBAL_TABLE_XID + " = ?"; + public static final String QUERY_GLOBAL_TRANSACTION = "select " + ALL_GLOBAL_COLUMNS + + " from " + GLOBAL_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.GLOBAL_TABLE_XID + " = ?"; /** * The constant QUERY_GLOBAL_TRANSACTION_ID. */ - public static final String QUERY_GLOBAL_TRANSACTION_BY_ID = "select " + ALL_GLOBAL_COLUMNS + " from " - + GLOBAL_TABLE_PLACEHOLD + " where " + ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_ID + " = ?"; + public static final String QUERY_GLOBAL_TRANSACTION_BY_ID = "select " + ALL_GLOBAL_COLUMNS + + " from " + GLOBAL_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_ID + " = ?"; /** * The constant DELETE_BRANCH_TRANSACTION_BY_BRANCH_ID. */ public static final String DELETE_BRANCH_TRANSACTION_BY_BRANCH_ID = "delete from " + BRANCH_TABLE_PLACEHOLD - + " where " + ServerTableColumnsName.BRANCH_TABLE_XID + " = ? and " + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID - + " = ?"; + + " where " + ServerTableColumnsName.BRANCH_TABLE_XID + " = ?" + + " and " + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID + " = ?"; /** * The constant DELETE_BRANCH_TRANSACTION_BY_XID. @@ -97,30 +101,34 @@ public abstract class AbstractLogStoreSqls implements LogStoreSqls { /** * The constant QUERY_BRANCH_TRANSACTION. */ - public static final String QUERY_BRANCH_TRANSACTION = "select " + ALL_BRANCH_COLUMNS + " from " - + BRANCH_TABLE_PLACEHOLD + " where " + ServerTableColumnsName.BRANCH_TABLE_XID + " = ? order by " - + ServerTableColumnsName.BRANCH_TABLE_GMT_CREATE + " asc"; + public static final String QUERY_BRANCH_TRANSACTION = "select " + ALL_BRANCH_COLUMNS + + " from " + BRANCH_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.BRANCH_TABLE_XID + " = ?" + + " order by " + ServerTableColumnsName.BRANCH_TABLE_GMT_CREATE + " asc"; /** * The constant QUERY_BRANCH_TRANSACTION_XIDS. */ - public static final String QUERY_BRANCH_TRANSACTION_XIDS = "select " + ALL_BRANCH_COLUMNS + " from " - + BRANCH_TABLE_PLACEHOLD + " where " + ServerTableColumnsName.BRANCH_TABLE_XID + " in (" + PRAMETER_PLACEHOLD + ") order by " - + ServerTableColumnsName.BRANCH_TABLE_GMT_CREATE + " asc"; + public static final String QUERY_BRANCH_TRANSACTION_XIDS = "select " + ALL_BRANCH_COLUMNS + + " from " + BRANCH_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.BRANCH_TABLE_XID + " in (" + PRAMETER_PLACEHOLD + ")" + + " order by " + ServerTableColumnsName.BRANCH_TABLE_GMT_CREATE + " asc"; /** * The constant CHECK_MAX_TRANS_ID. */ - public static final String QUERY_MAX_TRANS_ID = "select max(" + ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_ID - + ") from " + GLOBAL_TABLE_PLACEHOLD + " where " + ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_ID - + " < ? and " + ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_ID + " > ?"; + public static final String QUERY_MAX_TRANS_ID = "select max(" + ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_ID + ")" + + " from " + GLOBAL_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_ID + " < ?" + + " and " + ServerTableColumnsName.GLOBAL_TABLE_TRANSACTION_ID + " > ?"; /** * The constant CHECK_MAX_BTANCH_ID. */ - public static final String QUERY_MAX_BTANCH_ID = "select max(" + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID - + ") from " + BRANCH_TABLE_PLACEHOLD + " where " + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID + " < ? and " - + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID + " > ?"; + public static final String QUERY_MAX_BTANCH_ID = "select max(" + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID + ")" + + " from " + BRANCH_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID + " < ?" + + " and " + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID + " > ?"; @Override public abstract String getInsertGlobalTransactionSQL(String globalTable); @@ -149,13 +157,13 @@ public abstract class AbstractLogStoreSqls implements LogStoreSqls { @Override public abstract String getQueryGlobalTransactionForRecoverySQL(String globalTable); + @Override public abstract String getInsertBranchTransactionSQL(String branchTable); @Override public abstract String getUpdateBranchTransactionStatusSQL(String branchTable); - @Override public String getDeleteBranchTransactionByBranchIdSQL(String branchTable) { return DELETE_BRANCH_TRANSACTION_BY_BRANCH_ID.replace(BRANCH_TABLE_PLACEHOLD, branchTable); @@ -177,10 +185,13 @@ public abstract class AbstractLogStoreSqls implements LogStoreSqls { .replace(PRAMETER_PLACEHOLD, paramsPlaceHolder); } + + @Override public String getQueryGlobalMax(String globalTable) { return QUERY_MAX_TRANS_ID.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); } + @Override public String getQueryBranchMax(String branchTable) { return QUERY_MAX_BTANCH_ID.replace(BRANCH_TABLE_PLACEHOLD, branchTable); } diff --git a/core/src/main/java/io/seata/core/store/db/sql/log/MysqlLogStoreSqls.java b/core/src/main/java/io/seata/core/store/db/sql/log/MysqlLogStoreSqls.java index 594d15e24ee204825b921f9853679852c03b2e51..23b88905304b1e401db0a3ddc5facd210d5a372c 100644 --- a/core/src/main/java/io/seata/core/store/db/sql/log/MysqlLogStoreSqls.java +++ b/core/src/main/java/io/seata/core/store/db/sql/log/MysqlLogStoreSqls.java @@ -28,44 +28,51 @@ public class MysqlLogStoreSqls extends AbstractLogStoreSqls { /** * The constant INSERT_GLOBAL_TRANSACTION_MYSQL. */ - public static final String INSERT_GLOBAL_TRANSACTION_MYSQL = "insert into " + GLOBAL_TABLE_PLACEHOLD + "(" - + ALL_GLOBAL_COLUMNS + ")" + - "values(?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now()) "; + public static final String INSERT_GLOBAL_TRANSACTION_MYSQL = "insert into " + GLOBAL_TABLE_PLACEHOLD + + "(" + ALL_GLOBAL_COLUMNS + ")" + + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now())"; /** * The constant UPDATE_GLOBAL_TRANSACTION_STATUS_MYSQL. */ public static final String UPDATE_GLOBAL_TRANSACTION_STATUS_MYSQL = "update " + GLOBAL_TABLE_PLACEHOLD - + " set " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " = ?, " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + " = now() where " + ServerTableColumnsName.GLOBAL_TABLE_XID + " = ?"; + + " set " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " = ?," + + " " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + " = now()" + + " where " + ServerTableColumnsName.GLOBAL_TABLE_XID + " = ?"; /** * The constant QUERY_GLOBAL_TRANSACTION_BY_STATUS. */ - public static final String QUERY_GLOBAL_TRANSACTION_BY_STATUS_MYSQL = - "select " + ALL_GLOBAL_COLUMNS + " from " + GLOBAL_TABLE_PLACEHOLD - + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (" + PRAMETER_PLACEHOLD + ")" - + " order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + " limit ?"; + public static final String QUERY_GLOBAL_TRANSACTION_BY_STATUS_MYSQL = "select " + ALL_GLOBAL_COLUMNS + + " from " + GLOBAL_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (" + PRAMETER_PLACEHOLD + ")" + + " order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + + " limit ?"; /** * The constant QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_MYSQL. */ - public static final String QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_MYSQL = "select " + ALL_GLOBAL_COLUMNS + " from " - + GLOBAL_TABLE_PLACEHOLD + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (" + - "0, 2, 3, 4, 5, 6, 7, 8, 10 ,12, 14) order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + " limit ?"; + public static final String QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_MYSQL = "select " + ALL_GLOBAL_COLUMNS + + " from " + GLOBAL_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (0, 2, 3, 4, 5, 6, 7, 8, 10 ,12, 14)" + + " order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + + " limit ?"; /** * The constant INSERT_BRANCH_TRANSACTION_MYSQL. */ - public static final String INSERT_BRANCH_TRANSACTION_MYSQL = "insert into " + BRANCH_TABLE_PLACEHOLD + "(" - + ALL_BRANCH_COLUMNS + ")" + - "values (?, ?, ?, ?, ?, ?, ?, ?, ?, now(6), now(6))"; + public static final String INSERT_BRANCH_TRANSACTION_MYSQL = "insert into " + BRANCH_TABLE_PLACEHOLD + + "(" + ALL_BRANCH_COLUMNS + ")" + + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, now(6), now(6))"; /** * The constant UPDATE_BRANCH_TRANSACTION_STATUS_MYSQL. */ public static final String UPDATE_BRANCH_TRANSACTION_STATUS_MYSQL = "update " + BRANCH_TABLE_PLACEHOLD - + " set " + ServerTableColumnsName.BRANCH_TABLE_STATUS + " = ?, " + ServerTableColumnsName.BRANCH_TABLE_GMT_MODIFIED + " = now(6) where " - + ServerTableColumnsName.BRANCH_TABLE_XID + " = ? and " + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID + " = ?"; + + " set " + ServerTableColumnsName.BRANCH_TABLE_STATUS + " = ?," + + " " + ServerTableColumnsName.BRANCH_TABLE_GMT_MODIFIED + " = now(6)" + + " where " + ServerTableColumnsName.BRANCH_TABLE_XID + " = ?" + + " and " + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID + " = ?"; @Override public String getInsertGlobalTransactionSQL(String globalTable) { @@ -79,8 +86,8 @@ public class MysqlLogStoreSqls extends AbstractLogStoreSqls { @Override public String getQueryGlobalTransactionSQLByStatus(String globalTable, String paramsPlaceHolder) { - return QUERY_GLOBAL_TRANSACTION_BY_STATUS_MYSQL.replace(GLOBAL_TABLE_PLACEHOLD, globalTable).replace( - PRAMETER_PLACEHOLD, paramsPlaceHolder); + return QUERY_GLOBAL_TRANSACTION_BY_STATUS_MYSQL.replace(GLOBAL_TABLE_PLACEHOLD, globalTable) + .replace(PRAMETER_PLACEHOLD, paramsPlaceHolder); } @Override diff --git a/core/src/main/java/io/seata/core/store/db/sql/log/OracleLogStoreSqls.java b/core/src/main/java/io/seata/core/store/db/sql/log/OracleLogStoreSqls.java index e5e19c440830ca4efc58ac7f4c2fe21c50d21352..c401a69fa0d4009b1d00c0502e08c279b8ebe4f2 100644 --- a/core/src/main/java/io/seata/core/store/db/sql/log/OracleLogStoreSqls.java +++ b/core/src/main/java/io/seata/core/store/db/sql/log/OracleLogStoreSqls.java @@ -28,47 +28,55 @@ public class OracleLogStoreSqls extends AbstractLogStoreSqls { /** * The constant INSERT_GLOBAL_TRANSACTION_ORACLE. */ - public static final String INSERT_GLOBAL_TRANSACTION_ORACLE = "insert into " + GLOBAL_TABLE_PLACEHOLD + "(" - + ALL_GLOBAL_COLUMNS + ")" + - "values(?, ?, ?, ?, ?, ?, ?, ?, ?, sysdate, sysdate) "; + public static final String INSERT_GLOBAL_TRANSACTION_ORACLE = "insert into " + GLOBAL_TABLE_PLACEHOLD + + "(" + ALL_GLOBAL_COLUMNS + ")" + + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, sysdate, sysdate)"; /** * The constant UPDATE_GLOBAL_TRANSACTION_STATUS_ORACLE. */ public static final String UPDATE_GLOBAL_TRANSACTION_STATUS_ORACLE = "update " + GLOBAL_TABLE_PLACEHOLD - + " set " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " = ?, " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + " = sysdate where " + ServerTableColumnsName.GLOBAL_TABLE_XID + " = ?"; + + " set " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " = ?," + + " " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + " = sysdate" + + " where " + ServerTableColumnsName.GLOBAL_TABLE_XID + " = ?"; /** * The constant QUERY_GLOBAL_TRANSACTION_BY_STATUS_ORACLE. */ - public static final String QUERY_GLOBAL_TRANSACTION_BY_STATUS_ORACLE = - "select t.* from (" - + " select " + ALL_GLOBAL_COLUMNS + " from " + GLOBAL_TABLE_PLACEHOLD - + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (" + PRAMETER_PLACEHOLD + ")" - + " order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + ") t" - + " where ROWNUM <= ?"; + public static final String QUERY_GLOBAL_TRANSACTION_BY_STATUS_ORACLE = "select A.* from (" + + " select " + ALL_GLOBAL_COLUMNS + + " from " + GLOBAL_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (" + PRAMETER_PLACEHOLD + ")" + + " order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + + " ) A" + + " where ROWNUM <= ?"; /** * The constant QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_ORACLE. */ - public static final String QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_ORACLE = "select A.* from ( select " - + ALL_GLOBAL_COLUMNS + " from " + GLOBAL_TABLE_PLACEHOLD + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (" + - "0, 2, 3, 4, 5, 6, 7, 8, 10 ,12, 14) order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + " ) A where ROWNUM <= ?"; + public static final String QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_ORACLE = "select A.* from (" + + " select " + ALL_GLOBAL_COLUMNS + + " from " + GLOBAL_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (0, 2, 3, 4, 5, 6, 7, 8, 10 ,12, 14)" + + " order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + + " ) A" + + " where ROWNUM <= ?"; /** * The constant INSERT_BRANCH_TRANSACTION_ORACLE. */ - public static final String INSERT_BRANCH_TRANSACTION_ORACLE = "insert into " + BRANCH_TABLE_PLACEHOLD + "(" - + ALL_BRANCH_COLUMNS + ")" + - "values (?, ?, ?, ?, ?, ?, ?, ?, ?, systimestamp, systimestamp)"; + public static final String INSERT_BRANCH_TRANSACTION_ORACLE = "insert into " + BRANCH_TABLE_PLACEHOLD + + "(" + ALL_BRANCH_COLUMNS + ")" + + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, systimestamp, systimestamp)"; /** * The constant UPDATE_BRANCH_TRANSACTION_STATUS_ORACLE. */ public static final String UPDATE_BRANCH_TRANSACTION_STATUS_ORACLE = "update " + BRANCH_TABLE_PLACEHOLD - + " set " + ServerTableColumnsName.BRANCH_TABLE_STATUS + " = ?, " + ServerTableColumnsName.BRANCH_TABLE_GMT_MODIFIED - + " = systimestamp where " + ServerTableColumnsName.BRANCH_TABLE_XID + " = ? and " + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID - + " = ?"; + + " set " + ServerTableColumnsName.BRANCH_TABLE_STATUS + " = ?," + + " " + ServerTableColumnsName.BRANCH_TABLE_GMT_MODIFIED + " = systimestamp" + + " where " + ServerTableColumnsName.BRANCH_TABLE_XID + " = ?" + + " and " + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID + " = ?"; @Override public String getInsertGlobalTransactionSQL(String globalTable) { @@ -82,8 +90,8 @@ public class OracleLogStoreSqls extends AbstractLogStoreSqls { @Override public String getQueryGlobalTransactionSQLByStatus(String globalTable, String paramsPlaceHolder) { - return QUERY_GLOBAL_TRANSACTION_BY_STATUS_ORACLE.replace(GLOBAL_TABLE_PLACEHOLD, globalTable).replace( - PRAMETER_PLACEHOLD, paramsPlaceHolder); + return QUERY_GLOBAL_TRANSACTION_BY_STATUS_ORACLE.replace(GLOBAL_TABLE_PLACEHOLD, globalTable) + .replace(PRAMETER_PLACEHOLD, paramsPlaceHolder); } @Override diff --git a/core/src/main/java/io/seata/core/store/db/sql/log/PostgresqlLogStoreSqls.java b/core/src/main/java/io/seata/core/store/db/sql/log/PostgresqlLogStoreSqls.java index ae3b89cb5955b8fab1c9799a33d926751f9b96f5..13eeea92e6deab4742952ee69635495b4893746f 100644 --- a/core/src/main/java/io/seata/core/store/db/sql/log/PostgresqlLogStoreSqls.java +++ b/core/src/main/java/io/seata/core/store/db/sql/log/PostgresqlLogStoreSqls.java @@ -19,6 +19,7 @@ import io.seata.common.loader.LoadLevel; import io.seata.core.constants.ServerTableColumnsName; /** + * Database log store postgresql sql * @author will */ @LoadLevel(name = "postgresql") @@ -27,44 +28,51 @@ public class PostgresqlLogStoreSqls extends AbstractLogStoreSqls { /** * The constant INSERT_GLOBAL_TRANSACTION_POSTGRESQL. */ - public static final String INSERT_GLOBAL_TRANSACTION_POSTGRESQL = "insert into " + GLOBAL_TABLE_PLACEHOLD + "(" - + ALL_GLOBAL_COLUMNS + ")" + - "values(?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now()) "; + public static final String INSERT_GLOBAL_TRANSACTION_POSTGRESQL = "insert into " + GLOBAL_TABLE_PLACEHOLD + + "(" + ALL_GLOBAL_COLUMNS + ")" + + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now())"; /** * The constant UPDATE_GLOBAL_TRANSACTION_STATUS_POSTGRESQL. */ public static final String UPDATE_GLOBAL_TRANSACTION_STATUS_POSTGRESQL = "update " + GLOBAL_TABLE_PLACEHOLD - + " set " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " = ?, " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + " = now() where " + ServerTableColumnsName.GLOBAL_TABLE_XID + " = ?"; + + " set " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " = ?," + + " " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + " = now()" + + " where " + ServerTableColumnsName.GLOBAL_TABLE_XID + " = ?"; /** * This constant QUERY_GLOBAL_TRANSACTION_BY_STATUS_POSTGRESQL. */ - public static final String QUERY_GLOBAL_TRANSACTION_BY_STATUS_POSTGRESQL = - "select " + ALL_GLOBAL_COLUMNS + " from " + GLOBAL_TABLE_PLACEHOLD - + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (" + PRAMETER_PLACEHOLD + ")" - + " order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + " limit ?"; + public static final String QUERY_GLOBAL_TRANSACTION_BY_STATUS_POSTGRESQL = "select " + ALL_GLOBAL_COLUMNS + + " from " + GLOBAL_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (" + PRAMETER_PLACEHOLD + ")" + + " order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + + " limit ?"; /** * The constant QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_POSTGRESQL. */ - public static final String QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_POSTGRESQL = "select " + ALL_GLOBAL_COLUMNS + " from " - + GLOBAL_TABLE_PLACEHOLD + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (" + - "0, 2, 3, 4, 5, 6, 7, 8, 10 ,12, 14) order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + " limit ?"; + public static final String QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_POSTGRESQL = "select " + ALL_GLOBAL_COLUMNS + + " from " + GLOBAL_TABLE_PLACEHOLD + + " where " + ServerTableColumnsName.GLOBAL_TABLE_STATUS + " in (0, 2, 3, 4, 5, 6, 7, 8, 10 ,12, 14)" + + " order by " + ServerTableColumnsName.GLOBAL_TABLE_GMT_MODIFIED + + " limit ?"; /** * The constant INSERT_BRANCH_TRANSACTION_POSTGRESQL. */ - public static final String INSERT_BRANCH_TRANSACTION_POSTGRESQL = "insert into " + BRANCH_TABLE_PLACEHOLD + "(" - + ALL_BRANCH_COLUMNS + ")" + - "values (?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now())"; + public static final String INSERT_BRANCH_TRANSACTION_POSTGRESQL = "insert into " + BRANCH_TABLE_PLACEHOLD + + "(" + ALL_BRANCH_COLUMNS + ")" + + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now())"; /** * The constant UPDATE_BRANCH_TRANSACTION_STATUS_POSTGRESQL. */ public static final String UPDATE_BRANCH_TRANSACTION_STATUS_POSTGRESQL = "update " + BRANCH_TABLE_PLACEHOLD - + " set " + ServerTableColumnsName.BRANCH_TABLE_STATUS + " = ?, " + ServerTableColumnsName.BRANCH_TABLE_GMT_MODIFIED - + " = now() where " + ServerTableColumnsName.BRANCH_TABLE_XID + " = ? and " + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID + " = ?"; + + " set " + ServerTableColumnsName.BRANCH_TABLE_STATUS + " = ?," + + " " + ServerTableColumnsName.BRANCH_TABLE_GMT_MODIFIED + " = now()" + + " where " + ServerTableColumnsName.BRANCH_TABLE_XID + " = ?" + + " and " + ServerTableColumnsName.BRANCH_TABLE_BRANCH_ID + " = ?"; @Override public String getInsertGlobalTransactionSQL(String globalTable) { @@ -78,8 +86,8 @@ public class PostgresqlLogStoreSqls extends AbstractLogStoreSqls { @Override public String getQueryGlobalTransactionSQLByStatus(String globalTable, String paramsPlaceHolder) { - return QUERY_GLOBAL_TRANSACTION_BY_STATUS_POSTGRESQL.replace(GLOBAL_TABLE_PLACEHOLD, globalTable).replace( - PRAMETER_PLACEHOLD, paramsPlaceHolder); + return QUERY_GLOBAL_TRANSACTION_BY_STATUS_POSTGRESQL.replace(GLOBAL_TABLE_PLACEHOLD, globalTable) + .replace(PRAMETER_PLACEHOLD, paramsPlaceHolder); } @Override diff --git a/core/src/test/java/io/seata/core/context/RootContextTest.java b/core/src/test/java/io/seata/core/context/RootContextTest.java index 6987f017eec6cb7325916cd884d49259f054f8fc..73acbead445b1e0af095a793785f7b62ab56b2ca 100644 --- a/core/src/test/java/io/seata/core/context/RootContextTest.java +++ b/core/src/test/java/io/seata/core/context/RootContextTest.java @@ -17,6 +17,7 @@ package io.seata.core.context; import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.core.model.BranchType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -31,6 +32,8 @@ public class RootContextTest { private final String DEFAULT_XID = "default_xid"; + private final BranchType DEFAULT_BRANCH_TYPE = BranchType.AT; + /** * Test bind and unbind. */ @@ -94,4 +97,15 @@ public class RootContextTest { assertThat(RootContext.getXID()).isNull(); } + @Test + public void testBindBranchType_And_UnbindBranchType(){ + assertThat(RootContext.getBranchType()).isNull(); + assertThat(RootContext.unbindBranchType()).isNull(); + RootContext.bindBranchType(DEFAULT_BRANCH_TYPE); + assertThat(RootContext.unbindBranchType()).isEqualTo(DEFAULT_BRANCH_TYPE.name()); + RootContext.unbindBranchType(); + assertThat(RootContext.getBranchType()).isNull(); + assertThat(RootContext.unbindBranchType()).isNull(); + } + } diff --git a/core/src/test/java/io/seata/core/protocol/MessageFutureTest.java b/core/src/test/java/io/seata/core/protocol/MessageFutureTest.java index e0eabc77cb19a84da8ed0c73934f2279fecee026..b7d3699cf3c1758c143c5124aa0a48c986a420e3 100644 --- a/core/src/test/java/io/seata/core/protocol/MessageFutureTest.java +++ b/core/src/test/java/io/seata/core/protocol/MessageFutureTest.java @@ -49,16 +49,16 @@ public class MessageFutureTest { @Test public void testFieldSetGet() { String fromJson = "{\n" + - "\t\"requestMessage\":{\n" + - "\t\t\"body\":\"" + BODY_FIELD + "\",\n" + - "\t\t\"codec\":" + CODEC_FIELD + ",\n" + - "\t\t\"compressor\":" + COMPRESS_FIELD + ",\n" + - "\t\t\"headMap\":" + HEAD_FIELD + ",\n" + - "\t\t\"id\":" + ID_FIELD + ",\n" + - "\t\t\"messageType\":" + MSG_TYPE_FIELD + "\n" + - "\t},\n" + - "\t\"timeout\":" + TIME_OUT_FIELD + "\n" + - "}"; + "\t\"requestMessage\":{\n" + + "\t\t\"body\":\"" + BODY_FIELD + "\",\n" + + "\t\t\"codec\":" + CODEC_FIELD + ",\n" + + "\t\t\"compressor\":" + COMPRESS_FIELD + ",\n" + + "\t\t\"headMap\":" + HEAD_FIELD + ",\n" + + "\t\t\"id\":" + ID_FIELD + ",\n" + + "\t\t\"messageType\":" + MSG_TYPE_FIELD + "\n" + + "\t},\n" + + "\t\"timeout\":" + TIME_OUT_FIELD + "\n" + + "}"; MessageFuture fromJsonFuture = JSON.parseObject(fromJson, MessageFuture.class); assertThat(fromJsonFuture.getTimeout()).isEqualTo(TIME_OUT_FIELD); MessageFuture toJsonFuture = new MessageFuture(); diff --git a/core/src/test/java/io/seata/core/protocol/RpcMessageTest.java b/core/src/test/java/io/seata/core/protocol/RpcMessageTest.java index 98486a26ea378c43e51a387c2e56405d76f543d4..0eb83a8864dab18efc93d6ea4cca71b7caa3126d 100644 --- a/core/src/test/java/io/seata/core/protocol/RpcMessageTest.java +++ b/core/src/test/java/io/seata/core/protocol/RpcMessageTest.java @@ -42,13 +42,13 @@ public class RpcMessageTest { @Test public void testFieldGetSetFromJson() { String fromJson = "{\n" + - "\t\"body\":\"" + BODY_FIELD + "\",\n" + - "\t\"codec\":" + CODEC_FIELD + ",\n" + - "\t\"compressor\":" + COMPRESS_FIELD + ",\n" + - "\t\"headMap\":" + HEAD_FIELD + ",\n" + - "\t\"id\":" + ID_FIELD + ",\n" + - "\t\"messageType\":" + MSG_TYPE_FIELD + "\n" + - "}"; + "\t\"body\":\"" + BODY_FIELD + "\",\n" + + "\t\"codec\":" + CODEC_FIELD + ",\n" + + "\t\"compressor\":" + COMPRESS_FIELD + ",\n" + + "\t\"headMap\":" + HEAD_FIELD + ",\n" + + "\t\"id\":" + ID_FIELD + ",\n" + + "\t\"messageType\":" + MSG_TYPE_FIELD + "\n" + + "}"; RpcMessage fromJsonMessage = JSON.parseObject(fromJson, RpcMessage.class); assertThat(fromJsonMessage.getBody()).isEqualTo(BODY_FIELD); assertThat(fromJsonMessage.getId()).isEqualTo(ID_FIELD); diff --git a/core/src/test/java/io/seata/core/rpc/netty/RmRpcClientTest.java b/core/src/test/java/io/seata/core/rpc/netty/RmNettyClientTest.java similarity index 77% rename from core/src/test/java/io/seata/core/rpc/netty/RmRpcClientTest.java rename to core/src/test/java/io/seata/core/rpc/netty/RmNettyClientTest.java index 8f223992d44942274419acd3182ab035ac8b3f77..e87d38bd4af64fdffe24127c96f82d45a8b93a52 100644 --- a/core/src/test/java/io/seata/core/rpc/netty/RmRpcClientTest.java +++ b/core/src/test/java/io/seata/core/rpc/netty/RmNettyClientTest.java @@ -29,17 +29,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue; * * @author zhaojun */ -class RmRpcClientTest { +class RmNettyClientTest { @Test public void assertGetInstanceAfterDestroy() { - RmRpcClient oldClient = RmRpcClient.getInstance("ap", "group"); + RmNettyRemotingClient oldClient = RmNettyRemotingClient.getInstance("ap", "group"); AtomicBoolean initialized = getInitializeStatus(oldClient); oldClient.init(); assertTrue(initialized.get()); oldClient.destroy(); assertFalse(initialized.get()); - RmRpcClient newClient = RmRpcClient.getInstance("ap", "group"); + RmNettyRemotingClient newClient = RmNettyRemotingClient.getInstance("ap", "group"); Assertions.assertNotEquals(oldClient, newClient); initialized = getInitializeStatus(newClient); assertFalse(initialized.get()); @@ -48,11 +48,11 @@ class RmRpcClientTest { newClient.destroy(); } - private AtomicBoolean getInitializeStatus(final RmRpcClient rmRpcClient) { + private AtomicBoolean getInitializeStatus(final RmNettyRemotingClient rmNettyRemotingClient) { try { - Field field = rmRpcClient.getClass().getDeclaredField("initialized"); + Field field = rmNettyRemotingClient.getClass().getDeclaredField("initialized"); field.setAccessible(true); - return (AtomicBoolean) field.get(rmRpcClient); + return (AtomicBoolean) field.get(rmNettyRemotingClient); } catch (Exception ex) { throw new RuntimeException(ex.getMessage()); } diff --git a/core/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java b/core/src/test/java/io/seata/core/rpc/netty/TmNettyClientTest.java similarity index 86% rename from core/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java rename to core/src/test/java/io/seata/core/rpc/netty/TmNettyClientTest.java index 6734e486fe7c4663a9f252d20f546a453191cf62..35cb14ac882a299bf062d369c3f36e680c3efaea 100644 --- a/core/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java +++ b/core/src/test/java/io/seata/core/rpc/netty/TmNettyClientTest.java @@ -35,7 +35,7 @@ import java.util.concurrent.TimeUnit; * * @author slievrly xiajun.0706@163.com */ -public class TmRpcClientTest { +public class TmNettyClientTest { private static final ThreadPoolExecutor workingThreads = new ThreadPoolExecutor(100, 500, 500, TimeUnit.SECONDS, @@ -50,10 +50,10 @@ public class TmRpcClientTest { public void testGetInstance() throws Exception { String applicationId = "app 1"; String transactionServiceGroup = "group A"; - TmRpcClient tmRpcClient = TmRpcClient.getInstance(applicationId, transactionServiceGroup); - Field nettyClientKeyPoolField = getDeclaredField(tmRpcClient.getClientChannelManager(), "nettyClientKeyPool"); + TmNettyRemotingClient tmNettyRemotingClient = TmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup); + Field nettyClientKeyPoolField = getDeclaredField(tmNettyRemotingClient.getClientChannelManager(), "nettyClientKeyPool"); nettyClientKeyPoolField.setAccessible(true); - GenericKeyedObjectPool nettyClientKeyPool = (GenericKeyedObjectPool) nettyClientKeyPoolField.get(tmRpcClient.getClientChannelManager()); + GenericKeyedObjectPool nettyClientKeyPool = (GenericKeyedObjectPool) nettyClientKeyPoolField.get(tmNettyRemotingClient.getClientChannelManager()); NettyClientConfig defaultNettyClientConfig = new NettyClientConfig(); Assertions.assertEquals(defaultNettyClientConfig.getMaxPoolActive(), nettyClientKeyPool.getMaxActive()); Assertions.assertEquals(defaultNettyClientConfig.getMinPoolIdle(), nettyClientKeyPool.getMinIdle()); @@ -72,14 +72,14 @@ public class TmRpcClientTest { public void testInit() throws Exception { String applicationId = "app 1"; String transactionServiceGroup = "group A"; - TmRpcClient tmRpcClient = TmRpcClient.getInstance(applicationId, transactionServiceGroup); + TmNettyRemotingClient tmNettyRemotingClient = TmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup); - tmRpcClient.init(); + tmNettyRemotingClient.init(); - //check if attr of tmRpcClient object has been set success - Field clientBootstrapField = getDeclaredField(tmRpcClient, "clientBootstrap"); + //check if attr of tmNettyClient object has been set success + Field clientBootstrapField = getDeclaredField(tmNettyRemotingClient, "clientBootstrap"); clientBootstrapField.setAccessible(true); - RpcClientBootstrap clientBootstrap = (RpcClientBootstrap)clientBootstrapField.get(tmRpcClient); + NettyClientBootstrap clientBootstrap = (NettyClientBootstrap)clientBootstrapField.get(tmNettyRemotingClient); Field bootstrapField = getDeclaredField(clientBootstrap, "bootstrap"); bootstrapField.setAccessible(true); Bootstrap bootstrap = (Bootstrap) bootstrapField.get(clientBootstrap); diff --git a/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java b/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java index 90036bd4bb868a88ae615448ba465794fefe980b..40e7607ca3757a5a511b994a02ebb41e2187439e 100644 --- a/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java +++ b/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java @@ -100,9 +100,9 @@ public class ConsulRegistryServiceImpl implements RegistryService<ConsulListener * @return instance */ static ConsulRegistryServiceImpl getInstance() { - if (null == instance) { + if (instance == null) { synchronized (ConsulRegistryServiceImpl.class) { - if (null == instance) { + if (instance == null) { instance = new ConsulRegistryServiceImpl(); } } @@ -147,7 +147,7 @@ public class ConsulRegistryServiceImpl implements RegistryService<ConsulListener @Override public List<InetSocketAddress> lookup(String key) throws Exception { final String cluster = getServiceGroup(key); - if (null == cluster) { + if (cluster == null) { return null; } if (!listenerMap.containsKey(cluster)) { @@ -165,10 +165,12 @@ public class ConsulRegistryServiceImpl implements RegistryService<ConsulListener * @return client */ private ConsulClient getConsulClient() { - if (null == client) { + if (client == null) { synchronized (ConsulRegistryServiceImpl.class) { - if (null == client) { - client = new ConsulClient(FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY)); + if (client == null) { + String serverAddr = FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY); + InetSocketAddress inetSocketAddress = NetUtil.toInetSocketAddress(serverAddr); + client = new ConsulClient(inetSocketAddress.getHostName(), inetSocketAddress.getPort()); } } } @@ -247,7 +249,7 @@ public class ConsulRegistryServiceImpl implements RegistryService<ConsulListener * @param cluster */ private void refreshCluster(String cluster) { - if (null == cluster) { + if (cluster == null) { return; } Response<List<HealthService>> response = getHealthyServices(getClusterName(), -1, -1); @@ -264,7 +266,7 @@ public class ConsulRegistryServiceImpl implements RegistryService<ConsulListener * @param services */ private void refreshCluster(String cluster, List<HealthService> services) { - if (null == cluster || services == null) { + if (cluster == null || services == null) { return; } clusterAddressMap.put(cluster, services.stream() diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/loadbalance/RandomLoadBalance.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/loadbalance/RandomLoadBalance.java index 8587c097c651769adafd026f47b6fd18335f5423..61406d6658104b3f979b45d4069f70e71a99520d 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/loadbalance/RandomLoadBalance.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/loadbalance/RandomLoadBalance.java @@ -16,7 +16,7 @@ package io.seata.discovery.loadbalance; import java.util.List; -import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; import io.seata.common.loader.LoadLevel; @@ -28,11 +28,9 @@ import io.seata.common.loader.LoadLevel; @LoadLevel(name = "RandomLoadBalance", order = 2) public class RandomLoadBalance extends AbstractLoadBalance { - private final Random random = new Random(); - @Override protected <T> T doSelect(List<T> invokers) { int length = invokers.size(); - return invokers.get(random.nextInt(length)); + return invokers.get(ThreadLocalRandom.current().nextInt(length)); } } diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java index a8e5e7492870dcb4f6ffe1be5a5ee8caa16cbe4c..6bf4da74fe901ab26f83289a9a49406a12f39afa 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java @@ -46,9 +46,9 @@ public class FileRegistryServiceImpl implements RegistryService<ConfigChangeList * @return the instance */ static FileRegistryServiceImpl getInstance() { - if (null == instance) { + if (instance == null) { synchronized (FileRegistryServiceImpl.class) { - if (null == instance) { + if (instance == null) { instance = new FileRegistryServiceImpl(); } } @@ -79,7 +79,7 @@ public class FileRegistryServiceImpl implements RegistryService<ConfigChangeList @Override public List<InetSocketAddress> lookup(String key) throws Exception { String clusterName = getServiceGroup(key); - if (null == clusterName) { + if (clusterName == null) { return null; } String endpointStr = CONFIG.getConfig( diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryService.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryService.java index 1b5eee24f3ce9b306b63e05c4448913e3eded82f..2e4fc3da93d2cf318a03dbff3d6458d20c4fa35c 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryService.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryService.java @@ -16,9 +16,10 @@ package io.seata.discovery.registry; import java.net.InetSocketAddress; +import java.util.HashSet; import java.util.List; - -import io.seata.config.Configuration; +import java.util.Set; +import io.seata.config.ConfigurationCache; import io.seata.config.ConfigurationFactory; /** @@ -42,6 +43,8 @@ public interface RegistryService<T> { */ String CONFIG_SPLIT_CHAR = "."; + Set<String> SERVICE_GROUP_NAME = new HashSet<>(); + /** * Register. * @@ -98,7 +101,11 @@ public interface RegistryService<T> { * @return the service group name */ default String getServiceGroup(String key) { - Configuration config = ConfigurationFactory.getInstance(); - return config.getConfig(PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key); + key = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key; + if (!SERVICE_GROUP_NAME.contains(key)) { + ConfigurationCache.addConfigListener(key); + SERVICE_GROUP_NAME.add(key); + } + return ConfigurationFactory.getInstance().getConfig(key); } } diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryType.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryType.java index 574e95f23272e84375b709e2a2d698eb3e2daa13..87b109180c376cf878c3a2dc49abbfeb7f2c6dcc 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryType.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryType.java @@ -15,8 +15,6 @@ */ package io.seata.discovery.registry; -import io.seata.common.exception.NotSupportYetException; - /** * The enum Registry type. * @@ -72,6 +70,6 @@ public enum RegistryType { return registryType; } } - throw new NotSupportYetException("unsupported type:" + name); + throw new IllegalArgumentException("not support registry type: " + name); } } diff --git a/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java b/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java index 663234beea118b4070074e7e240639fb45b8fbdb..33c61e83188f305e538df9e76a3465d1f114588a 100644 --- a/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java +++ b/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java @@ -27,6 +27,6 @@ class ConfigurationFactoryTest { void getInstance() { Configuration configuration = ConfigurationFactory.getInstance(); // check singleton - Assertions.assertEquals(configuration, ConfigurationFactory.getInstance()); + Assertions.assertEquals(configuration.getClass().getName(), ConfigurationFactory.getInstance().getClass().getName()); } } \ No newline at end of file diff --git a/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java b/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java index 3dbfcbcb5fcd93a3e9d8cfec629afa966b754b81..82fdd1153154672224732ed288c5ddc6e5296bb1 100644 --- a/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java +++ b/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java @@ -111,9 +111,9 @@ public class EtcdRegistryServiceImpl implements RegistryService<Watch.Listener> * @return instance */ static EtcdRegistryServiceImpl getInstance() { - if (null == instance) { + if (instance == null) { synchronized (EtcdRegistryServiceImpl.class) { - if (null == instance) { + if (instance == null) { instance = new EtcdRegistryServiceImpl(); } } @@ -166,7 +166,7 @@ public class EtcdRegistryServiceImpl implements RegistryService<Watch.Listener> @Override public void unsubscribe(String cluster, Watch.Listener listener) throws Exception { Set<Watch.Listener> subscribeSet = listenerMap.get(cluster); - if (null != subscribeSet) { + if (subscribeSet != null) { Set<Watch.Listener> newSubscribeSet = subscribeSet.stream() .filter(eventListener -> !eventListener.equals(listener)) .collect(Collectors.toSet()); @@ -178,7 +178,7 @@ public class EtcdRegistryServiceImpl implements RegistryService<Watch.Listener> @Override public List<InetSocketAddress> lookup(String key) throws Exception { final String cluster = getServiceGroup(key); - if (null == cluster) { + if (cluster == null) { return null; } if (!listenerMap.containsKey(cluster)) { @@ -214,9 +214,9 @@ public class EtcdRegistryServiceImpl implements RegistryService<Watch.Listener> @Override public void close() throws Exception { - if (null != lifeKeeper) { + if (lifeKeeper != null) { lifeKeeper.stop(); - if (null != lifeKeeperFuture) { + if (lifeKeeperFuture != null) { lifeKeeperFuture.get(3, TimeUnit.SECONDS); } } @@ -230,7 +230,7 @@ public class EtcdRegistryServiceImpl implements RegistryService<Watch.Listener> * @throws Exception */ private void refreshCluster(String cluster) throws Exception { - if (null == cluster) { + if (cluster == null) { return; } //1.get all available registries @@ -250,9 +250,9 @@ public class EtcdRegistryServiceImpl implements RegistryService<Watch.Listener> * @return client */ private Client getClient() { - if (null == client) { + if (client == null) { synchronized (EtcdRegistryServiceImpl.class) { - if (null == client) { + if (client == null) { String testEndpoint = System.getProperty(TEST_ENDPONT); if (StringUtils.isNotBlank(testEndpoint)) { client = Client.builder().endpoints(testEndpoint).build(); diff --git a/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java b/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java index 1adbabbc2e5762e1d60a4e4cef28b1b348491ade..8bff9b37c312aba538901dd60d4385975f60027e 100644 --- a/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java +++ b/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java @@ -79,9 +79,9 @@ public class EurekaRegistryServiceImpl implements RegistryService<EurekaEventLis } static EurekaRegistryServiceImpl getInstance() { - if (null == instance) { + if (instance == null) { synchronized (EurekaRegistryServiceImpl.class) { - if (null == instance) { + if (instance == null) { clusterAddressMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY); instanceConfig = new CustomEurekaInstanceConfig(); instance = new EurekaRegistryServiceImpl(); @@ -125,7 +125,7 @@ public class EurekaRegistryServiceImpl implements RegistryService<EurekaEventLis @Override public List<InetSocketAddress> lookup(String key) throws Exception { String clusterName = getServiceGroup(key); - if (null == clusterName) { + if (clusterName == null) { return null; } if (!subscribeListener) { @@ -207,17 +207,17 @@ public class EurekaRegistryServiceImpl implements RegistryService<EurekaEventLis private String getApplicationName() { String application = FILE_CONFIG.getConfig(getEurekaApplicationFileKey()); - if (null == application) { + if (application == null) { application = DEFAULT_APPLICATION; } return application; } private EurekaClient getEurekaClient(boolean needRegister) throws EurekaRegistryException { - if (null == eurekaClient) { + if (eurekaClient == null) { synchronized (EurekaRegistryServiceImpl.class) { try { - if (null == eurekaClient) { + if (eurekaClient == null) { if (!needRegister) { instanceConfig = new CustomEurekaInstanceConfig(); } diff --git a/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java b/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java index ac5564c2c20699d26580dfce30a42952507dc83e..c2652efb669e1758830c8226fa915c72ccbaa636 100644 --- a/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java +++ b/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java @@ -15,27 +15,26 @@ */ package io.seata.discovery.registry.nacos; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.stream.Collectors; - -import com.alibaba.nacos.api.naming.NamingFactory; +import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.listener.EventListener; import com.alibaba.nacos.api.naming.listener.NamingEvent; import com.alibaba.nacos.api.naming.pojo.Instance; import com.alibaba.nacos.client.naming.utils.CollectionUtils; - import io.seata.common.util.StringUtils; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; import io.seata.config.ConfigurationKeys; import io.seata.discovery.registry.RegistryService; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; + /** * The type Nacos registry service. * @@ -44,12 +43,14 @@ import io.seata.discovery.registry.RegistryService; public class NacosRegistryServiceImpl implements RegistryService<EventListener> { private static final String DEFAULT_NAMESPACE = ""; private static final String DEFAULT_CLUSTER = "default"; + private static final String DEFAULT_GROUP = "DEFAULT_GROUP"; private static final String DEFAULT_APPLICATION = "seata-server"; private static final String PRO_SERVER_ADDR_KEY = "serverAddr"; private static final String PRO_NAMESPACE_KEY = "namespace"; private static final String REGISTRY_TYPE = "nacos"; private static final String REGISTRY_CLUSTER = "cluster"; private static final String PRO_APPLICATION_KEY = "application"; + private static final String PRO_GROUP_KEY = "group"; private static final String USER_NAME = "username"; private static final String PASSWORD = "password"; private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; @@ -68,9 +69,9 @@ public class NacosRegistryServiceImpl implements RegistryService<EventListener> * @return the instance */ static NacosRegistryServiceImpl getInstance() { - if (null == instance) { + if (instance == null) { synchronized (NacosRegistryServiceImpl.class) { - if (null == instance) { + if (instance == null) { instance = new NacosRegistryServiceImpl(); } } @@ -81,13 +82,13 @@ public class NacosRegistryServiceImpl implements RegistryService<EventListener> @Override public void register(InetSocketAddress address) throws Exception { validAddress(address); - getNamingInstance().registerInstance(getServiceName(), address.getAddress().getHostAddress(), address.getPort(), getClusterName()); + getNamingInstance().registerInstance(getServiceName(), getServiceGroup(), address.getAddress().getHostAddress(), address.getPort(), getClusterName()); } @Override public void unregister(InetSocketAddress address) throws Exception { validAddress(address); - getNamingInstance().deregisterInstance(getServiceName(), address.getAddress().getHostAddress(), address.getPort(), getClusterName()); + getNamingInstance().deregisterInstance(getServiceName(), getServiceGroup(), address.getAddress().getHostAddress(), address.getPort(), getClusterName()); } @Override @@ -96,7 +97,7 @@ public class NacosRegistryServiceImpl implements RegistryService<EventListener> clusters.add(cluster); LISTENER_SERVICE_MAP.putIfAbsent(cluster, new ArrayList<>()); LISTENER_SERVICE_MAP.get(cluster).add(listener); - getNamingInstance().subscribe(getServiceName(), clusters, listener); + getNamingInstance().subscribe(getServiceName(), getServiceGroup(), clusters, listener); } @Override @@ -104,19 +105,19 @@ public class NacosRegistryServiceImpl implements RegistryService<EventListener> List<String> clusters = new ArrayList<>(); clusters.add(cluster); List<EventListener> subscribeList = LISTENER_SERVICE_MAP.get(cluster); - if (null != subscribeList) { + if (subscribeList != null) { List<EventListener> newSubscribeList = subscribeList.stream() .filter(eventListener -> !eventListener.equals(listener)) .collect(Collectors.toList()); LISTENER_SERVICE_MAP.put(cluster, newSubscribeList); } - getNamingInstance().unsubscribe(getServiceName(), clusters, listener); + getNamingInstance().unsubscribe(getServiceName(), getServiceGroup(), clusters, listener); } @Override public List<InetSocketAddress> lookup(String key) throws Exception { String clusterName = getServiceGroup(key); - if (null == clusterName) { + if (clusterName == null) { return null; } if (!LISTENER_SERVICE_MAP.containsKey(clusterName)) { @@ -124,7 +125,7 @@ public class NacosRegistryServiceImpl implements RegistryService<EventListener> if (!LISTENER_SERVICE_MAP.containsKey(clusterName)) { List<String> clusters = new ArrayList<>(); clusters.add(clusterName); - List<Instance> firstAllInstances = getNamingInstance().getAllInstances(getServiceName(), clusters); + List<Instance> firstAllInstances = getNamingInstance().getAllInstances(getServiceName(), getServiceGroup(), clusters); if (null != firstAllInstances) { List<InetSocketAddress> newAddressList = firstAllInstances.stream() .filter(instance -> instance.isEnabled() && instance.isHealthy()) @@ -133,7 +134,7 @@ public class NacosRegistryServiceImpl implements RegistryService<EventListener> CLUSTER_ADDRESS_MAP.put(clusterName, newAddressList); } subscribe(clusterName, event -> { - List<Instance> instances = ((NamingEvent)event).getInstances(); + List<Instance> instances = ((NamingEvent) event).getInstances(); if (null == instances && null != CLUSTER_ADDRESS_MAP.get(clusterName)) { CLUSTER_ADDRESS_MAP.remove(clusterName); } else if (!CollectionUtils.isEmpty(instances)) { @@ -156,7 +157,7 @@ public class NacosRegistryServiceImpl implements RegistryService<EventListener> } private void validAddress(InetSocketAddress address) { - if (null == address.getHostName() || 0 == address.getPort()) { + if (address.getHostName() == null || 0 == address.getPort()) { throw new IllegalArgumentException("invalid address:" + address); } } @@ -168,10 +169,10 @@ public class NacosRegistryServiceImpl implements RegistryService<EventListener> * @throws Exception the exception */ public static NamingService getNamingInstance() throws Exception { - if (null == naming) { + if (naming == null) { synchronized (NacosRegistryServiceImpl.class) { - if (null == naming) { - naming = NamingFactory.createNamingService(getNamingProperties()); + if (naming == null) { + naming = NacosFactory.createNamingService(getNamingProperties()); } } } @@ -180,28 +181,28 @@ public class NacosRegistryServiceImpl implements RegistryService<EventListener> private static Properties getNamingProperties() { Properties properties = new Properties(); - if (null != System.getProperty(PRO_SERVER_ADDR_KEY)) { + if (System.getProperty(PRO_SERVER_ADDR_KEY) != null) { properties.setProperty(PRO_SERVER_ADDR_KEY, System.getProperty(PRO_SERVER_ADDR_KEY)); } else { String address = FILE_CONFIG.getConfig(getNacosAddrFileKey()); - if (null != address) { + if (address != null) { properties.setProperty(PRO_SERVER_ADDR_KEY, address); } } - if (null != System.getProperty(PRO_NAMESPACE_KEY)) { + if (System.getProperty(PRO_NAMESPACE_KEY) != null) { properties.setProperty(PRO_NAMESPACE_KEY, System.getProperty(PRO_NAMESPACE_KEY)); } else { String namespace = FILE_CONFIG.getConfig(getNacosNameSpaceFileKey()); - if (null == namespace) { + if (namespace == null) { namespace = DEFAULT_NAMESPACE; } properties.setProperty(PRO_NAMESPACE_KEY, namespace); } String userName = StringUtils.isNotBlank(System.getProperty(USER_NAME)) ? System.getProperty(USER_NAME) - : FILE_CONFIG.getConfig(getNacosUserName()); + : FILE_CONFIG.getConfig(getNacosUserName()); if (StringUtils.isNotBlank(userName)) { String password = StringUtils.isNotBlank(System.getProperty(PASSWORD)) ? System.getProperty(PASSWORD) - : FILE_CONFIG.getConfig(getNacosPassword()); + : FILE_CONFIG.getConfig(getNacosPassword()); if (StringUtils.isNotBlank(password)) { properties.setProperty(USER_NAME, userName); properties.setProperty(PASSWORD, password); @@ -218,6 +219,10 @@ public class NacosRegistryServiceImpl implements RegistryService<EventListener> return FILE_CONFIG.getConfig(getNacosApplicationFileKey(), DEFAULT_APPLICATION); } + private static String getServiceGroup() { + return FILE_CONFIG.getConfig(getNacosApplicationGroupKey(), DEFAULT_GROUP); + } + private static String getNacosAddrFileKey() { return String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, ConfigurationKeys.FILE_ROOT_REGISTRY, REGISTRY_TYPE, PRO_SERVER_ADDR_KEY); } @@ -234,13 +239,15 @@ public class NacosRegistryServiceImpl implements RegistryService<EventListener> return String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, ConfigurationKeys.FILE_ROOT_REGISTRY, REGISTRY_TYPE, PRO_APPLICATION_KEY); } + private static String getNacosApplicationGroupKey() { + return String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, ConfigurationKeys.FILE_ROOT_REGISTRY, REGISTRY_TYPE, PRO_GROUP_KEY); + } + private static String getNacosUserName() { - return String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, ConfigurationKeys.FILE_ROOT_CONFIG, REGISTRY_TYPE, - USER_NAME); + return String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, ConfigurationKeys.FILE_ROOT_REGISTRY, REGISTRY_TYPE, USER_NAME); } private static String getNacosPassword() { - return String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, ConfigurationKeys.FILE_ROOT_CONFIG, REGISTRY_TYPE, - PASSWORD); + return String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, ConfigurationKeys.FILE_ROOT_REGISTRY, REGISTRY_TYPE, PASSWORD); } } diff --git a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java index 6276dfa517ce276e6a5d6e1eab9edcebf5a53ce5..c53c143fcaaa27c85c08f18ba886fed559b0c211 100644 --- a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java +++ b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java @@ -127,9 +127,9 @@ public class RedisRegistryServiceImpl implements RegistryService<RedisListener> * @return the instance */ static RedisRegistryServiceImpl getInstance() { - if (null == instance) { + if (instance == null) { synchronized (RedisRegistryServiceImpl.class) { - if (null == instance) { + if (instance == null) { instance = new RedisRegistryServiceImpl(); } } @@ -180,7 +180,7 @@ public class RedisRegistryServiceImpl implements RegistryService<RedisListener> @Override public List<InetSocketAddress> lookup(String key) { String clusterName = getServiceGroup(key); - if (null == clusterName) { + if (clusterName == null) { return null; } if (!LISTENER_SERVICE_MAP.containsKey(clusterName)) { @@ -189,7 +189,7 @@ public class RedisRegistryServiceImpl implements RegistryService<RedisListener> try (Jedis jedis = jedisPool.getResource()) { instances = jedis.hgetAll(redisRegistryKey); } - if (null != instances && !instances.isEmpty()) { + if (instances != null && !instances.isEmpty()) { Set<InetSocketAddress> newAddressSet = instances.keySet().stream() .map(NetUtil::toInetSocketAddress) .collect(Collectors.toSet()); diff --git a/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java b/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java index 4224c5a332fa72aaa0122f83694548178cac5799..f5daea541986007c9af5f7b1724657412b9354f3 100644 --- a/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java +++ b/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java @@ -89,9 +89,9 @@ public class SofaRegistryServiceImpl implements RegistryService<SubscriberDataOb * @return the instance */ static SofaRegistryServiceImpl getInstance() { - if (null == instance) { + if (instance == null) { synchronized (SofaRegistryServiceImpl.class) { - if (null == instance) { + if (instance == null) { registryProps = getNamingProperties(); instance = new SofaRegistryServiceImpl(); } @@ -118,9 +118,9 @@ public class SofaRegistryServiceImpl implements RegistryService<SubscriberDataOb } private RegistryClient getRegistryInstance() { - if (null == registryClient) { + if (registryClient == null) { synchronized (SofaRegistryServiceImpl.class) { - if (null == registryClient) { + if (registryClient == null) { String address = registryProps.getProperty(PRO_SERVER_ADDR_KEY); final String portStr = StringUtils.substringAfter(address, HOST_SEPERATOR); @@ -131,8 +131,9 @@ public class SofaRegistryServiceImpl implements RegistryService<SubscriberDataOb .setRegistryEndpoint(StringUtils.substringBefore(address, HOST_SEPERATOR)) .setRegistryEndpointPort(Integer.parseInt(portStr)).build(); - registryClient = new DefaultRegistryClient(config); - ((DefaultRegistryClient)registryClient).init(); + DefaultRegistryClient result = new DefaultRegistryClient(config); + result.init(); + registryClient = result; } } } @@ -158,14 +159,14 @@ public class SofaRegistryServiceImpl implements RegistryService<SubscriberDataOb @Override public List<InetSocketAddress> lookup(String key) throws Exception { String clusterName = getServiceGroup(key); - if (null == clusterName) { + if (clusterName == null) { return null; } if (!LISTENER_SERVICE_MAP.containsKey(clusterName)) { CountDownLatch respondRegistries = new CountDownLatch(1); subscribe(clusterName, (dataId, data) -> { Map<String, List<String>> instances = data.getZoneData(); - if (null == instances && null != CLUSTER_ADDRESS_MAP.get(clusterName)) { + if (instances == null && CLUSTER_ADDRESS_MAP.get(clusterName) != null) { CLUSTER_ADDRESS_MAP.remove(clusterName); } else { List<InetSocketAddress> tranformData = flatData(instances); @@ -203,59 +204,59 @@ public class SofaRegistryServiceImpl implements RegistryService<SubscriberDataOb private static Properties getNamingProperties() { Properties properties = new Properties(); - if (null != System.getProperty(SOFA_FILEKEY_PREFIX + PRO_SERVER_ADDR_KEY)) { + if (System.getProperty(SOFA_FILEKEY_PREFIX + PRO_SERVER_ADDR_KEY) != null) { properties.setProperty(PRO_SERVER_ADDR_KEY, System.getProperty(SOFA_FILEKEY_PREFIX + PRO_SERVER_ADDR_KEY)); } else { String address = FILE_CONFIG.getConfig(getSofaAddrFileKey()); - if (null != address) { + if (address != null) { properties.setProperty(PRO_SERVER_ADDR_KEY, address); } } - if (null != System.getProperty(SOFA_FILEKEY_PREFIX + PRO_REGION_KEY)) { + if (System.getProperty(SOFA_FILEKEY_PREFIX + PRO_REGION_KEY) != null) { properties.setProperty(PRO_REGION_KEY, System.getProperty(SOFA_FILEKEY_PREFIX + PRO_REGION_KEY)); } else { String region = FILE_CONFIG.getConfig(getSofaRegionFileKey()); - if (null == region) { + if (region == null) { region = DEFAULT_LOCAL_REGION; } properties.setProperty(PRO_REGION_KEY, region); } - if (null != System.getProperty(SOFA_FILEKEY_PREFIX + PRO_DATACENTER_KEY)) { + if (System.getProperty(SOFA_FILEKEY_PREFIX + PRO_DATACENTER_KEY) != null) { properties.setProperty(PRO_DATACENTER_KEY, System.getProperty(SOFA_FILEKEY_PREFIX + PRO_DATACENTER_KEY)); } else { String datacenter = FILE_CONFIG.getConfig(getSofaDataCenterFileKey()); - if (null == datacenter) { + if (datacenter == null) { datacenter = DEFAULT_LOCAL_DATACENTER; } properties.setProperty(PRO_DATACENTER_KEY, datacenter); } - if (null != System.getProperty(SOFA_FILEKEY_PREFIX + PRO_GROUP_KEY)) { + if (System.getProperty(SOFA_FILEKEY_PREFIX + PRO_GROUP_KEY) != null) { properties.setProperty(PRO_GROUP_KEY, System.getProperty(SOFA_FILEKEY_PREFIX + PRO_GROUP_KEY)); } else { String group = FILE_CONFIG.getConfig(getSofaGroupFileKey()); - if (null == group) { + if (group == null) { group = DEFAULT_GROUP; } properties.setProperty(PRO_GROUP_KEY, group); } - if (null != System.getProperty(SOFA_FILEKEY_PREFIX + PRO_CLUSTER_KEY)) { + if (System.getProperty(SOFA_FILEKEY_PREFIX + PRO_CLUSTER_KEY) != null) { properties.setProperty(PRO_CLUSTER_KEY, System.getProperty(SOFA_FILEKEY_PREFIX + PRO_CLUSTER_KEY)); } else { String cluster = FILE_CONFIG.getConfig(getSofaClusterFileKey()); - if (null == cluster) { + if (cluster == null) { cluster = DEFAULT_CLUSTER; } properties.setProperty(PRO_CLUSTER_KEY, cluster); } - if (null != System.getProperty(SOFA_FILEKEY_PREFIX + PRO_ADDRESS_WAIT_TIME_KEY)) { + if (System.getProperty(SOFA_FILEKEY_PREFIX + PRO_ADDRESS_WAIT_TIME_KEY) != null) { properties.setProperty(PRO_ADDRESS_WAIT_TIME_KEY, System.getProperty(SOFA_FILEKEY_PREFIX + PRO_ADDRESS_WAIT_TIME_KEY)); } else { String group = FILE_CONFIG.getConfig(getSofaAddressWaitTimeFileKey()); - if (null == group) { + if (group == null) { group = DEFAULT_ADDRESS_WAIT_TIME; } properties.setProperty(PRO_ADDRESS_WAIT_TIME_KEY, group); @@ -294,7 +295,7 @@ public class SofaRegistryServiceImpl implements RegistryService<SubscriberDataOb private String getApplicationName() { String application = FILE_CONFIG.getConfig(getApplicationFileKey()); - if (null == application) { + if (application == null) { application = DEFAULT_APPLICATION; } return application; diff --git a/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java b/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java index 4f33cbc5c1ca9acd4a8dedca73cebb37297a6605..6de36955ad86f57fdf9ad1080118ff464a5706ef 100644 --- a/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java +++ b/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java @@ -64,6 +64,8 @@ public class ZookeeperRegisterServiceImpl implements RegistryService<IZkChildLis private static final String AUTH_PASSWORD = "password"; private static final String SESSION_TIME_OUT_KEY = "sessionTimeout"; private static final String CONNECT_TIME_OUT_KEY = "connectTimeout"; + private static final int DEFAULT_SESSION_TIMEOUT = 6000; + private static final int DEFAULT_CONNECT_TIMEOUT = 2000; private static final String FILE_CONFIG_KEY_PREFIX = FILE_ROOT_REGISTRY + FILE_CONFIG_SPLIT_CHAR + REGISTRY_TYPE + FILE_CONFIG_SPLIT_CHAR; private static final String ROOT_PATH = ZK_PATH_SPLIT_CHAR + FILE_ROOT_REGISTRY + ZK_PATH_SPLIT_CHAR + REGISTRY_TYPE @@ -80,9 +82,9 @@ public class ZookeeperRegisterServiceImpl implements RegistryService<IZkChildLis } static ZookeeperRegisterServiceImpl getInstance() { - if (null == instance) { + if (instance == null) { synchronized (ZookeeperRegisterServiceImpl.class) { - if (null == instance) { + if (instance == null) { instance = new ZookeeperRegisterServiceImpl(); } } @@ -133,7 +135,7 @@ public class ZookeeperRegisterServiceImpl implements RegistryService<IZkChildLis @Override public void subscribe(String cluster, IZkChildListener listener) throws Exception { - if (null == cluster) { + if (cluster == null) { return; } @@ -148,7 +150,7 @@ public class ZookeeperRegisterServiceImpl implements RegistryService<IZkChildLis @Override public void unsubscribe(String cluster, IZkChildListener listener) throws Exception { - if (null == cluster) { + if (cluster == null) { return; } String path = ROOT_PATH + cluster; @@ -156,7 +158,7 @@ public class ZookeeperRegisterServiceImpl implements RegistryService<IZkChildLis getClientInstance().unsubscribeChildChanges(path, listener); List<IZkChildListener> subscribeList = LISTENER_SERVICE_MAP.get(cluster); - if (null != subscribeList) { + if (subscribeList != null) { List<IZkChildListener> newSubscribeList = subscribeList.stream() .filter(eventListener -> !eventListener.equals(listener)) .collect(Collectors.toList()); @@ -175,7 +177,7 @@ public class ZookeeperRegisterServiceImpl implements RegistryService<IZkChildLis public List<InetSocketAddress> lookup(String key) throws Exception { String clusterName = getServiceGroup(key); - if (null == clusterName) { + if (clusterName == null) { return null; } @@ -206,10 +208,10 @@ public class ZookeeperRegisterServiceImpl implements RegistryService<IZkChildLis private ZkClient getClientInstance() { if (zkClient == null) { synchronized (ZookeeperRegisterServiceImpl.class) { - if (null == zkClient) { + if (zkClient == null) { zkClient = buildZkClient(FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY), - FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + SESSION_TIME_OUT_KEY), - FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + CONNECT_TIME_OUT_KEY), + FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + SESSION_TIME_OUT_KEY, DEFAULT_SESSION_TIMEOUT), + FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + CONNECT_TIME_OUT_KEY, DEFAULT_CONNECT_TIMEOUT), FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + AUTH_USERNAME), FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + AUTH_PASSWORD)); } @@ -221,15 +223,15 @@ public class ZookeeperRegisterServiceImpl implements RegistryService<IZkChildLis // visible for test. ZkClient buildZkClient(String address, int sessionTimeout, int connectTimeout,String... authInfo) { ZkClient zkClient = new ZkClient(address, sessionTimeout, connectTimeout); - if (!zkClient.exists(ROOT_PATH_WITHOUT_SUFFIX)) { - zkClient.createPersistent(ROOT_PATH_WITHOUT_SUFFIX, true); - } - if (null != authInfo && authInfo.length == 2) { + if (authInfo != null && authInfo.length == 2) { if (!StringUtils.isBlank(authInfo[0]) && !StringUtils.isBlank(authInfo[1])) { StringBuilder auth = new StringBuilder(authInfo[0]).append(":").append(authInfo[1]); zkClient.addAuthInfo("digest", auth.toString().getBytes()); } } + if (!zkClient.exists(ROOT_PATH_WITHOUT_SUFFIX)) { + zkClient.createPersistent(ROOT_PATH_WITHOUT_SUFFIX, true); + } zkClient.subscribeStateChanges(new IZkStateListener() { @Override diff --git a/distribution/pom.xml b/distribution/pom.xml index b9d46b7a6c0b146cf356a71fc1bd0e02a4f8062b..2da229687288b89594bcce7568591231ebdae4bb 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -27,11 +27,6 @@ <packaging>pom</packaging> <name>seata-distribution ${project.version}</name> - <properties> - <mysql.jdbc.version>5.1.35</mysql.jdbc.version> - <mysql8.jdbc.version>8.0.19</mysql8.jdbc.version> - </properties> - <dependencies> <dependency> <groupId>io.seata</groupId> diff --git a/integration/dubbo-alibaba/src/main/java/io/seata/integration/dubbo/alibaba/AlibabaDubboTransactionPropagationFilter.java b/integration/dubbo-alibaba/src/main/java/io/seata/integration/dubbo/alibaba/AlibabaDubboTransactionPropagationFilter.java index e3134a415db85808709dbd0b4922302a6edb3180..55341999b2270643f472dffa83538004f049d4b8 100644 --- a/integration/dubbo-alibaba/src/main/java/io/seata/integration/dubbo/alibaba/AlibabaDubboTransactionPropagationFilter.java +++ b/integration/dubbo-alibaba/src/main/java/io/seata/integration/dubbo/alibaba/AlibabaDubboTransactionPropagationFilter.java @@ -22,8 +22,10 @@ import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.Result; import com.alibaba.dubbo.rpc.RpcContext; import com.alibaba.dubbo.rpc.RpcException; +import io.seata.common.util.StringUtils; import io.seata.core.context.RootContext; import io.seata.core.constants.DubboConstants; +import io.seata.core.model.BranchType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,45 +45,51 @@ public class AlibabaDubboTransactionPropagationFilter implements Filter { return invoker.invoke(invocation); } String xid = RootContext.getXID(); - String xidInterceptorType = RootContext.getXIDInterceptorType(); + String branchType = RootContext.getBranchType(); String rpcXid = getRpcXid(); - String rpcXidInterceptorType = RpcContext.getContext().getAttachment(RootContext.KEY_XID_INTERCEPTOR_TYPE); + String rpcBranchType = RpcContext.getContext().getAttachment(RootContext.KEY_BRANCH_TYPE); if (LOGGER.isDebugEnabled()) { LOGGER.debug("xid in RootContext[{}] xid in RpcContext[{}]", xid, rpcXid); } boolean bind = false; if (xid != null) { RpcContext.getContext().setAttachment(RootContext.KEY_XID, xid); - RpcContext.getContext().setAttachment(RootContext.KEY_XID_INTERCEPTOR_TYPE, xidInterceptorType); + RpcContext.getContext().setAttachment(RootContext.KEY_BRANCH_TYPE, branchType); } else { if (rpcXid != null) { RootContext.bind(rpcXid); - RootContext.bindInterceptorType(rpcXidInterceptorType); + if (StringUtils.equals(BranchType.TCC.name(), rpcBranchType)) { + RootContext.bindBranchType(BranchType.TCC); + } bind = true; if (LOGGER.isDebugEnabled()) { - LOGGER.debug("bind[{}] interceptorType[{}] to RootContext", rpcXid, rpcXidInterceptorType); + LOGGER.debug("bind xid [{}] branchType [{}] to RootContext", rpcXid, rpcBranchType); } } } try { return invoker.invoke(invocation); - } finally { if (bind) { - String unbindInterceptorType = RootContext.unbindInterceptorType(); String unbindXid = RootContext.unbind(); + String previousBranchType = RootContext.getBranchType(); + if (StringUtils.equals(BranchType.TCC.name(), previousBranchType)) { + RootContext.unbindBranchType(); + } if (LOGGER.isDebugEnabled()) { - LOGGER.debug("unbind[{}] interceptorType[{}] from RootContext", unbindXid, unbindInterceptorType); + LOGGER.debug("unbind xid [{}] branchType [{}] from RootContext", unbindXid, previousBranchType); } if (!rpcXid.equalsIgnoreCase(unbindXid)) { - LOGGER.warn("xid in change during RPC from {} to {}, xidInterceptorType from {} to {} ", rpcXid, - unbindXid, rpcXidInterceptorType, unbindInterceptorType); + LOGGER.warn("xid in change during RPC from {} to {},branchType from {} to {}", rpcXid, unbindXid, + rpcBranchType != null ? rpcBranchType : "AT", previousBranchType); if (unbindXid != null) { RootContext.bind(unbindXid); - RootContext.bindInterceptorType(unbindInterceptorType); - LOGGER.warn("bind [{}] interceptorType[{}] back to RootContext", unbindXid, - unbindInterceptorType); + LOGGER.warn("bind xid [{}] back to RootContext", unbindXid); + if (StringUtils.equals(BranchType.TCC.name(), previousBranchType)) { + RootContext.bindBranchType(BranchType.TCC); + LOGGER.warn("bind branchType [{}] back to RootContext", previousBranchType); + } } } } diff --git a/integration/dubbo/src/main/java/io/seata/integration/dubbo/ApacheDubboTransactionPropagationFilter.java b/integration/dubbo/src/main/java/io/seata/integration/dubbo/ApacheDubboTransactionPropagationFilter.java index 82abbe6f1017050c3f5fd3ebc24b8f49bde5d621..8a40ed20a39f7eb2055c83915c322bd4d00b6825 100644 --- a/integration/dubbo/src/main/java/io/seata/integration/dubbo/ApacheDubboTransactionPropagationFilter.java +++ b/integration/dubbo/src/main/java/io/seata/integration/dubbo/ApacheDubboTransactionPropagationFilter.java @@ -15,7 +15,10 @@ */ package io.seata.integration.dubbo; +import io.seata.common.util.StringUtils; +import io.seata.core.constants.DubboConstants; import io.seata.core.context.RootContext; +import io.seata.core.model.BranchType; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.rpc.Filter; import org.apache.dubbo.rpc.Invocation; @@ -25,7 +28,6 @@ import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.seata.core.constants.DubboConstants; /** * The type Transaction propagation filter. @@ -40,24 +42,26 @@ public class ApacheDubboTransactionPropagationFilter implements Filter { @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { String xid = RootContext.getXID(); - String xidInterceptorType = RootContext.getXIDInterceptorType(); + String branchType = RootContext.getBranchType(); String rpcXid = getRpcXid(); - String rpcXidInterceptorType = RpcContext.getContext().getAttachment(RootContext.KEY_XID_INTERCEPTOR_TYPE); + String rpcBranchType = RpcContext.getContext().getAttachment(RootContext.KEY_BRANCH_TYPE); if (LOGGER.isDebugEnabled()) { LOGGER.debug("xid in RootContext[{}] xid in RpcContext[{}]", xid, rpcXid); } boolean bind = false; if (xid != null) { RpcContext.getContext().setAttachment(RootContext.KEY_XID, xid); - RpcContext.getContext().setAttachment(RootContext.KEY_XID_INTERCEPTOR_TYPE, xidInterceptorType); + RpcContext.getContext().setAttachment(RootContext.KEY_BRANCH_TYPE, branchType); } else { if (rpcXid != null) { RootContext.bind(rpcXid); - RootContext.bindInterceptorType(rpcXidInterceptorType); + if (StringUtils.equals(BranchType.TCC.name(), rpcBranchType)) { + RootContext.bindBranchType(BranchType.TCC); + } bind = true; if (LOGGER.isDebugEnabled()) { - LOGGER.debug("bind[{}] interceptorType[{}] to RootContext", rpcXid, rpcXidInterceptorType); + LOGGER.debug("bind xid [{}] branchType [{}] to RootContext", rpcXid, rpcBranchType); } } } @@ -65,17 +69,24 @@ public class ApacheDubboTransactionPropagationFilter implements Filter { return invoker.invoke(invocation); } finally { if (bind) { - String unbindInterceptorType = RootContext.unbindInterceptorType(); String unbindXid = RootContext.unbind(); + String previousBranchType = RootContext.getBranchType(); + if (StringUtils.equals(BranchType.TCC.name(), previousBranchType)) { + RootContext.unbindBranchType(); + } if (LOGGER.isDebugEnabled()) { - LOGGER.debug("unbind[{}] interceptorType[{}] from RootContext", unbindXid, unbindInterceptorType); + LOGGER.debug("unbind xid [{}] branchType [{}] from RootContext", unbindXid, previousBranchType); } if (!rpcXid.equalsIgnoreCase(unbindXid)) { - LOGGER.warn("xid in change during RPC from {} to {}, xidInterceptorType from {} to {} ", rpcXid, unbindXid, rpcXidInterceptorType, unbindInterceptorType); + LOGGER.warn("xid in change during RPC from {} to {},branchType from {} to {}", rpcXid, unbindXid, + rpcBranchType != null ? rpcBranchType : "AT", previousBranchType); if (unbindXid != null) { RootContext.bind(unbindXid); - RootContext.bindInterceptorType(unbindInterceptorType); - LOGGER.warn("bind [{}] interceptorType[{}] back to RootContext", unbindXid, unbindInterceptorType); + LOGGER.warn("bind xid [{}] back to RootContext", unbindXid); + if (StringUtils.equals(BranchType.TCC.name(), previousBranchType)) { + RootContext.bindBranchType(BranchType.TCC); + LOGGER.warn("bind branchType [{}] back to RootContext", previousBranchType); + } } } } diff --git a/integration/http/src/test/java/io/seata/integration/http/MockWebServer.java b/integration/http/src/test/java/io/seata/integration/http/MockWebServer.java index f550c3c20159a37f0d26fd1806db8d33a2376b70..b38ab461db6e8fcf05f8b30040d5b2eec277d650 100644 --- a/integration/http/src/test/java/io/seata/integration/http/MockWebServer.java +++ b/integration/http/src/test/java/io/seata/integration/http/MockWebServer.java @@ -57,7 +57,7 @@ public class MockWebServer { } catch (IOException e) { e.printStackTrace(); } finally { - if (null != serverSocket) { + if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { @@ -123,9 +123,6 @@ public class MockWebServer { return map; } - public static void main(String[] args) { - new MockWebServer().start(8081); - } public static Map<String, Object> getUrlParams(String param) { Map<String, Object> map = new HashMap<String, Object>(0); diff --git a/integration/motan/src/main/java/io/seata/integration/motan/MotanTransactionFilter.java b/integration/motan/src/main/java/io/seata/integration/motan/MotanTransactionFilter.java index 4b0d34d3956f6b668e9bcaa65faedf5f4a3e7853..d4a76033277cd7175078bb00ceb1a2ff2efdb6c8 100644 --- a/integration/motan/src/main/java/io/seata/integration/motan/MotanTransactionFilter.java +++ b/integration/motan/src/main/java/io/seata/integration/motan/MotanTransactionFilter.java @@ -46,7 +46,7 @@ public class MotanTransactionFilter implements Filter { boolean bind = false; if (currentXid != null) { request.getAttachments().put(RootContext.KEY_XID, currentXid); - } else if (null != requestXid) { + } else if (requestXid != null) { RootContext.bind(requestXid); bind = true; if (LOGGER.isDebugEnabled()) { diff --git a/metrics/seata-metrics-core/src/main/java/io/seata/metrics/exporter/ExporterType.java b/metrics/seata-metrics-core/src/main/java/io/seata/metrics/exporter/ExporterType.java index 5342149902e6ac38cebad2a0ba54ba336b7bff54..a147a4d5039c58ddba5a95e097e476827c6eaffe 100644 --- a/metrics/seata-metrics-core/src/main/java/io/seata/metrics/exporter/ExporterType.java +++ b/metrics/seata-metrics-core/src/main/java/io/seata/metrics/exporter/ExporterType.java @@ -15,8 +15,6 @@ */ package io.seata.metrics.exporter; -import io.seata.common.exception.NotSupportYetException; - /** * Supported metrics exporter type * @@ -42,7 +40,7 @@ public enum ExporterType { if (PROMETHEUS.name().equalsIgnoreCase(name)) { return PROMETHEUS; } else { - throw new NotSupportYetException("unsupported type:" + name); + throw new IllegalArgumentException("not support exporter type: " + name); } } } diff --git a/metrics/seata-metrics-core/src/main/java/io/seata/metrics/registry/RegistryType.java b/metrics/seata-metrics-core/src/main/java/io/seata/metrics/registry/RegistryType.java index 5b15d4a42043fee537468d188b3bf9b9290e4638..6c3f5bc6193959c4d57a8ee3d2094134f8a94f59 100644 --- a/metrics/seata-metrics-core/src/main/java/io/seata/metrics/registry/RegistryType.java +++ b/metrics/seata-metrics-core/src/main/java/io/seata/metrics/registry/RegistryType.java @@ -15,8 +15,6 @@ */ package io.seata.metrics.registry; -import io.seata.common.exception.NotSupportYetException; - /** * Supported metrics registry type * @@ -42,7 +40,7 @@ public enum RegistryType { if (COMPACT.name().equalsIgnoreCase(name)) { return COMPACT; } else { - throw new NotSupportYetException("unsupported type:" + name); + throw new IllegalArgumentException("not support registry type: " + name); } } } diff --git a/pom.xml b/pom.xml index 75218d748174e532ddec6341a125ad013bcae3fd..019ceb1c06c70f422a2d6807e3a1955a6db854e6 100644 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,7 @@ <developer> <id>Seata</id> <name>Seata</name> - <url>http://seata.io</url> + <url>https://seata.io</url> </developer> </developers> @@ -88,7 +88,7 @@ <properties> <!-- seata version --> - <revision>1.2.0</revision> + <revision>1.3.0</revision> <!-- Compiler settings properties --> <maven.compiler.source>1.8</maven.compiler.source> @@ -121,6 +121,9 @@ <checkstyle.skip>true</checkstyle.skip> <license.skip>true</license.skip> + <!-- for jdbc driver when package --> + <mysql.jdbc.version>5.1.35</mysql.jdbc.version> + <mysql8.jdbc.version>8.0.19</mysql8.jdbc.version> </properties> <!--test--> @@ -336,12 +339,11 @@ <encoding>UTF-8</encoding> <consoleOutput>true</consoleOutput> <failsOnError>true</failsOnError> - <failOnViolation>false</failOnViolation> <excludes>**/generated/**/*</excludes> <excludes>io/seata/integration/grpc/interceptor/</excludes> </configuration> <goals> - <goal>check</goal> + <goal>checkstyle</goal> </goals> </execution> </executions> diff --git a/rm-datasource/pom.xml b/rm-datasource/pom.xml index 5e56a1e2d4ac80a64894b8eb75f098e8aadf30cc..a9bda3b8e45cc2881255633ab20661995c1aae56 100644 --- a/rm-datasource/pom.xml +++ b/rm-datasource/pom.xml @@ -83,7 +83,6 @@ <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> - <scope>test</scope> </dependency> <dependency> diff --git a/rm-datasource/src/main/java/io/seata/rm/GlobalLockTemplate.java b/rm-datasource/src/main/java/io/seata/rm/GlobalLockTemplate.java index 2a92a144fe9d245ffadbde257235227a77525ba9..2127e7a6d7766a149b39a6e32e8d419378f4784f 100644 --- a/rm-datasource/src/main/java/io/seata/rm/GlobalLockTemplate.java +++ b/rm-datasource/src/main/java/io/seata/rm/GlobalLockTemplate.java @@ -37,15 +37,20 @@ public class GlobalLockTemplate<T> { public Object execute(Callable<T> business) throws Exception { Object rs; - try { - // add global lock declare + //fix nested situation + boolean hasInGlobalLock = RootContext.requireGlobalLock(); + // add global lock declare + if (!hasInGlobalLock) { RootContext.bindGlobalLockFlag(); - + } + try { // Do Your Business rs = business.call(); } finally { //clean the global lock declare - RootContext.unbindGlobalLockFlag(); + if (!hasInGlobalLock) { + RootContext.unbindGlobalLockFlag(); + } } return rs; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractConnectionProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractConnectionProxy.java index 6c97d0d571096ae4df6bd7d4c79a8e7b1b1f65cf..3046ecacb00140e253bf7c55e2c766e0c15888cb 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractConnectionProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractConnectionProxy.java @@ -15,13 +15,14 @@ */ package io.seata.rm.datasource; +import io.seata.common.util.StringUtils; import io.seata.core.context.RootContext; +import io.seata.core.model.BranchType; import io.seata.rm.datasource.sql.SQLVisitorFactory; import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.SQLType; - import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; @@ -108,15 +109,16 @@ public abstract class AbstractConnectionProxy implements Connection { String dbType = getDbType(); // support oracle 10.2+ PreparedStatement targetPreparedStatement = null; - if (RootContext.inGlobalTransaction()) { + if (StringUtils.equals(BranchType.AT.name(), RootContext.getBranchType())) { List<SQLRecognizer> sqlRecognizers = SQLVisitorFactory.get(sql, dbType); if (sqlRecognizers != null && sqlRecognizers.size() == 1) { SQLRecognizer sqlRecognizer = sqlRecognizers.get(0); if (sqlRecognizer != null && sqlRecognizer.getSQLType() == SQLType.INSERT) { - String tableName = ColumnUtils.delEscape(sqlRecognizer.getTableName(), dbType); TableMeta tableMeta = TableMetaCacheFactory.getTableMetaCache(dbType).getTableMeta(getTargetConnection(), - tableName, getDataSourceProxy().getResourceId()); - targetPreparedStatement = getTargetConnection().prepareStatement(sql, new String[]{tableMeta.getPkName()}); + sqlRecognizer.getTableName(), getDataSourceProxy().getResourceId()); + String[] pkNameArray = new String[tableMeta.getPrimaryKeyOnlyName().size()]; + tableMeta.getPrimaryKeyOnlyName().toArray(pkNameArray); + targetPreparedStatement = getTargetConnection().prepareStatement(sql,pkNameArray); } } } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java index 1984393514ea138098eece7d329d43afdb2f4578..93792ef8c089da044e75e0fe7a5ae3221d8505ec 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java @@ -14,8 +14,8 @@ * limitations under the License. */ package io.seata.rm.datasource; -import io.seata.sqlparser.struct.Null; +import io.seata.sqlparser.struct.Null; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; @@ -36,7 +36,9 @@ import java.sql.Time; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * The type Abstract prepared statement proxy. @@ -49,14 +51,10 @@ public abstract class AbstractPreparedStatementProxy extends StatementProxy<Prep /** * The Parameters. */ - protected ArrayList<Object>[] parameters; + protected Map<Integer,ArrayList<Object>> parameters; - private void initParameterHolder() throws SQLException { - int paramCount = targetStatement.getParameterMetaData().getParameterCount(); - this.parameters = new ArrayList[paramCount]; - for (int i = 0; i < paramCount; i++) { - parameters[i] = new ArrayList<>(); - } + private void initParameterHolder() { + this.parameters = new HashMap<>(); } /** @@ -93,7 +91,7 @@ public abstract class AbstractPreparedStatementProxy extends StatementProxy<Prep * @return the params by index */ public List<Object> getParamsByIndex(int index) { - return parameters[index]; + return parameters.get(index); } /** @@ -103,7 +101,7 @@ public abstract class AbstractPreparedStatementProxy extends StatementProxy<Prep * @param x the x */ protected void setParamByIndex(int index, Object x) { - parameters[--index].add(x); + parameters.computeIfAbsent(index,e -> new ArrayList<>()).add(x); } @Override diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractStatementProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractStatementProxy.java index 69d590904c0a8387da0e9aa023710afdf972329b..584138e23a0aff19426179a7e0950bd0917305e4 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractStatementProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractStatementProxy.java @@ -15,6 +15,8 @@ */ package io.seata.rm.datasource; +import javax.sql.rowset.CachedRowSet; +import javax.sql.rowset.RowSetProvider; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -40,6 +42,11 @@ public abstract class AbstractStatementProxy<T extends Statement> implements Sta */ protected T targetStatement; + /** + * The generated keys cached row set. + */ + private CachedRowSet generatedKeysRowSet; + /** * The Target sql. */ @@ -242,7 +249,13 @@ public abstract class AbstractStatementProxy<T extends Statement> implements Sta @Override public ResultSet getGeneratedKeys() throws SQLException { - return targetStatement.getGeneratedKeys(); + if (generatedKeysRowSet != null) { + return generatedKeysRowSet; + } + ResultSet rs = targetStatement.getGeneratedKeys(); + generatedKeysRowSet = RowSetProvider.newFactory().createCachedRowSet(); + generatedKeysRowSet.populate(rs); + return generatedKeysRowSet; } @Override diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/ColumnUtils.java b/rm-datasource/src/main/java/io/seata/rm/datasource/ColumnUtils.java index 4f70009f20593b44e8f24d8011e8993cf51f6a35..4b584be904371d7a178bc7e0b40c795687da848d 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/ColumnUtils.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/ColumnUtils.java @@ -30,6 +30,8 @@ import java.util.List; */ public final class ColumnUtils { + private static final String DOT = "."; + /** * The escape */ @@ -107,6 +109,11 @@ public final class ColumnUtils { return colName; } if (colName.charAt(0) == escape.value && colName.charAt(colName.length() - 1) == escape.value) { + final String withScheme = escape.value + DOT + escape.value; + int index = colName.indexOf(withScheme); + if (index > -1) { + return colName.substring(1, index) + DOT + colName.substring(index + withScheme.length(), colName.length() - 1); + } return colName.substring(1, colName.length() - 1); } return colName; @@ -166,8 +173,13 @@ public final class ColumnUtils { } } - StringBuilder result = new StringBuilder(2 * (String.valueOf(escape.value).length()) + colName.length()); - return result.append(escape.value).append(colName).append(escape.value).toString(); + char[] buf = new char[colName.length() + 2]; + buf[0] = escape.value; + buf[buf.length - 1] = escape.value; + + colName.getChars(0,colName.length(),buf,1); + + return new String(buf).intern(); } private static boolean isMysqlSeries(String dbType) { diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/DataCompareUtils.java b/rm-datasource/src/main/java/io/seata/rm/datasource/DataCompareUtils.java index 36209b0193c5c62626f18e883933560f77974f0c..4e1ec2903e8ce9fe081613556f490c962362f1bf 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/DataCompareUtils.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/DataCompareUtils.java @@ -28,10 +28,12 @@ import io.seata.rm.datasource.undo.parser.FastjsonUndoLogParser; import java.math.BigDecimal; import java.sql.Timestamp; import java.sql.Types; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.HashMap; +import java.util.Comparator; +import java.util.stream.Collectors; /** * The type Data compare utils. @@ -59,7 +61,7 @@ public class DataCompareUtils { return Result.build(false); } else { if (StringUtils.equalsIgnoreCase(f0.getName(), f1.getName()) - && f0.getType() == f1.getType()) { + && f0.getType() == f1.getType()) { if (f0.getValue() == null) { return Result.build(f1.getValue() == null); } else { @@ -123,7 +125,7 @@ public class DataCompareUtils { return Result.build(false, null); } if (beforeImage.getTableName().equalsIgnoreCase(afterImage.getTableName()) - && CollectionUtils.isSizeEquals(beforeImage.getRows(), afterImage.getRows())) { + && CollectionUtils.isSizeEquals(beforeImage.getRows(), afterImage.getRows())) { //when image is EmptyTableRecords, getTableMeta will throw an exception if (CollectionUtils.isEmpty(beforeImage.getRows())) { return Result.ok(); @@ -153,9 +155,9 @@ public class DataCompareUtils { private static Result<Boolean> compareRows(TableMeta tableMetaData, List<Row> oldRows, List<Row> newRows) { // old row to map - Map<String, Map<String, Field>> oldRowsMap = rowListToMap(oldRows, tableMetaData.getPkName()); + Map<String, Map<String, Field>> oldRowsMap = rowListToMap(oldRows, tableMetaData.getPrimaryKeyOnlyName()); // new row to map - Map<String, Map<String, Field>> newRowsMap = rowListToMap(newRows, tableMetaData.getPkName()); + Map<String, Map<String, Field>> newRowsMap = rowListToMap(newRows, tableMetaData.getPrimaryKeyOnlyName()); // compare data for (Map.Entry<String, Map<String, Field>> oldEntry : oldRowsMap.entrySet()) { String key = oldEntry.getKey(); @@ -180,23 +182,33 @@ public class DataCompareUtils { return Result.ok(); } - private static Map<String, Map<String, Field>> rowListToMap(List<Row> rowList, String primaryKey) { + public static Map<String, Map<String, Field>> rowListToMap(List<Row> rowList, List<String> primaryKeyList) { // {value of primaryKey, value of all columns} Map<String, Map<String, Field>> rowMap = new HashMap<>(); for (Row row : rowList) { + //ensure the order of column + List<Field> rowFieldList = row.getFields().stream() + .sorted(Comparator.comparing(Field::getName)) + .collect(Collectors.toList()); // {uppercase fieldName : field} Map<String, Field> colsMap = new HashMap<>(); - String rowKey = null; - for (int j = 0; j < row.getFields().size(); j++) { - Field field = row.getFields().get(j); - if (field.getName().equalsIgnoreCase(primaryKey)) { - rowKey = String.valueOf(field.getValue()); + StringBuilder rowKey = new StringBuilder(); + boolean firstUnderline = false; + for (int j = 0; j < rowFieldList.size(); j++) { + Field field = rowFieldList.get(j); + if (primaryKeyList.stream().anyMatch(e -> field.getName().equals(e))) { + if (firstUnderline && j > 0) { + rowKey.append("_"); + } + rowKey.append(String.valueOf(field.getValue())); + firstUnderline = true; } colsMap.put(field.getName().trim().toUpperCase(), field); } - rowMap.put(rowKey, colsMap); + rowMap.put(rowKey.toString(), colsMap); } return rowMap; } + } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java index da63ee70a0731454faba4a6e455f0bff7c81e6e9..a42a23ed3d44cb6d6f6991e66d7ac4a04252455b 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java @@ -15,12 +15,6 @@ */ package io.seata.rm.datasource; -import java.net.InetSocketAddress; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeoutException; - import io.seata.common.exception.FrameworkException; import io.seata.common.exception.NotSupportYetException; import io.seata.common.exception.ShouldNeverHappenException; @@ -38,9 +32,8 @@ import io.seata.core.model.ResourceManagerInbound; import io.seata.core.protocol.ResultCode; import io.seata.core.protocol.transaction.GlobalLockQueryRequest; import io.seata.core.protocol.transaction.GlobalLockQueryResponse; -import io.seata.core.rpc.netty.NettyClientConfig; -import io.seata.core.rpc.netty.RmRpcClient; -import io.seata.core.rpc.netty.TmRpcClient; +import io.seata.core.rpc.netty.RmNettyRemotingClient; +import io.seata.core.rpc.netty.TmNettyRemotingClient; import io.seata.discovery.loadbalance.LoadBalanceFactory; import io.seata.discovery.registry.RegistryFactory; import io.seata.rm.AbstractResourceManager; @@ -48,6 +41,12 @@ import io.seata.rm.datasource.undo.UndoLogManagerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.net.InetSocketAddress; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeoutException; + import static io.seata.common.exception.FrameworkErrorCode.NoAvailableService; /** @@ -82,11 +81,8 @@ public class DataSourceManager extends AbstractResourceManager implements Initia request.setResourceId(resourceId); GlobalLockQueryResponse response = null; - if (RootContext.inGlobalTransaction()) { - response = (GlobalLockQueryResponse)RmRpcClient.getInstance().sendMsgWithResponse(request); - } else if (RootContext.requireGlobalLock()) { - response = (GlobalLockQueryResponse)RmRpcClient.getInstance().sendMsgWithResponse(loadBalance(), - request, NettyClientConfig.getRpcRequestTimeout()); + if (RootContext.inGlobalTransaction() || RootContext.requireGlobalLock()) { + response = (GlobalLockQueryResponse) RmNettyRemotingClient.getInstance().sendSyncRequest(request); } else { throw new RuntimeException("unknow situation!"); } @@ -104,12 +100,13 @@ public class DataSourceManager extends AbstractResourceManager implements Initia } + @Deprecated @SuppressWarnings("unchecked") private String loadBalance() { InetSocketAddress address = null; try { List<InetSocketAddress> inetSocketAddressList = RegistryFactory.getInstance().lookup( - TmRpcClient.getInstance().getTransactionServiceGroup()); + TmNettyRemotingClient.getInstance().getTransactionServiceGroup()); address = LoadBalanceFactory.getInstance().select(inetSocketAddressList); } catch (Exception ignore) { LOGGER.error(ignore.getMessage()); @@ -144,7 +141,7 @@ public class DataSourceManager extends AbstractResourceManager implements Initia @Override public void registerResource(Resource resource) { - DataSourceProxy dataSourceProxy = (DataSourceProxy)resource; + DataSourceProxy dataSourceProxy = (DataSourceProxy) resource; dataSourceCache.put(dataSourceProxy.getResourceId(), dataSourceProxy); super.registerResource(dataSourceProxy); } @@ -161,7 +158,7 @@ public class DataSourceManager extends AbstractResourceManager implements Initia * @return the data source proxy */ public DataSourceProxy get(String resourceId) { - return (DataSourceProxy)dataSourceCache.get(resourceId); + return (DataSourceProxy) dataSourceCache.get(resourceId); } @Override diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java index 49078360ee7bb85902d09d2e23e6c4dac3e98adb..cdbaa27e7d63a5a4fda87cd44e929e43492da535 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java @@ -30,6 +30,7 @@ import io.seata.core.model.Resource; import io.seata.rm.DefaultResourceManager; import io.seata.rm.datasource.sql.struct.TableMetaCacheFactory; import io.seata.rm.datasource.util.JdbcUtils; +import io.seata.sqlparser.util.JdbcConstants; import static io.seata.core.constants.DefaultValues.DEFAULT_CLIENT_TABLE_META_CHECK_ENABLE; @@ -48,6 +49,8 @@ public class DataSourceProxy extends AbstractDataSourceProxy implements Resource private String dbType; + private String userName; + /** * Enable the table meta checker */ @@ -87,6 +90,9 @@ public class DataSourceProxy extends AbstractDataSourceProxy implements Resource try (Connection connection = dataSource.getConnection()) { jdbcUrl = connection.getMetaData().getURL(); dbType = JdbcUtils.getDbType(jdbcUrl); + if (JdbcConstants.ORACLE.equals(dbType)) { + userName = connection.getMetaData().getUserName(); + } } catch (SQLException e) { throw new IllegalStateException("can not init dataSource", e); } @@ -140,6 +146,20 @@ public class DataSourceProxy extends AbstractDataSourceProxy implements Resource @Override public String getResourceId() { + if (JdbcConstants.POSTGRESQL.equals(dbType)) { + return getPGResourceId(); + } else if (JdbcConstants.ORACLE.equals(dbType) && userName != null) { + return getDefaultResourceId() + "/" + userName; + } else { + return getDefaultResourceId(); + } + } + + /** + * get the default resource id + * @return resource id + */ + private String getDefaultResourceId() { if (jdbcUrl.contains("?")) { return jdbcUrl.substring(0, jdbcUrl.indexOf('?')); } else { @@ -147,6 +167,40 @@ public class DataSourceProxy extends AbstractDataSourceProxy implements Resource } } + /** + * prevent pg sql url like + * jdbc:postgresql://127.0.0.1:5432/seata?currentSchema=public + * jdbc:postgresql://127.0.0.1:5432/seata?currentSchema=seata + * cause the duplicated resourceId + * it will cause the problem like + * 1.get file lock fail + * 2.error table meta cache + * @return resourceId + */ + private String getPGResourceId() { + if (jdbcUrl.contains("?")) { + StringBuilder jdbcUrlBuilder = new StringBuilder(); + jdbcUrlBuilder.append(jdbcUrl.substring(0, jdbcUrl.indexOf('?'))); + StringBuilder paramsBuilder = new StringBuilder(); + String paramUrl = jdbcUrl.substring(jdbcUrl.indexOf('?') + 1, jdbcUrl.length()); + String[] urlParams = paramUrl.split("&"); + for (String urlParam : urlParams) { + if (urlParam.contains("currentSchema")) { + paramsBuilder.append(urlParam); + break; + } + } + + if (paramsBuilder.length() > 0) { + jdbcUrlBuilder.append("?"); + jdbcUrlBuilder.append(paramsBuilder); + } + return jdbcUrlBuilder.toString(); + } else { + return jdbcUrl; + } + } + @Override public BranchType getBranchType() { return BranchType.AT; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java index 699a96792c3dfd901f4afc52a8f3ed953b1d2871..1272ca672ebdfe159bf64d36905f0461ad64ebc7 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java @@ -19,6 +19,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Map; import io.seata.rm.datasource.exec.ExecuteTemplate; import io.seata.sqlparser.ParametersHolder; @@ -32,7 +33,7 @@ public class PreparedStatementProxy extends AbstractPreparedStatementProxy implements PreparedStatement, ParametersHolder { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { return parameters; } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/SqlGenerateUtils.java b/rm-datasource/src/main/java/io/seata/rm/datasource/SqlGenerateUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..10cf6871e1613a16e9f0776032fee2daddcb2cd1 --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/SqlGenerateUtils.java @@ -0,0 +1,120 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.rm.datasource; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +import io.seata.rm.datasource.sql.struct.Field; + +/** + * generate sql and set value to sql + * + * @author JerryYin + */ +public class SqlGenerateUtils { + + private SqlGenerateUtils() { + + } + + /** + * each pk is a condition.the result will like :" (id,userCode) in ((?,?) (?,?))" + * Build where condition by pks string. + * + * @param pkNameList pk column name list + * @param rowSize the row size of records + * @param dbType the type of database + * @return return where condition sql string.the sql can search all related records not just one. + * @throws SQLException the sql exception + */ + public static String buildWhereConditionByPKs(List<String> pkNameList, int rowSize, String dbType) + throws SQLException { + StringBuilder whereStr = new StringBuilder(); + //we must consider the situation of composite primary key + + whereStr.append(" ("); + for (int i = 0; i < pkNameList.size(); i++) { + if (i > 0) { + whereStr.append(","); + } + whereStr.append(ColumnUtils.addEscape(pkNameList.get(i), dbType)); + } + whereStr.append(" ) in ( "); + + for (int i = 0; i < rowSize; i++) { + //each row is a bracket + if (i > 0) { + whereStr.append(","); + } + whereStr.append(" ("); + for (int x = 0; x < pkNameList.size(); x++) { + if (x > 0) { + whereStr.append(","); + } + whereStr.append("?"); + } + whereStr.append(") "); + } + whereStr.append(" )"); + + return whereStr.toString(); + } + + /** + * set parameter for PreparedStatement, this is only used in pk sql. + * + * @param pkRowsList + * @param pkColumnNameList + * @param pst + * @throws SQLException + */ + public static void setParamForPk(List<Map<String, Field>> pkRowsList, List<String> pkColumnNameList, + PreparedStatement pst) throws SQLException { + int paramIndex = 1; + for (int i = 0; i < pkRowsList.size(); i++) { + Map<String, Field> rowData = pkRowsList.get(i); + for (String columnName : pkColumnNameList) { + Field pkField = rowData.get(columnName); + pst.setObject(paramIndex, pkField.getValue(), pkField.getType()); + paramIndex++; + } + } + } + + /** + * each pk is a condition.the result will like :" id =? and userCode =?" + * + * @param pkNameList + * @return return where condition sql string.the sql can just search one related record. + */ + public static String buildWhereConditionByPKs(List<String> pkNameList, String dbType) { + StringBuilder whereStr = new StringBuilder(); + //we must consider the situation of composite primary key + for (int i = 0; i < pkNameList.size(); i++) { + if (i > 0) { + whereStr.append(" and "); + } + String pkName = pkNameList.get(i); + whereStr.append(ColumnUtils.addEscape(pkName, dbType)); + whereStr.append(" = ? "); + } + return whereStr.toString(); + } + +} diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java index abd864d0c6eea6ab0645914b1030778c6e0b2c90..348866e8802c7e970fb3a1decf361a4fa1004ea1 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java @@ -21,12 +21,14 @@ import java.sql.Statement; import java.util.List; import java.util.concurrent.Callable; +import io.seata.common.exception.NotSupportYetException; import io.seata.rm.datasource.AbstractConnectionProxy; import io.seata.rm.datasource.ConnectionContext; import io.seata.rm.datasource.ConnectionProxy; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLRecognizer; +import io.seata.sqlparser.util.JdbcConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,7 +60,7 @@ public abstract class AbstractDMLBaseExecutor<T, S extends Statement> extends Ba * * @param statementProxy the statement proxy * @param statementCallback the statement callback - * @param sqlRecognizer the multi sql recognizer + * @param sqlRecognizers the multi sql recognizer */ public AbstractDMLBaseExecutor(StatementProxy<S> statementProxy, StatementCallback<T, S> statementCallback, List<SQLRecognizer> sqlRecognizers) { @@ -83,6 +85,10 @@ public abstract class AbstractDMLBaseExecutor<T, S extends Statement> extends Ba * @throws Exception the exception */ protected T executeAutoCommitFalse(Object[] args) throws Exception { + if (!JdbcConstants.MYSQL.equalsIgnoreCase(getDbType()) && getTableMeta().getPrimaryKeyOnlyName().size() > 1) + { + throw new NotSupportYetException("multi pk only support mysql!"); + } TableRecords beforeImage = beforeImage(); T result = statementCallback.execute(statementProxy.getTargetStatement(), args); TableRecords afterImage = afterImage(beforeImage); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseInsertExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..e2b66ea834a1df7c096a78fbc10b3597b312d1da --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseInsertExecutor.java @@ -0,0 +1,408 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.rm.datasource.exec; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Objects; + +import com.google.common.collect.Lists; +import io.seata.common.exception.NotSupportYetException; +import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.util.CollectionUtils; +import io.seata.rm.datasource.ColumnUtils; +import io.seata.rm.datasource.PreparedStatementProxy; +import io.seata.rm.datasource.StatementProxy; +import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.rm.datasource.sql.struct.TableRecords; +import io.seata.sqlparser.SQLInsertRecognizer; +import io.seata.sqlparser.SQLRecognizer; +import io.seata.sqlparser.struct.Null; +import io.seata.sqlparser.struct.Sequenceable; +import io.seata.sqlparser.struct.SqlDefaultExpr; +import io.seata.sqlparser.struct.SqlMethodExpr; +import io.seata.sqlparser.struct.SqlSequenceExpr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Base Insert Executor. + * @author jsbxyyx + */ +public abstract class BaseInsertExecutor<T, S extends Statement> extends AbstractDMLBaseExecutor<T, S> implements InsertExecutor<T> { + + private static final Logger LOGGER = LoggerFactory.getLogger(BaseInsertExecutor.class); + + protected static final String PLACEHOLDER = "?"; + + /** + * Instantiates a new Abstract dml base executor. + * + * @param statementProxy the statement proxy + * @param statementCallback the statement callback + * @param sqlRecognizer the sql recognizer + */ + public BaseInsertExecutor(StatementProxy<S> statementProxy, StatementCallback<T, S> statementCallback, + SQLRecognizer sqlRecognizer) { + super(statementProxy, statementCallback, sqlRecognizer); + } + + @Override + protected TableRecords beforeImage() throws SQLException { + return TableRecords.empty(getTableMeta()); + } + + @Override + protected TableRecords afterImage(TableRecords beforeImage) throws SQLException { + Map<String,List<Object>> pkValues = getPkValues(); + TableRecords afterImage = buildTableRecords(pkValues); + if (afterImage == null) { + throw new SQLException("Failed to build after-image for insert"); + } + return afterImage; + } + + protected boolean containsPK() { + SQLInsertRecognizer recognizer = (SQLInsertRecognizer) sqlRecognizer; + List<String> insertColumns = recognizer.getInsertColumns(); + if (CollectionUtils.isEmpty(insertColumns)) { + return false; + } + return containsPK(insertColumns); + } + + /** + * judge sql specify column + * @return true: contains column. false: not contains column. + */ + protected boolean containsColumns() { + return !((SQLInsertRecognizer) sqlRecognizer).insertColumnsIsEmpty(); + } + + /** + * get pk index + * @return the key is pk column name and the value is index of the pk column + */ + protected Map<String,Integer> getPkIndex() { + Map<String,Integer> pkIndexMap = new HashMap<>(); + SQLInsertRecognizer recognizer = (SQLInsertRecognizer) sqlRecognizer; + List<String> insertColumns = recognizer.getInsertColumns(); + if (CollectionUtils.isNotEmpty(insertColumns)) { + final int insertColumnsSize = insertColumns.size(); + for (int paramIdx = 0; paramIdx < insertColumnsSize; paramIdx++) { + String sqlColumnName = insertColumns.get(paramIdx); + if (containPK(sqlColumnName)) { + pkIndexMap.put(getStandardColumnName(sqlColumnName),paramIdx); + } + } + return pkIndexMap; + } + int pkIndex = -1; + Map<String, ColumnMeta> allColumns = getTableMeta().getAllColumns(); + for (Map.Entry<String, ColumnMeta> entry : allColumns.entrySet()) { + pkIndex++; + if (containPK(entry.getValue().getColumnName())) { + pkIndexMap.put(ColumnUtils.delEscape(entry.getValue().getColumnName(),getDbType()),pkIndex); + } + } + return pkIndexMap; + } + + + /** + * parse primary key value from statement. + * @return + */ + protected Map<String,List<Object>> parsePkValuesFromStatement() { + // insert values including PK + SQLInsertRecognizer recognizer = (SQLInsertRecognizer) sqlRecognizer; + final Map<String, Integer> pkIndexMap = getPkIndex(); + if (pkIndexMap.isEmpty()) { + throw new ShouldNeverHappenException("pkIndex is not found"); + } + Map<String,List<Object>> pkValuesMap = new HashMap<>(); + boolean ps = true; + if (statementProxy instanceof PreparedStatementProxy) { + PreparedStatementProxy preparedStatementProxy = (PreparedStatementProxy) statementProxy; + + List<List<Object>> insertRows = recognizer.getInsertRows(pkIndexMap.values()); + if (insertRows != null && !insertRows.isEmpty()) { + Map<Integer,ArrayList<Object>> parameters = preparedStatementProxy.getParameters(); + final int rowSize = insertRows.size(); + int totalPlaceholderNum = -1; + for (int i = 0; i < rowSize; i++) { + List<Object> row = insertRows.get(i); + // oracle insert sql statement specify RETURN_GENERATED_KEYS will append :rowid on sql end + // insert parameter count will than the actual +1 + if (row.isEmpty()) { + continue; + } + int currentRowPlaceholderNum = -1; + for (Object r : row) { + if (PLACEHOLDER.equals(r)) { + totalPlaceholderNum += 1; + currentRowPlaceholderNum += 1; + } + } + for (String pkKey:pkIndexMap.keySet()) + { + List pkValues = pkValuesMap.get(pkKey); + if (Objects.isNull(pkValues)) + { + pkValues = new ArrayList(rowSize); + } + int pkIndex = pkIndexMap.get(pkKey); + Object pkValue = row.get(pkIndex); + if (PLACEHOLDER.equals(pkValue)) { + int currentRowNotPlaceholderNumBeforePkIndex = 0; + for (int n = 0, len = row.size(); n < len; n++) { + Object r = row.get(n); + if (n < pkIndex && !PLACEHOLDER.equals(r)) { + currentRowNotPlaceholderNumBeforePkIndex++; + } + } + int idx = totalPlaceholderNum - currentRowPlaceholderNum + pkIndex - currentRowNotPlaceholderNumBeforePkIndex; + ArrayList<Object> parameter = parameters.get(idx + 1); + pkValues.addAll(parameter); + } else { + pkValues.add(pkValue); + } + if (!pkValuesMap.containsKey(ColumnUtils.delEscape(pkKey, getDbType()))) + { + pkValuesMap.put(ColumnUtils.delEscape(pkKey, getDbType()), pkValues); + } + } + } + } + } else { + ps = false; + List<List<Object>> insertRows = recognizer.getInsertRows(pkIndexMap.values()); + for (List<Object> row : insertRows) { + for (String pkKey:pkIndexMap.keySet()) { + int pkIndex = pkIndexMap.get(pkKey); + List<Object> pkValues = pkValuesMap.get(pkKey); + if (Objects.isNull(pkValues)) { + pkValuesMap.put(ColumnUtils.delEscape(pkKey, getDbType()), Lists.newArrayList(row.get(pkIndex))); + } else { + pkValues.add(row.get(pkIndex)); + } + } + } + } + if (pkValuesMap.isEmpty()) { + throw new ShouldNeverHappenException(); + } + boolean b = this.checkPkValues(pkValuesMap, ps); + if (!b) { + throw new NotSupportYetException(String.format("not support sql [%s]", sqlRecognizer.getOriginalSQL())); + } + return pkValuesMap; + } + + /** + * default get generated keys. + * @return + * @throws SQLException + */ + public List<Object> getGeneratedKeys() throws SQLException { + // PK is just auto generated + ResultSet genKeys = statementProxy.getGeneratedKeys(); + List<Object> pkValues = new ArrayList<>(); + while (genKeys.next()) { + Object v = genKeys.getObject(1); + pkValues.add(v); + } + if (pkValues.isEmpty()) { + throw new NotSupportYetException(String.format("not support sql [%s]", sqlRecognizer.getOriginalSQL())); + } + try { + genKeys.beforeFirst(); + } catch (SQLException e) { + LOGGER.warn("Fail to reset ResultSet cursor. can not get primary key value"); + } + return pkValues; + } + + /** + * the modify for test + */ + protected List<Object> getPkValuesBySequence(SqlSequenceExpr expr) throws SQLException { + List<Object> pkValues = null; + try { + pkValues = getGeneratedKeys(); + } catch (NotSupportYetException | SQLException ignore) { + } + + if (!CollectionUtils.isEmpty(pkValues)) { + return pkValues; + } + + Sequenceable sequenceable = (Sequenceable) this; + final String sql = sequenceable.getSequenceSql(expr); + LOGGER.warn("Fail to get auto-generated keys, use '{}' instead. Be cautious, statement could be polluted. Recommend you set the statement to return generated keys.", sql); + + ResultSet genKeys; + genKeys = statementProxy.getConnection().createStatement().executeQuery(sql); + pkValues = new ArrayList<>(); + while (genKeys.next()) { + Object v = genKeys.getObject(1); + pkValues.add(v); + } + return pkValues; + } + + /** + * check pk values for multi Pk + * At most one null per row. + * Method is not allowed. + * @param pkValues + * @return + */ + protected boolean checkPkValuesForMultiPk(Map<String,List<Object>> pkValues) { + Set<String> pkNames = pkValues.keySet(); + if (pkNames.isEmpty()) + { + throw new ShouldNeverHappenException(); + } + int rowSize = pkValues.get(pkNames.iterator().next()).size(); + for (int i = 0;i < rowSize; i++) + { + int n = 0; + int m = 0; + for (String name : pkNames) + { + Object pkValue = pkValues.get(name).get(i); + if (pkValue instanceof Null) { + n++; + } + if (pkValue instanceof SqlMethodExpr) { + m++; + } + } + if (n > 1) + { + return false; + } + if (m > 0) + { + return false; + } + } + return true; + } + + protected boolean checkPkValues(Map<String,List<Object>> pkValues, boolean ps) { + Set<String> pkNames = pkValues.keySet(); + if (pkNames.size() == 1) { + return checkPkValuesForSinglePk(pkValues.get(pkNames.iterator().next()),ps); + } + else { + return checkPkValuesForMultiPk(pkValues); + } + } + + /** + * check pk values for single pk + * @param pkValues + * @param ps true: is prepared statement. false: normal statement. + * @return true: support. false: not support. + */ + protected boolean checkPkValuesForSinglePk(List<Object> pkValues, boolean ps) { + /* + ps = true + ----------------------------------------------- + one more + null O O + value O O + method O O + sequence O O + default O O + ----------------------------------------------- + ps = false + ----------------------------------------------- + one more + null O X + value O O + method X X + sequence O X + default O X + ----------------------------------------------- + */ + int n = 0, v = 0, m = 0, s = 0, d = 0; + for (Object pkValue : pkValues) { + if (pkValue instanceof Null) { + n++; + continue; + } + if (pkValue instanceof SqlMethodExpr) { + m++; + continue; + } + if (pkValue instanceof SqlSequenceExpr) { + s++; + continue; + } + if (pkValue instanceof SqlDefaultExpr) { + d++; + continue; + } + v++; + } + + if (!ps) { + if (m > 0) { + return false; + } + if (n == 1 && v == 0 && m == 0 && s == 0 && d == 0) { + return true; + } + if (n == 0 && v > 0 && m == 0 && s == 0 && d == 0) { + return true; + } + if (n == 0 && v == 0 && m == 0 && s == 1 && d == 0) { + return true; + } + if (n == 0 && v == 0 && m == 0 && s == 0 && d == 1) { + return true; + } + return false; + } + + if (n > 0 && v == 0 && m == 0 && s == 0 && d == 0) { + return true; + } + if (n == 0 && v > 0 && m == 0 && s == 0 && d == 0) { + return true; + } + if (n == 0 && v == 0 && m > 0 && s == 0 && d == 0) { + return true; + } + if (n == 0 && v == 0 && m == 0 && s > 0 && d == 0) { + return true; + } + if (n == 0 && v == 0 && m == 0 && s == 0 && d > 0) { + return true; + } + return false; + } + +} diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java index 7079f4eac1561ff5d9bf6cf06d7b0dc1c999ae7d..5f35bd1b04d6440f9a2d89c56b68061f6b6f0be5 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseTransactionalExecutor.java @@ -15,12 +15,20 @@ */ package io.seata.rm.datasource.exec; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Map; +import java.util.Objects; + import io.seata.common.util.CollectionUtils; import io.seata.common.util.IOUtil; import io.seata.common.util.StringUtils; import io.seata.core.context.RootContext; import io.seata.rm.datasource.ColumnUtils; import io.seata.rm.datasource.ConnectionProxy; +import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.TableMeta; @@ -32,13 +40,8 @@ import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.SQLType; import io.seata.sqlparser.WhereRecognizer; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; import java.util.ArrayList; import java.util.List; -import java.util.StringJoiner; /** * The type Base transactional executor. @@ -71,6 +74,8 @@ public abstract class BaseTransactionalExecutor<T, S extends Statement> implemen private TableMeta tableMeta; + private static final String NEXT_LINE = "\n"; + /** * Instantiates a new Base transactional executor. * @@ -90,7 +95,7 @@ public abstract class BaseTransactionalExecutor<T, S extends Statement> implemen * * @param statementProxy the statement proxy * @param statementCallback the statement callback - * @param sqlRecognizer the multi sql recognizer + * @param sqlRecognizers the multi sql recognizer */ public BaseTransactionalExecutor(StatementProxy<S> statementProxy, StatementCallback<T, S> statementCallback, List<SQLRecognizer> sqlRecognizers) { @@ -119,21 +124,6 @@ public abstract class BaseTransactionalExecutor<T, S extends Statement> implemen */ protected abstract T doExecute(Object... args) throws Throwable; - /** - * Build where condition by p ks string. - * - * @param pkRows the pk rows - * @return the string - * @throws SQLException the sql exception - */ - protected String buildWhereConditionByPKs(List<Field> pkRows) throws SQLException { - StringJoiner whereConditionAppender = new StringJoiner(",", getColumnNameInSQL(pkRows.get(0).getName()) + " in (", ")"); - for (Field field : pkRows) { - whereConditionAppender.add("?"); - } - return whereConditionAppender.toString(); - - } /** * build buildWhereCondition @@ -158,6 +148,10 @@ public abstract class BaseTransactionalExecutor<T, S extends Statement> implemen } whereCondition = whereConditionSb.toString(); } + // fix druid bug parse where contain \n + if (StringUtils.isNotBlank(whereCondition) && whereCondition.contains(NEXT_LINE)) { + whereCondition = whereCondition.replace(NEXT_LINE, " "); + } return whereCondition; } @@ -172,6 +166,26 @@ public abstract class BaseTransactionalExecutor<T, S extends Statement> implemen return tableAlias == null ? columnName : tableAlias + "." + columnName; } + /** + * Gets several column name in sql. + * + * @param columnNameList the column name + * @return the column name in sql + */ + protected String getColumnNamesInSQL(List<String> columnNameList) { + if (Objects.isNull(columnNameList) || columnNameList.isEmpty()) { + return null; + } + StringBuffer columnNamesStr = new StringBuffer(); + for (int i = 0; i < columnNameList.size(); i++) { + if (i > 0) { + columnNamesStr.append(" , "); + } + columnNamesStr.append(getColumnNameInSQL(columnNameList.get(i))); + } + return columnNamesStr.toString(); + } + /** * Gets from table in sql. * @@ -222,15 +236,32 @@ public abstract class BaseTransactionalExecutor<T, S extends Statement> implemen return getTableMeta().containsPK(newColumns); } + /** * compare column name and primary key name * * @param columnName the primary key column name - * @return true: equal false: not equal + * @return true: contain false: not contain */ - protected boolean equalsPK(String columnName) { + protected boolean containPK(String columnName) { String newColumnName = ColumnUtils.delEscape(columnName, getDbType()); - return StringUtils.equalsIgnoreCase(getTableMeta().getPkName(), newColumnName); + return CollectionUtils.toUpperList(getTableMeta().getPrimaryKeyOnlyName()).contains(newColumnName.toUpperCase()); + } + + + /** + * get standard column name from user sql column name + * + * @return + */ + protected String getStandardColumnName(String userColumnName) { + String newUserColumnName = ColumnUtils.delEscape(userColumnName, getDbType()); + for (String cn : getTableMeta().getPrimaryKeyOnlyName()) { + if (cn.toUpperCase().equals(newUserColumnName.toUpperCase())) { + return cn; + } + } + return null; } /** @@ -259,7 +290,7 @@ public abstract class BaseTransactionalExecutor<T, S extends Statement> implemen * build lockKey * * @param rowsIncludingPK the records - * @return the string + * @return the string as local key. the local key example(multi pk): "t_user:1_a,2_b" */ protected String buildLockKey(TableRecords rowsIncludingPK) { if (rowsIncludingPK.size() == 0) { @@ -270,11 +301,18 @@ public abstract class BaseTransactionalExecutor<T, S extends Statement> implemen sb.append(rowsIncludingPK.getTableMeta().getTableName()); sb.append(":"); int filedSequence = 0; - List<Field> pkRows = rowsIncludingPK.pkRows(); - for (Field field : pkRows) { - sb.append(field.getValue()); + List<Map<String, Field>> pksRows = rowsIncludingPK.pkRows(); + for (Map<String, Field> rowMap : pksRows) { + int pkSplitIndex = 0; + for (String pkName : getTableMeta().getPrimaryKeyOnlyName()) { + if (pkSplitIndex > 0) { + sb.append("_"); + } + sb.append(rowMap.get(pkName).getValue()); + pkSplitIndex++; + } filedSequence++; - if (filedSequence < pkRows.size()) { + if (filedSequence < pksRows.size()) { sb.append(","); } } @@ -331,22 +369,34 @@ public abstract class BaseTransactionalExecutor<T, S extends Statement> implemen /** * build TableRecords * - * @param pkValues the pkValues + * @param pkValuesMap the pkValuesMap * @return return TableRecords; * @throws SQLException */ - protected TableRecords buildTableRecords(List<Object> pkValues) throws SQLException { - String pk = getTableMeta().getEscapePkName(getDbType()); - StringJoiner pkValuesJoiner = new StringJoiner(" , ", - "SELECT * FROM " + getFromTableInSQL() + " WHERE " + pk + " in (", ")"); - for (Object pkValue : pkValues) { - pkValuesJoiner.add("?"); - } - + protected TableRecords buildTableRecords(Map<String, List<Object>> pkValuesMap) throws SQLException { + List<String> pkColumnNameList = getTableMeta().getPrimaryKeyOnlyName(); + StringBuilder sql = new StringBuilder() + .append("SELECT * FROM ") + .append(getFromTableInSQL()) + .append(" WHERE "); + // build check sql + String firstKey = pkValuesMap.keySet().stream().findFirst().get(); + int rowSize = pkValuesMap.get(firstKey).size(); + sql.append(SqlGenerateUtils.buildWhereConditionByPKs(pkColumnNameList, rowSize, getDbType())); + + PreparedStatement ps = null; ResultSet rs = null; - try (PreparedStatement ps = statementProxy.getConnection().prepareStatement(pkValuesJoiner.toString())) { - for (int i = 1, s = pkValues.size(); i <= s; i++) { - ps.setObject(i, pkValues.get(i - 1)); + try { + ps = statementProxy.getConnection().prepareStatement(sql.toString()); + + int paramIndex = 1; + for (int r = 0; r < rowSize; r++) { + for (int c = 0; c < pkColumnNameList.size(); c++) { + List<Object> pkColumnValueList = pkValuesMap.get(pkColumnNameList.get(c)); + int dataType = tableMeta.getColumnMeta(pkColumnNameList.get(c)).getDataType(); + ps.setObject(paramIndex, pkColumnValueList.get(r), dataType); + paramIndex++; + } } rs = ps.executeQuery(); return TableRecords.buildRecords(getTableMeta(), rs); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java index 0ec64edfafdedae740fb8fd94a82341152b51d9d..3c1c98046794de82d240936e066ee6fd1bc454fb 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java @@ -21,11 +21,10 @@ import java.util.ArrayList; import java.util.List; import java.util.StringJoiner; +import io.seata.rm.datasource.ColumnUtils; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; -import io.seata.rm.datasource.undo.KeywordChecker; -import io.seata.rm.datasource.undo.KeywordCheckerFactory; import io.seata.sqlparser.SQLDeleteRecognizer; import io.seata.sqlparser.SQLRecognizer; import org.apache.commons.lang.StringUtils; @@ -62,7 +61,6 @@ public class DeleteExecutor<T, S extends Statement> extends AbstractDMLBaseExecu } private String buildBeforeImageSQL(SQLDeleteRecognizer visitor, TableMeta tableMeta, ArrayList<List<Object>> paramAppenderList) { - KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(getDbType()); String whereCondition = buildWhereCondition(visitor, paramAppenderList); StringBuilder suffix = new StringBuilder(" FROM ").append(getFromTableInSQL()); if (StringUtils.isNotBlank(whereCondition)) { @@ -71,7 +69,7 @@ public class DeleteExecutor<T, S extends Statement> extends AbstractDMLBaseExecu suffix.append(" FOR UPDATE"); StringJoiner selectSQLAppender = new StringJoiner(", ", "SELECT ", suffix.toString()); for (String column : tableMeta.getAllColumns().keySet()) { - selectSQLAppender.add(getColumnNameInSQL(keywordChecker.checkAndReplace(column))); + selectSQLAppender.add(getColumnNameInSQL(ColumnUtils.addEscape(column, getDbType()))); } return selectSQLAppender.toString(); } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/ExecuteTemplate.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/ExecuteTemplate.java index b7803209487b5ff72d6dbcc6888e7af5544de4ac..0fd97941bbbc7dbf94f10971d0745c17b8f08d4e 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/ExecuteTemplate.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/ExecuteTemplate.java @@ -15,12 +15,14 @@ */ package io.seata.rm.datasource.exec; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.util.StringUtils; import io.seata.common.util.CollectionUtils; import io.seata.core.context.RootContext; +import io.seata.core.model.BranchType; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.sql.SQLVisitorFactory; import io.seata.sqlparser.SQLRecognizer; - import java.sql.SQLException; import java.sql.Statement; import java.util.List; @@ -54,7 +56,7 @@ public class ExecuteTemplate { * * @param <T> the type parameter * @param <S> the type parameter - * @param sqlRecognizer the sql recognizer + * @param sqlRecognizers the sql recognizer list * @param statementProxy the statement proxy * @param statementCallback the statement callback * @param args the args @@ -66,15 +68,16 @@ public class ExecuteTemplate { StatementCallback<T, S> statementCallback, Object... args) throws SQLException { - if (!RootContext.inGlobalTransaction() && !RootContext.requireGlobalLock()) { + if (!RootContext.requireGlobalLock() && !StringUtils.equals(BranchType.AT.name(), RootContext.getBranchType())) { // Just work as original statement return statementCallback.execute(statementProxy.getTargetStatement(), args); } - if (sqlRecognizers == null) { + String dbType = statementProxy.getConnectionProxy().getDbType(); + if (CollectionUtils.isEmpty(sqlRecognizers)) { sqlRecognizers = SQLVisitorFactory.get( statementProxy.getTargetSQL(), - statementProxy.getConnectionProxy().getDbType()); + dbType); } Executor<T> executor; if (CollectionUtils.isEmpty(sqlRecognizers)) { @@ -84,7 +87,9 @@ public class ExecuteTemplate { SQLRecognizer sqlRecognizer = sqlRecognizers.get(0); switch (sqlRecognizer.getSQLType()) { case INSERT: - executor = new InsertExecutor<>(statementProxy, statementCallback, sqlRecognizer); + executor = EnhancedServiceLoader.load(InsertExecutor.class, dbType, + new Class[]{StatementProxy.class, StatementCallback.class, SQLRecognizer.class}, + new Object[]{statementProxy, statementCallback, sqlRecognizer}); break; case UPDATE: executor = new UpdateExecutor<>(statementProxy, statementCallback, sqlRecognizer); @@ -115,4 +120,5 @@ public class ExecuteTemplate { } return rs; } + } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/InsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/InsertExecutor.java index 67e1d53db02d5ecc27441c5632821efbdfea7455..54b069beaf1137b2a36e970e922980a2902dbfc4 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/InsertExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/InsertExecutor.java @@ -13,380 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.seata.rm.datasource.exec; -import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; - -import io.seata.common.exception.NotSupportYetException; -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.rm.datasource.PreparedStatementProxy; -import io.seata.rm.datasource.StatementProxy; -import io.seata.rm.datasource.sql.struct.ColumnMeta; -import io.seata.rm.datasource.sql.struct.TableRecords; -import io.seata.sqlparser.SQLInsertRecognizer; -import io.seata.sqlparser.SQLRecognizer; -import io.seata.sqlparser.struct.Null; -import io.seata.sqlparser.struct.SqlDefaultExpr; -import io.seata.sqlparser.struct.SqlMethodExpr; -import io.seata.sqlparser.struct.SqlSequenceExpr; -import io.seata.sqlparser.util.JdbcConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** - * The type Insert executor. - * - * @param <T> the type parameter - * @param <S> the type parameter - * @author yuanguoyao + * @author jsbxyyx */ -public class InsertExecutor<T, S extends Statement> extends AbstractDMLBaseExecutor<T, S> { - - private static final Logger LOGGER = LoggerFactory.getLogger(InsertExecutor.class); - protected static final String ERR_SQL_STATE = "S1009"; - - private static final String PLACEHOLDER = "?"; +public interface InsertExecutor<T> extends Executor<T> { /** - * Instantiates a new Insert executor. + * get primary key values. * - * @param statementProxy the statement proxy - * @param statementCallback the statement callback - * @param sqlRecognizer the sql recognizer - */ - public InsertExecutor(StatementProxy<S> statementProxy, StatementCallback<T,S> statementCallback, - SQLRecognizer sqlRecognizer) { - super(statementProxy, statementCallback, sqlRecognizer); - } - - @Override - protected TableRecords beforeImage() throws SQLException { - return TableRecords.empty(getTableMeta()); - } - - @Override - protected TableRecords afterImage(TableRecords beforeImage) throws SQLException { - //Pk column exists or PK is just auto generated - List<Object> pkValues = containsPK() ? getPkValuesByColumn() : - (containsColumns() ? getPkValuesByAuto() : getPkValuesByColumn()); - - TableRecords afterImage = buildTableRecords(pkValues); - - if (afterImage == null) { - throw new SQLException("Failed to build after-image for insert"); - } - - return afterImage; - } - - protected boolean containsPK() { - SQLInsertRecognizer recognizer = (SQLInsertRecognizer) sqlRecognizer; - List<String> insertColumns = recognizer.getInsertColumns(); - if (CollectionUtils.isEmpty(insertColumns)) { - return false; - } - return containsPK(insertColumns); - } - - protected boolean containsColumns() { - SQLInsertRecognizer recognizer = (SQLInsertRecognizer) sqlRecognizer; - List<String> insertColumns = recognizer.getInsertColumns(); - return insertColumns != null && !insertColumns.isEmpty(); - } - - protected List<Object> getPkValuesByColumn() throws SQLException { - // insert values including PK - SQLInsertRecognizer recognizer = (SQLInsertRecognizer) sqlRecognizer; - final int pkIndex = getPkIndex(); - if (pkIndex == -1) { - throw new ShouldNeverHappenException(String.format("pkIndex is %d", pkIndex)); - } - List<Object> pkValues = null; - if (statementProxy instanceof PreparedStatementProxy) { - PreparedStatementProxy preparedStatementProxy = (PreparedStatementProxy) statementProxy; - - List<List<Object>> insertRows = recognizer.getInsertRows(); - if (insertRows != null && !insertRows.isEmpty()) { - ArrayList<Object>[] parameters = preparedStatementProxy.getParameters(); - final int rowSize = insertRows.size(); - - if (rowSize == 1) { - Object pkValue = insertRows.get(0).get(pkIndex); - if (PLACEHOLDER.equals(pkValue)) { - pkValues = parameters[pkIndex]; - } else { - pkValues = insertRows.stream().map(insertRow -> insertRow.get(pkIndex)).collect(Collectors.toList()); - } - } else { - int totalPlaceholderNum = -1; - pkValues = new ArrayList<>(rowSize); - for (int i = 0; i < rowSize; i++) { - List<Object> row = insertRows.get(i); - // oracle insert sql statement specify RETURN_GENERATED_KEYS will append :rowid on sql end - // insert parameter count will than the actual +1 - if (row.isEmpty()) { - continue; - } - Object pkValue = row.get(pkIndex); - int currentRowPlaceholderNum = -1; - for (Object r : row) { - if (PLACEHOLDER.equals(r)) { - totalPlaceholderNum += 1; - currentRowPlaceholderNum += 1; - } - } - if (PLACEHOLDER.equals(pkValue)) { - int idx = pkIndex; - if (i != 0) { - idx = totalPlaceholderNum - currentRowPlaceholderNum + pkIndex; - } - ArrayList<Object> parameter = parameters[idx]; - pkValues.addAll(parameter); - } else { - pkValues.add(pkValue); - } - } - } - } - } else { - List<List<Object>> insertRows = recognizer.getInsertRows(); - pkValues = new ArrayList<>(insertRows.size()); - for (List<Object> row : insertRows) { - pkValues.add(row.get(pkIndex)); - } - } - if (pkValues == null) { - throw new ShouldNeverHappenException(); - } - boolean b = this.checkPkValues(pkValues); - if (!b) { - throw new NotSupportYetException(String.format("not support sql [%s]", sqlRecognizer.getOriginalSQL())); - } - if (!pkValues.isEmpty() && pkValues.get(0) instanceof SqlSequenceExpr) { - pkValues = getPkValuesBySequence(pkValues.get(0)); - } - else if (!pkValues.isEmpty() && pkValues.get(0) instanceof SqlDefaultExpr) { - pkValues = getPkValuesByDefault(); - } - // pk auto generated while column exists and value is null - else if (!pkValues.isEmpty() && pkValues.get(0) instanceof Null) { - pkValues = getPkValuesByAuto(); - } - return pkValues; - } - - /** - * get primary key values by default - * @return + * @return The primary key value. * @throws SQLException */ - private List<Object> getPkValuesByDefault() throws SQLException { - // current version 1.2 only support postgresql. - // mysql default keyword the logic not support. (sample: insert into test(id, name) values(default, 'xx')) - Map<String, ColumnMeta> pkMetaMap = getTableMeta().getPrimaryKeyMap(); - ColumnMeta pkMeta = pkMetaMap.values().iterator().next(); - String columnDef = pkMeta.getColumnDef(); - // sample: nextval('test_id_seq'::regclass) - String seq = org.apache.commons.lang.StringUtils.substringBetween(columnDef, "'", "'"); - String function = org.apache.commons.lang.StringUtils.substringBetween(columnDef, "", "("); - if (StringUtils.isBlank(seq)) { - throw new ShouldNeverHappenException("get primary key value failed, cause columnDef is " + columnDef); - } - return getPkValuesBySequence(new SqlSequenceExpr("'" + seq + "'", function)); - } + Map<String, List<Object>> getPkValues() throws SQLException; /** - * get primary key values by sequence. - * @param expr + * get primary key values by insert column. + * * @return * @throws SQLException */ - protected List<Object> getPkValuesBySequence(Object expr) throws SQLException { - // priority use defaultGeneratedKeys - List<Object> pkValues = null; - try { - pkValues = defaultGeneratedKeys(); - } catch (NotSupportYetException | SQLException ignore) { - } - - if (!CollectionUtils.isEmpty(pkValues)) { - return pkValues; - } - - ResultSet genKeys; - if (expr instanceof SqlSequenceExpr) { - SqlSequenceExpr sequenceExpr = (SqlSequenceExpr) expr; - String sql = "SELECT " + sequenceExpr.getSequence() + ".currval FROM DUAL"; - if (StringUtils.equalsIgnoreCase(JdbcConstants.POSTGRESQL, getDbType())) { - sql = "SELECT currval(" + sequenceExpr.getSequence() + ")"; - } - LOGGER.warn("Fail to get auto-generated keys, use '{}' instead. Be cautious, statement could be polluted. Recommend you set the statement to return generated keys.", sql); - genKeys = statementProxy.getConnection().createStatement().executeQuery(sql); - } else { - throw new NotSupportYetException(String.format("not support expr [%s]", expr.getClass().getName())); - } - pkValues = new ArrayList<>(); - while (genKeys.next()) { - Object v = genKeys.getObject(1); - pkValues.add(v); - } - return pkValues; - } - - protected List<Object> getPkValuesByAuto() throws SQLException { - boolean mysql = StringUtils.equalsIgnoreCase(JdbcConstants.MYSQL, getDbType()); - if (mysql) { - return mysqlGeneratedKeys(); - } - return defaultGeneratedKeys(); - } - - /** - * get pk index - * @return -1 not found pk index - */ - protected int getPkIndex() { - SQLInsertRecognizer recognizer = (SQLInsertRecognizer) sqlRecognizer; - List<String> insertColumns = recognizer.getInsertColumns(); - if (CollectionUtils.isNotEmpty(insertColumns)) { - final int insertColumnsSize = insertColumns.size(); - int pkIndex = -1; - for (int paramIdx = 0; paramIdx < insertColumnsSize; paramIdx++) { - if (equalsPK(insertColumns.get(paramIdx))) { - pkIndex = paramIdx; - break; - } - } - return pkIndex; - } - int pkIndex = -1; - Map<String, ColumnMeta> allColumns = getTableMeta().getAllColumns(); - for (Map.Entry<String, ColumnMeta> entry : allColumns.entrySet()) { - pkIndex++; - if (equalsPK(entry.getValue().getColumnName())) { - break; - } - } - return pkIndex; - } - - /** - * check pk values - * @param pkValues - * @return true: support. false: not support. - */ - protected boolean checkPkValues(List<Object> pkValues) { - /* - ----------------------------------------------- - one more - null O O - value O O - method X X - sequence O X - ----------------------------------------------- - null value method sequence - null O X X X - value X O X X - method X X X X - sequence X X X X - ----------------------------------------------- - */ - int n = 0, v = 0, m = 0, s = 0; - for (Object pkValue : pkValues) { - if (pkValue instanceof Null) { - n++; - continue; - } - if (pkValue instanceof SqlMethodExpr) { - m++; - break; - } - if (pkValue instanceof SqlSequenceExpr) { - s++; - continue; - } - v++; - } - // not support sql primary key is function. - if (m > 0) { - return false; - } - if (n > 0 && v == 0 && s == 0) { - return true; - } - if (n == 0 && v > 0 && s == 0) { - return true; - } - if (n == 0 && v == 0 && s == 1) { - return true; - } - return false; - } - - /** - * mysql get generated keys - * @return the primary key value - * @throws SQLException the SQL exception - */ - private List<Object> mysqlGeneratedKeys() throws SQLException { - // PK is just auto generated - Map<String, ColumnMeta> pkMetaMap = getTableMeta().getPrimaryKeyMap(); - ColumnMeta pkMeta = pkMetaMap.values().iterator().next(); - if (!pkMeta.isAutoincrement()) { - throw new ShouldNeverHappenException(); - } - - ResultSet genKeys; - try { - genKeys = statementProxy.getTargetStatement().getGeneratedKeys(); - } catch (SQLException e) { - // java.sql.SQLException: Generated keys not requested. You need to - // specify Statement.RETURN_GENERATED_KEYS to - // Statement.executeUpdate() or Connection.prepareStatement(). - if (ERR_SQL_STATE.equalsIgnoreCase(e.getSQLState())) { - LOGGER.warn("Fail to get auto-generated keys, use 'SELECT LAST_INSERT_ID()' instead. Be cautious, statement could be polluted. Recommend you set the statement to return generated keys."); - genKeys = statementProxy.getTargetStatement().executeQuery("SELECT LAST_INSERT_ID()"); - } else { - throw e; - } - } - List<Object> pkValues = new ArrayList<>(); - while (genKeys.next()) { - Object v = genKeys.getObject(1); - pkValues.add(v); - } - try { - genKeys.beforeFirst(); - } catch (SQLException e) { - LOGGER.warn("Fail to reset ResultSet cursor. can not get primary key value"); - } - return pkValues; - } - - /** - * default get generated keys - * @return the primary key value - * @throws SQLException the SQL exception - */ - private List<Object> defaultGeneratedKeys() throws SQLException { - ResultSet genKeys = statementProxy.getTargetStatement().getGeneratedKeys(); - List<Object> pkValues = new ArrayList<>(); - while (genKeys.next()) { - Object v = genKeys.getObject(1); - pkValues.add(v); - } - if (pkValues.isEmpty()) { - throw new NotSupportYetException(String.format("not support sql [%s]", sqlRecognizer.getOriginalSQL())); - } - return pkValues; - } + Map<String, List<Object>> getPkValuesByColumn() throws SQLException; } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiDeleteExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiDeleteExecutor.java index efd477343bc5684a0726dffd50a2c470dd036706..1c8d34e63bc903d0bcfa34ea9364d6a9d408127f 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiDeleteExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiDeleteExecutor.java @@ -18,11 +18,10 @@ package io.seata.rm.datasource.exec; import io.seata.common.util.StringUtils; +import io.seata.rm.datasource.ColumnUtils; import io.seata.rm.datasource.StatementProxy; import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; -import io.seata.rm.datasource.undo.KeywordChecker; -import io.seata.rm.datasource.undo.KeywordCheckerFactory; import io.seata.sqlparser.SQLDeleteRecognizer; import io.seata.sqlparser.SQLRecognizer; @@ -50,7 +49,6 @@ public class MultiDeleteExecutor<T, S extends Statement> extends AbstractDMLBase DeleteExecutor executor = new DeleteExecutor(statementProxy, statementCallback, sqlRecognizers.get(0)); return executor.beforeImage(); } - final KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(getDbType()); final TableMeta tmeta = getTableMeta(sqlRecognizers.get(0).getTableName()); final ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); StringBuilder whereCondition = new StringBuilder(); @@ -75,7 +73,7 @@ public class MultiDeleteExecutor<T, S extends Statement> extends AbstractDMLBase suffix.append(" FOR UPDATE"); final StringJoiner selectSQLAppender = new StringJoiner(", ", "SELECT ", suffix.toString()); for (String column : tmeta.getAllColumns().keySet()) { - selectSQLAppender.add(getColumnNameInSQL(keywordChecker.checkAndReplace(column))); + selectSQLAppender.add(getColumnNameInSQL(ColumnUtils.addEscape(column, getDbType()))); } return buildTableRecords(tmeta, selectSQLAppender.toString(), paramAppenderList); } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java index 35dda618e8134ba7d23d3a798c1e90eb5dd4ba31..dcd21ce88478266c16f3d29f06b53984f24a2c08 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/MultiUpdateExecutor.java @@ -15,25 +15,30 @@ */ package io.seata.rm.datasource.exec; -import io.seata.common.util.IOUtil; -import io.seata.common.util.StringUtils; -import io.seata.rm.datasource.StatementProxy; -import io.seata.rm.datasource.sql.struct.Field; -import io.seata.rm.datasource.sql.struct.TableMeta; -import io.seata.rm.datasource.sql.struct.TableRecords; -import io.seata.sqlparser.SQLRecognizer; -import io.seata.sqlparser.SQLUpdateRecognizer; - import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.HashSet; import java.util.StringJoiner; +import io.seata.common.util.IOUtil; +import io.seata.common.util.StringUtils; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.constants.DefaultValues; +import io.seata.rm.datasource.ColumnUtils; +import io.seata.rm.datasource.SqlGenerateUtils; +import io.seata.rm.datasource.StatementProxy; +import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.rm.datasource.sql.struct.TableRecords; +import io.seata.sqlparser.SQLRecognizer; +import io.seata.sqlparser.SQLUpdateRecognizer; + /** * The type MultiSql executor. * @@ -42,6 +47,19 @@ import java.util.StringJoiner; * @author wangwei-ying */ public class MultiUpdateExecutor<T, S extends Statement> extends AbstractDMLBaseExecutor<T, S> { + + private static final Configuration CONFIG = ConfigurationFactory.getInstance(); + + private static final boolean ONLY_CARE_UPDATE_COLUMNS = CONFIG.getBoolean( + ConfigurationKeys.TRANSACTION_UNDO_ONLY_CARE_UPDATE_COLUMNS, DefaultValues.DEFAULT_ONLY_CARE_UPDATE_COLUMNS); + + /** + * Instantiates a new Multi update executor. + * + * @param statementProxy the statement proxy + * @param statementCallback the statement callback + * @param sqlRecognizers the sql recognizers + */ public MultiUpdateExecutor(StatementProxy<S> statementProxy, StatementCallback<T, S> statementCallback, List<SQLRecognizer> sqlRecognizers) { super(statementProxy, statementCallback, sqlRecognizers); } @@ -77,9 +95,6 @@ public class MultiUpdateExecutor<T, S extends Statement> extends AbstractDMLBase } } StringBuilder prefix = new StringBuilder("SELECT "); - if (!containsPK(new ArrayList<>(updateColumnsSet))) { - prefix.append(getColumnNameInSQL(tmeta.getEscapePkName(getDbType()))).append(", "); - } final StringBuilder suffix = new StringBuilder(" FROM ").append(getFromTableInSQL()); if (noWhereCondition) { //select all rows @@ -89,8 +104,17 @@ public class MultiUpdateExecutor<T, S extends Statement> extends AbstractDMLBase } suffix.append(" FOR UPDATE"); final StringJoiner selectSQLAppender = new StringJoiner(", ", prefix, suffix.toString()); - for (String updateCol : updateColumnsSet) { - selectSQLAppender.add(updateCol); + if (ONLY_CARE_UPDATE_COLUMNS) { + if (!containsPK(new ArrayList<>(updateColumnsSet))) { + selectSQLAppender.add(getColumnNamesInSQL(tmeta.getEscapePkNameList(getDbType()))); + } + for (String updateCol : updateColumnsSet) { + selectSQLAppender.add(updateCol); + } + } else { + for (String columnName : tmeta.getAllColumns().keySet()) { + selectSQLAppender.add(ColumnUtils.addEscape(columnName, getDbType())); + } } return buildTableRecords(tmeta, selectSQLAppender.toString(), paramAppenderList); } @@ -108,11 +132,7 @@ public class MultiUpdateExecutor<T, S extends Statement> extends AbstractDMLBase String selectSQL = buildAfterImageSQL(tmeta, beforeImage); ResultSet rs = null; try (PreparedStatement pst = statementProxy.getConnection().prepareStatement(selectSQL);) { - List<Field> pkRows = beforeImage.pkRows(); - for (int i = 1; i <= pkRows.size(); i++) { - Field pkField = pkRows.get(i - 1); - pst.setObject(i, pkField.getValue(), pkField.getType()); - } + SqlGenerateUtils.setParamForPk(beforeImage.pkRows(),getTableMeta().getPrimaryKeyOnlyName(),pst); rs = pst.executeQuery(); return TableRecords.buildRecords(tmeta, rs); } finally { @@ -129,14 +149,19 @@ public class MultiUpdateExecutor<T, S extends Statement> extends AbstractDMLBase updateColumnsSet.addAll(sqlUpdateRecognizer.getUpdateColumns()); } StringBuilder prefix = new StringBuilder("SELECT "); - if (!containsPK(new ArrayList<>(updateColumnsSet))) { - // PK should be included. - prefix.append(getColumnNameInSQL(tableMeta.getEscapePkName(getDbType()))).append(", "); - } - String suffix = " FROM " + getFromTableInSQL() + " WHERE " + buildWhereConditionByPKs(beforeImage.pkRows()); + String suffix = " FROM " + getFromTableInSQL() + " WHERE " + SqlGenerateUtils.buildWhereConditionByPKs(tableMeta.getPrimaryKeyOnlyName(),beforeImage.pkRows().size(),getDbType()); StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix); - for (String column : updateColumnsSet) { - selectSQLJoiner.add(column); + if (ONLY_CARE_UPDATE_COLUMNS) { + if (!containsPK(new ArrayList<>(updateColumnsSet))) { + selectSQLJoiner.add(getColumnNamesInSQL(tableMeta.getEscapePkNameList(getDbType()))); + } + for (String updateCol : updateColumnsSet) { + selectSQLJoiner.add(updateCol); + } + } else { + for (String columnName : tableMeta.getAllColumns().keySet()) { + selectSQLJoiner.add(ColumnUtils.addEscape(columnName, getDbType())); + } } return selectSQLJoiner.toString(); } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/SelectForUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/SelectForUpdateExecutor.java index bb0c3b81deba3da78430d26dbb17b1be9359cae4..b504059c5f71f84caf730e178c2fd91f7a8bbc29 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/SelectForUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/SelectForUpdateExecutor.java @@ -136,7 +136,7 @@ public class SelectForUpdateExecutor<T, S extends Statement> extends BaseTransac private String buildSelectSQL(ArrayList<List<Object>> paramAppenderList) { SQLSelectRecognizer recognizer = (SQLSelectRecognizer)sqlRecognizer; StringBuilder selectSQLAppender = new StringBuilder("SELECT "); - selectSQLAppender.append(getColumnNameInSQL(getTableMeta().getPkName())); + selectSQLAppender.append(getColumnNamesInSQL(getTableMeta().getEscapePkNameList(getDbType()))); selectSQLAppender.append(" FROM ").append(getFromTableInSQL()); String whereCondition = buildWhereCondition(recognizer, paramAppenderList); if (StringUtils.isNotBlank(whereCondition)) { diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java index b303e2a24abde19729aca9b1ed346edd7a09034d..db6105c19ead0db1362c261e44f33e4e82f74d0b 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/UpdateExecutor.java @@ -15,6 +15,20 @@ */ package io.seata.rm.datasource.exec; +import io.seata.common.util.IOUtil; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.constants.DefaultValues; +import io.seata.rm.datasource.ColumnUtils; +import io.seata.rm.datasource.SqlGenerateUtils; +import io.seata.rm.datasource.StatementProxy; +import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.rm.datasource.sql.struct.TableRecords; +import io.seata.sqlparser.SQLRecognizer; +import io.seata.sqlparser.SQLUpdateRecognizer; +import org.apache.commons.lang.StringUtils; + import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -23,26 +37,20 @@ import java.util.ArrayList; import java.util.List; import java.util.StringJoiner; -import io.seata.common.util.IOUtil; -import io.seata.rm.datasource.StatementProxy; - -import io.seata.sqlparser.SQLRecognizer; -import io.seata.sqlparser.SQLUpdateRecognizer; -import io.seata.rm.datasource.sql.struct.Field; -import io.seata.rm.datasource.sql.struct.TableMeta; -import io.seata.rm.datasource.sql.struct.TableRecords; -import org.apache.commons.lang.StringUtils; - /** * The type Update executor. * - * @author sharajava - * * @param <T> the type parameter * @param <S> the type parameter + * @author sharajava */ public class UpdateExecutor<T, S extends Statement> extends AbstractDMLBaseExecutor<T, S> { + private static final Configuration CONFIG = ConfigurationFactory.getInstance(); + + private static final boolean ONLY_CARE_UPDATE_COLUMNS = CONFIG.getBoolean( + ConfigurationKeys.TRANSACTION_UNDO_ONLY_CARE_UPDATE_COLUMNS, DefaultValues.DEFAULT_ONLY_CARE_UPDATE_COLUMNS); + /** * Instantiates a new Update executor. * @@ -50,14 +58,13 @@ public class UpdateExecutor<T, S extends Statement> extends AbstractDMLBaseExecu * @param statementCallback the statement callback * @param sqlRecognizer the sql recognizer */ - public UpdateExecutor(StatementProxy<S> statementProxy, StatementCallback<T,S> statementCallback, + public UpdateExecutor(StatementProxy<S> statementProxy, StatementCallback<T, S> statementCallback, SQLRecognizer sqlRecognizer) { super(statementProxy, statementCallback, sqlRecognizer); } @Override protected TableRecords beforeImage() throws SQLException { - ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); TableMeta tmeta = getTableMeta(); String selectSQL = buildBeforeImageSQL(tmeta, paramAppenderList); @@ -65,12 +72,8 @@ public class UpdateExecutor<T, S extends Statement> extends AbstractDMLBaseExecu } private String buildBeforeImageSQL(TableMeta tableMeta, ArrayList<List<Object>> paramAppenderList) { - SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer)sqlRecognizer; - List<String> updateColumns = recognizer.getUpdateColumns(); + SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer) sqlRecognizer; StringBuilder prefix = new StringBuilder("SELECT "); - if (!containsPK(updateColumns)) { - prefix.append(getColumnNameInSQL(tableMeta.getEscapePkName(getDbType()))).append(", "); - } StringBuilder suffix = new StringBuilder(" FROM ").append(getFromTableInSQL()); String whereCondition = buildWhereCondition(recognizer, paramAppenderList); if (StringUtils.isNotBlank(whereCondition)) { @@ -78,8 +81,18 @@ public class UpdateExecutor<T, S extends Statement> extends AbstractDMLBaseExecu } suffix.append(" FOR UPDATE"); StringJoiner selectSQLJoin = new StringJoiner(", ", prefix.toString(), suffix.toString()); - for (String updateColumn : updateColumns) { - selectSQLJoin.add(updateColumn); + if (ONLY_CARE_UPDATE_COLUMNS) { + List<String> updateColumns = recognizer.getUpdateColumns(); + if (!containsPK(updateColumns)) { + selectSQLJoin.add(getColumnNamesInSQL(tableMeta.getEscapePkNameList(getDbType()))); + } + for (String columnName : updateColumns) { + selectSQLJoin.add(columnName); + } + } else { + for (String columnName : tableMeta.getAllColumns().keySet()) { + selectSQLJoin.add(ColumnUtils.addEscape(columnName, getDbType())); + } } return selectSQLJoin.toString(); } @@ -93,11 +106,7 @@ public class UpdateExecutor<T, S extends Statement> extends AbstractDMLBaseExecu String selectSQL = buildAfterImageSQL(tmeta, beforeImage); ResultSet rs = null; try (PreparedStatement pst = statementProxy.getConnection().prepareStatement(selectSQL)) { - List<Field> pkRows = beforeImage.pkRows(); - for (int i = 1; i <= pkRows.size(); i++) { - Field pkField = pkRows.get(i - 1); - pst.setObject(i, pkField.getValue(), pkField.getType()); - } + SqlGenerateUtils.setParamForPk(beforeImage.pkRows(), getTableMeta().getPrimaryKeyOnlyName(), pst); rs = pst.executeQuery(); return TableRecords.buildRecords(tmeta, rs); } finally { @@ -106,17 +115,23 @@ public class UpdateExecutor<T, S extends Statement> extends AbstractDMLBaseExecu } private String buildAfterImageSQL(TableMeta tableMeta, TableRecords beforeImage) throws SQLException { - SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer)sqlRecognizer; - List<String> updateColumns = recognizer.getUpdateColumns(); StringBuilder prefix = new StringBuilder("SELECT "); - if (!containsPK(updateColumns)) { - // PK should be included. - prefix.append(getColumnNameInSQL(tableMeta.getEscapePkName(getDbType()))).append(", "); - } - String suffix = " FROM " + getFromTableInSQL() + " WHERE " + buildWhereConditionByPKs(beforeImage.pkRows()); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(tableMeta.getPrimaryKeyOnlyName(), beforeImage.pkRows().size(), getDbType()); + String suffix = " FROM " + getFromTableInSQL() + " WHERE " + whereSql; StringJoiner selectSQLJoiner = new StringJoiner(", ", prefix.toString(), suffix); - for (String column : updateColumns) { - selectSQLJoiner.add(column); + if (ONLY_CARE_UPDATE_COLUMNS) { + SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer) sqlRecognizer; + List<String> updateColumns = recognizer.getUpdateColumns(); + if (!containsPK(updateColumns)) { + selectSQLJoiner.add(getColumnNamesInSQL(tableMeta.getEscapePkNameList(getDbType()))); + } + for (String columnName : updateColumns) { + selectSQLJoiner.add(columnName); + } + } else { + for (String columnName : tableMeta.getAllColumns().keySet()) { + selectSQLJoiner.add(ColumnUtils.addEscape(columnName, getDbType())); + } } return selectSQLJoiner.toString(); } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..51295508bb9d09a99e23315172173ea8e0561d47 --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertExecutor.java @@ -0,0 +1,176 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.rm.datasource.exec.mysql; + +import io.seata.common.exception.NotSupportYetException; +import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.loader.LoadLevel; +import io.seata.common.loader.Scope; +import io.seata.common.util.StringUtils; +import io.seata.rm.datasource.StatementProxy; +import io.seata.rm.datasource.exec.BaseInsertExecutor; +import io.seata.rm.datasource.exec.StatementCallback; +import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.sqlparser.SQLRecognizer; +import io.seata.sqlparser.struct.Defaultable; +import io.seata.sqlparser.struct.Null; +import io.seata.sqlparser.struct.SqlMethodExpr; +import io.seata.sqlparser.util.JdbcConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.HashSet; +import java.util.Set; +import java.util.ArrayList; + +/** + * @author jsbxyyx + */ +@LoadLevel(name = JdbcConstants.MYSQL, scope = Scope.PROTOTYPE) +public class MySQLInsertExecutor extends BaseInsertExecutor implements Defaultable { + + private static final Logger LOGGER = LoggerFactory.getLogger(MySQLInsertExecutor.class); + + /** + * the modify for test + */ + public static final String ERR_SQL_STATE = "S1009"; + + /** + * Instantiates a new Abstract dml base executor. + * + * @param statementProxy the statement proxy + * @param statementCallback the statement callback + * @param sqlRecognizer the sql recognizer + */ + public MySQLInsertExecutor(StatementProxy statementProxy, StatementCallback statementCallback, + SQLRecognizer sqlRecognizer) { + super(statementProxy, statementCallback, sqlRecognizer); + } + + @Override + public Map<String,List<Object>> getPkValues() throws SQLException { + Map<String,List<Object>> pkValuesMap = null; + List<String> pkColumnNameList = getTableMeta().getPrimaryKeyOnlyName(); + Boolean isContainsPk = containsPK(); + //when there is only one pk in the table + if (getTableMeta().getPrimaryKeyOnlyName().size() == 1) { + if (isContainsPk) { + pkValuesMap = getPkValuesByColumn(); + } + else if (containsColumns()) { + pkValuesMap = getPkValuesByAuto(); + } + else { + pkValuesMap = getPkValuesByColumn(); + } + } else { + //when there is multiple pk in the table + //1,all pk columns are filled value. + //2,the auto increment pk column value is null, and other pk value are not null. + pkValuesMap = getPkValuesByColumn(); + for (String columnName:pkColumnNameList) { + if (!pkValuesMap.containsKey(columnName)) { + ColumnMeta pkColumnMeta = getTableMeta().getColumnMeta(columnName); + if (Objects.nonNull(pkColumnMeta) && pkColumnMeta.isAutoincrement()) { + //3,the auto increment pk column is not exits in sql, and other pk are exits also the value is not null. + pkValuesMap.putAll(getPkValuesByAuto()); + } + } + } + } + return pkValuesMap; + } + + /** + * the modify for test + */ + public Map<String, List<Object>> getPkValuesByAuto() throws SQLException { + // PK is just auto generated + Map<String, List<Object>> pkValuesMap = new HashMap<>(8); + Map<String, ColumnMeta> pkMetaMap = getTableMeta().getPrimaryKeyMap(); + String autoColumnName = ""; + for (String pkColumnName : pkMetaMap.keySet()) { + if (pkMetaMap.get(pkColumnName).isAutoincrement()) + { + autoColumnName = pkColumnName; + break; + } + } + if (StringUtils.isBlank(autoColumnName)) + { + throw new ShouldNeverHappenException(); + } + + ResultSet genKeys; + try { + genKeys = statementProxy.getGeneratedKeys(); + } catch (SQLException e) { + // java.sql.SQLException: Generated keys not requested. You need to + // specify Statement.RETURN_GENERATED_KEYS to + // Statement.executeUpdate() or Connection.prepareStatement(). + if (ERR_SQL_STATE.equalsIgnoreCase(e.getSQLState())) { + LOGGER.warn("Fail to get auto-generated keys, use 'SELECT LAST_INSERT_ID()' instead. Be cautious, statement could be polluted. Recommend you set the statement to return generated keys."); + genKeys = statementProxy.getTargetStatement().executeQuery("SELECT LAST_INSERT_ID()"); + } else { + throw e; + } + } + List<Object> pkValues = new ArrayList<>(); + while (genKeys.next()) { + Object v = genKeys.getObject(1); + pkValues.add(v); + } + try { + genKeys.beforeFirst(); + } catch (SQLException e) { + LOGGER.warn("Fail to reset ResultSet cursor. can not get primary key value"); + } + pkValuesMap.put(autoColumnName,pkValues); + return pkValuesMap; + } + + @Override + public Map<String,List<Object>> getPkValuesByColumn() throws SQLException { + Map<String,List<Object>> pkValuesMap = parsePkValuesFromStatement(); + Set<String> keySet = new HashSet<>(pkValuesMap.keySet()); + //auto increment + for (String pkKey:keySet) { + List<Object> pkValues = pkValuesMap.get(pkKey); + // pk auto generated while single insert primary key is expression + if (pkValues.size() == 1 && (pkValues.get(0) instanceof SqlMethodExpr)) { + pkValuesMap.putAll(getPkValuesByAuto()); + } + // pk auto generated while column exists and value is null + else if (!pkValues.isEmpty() && pkValues.get(0) instanceof Null) { + pkValuesMap.putAll(getPkValuesByAuto()); + } + } + return pkValuesMap; + } + + @Override + public List<Object> getPkValuesByDefault() throws SQLException { + // mysql default keyword the logic not support. (sample: insert into test(id, name) values(default, 'xx')) + throw new NotSupportYetException(); + } +} diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/oracle/OracleInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/oracle/OracleInsertExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..6b0a9217705071c390e2a5f89878301f2b984d4a --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/oracle/OracleInsertExecutor.java @@ -0,0 +1,97 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.rm.datasource.exec.oracle; + +import io.seata.common.exception.NotSupportYetException; +import io.seata.common.loader.LoadLevel; +import io.seata.common.loader.Scope; +import io.seata.rm.datasource.StatementProxy; +import io.seata.rm.datasource.exec.BaseInsertExecutor; +import io.seata.rm.datasource.exec.StatementCallback; +import io.seata.sqlparser.SQLRecognizer; +import io.seata.sqlparser.struct.Null; +import io.seata.sqlparser.struct.Sequenceable; +import io.seata.sqlparser.struct.SqlMethodExpr; +import io.seata.sqlparser.struct.SqlSequenceExpr; +import io.seata.sqlparser.util.JdbcConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * @author jsbxyyx + */ +@LoadLevel(name = JdbcConstants.ORACLE, scope = Scope.PROTOTYPE) +public class OracleInsertExecutor extends BaseInsertExecutor implements Sequenceable { + + private static final Logger LOGGER = LoggerFactory.getLogger(OracleInsertExecutor.class); + + /** + * Instantiates a new Abstract dml base executor. + * + * @param statementProxy the statement proxy + * @param statementCallback the statement callback + * @param sqlRecognizer the sql recognizer + */ + public OracleInsertExecutor(StatementProxy statementProxy, StatementCallback statementCallback, + SQLRecognizer sqlRecognizer) { + super(statementProxy, statementCallback, sqlRecognizer); + } + + @Override + public Map<String,List<Object>> getPkValues() throws SQLException { + Map<String,List<Object>> pkValuesMap = null; + Boolean isContainsPk = containsPK(); + //when there is only one pk in the table + if (isContainsPk) { + pkValuesMap = getPkValuesByColumn(); + } + else if (containsColumns()) { + String columnName = getTableMeta().getPrimaryKeyOnlyName().get(0); + pkValuesMap = Collections.singletonMap(columnName, getGeneratedKeys()); + } + else { + pkValuesMap = getPkValuesByColumn(); + } + return pkValuesMap; + } + + @Override + public Map<String,List<Object>> getPkValuesByColumn() throws SQLException { + Map<String,List<Object>> pkValuesMap = parsePkValuesFromStatement(); + String pkKey = pkValuesMap.keySet().iterator().next(); + List<Object> pkValues = pkValuesMap.get(pkKey); + + if (!pkValues.isEmpty() && pkValues.get(0) instanceof SqlSequenceExpr) { + pkValuesMap.put(pkKey,getPkValuesBySequence((SqlSequenceExpr) pkValues.get(0))); + } else if (pkValues.size() == 1 && pkValues.get(0) instanceof SqlMethodExpr) { + pkValuesMap.put(pkKey,getGeneratedKeys()); + } else if (pkValues.size() == 1 && pkValues.get(0) instanceof Null) { + throw new NotSupportYetException("oracle not support null"); + } + + return pkValuesMap; + } + + @Override + public String getSequenceSql(SqlSequenceExpr expr) { + return "SELECT " + expr.getSequence() + ".currval FROM DUAL"; + } +} diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/postgresql/PostgresqlInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/postgresql/PostgresqlInsertExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..a08a8a0462544fcdb6e4343ec4f287575cf6110c --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/postgresql/PostgresqlInsertExecutor.java @@ -0,0 +1,118 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.rm.datasource.exec.postgresql; + +import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.loader.LoadLevel; +import io.seata.common.loader.Scope; +import io.seata.common.util.StringUtils; +import io.seata.rm.datasource.StatementProxy; +import io.seata.rm.datasource.exec.BaseInsertExecutor; +import io.seata.rm.datasource.exec.StatementCallback; +import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.sqlparser.SQLRecognizer; +import io.seata.sqlparser.struct.Defaultable; +import io.seata.sqlparser.struct.Sequenceable; +import io.seata.sqlparser.struct.SqlMethodExpr; +import io.seata.sqlparser.struct.SqlSequenceExpr; +import io.seata.sqlparser.struct.SqlDefaultExpr; +import io.seata.sqlparser.util.JdbcConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +/** + * @author jsbxyyx + */ +@LoadLevel(name = JdbcConstants.POSTGRESQL, scope = Scope.PROTOTYPE) +public class PostgresqlInsertExecutor extends BaseInsertExecutor implements Sequenceable, Defaultable { + + private static final Logger LOGGER = LoggerFactory.getLogger(PostgresqlInsertExecutor.class); + + /** + * Instantiates a new Abstract dml base executor. + * + * @param statementProxy the statement proxy + * @param statementCallback the statement callback + * @param sqlRecognizer the sql recognizer + */ + public PostgresqlInsertExecutor(StatementProxy statementProxy, StatementCallback statementCallback, + SQLRecognizer sqlRecognizer) { + super(statementProxy, statementCallback, sqlRecognizer); + } + + @Override + public Map<String,List<Object>> getPkValues() throws SQLException { + Map<String,List<Object>> pkValuesMap = null; + Boolean isContainsPk = containsPK(); + //when there is only one pk in the table + if (isContainsPk) { + pkValuesMap = getPkValuesByColumn(); + } + else if (containsColumns()) { + String columnName = getTableMeta().getPrimaryKeyOnlyName().get(0); + pkValuesMap = Collections.singletonMap(columnName, getGeneratedKeys()); + } + else { + pkValuesMap = getPkValuesByColumn(); + } + return pkValuesMap; + } + + @Override + public Map<String,List<Object>> getPkValuesByColumn() throws SQLException { + Map<String,List<Object>> pkValuesMap = parsePkValuesFromStatement(); + String pkKey = pkValuesMap.keySet().iterator().next(); + List<Object> pkValues = pkValuesMap.get(pkKey); + if (!pkValues.isEmpty() && pkValues.get(0) instanceof SqlSequenceExpr) { + pkValuesMap.put(pkKey,getPkValuesBySequence((SqlSequenceExpr) pkValues.get(0))); + } else if (!pkValues.isEmpty() && pkValues.get(0) instanceof SqlMethodExpr) { + pkValuesMap.put(pkKey,getGeneratedKeys()); + } else if (!pkValues.isEmpty() && pkValues.get(0) instanceof SqlDefaultExpr) { + pkValuesMap.put(pkKey,getPkValuesByDefault()); + } + + return pkValuesMap; + } + + /** + * get primary key values by default + * @return + * @throws SQLException + */ + @Override + public List<Object> getPkValuesByDefault() throws SQLException { + // current version 1.2 only support postgresql. + Map<String, ColumnMeta> pkMetaMap = getTableMeta().getPrimaryKeyMap(); + ColumnMeta pkMeta = pkMetaMap.values().iterator().next(); + String columnDef = pkMeta.getColumnDef(); + // sample: nextval('test_id_seq'::regclass) + String seq = org.apache.commons.lang.StringUtils.substringBetween(columnDef, "'", "'"); + String function = org.apache.commons.lang.StringUtils.substringBetween(columnDef, "", "("); + if (StringUtils.isBlank(seq)) { + throw new ShouldNeverHappenException("get primary key value failed, cause columnDef is " + columnDef); + } + return getPkValuesBySequence(new SqlSequenceExpr("'" + seq + "'", function)); + } + + @Override + public String getSequenceSql(SqlSequenceExpr expr) { + return "SELECT currval(" + expr.getSequence() + ")"; + } +} diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/serial/SerialArray.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/serial/SerialArray.java new file mode 100644 index 0000000000000000000000000000000000000000..ce70feda4bb03ba91f3ff409bd8a0cc06f2a23d3 --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/serial/SerialArray.java @@ -0,0 +1,190 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.rm.datasource.sql.serial; + +import javax.sql.rowset.serial.SerialBlob; +import javax.sql.rowset.serial.SerialClob; +import javax.sql.rowset.serial.SerialDatalink; +import javax.sql.rowset.serial.SerialException; +import javax.sql.rowset.serial.SerialJavaObject; +import java.net.URL; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Map; + +/** + * used for jdbc type is JDBCType.ARRAY serialize. + * + * @author jsbxyyx + */ +public class SerialArray implements java.sql.Array, java.io.Serializable { + + static final long serialVersionUID = 1L; + + private Object[] elements; + private int baseType; + private String baseTypeName; + private int len; + + public SerialArray() { + } + + public SerialArray(java.sql.Array array) throws SerialException, SQLException { + if (array == null) { + throw new SQLException("Cannot instantiate a SerialArray " + + "object with a null Array object"); + } + + if ((elements = (Object[]) array.getArray()) == null) { + throw new SQLException("Invalid Array object. Calls to Array.getArray() " + + "return null value which cannot be serialized"); + } + + baseType = array.getBaseType(); + baseTypeName = array.getBaseTypeName(); + len = elements.length; + + switch (baseType) { + case java.sql.Types.BLOB: + for (int i = 0; i < len; i++) { + elements[i] = new SerialBlob((Blob) elements[i]); + } + break; + case java.sql.Types.CLOB: + for (int i = 0; i < len; i++) { + elements[i] = new SerialClob((Clob) elements[i]); + } + break; + case java.sql.Types.DATALINK: + for (int i = 0; i < len; i++) { + elements[i] = new SerialDatalink((URL) elements[i]); + } + break; + case java.sql.Types.JAVA_OBJECT: + for (int i = 0; i < len; i++) { + elements[i] = new SerialJavaObject(elements[i]); + } + break; + default: + break; + } + } + + @Override + public String getBaseTypeName() throws SQLException { + return baseTypeName; + } + + public void setBaseTypeName(String baseTypeName) { + this.baseTypeName = baseTypeName; + } + + @Override + public int getBaseType() throws SQLException { + return baseType; + } + + public void setBaseType(int baseType) { + this.baseType = baseType; + } + + @Override + public Object getArray() throws SQLException { + return elements; + } + + @Override + public Object getArray(Map<String, Class<?>> map) throws SQLException { + return elements; + } + + @Override + public Object getArray(long index, int count) throws SQLException { + return elements; + } + + @Override + public Object getArray(long index, int count, Map<String, Class<?>> map) throws SQLException { + return elements; + } + + @Override + public ResultSet getResultSet() throws SQLException { + // don't throws exception. + return null; + } + + @Override + public ResultSet getResultSet(Map<String, Class<?>> map) throws SQLException { + // don't throws exception. + return null; + } + + @Override + public ResultSet getResultSet(long index, int count) throws SQLException { + // don't throws exception. + return null; + } + + @Override + public ResultSet getResultSet(long index, int count, Map<String, Class<?>> map) throws SQLException { + // don't throws exception. + return null; + } + + @Override + public void free() throws SQLException { + if (elements != null) { + elements = null; + baseTypeName = null; + } + } + + public Object[] getElements() { + return elements; + } + + public void setElements(Object[] elements) { + this.elements = elements; + this.len = elements != null ? elements.length : 0; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof SerialArray) { + SerialArray sa = (SerialArray) obj; + return baseType == sa.baseType && + baseTypeName.equals(sa.baseTypeName) && + Arrays.equals(elements, sa.elements); + } + return false; + } + + @Override + public int hashCode() { + return (((31 + Arrays.hashCode(elements)) * 31 + len) * 31 + + baseType) * 31 + baseTypeName.hashCode(); + } + +} diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/ColumnMeta.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/ColumnMeta.java index 4540abc423e3650775e111660796a34b4c1e6444..3eb288d62f4f717d6b3d02da778da3ef2fa316c4 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/ColumnMeta.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/ColumnMeta.java @@ -37,7 +37,7 @@ public class ColumnMeta { private String columnDef; private int sqlDataType; private int sqlDatetimeSub; - private int charOctetLength; + private Object charOctetLength; private int ordinalPosition; private String isNullAble; private String isAutoincrement; @@ -337,7 +337,7 @@ public class ColumnMeta { * * @return the char octet length */ - public int getCharOctetLength() { + public Object getCharOctetLength() { return charOctetLength; } @@ -346,7 +346,7 @@ public class ColumnMeta { * * @param charOctetLength the char octet length */ - public void setCharOctetLength(int charOctetLength) { + public void setCharOctetLength(Object charOctetLength) { this.charOctetLength = charOctetLength; } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Row.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Row.java index 85a419fbaf98b83c4b80585d6869a4cdf9b1778c..9255836e760ac02893bb0a76b6d7c3b97f1e54da 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Row.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Row.java @@ -18,7 +18,6 @@ package io.seata.rm.datasource.sql.struct; import java.util.ArrayList; import java.util.List; -import io.seata.common.exception.NotSupportYetException; /** * The type Row. @@ -74,9 +73,6 @@ public class Row { pkFields.add(field); } } - if (pkFields.size() > 1) { - throw new NotSupportYetException("Multi-PK"); - } return pkFields; } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java index b5ee6ff11dd696a139f4fbfc2ed6d8c33bd394ef..7760ad92636dce614f77b0c0ebd5f4042f4eee5b 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java @@ -38,6 +38,7 @@ public class TableMeta { /** * key: column name */ + private Map<String, ColumnMeta> allColumns = new LinkedHashMap<String, ColumnMeta>(); /** * key: index name @@ -122,9 +123,6 @@ public class TableMeta { } } - if (pk.size() > 1) { - throw new NotSupportYetException(String.format("%s contains multi PK, but current not support.", tableName)); - } if (pk.size() < 1) { throw new NotSupportYetException(String.format("%s needs to contain the primary key.", tableName)); } @@ -146,22 +144,13 @@ public class TableMeta { return list; } - /** - * Gets pk name. - * - * @return the pk name - */ - public String getPkName() { - return getPrimaryKeyOnlyName().get(0); - } - /** * Gets add escape pk name. * @param dbType * @return */ - public String getEscapePkName(String dbType) { - return ColumnUtils.addEscape(getPkName(), dbType); + public List<String> getEscapePkNameList(String dbType) { + return ColumnUtils.addEscape(getPrimaryKeyOnlyName(), dbType); } /** @@ -180,6 +169,8 @@ public class TableMeta { return false; } + + //at least contain one pk if (cols.containsAll(pk)) { return true; } else { diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java index 2c99124887197a4c9aec50d04ad44f6ee9fd3cba..0f9c47d6191f6c1ad25565205141a4d405ba4e92 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java @@ -16,17 +16,25 @@ package io.seata.rm.datasource.sql.struct; import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.rm.datasource.sql.serial.SerialArray; import javax.sql.rowset.serial.SerialBlob; import javax.sql.rowset.serial.SerialClob; +import javax.sql.rowset.serial.SerialDatalink; +import javax.sql.rowset.serial.SerialJavaObject; +import javax.sql.rowset.serial.SerialRef; +import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.JDBCType; +import java.sql.Ref; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * The type Table records. @@ -127,19 +135,20 @@ public class TableRecords { /** * Pk rows list. * - * @return the list + * @return return a list. each element of list is a map,the map hold the pk column name as a key and field as the value */ - public List<Field> pkRows() { - final String pkName = getTableMeta().getPkName(); - List<Field> pkRows = new ArrayList<>(); + public List<Map<String,Field>> pkRows() { + final Map<String, ColumnMeta> primaryKeyMap = getTableMeta().getPrimaryKeyMap(); + List<Map<String,Field>> pkRows = new ArrayList<>(); for (Row row : rows) { List<Field> fields = row.getFields(); + Map<String,Field> rowMap = new HashMap<>(3); for (Field field : fields) { - if (field.getName().equalsIgnoreCase(pkName)) { - pkRows.add(field); - break; + if (primaryKeyMap.containsKey(field.getName())) { + rowMap.put(field.getName(),field); } } + pkRows.add(rowMap); } return pkRows; } @@ -181,26 +190,47 @@ public class TableRecords { for (int i = 1; i <= columnCount; i++) { String colName = resultSetMetaData.getColumnName(i); ColumnMeta col = tmeta.getColumnMeta(colName); + int dataType = col.getDataType(); Field field = new Field(); field.setName(col.getColumnName()); - if (tmeta.getPkName().equalsIgnoreCase(field.getName())) { + if (tmeta.getPrimaryKeyMap().containsKey(colName)) { field.setKeyType(KeyType.PRIMARY_KEY); } - field.setType(col.getDataType()); + field.setType(dataType); // mysql will not run in this code // cause mysql does not use java.sql.Blob, java.sql.sql.Clob to process Blob and Clob column - if (col.getDataType() == JDBCType.BLOB.getVendorTypeNumber()) { + if (dataType == JDBCType.BLOB.getVendorTypeNumber()) { Blob blob = resultSet.getBlob(i); if (blob != null) { field.setValue(new SerialBlob(blob)); } - - } else if (col.getDataType() == JDBCType.CLOB.getVendorTypeNumber()) { + } else if (dataType == JDBCType.CLOB.getVendorTypeNumber()) { Clob clob = resultSet.getClob(i); if (clob != null) { field.setValue(new SerialClob(clob)); } + } else if (dataType == JDBCType.ARRAY.getVendorTypeNumber()) { + Array array = resultSet.getArray(i); + if (array != null) { + field.setValue(new SerialArray(array)); + } + } else if (dataType == JDBCType.REF.getVendorTypeNumber()) { + Ref ref = resultSet.getRef(i); + if (ref != null) { + field.setValue(new SerialRef(ref)); + } + } else if (dataType == JDBCType.DATALINK.getVendorTypeNumber()) { + java.net.URL url = resultSet.getURL(i); + if (url != null) { + field.setValue(new SerialDatalink(url)); + } + } else if (dataType == JDBCType.JAVA_OBJECT.getVendorTypeNumber()) { + Object object = resultSet.getObject(i); + if (object != null) { + field.setValue(new SerialJavaObject(object)); + } } else { + // JDBCType.DISTINCT, JDBCType.STRUCT etc... field.setValue(resultSet.getObject(i)); } @@ -229,7 +259,7 @@ public class TableRecords { } @Override - public List<Field> pkRows() { + public List<Map<String,Field>> pkRows() { return new ArrayList<>(); } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java index a50a395119a69e02a53b4ce386595dad31d8f769..07654739f4facea54ac6ed5537f1180c9a266d77 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/AbstractTableMetaCache.java @@ -60,19 +60,11 @@ public abstract class AbstractTableMetaCache implements TableMetaCache { try { return fetchSchema(connection, tableName); } catch (SQLException e) { - LOGGER.error("get cache error:{}", e.getMessage(), e); + LOGGER.error("get table meta error:{}", e.getMessage(), e); return null; } }); - if (tmeta == null) { - try { - tmeta = fetchSchema(connection, tableName); - } catch (SQLException e) { - LOGGER.error("get table meta error:{}", e.getMessage(), e); - } - } - if (tmeta == null) { throw new ShouldNeverHappenException(String.format("[xid:%s]get tablemeta failed", RootContext.getXID())); } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java index 5f9cf811a3b6e3f87e032308e6e47a20006b6a6f..9adcb8570474e1458876d76f4f0bcf2af6962cf5 100755 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCache.java @@ -24,12 +24,11 @@ import java.sql.Statement; import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.loader.LoadLevel; +import io.seata.rm.datasource.ColumnUtils; import io.seata.rm.datasource.sql.struct.ColumnMeta; import io.seata.rm.datasource.sql.struct.IndexMeta; import io.seata.rm.datasource.sql.struct.IndexType; import io.seata.rm.datasource.sql.struct.TableMeta; -import io.seata.rm.datasource.undo.KeywordChecker; -import io.seata.rm.datasource.undo.KeywordCheckerFactory; import io.seata.sqlparser.util.JdbcConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,8 +43,6 @@ public class MysqlTableMetaCache extends AbstractTableMetaCache { private static final Logger LOGGER = LoggerFactory.getLogger(MysqlTableMetaCache.class); - private KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.MYSQL); - @Override protected String getCacheKey(Connection connection, String tableName, String resourceId) { StringBuilder cacheKey = new StringBuilder(resourceId); @@ -79,15 +76,13 @@ public class MysqlTableMetaCache extends AbstractTableMetaCache { @Override protected TableMeta fetchSchema(Connection connection, String tableName) throws SQLException { - String sql = "SELECT * FROM " + keywordChecker.checkAndReplace(tableName) + " LIMIT 1"; + String sql = "SELECT * FROM " + ColumnUtils.addEscape(tableName, JdbcConstants.MYSQL) + " LIMIT 1"; try (Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery(sql)) { + ResultSet rs = stmt.executeQuery(sql)) { return resultSetMetaToSchema(rs.getMetaData(), connection.getMetaData()); - } - catch (SQLException sqlEx) { + } catch (SQLException sqlEx) { throw sqlEx; - } - catch (Exception e) { + } catch (Exception e) { throw new SQLException(String.format("Failed to fetch schema of %s", tableName), e); } } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java index 7c03b8408e00afd6fcc8cee033733a1825b0afbc..6f8512c27c04e04001179ae8a3daf6a32ca72b8f 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCache.java @@ -61,11 +61,9 @@ public class OracleTableMetaCache extends AbstractTableMetaCache { protected TableMeta fetchSchema(Connection connection, String tableName) throws SQLException { try { return resultSetMetaToSchema(connection.getMetaData(), tableName); - } - catch (SQLException sqlEx) { + } catch (SQLException sqlEx) { throw sqlEx; - } - catch (Exception e) { + } catch (Exception e) { throw new SQLException(String.format("Failed to fetch schema of %s", tableName), e); } } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java index f2b086f9b75a0f4eb69bd2b92087dfd386f28301..d7be9049e8031f07c55f47ff790765ac6716d6c3 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCache.java @@ -19,8 +19,6 @@ import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; - import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.loader.LoadLevel; import io.seata.common.util.StringUtils; @@ -28,8 +26,6 @@ import io.seata.rm.datasource.sql.struct.ColumnMeta; import io.seata.rm.datasource.sql.struct.IndexMeta; import io.seata.rm.datasource.sql.struct.IndexType; import io.seata.rm.datasource.sql.struct.TableMeta; -import io.seata.rm.datasource.undo.KeywordChecker; -import io.seata.rm.datasource.undo.KeywordCheckerFactory; import io.seata.sqlparser.util.JdbcConstants; /** @@ -40,8 +36,6 @@ import io.seata.sqlparser.util.JdbcConstants; @LoadLevel(name = JdbcConstants.POSTGRESQL) public class PostgresqlTableMetaCache extends AbstractTableMetaCache { - private KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.POSTGRESQL); - @Override protected String getCacheKey(Connection connection, String tableName, String resourceId) { StringBuilder cacheKey = new StringBuilder(resourceId); @@ -64,21 +58,13 @@ public class PostgresqlTableMetaCache extends AbstractTableMetaCache { @Override protected TableMeta fetchSchema(Connection connection, String tableName) throws SQLException { - Statement stmt = null; try { - stmt = connection.createStatement(); DatabaseMetaData dbmd = connection.getMetaData(); - tableName = keywordChecker.checkAndReplace(tableName); return resultSetMetaToSchema(dbmd, tableName); + } catch (SQLException sqlEx) { + throw sqlEx; } catch (Exception e) { - if (e instanceof SQLException) { - throw e; - } throw new SQLException("Failed to fetch schema of " + tableName, e); - } finally { - if (stmt != null) { - stmt.close(); - } } } @@ -105,7 +91,7 @@ public class PostgresqlTableMetaCache extends AbstractTableMetaCache { * select * from "Test".test * select * from "Test"."Select" */ - if (null != schemaName) { + if (schemaName != null) { if (schemaName.startsWith("\"") && schemaName.endsWith("\"")) { schemaName = schemaName.replaceAll("(^\")|(\"$)", ""); } else { @@ -137,7 +123,7 @@ public class PostgresqlTableMetaCache extends AbstractTableMetaCache { col.setColumnDef(rsColumns.getString("COLUMN_DEF")); col.setSqlDataType(rsColumns.getInt("SQL_DATA_TYPE")); col.setSqlDatetimeSub(rsColumns.getInt("SQL_DATETIME_SUB")); - col.setCharOctetLength(rsColumns.getInt("CHAR_OCTET_LENGTH")); + col.setCharOctetLength(rsColumns.getObject("CHAR_OCTET_LENGTH")); col.setOrdinalPosition(rsColumns.getInt("ORDINAL_POSITION")); col.setIsNullAble(rsColumns.getString("IS_NULLABLE")); col.setIsAutoincrement(rsColumns.getString("IS_AUTOINCREMENT")); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java index d1efb2fe6efb07b3012c91ac81511c211805a0e1..b529acaedb084be9e326739986898dfd706362be 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java @@ -17,6 +17,8 @@ package io.seata.rm.datasource.undo; import javax.sql.rowset.serial.SerialBlob; import javax.sql.rowset.serial.SerialClob; +import javax.sql.rowset.serial.SerialDatalink; +import java.sql.Array; import java.sql.Connection; import java.sql.JDBCType; import java.sql.PreparedStatement; @@ -31,7 +33,10 @@ import io.seata.common.util.StringUtils; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.model.Result; +import io.seata.rm.datasource.ColumnUtils; import io.seata.rm.datasource.DataCompareUtils; +import io.seata.rm.datasource.SqlGenerateUtils; +import io.seata.rm.datasource.sql.serial.SerialArray; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.KeyType; import io.seata.rm.datasource.sql.struct.Row; @@ -43,6 +48,9 @@ import org.slf4j.LoggerFactory; import static io.seata.core.constants.DefaultValues.DEFAULT_TRANSACTION_UNDO_DATA_VALIDATION; +import java.util.Map; +import java.util.stream.Collectors; + /** * The type Abstract undo executor. * @@ -60,13 +68,13 @@ public abstract class AbstractUndoExecutor { * template of check sql * TODO support multiple primary key */ - private static final String CHECK_SQL_TEMPLATE = "SELECT * FROM %s WHERE %s in (%s)"; + private static final String CHECK_SQL_TEMPLATE = "SELECT * FROM %s WHERE %s"; /** * Switch of undo data validation */ public static final boolean IS_UNDO_DATA_VALIDATION_ENABLE = ConfigurationFactory.getInstance() - .getBoolean(ConfigurationKeys.TRANSACTION_UNDO_DATA_VALIDATION, DEFAULT_TRANSACTION_UNDO_DATA_VALIDATION); + .getBoolean(ConfigurationKeys.TRANSACTION_UNDO_DATA_VALIDATION, DEFAULT_TRANSACTION_UNDO_DATA_VALIDATION); /** * The Sql undo log. @@ -105,30 +113,23 @@ public abstract class AbstractUndoExecutor { * @throws SQLException the sql exception */ public void executeOn(Connection conn) throws SQLException { - if (IS_UNDO_DATA_VALIDATION_ENABLE && !dataValidationAndGoOn(conn)) { return; } - try { String undoSQL = buildUndoSQL(); - PreparedStatement undoPST = conn.prepareStatement(undoSQL); - TableRecords undoRows = getUndoRows(); - for (Row undoRow : undoRows.getRows()) { ArrayList<Field> undoValues = new ArrayList<>(); - Field pkValue = null; + List<Field> pkValueList = getOrderedPkList(undoRows, undoRow, getDbType(conn)); for (Field field : undoRow.getFields()) { - if (field.getKeyType() == KeyType.PRIMARY_KEY) { - pkValue = field; - } else { + if (field.getKeyType() != KeyType.PRIMARY_KEY) { undoValues.add(field); } } - undoPrepare(undoPST, undoValues, pkValue); + undoPrepare(undoPST, undoValues, pkValueList); undoPST.executeUpdate(); } @@ -139,7 +140,6 @@ public abstract class AbstractUndoExecutor { } else { throw new SQLException(ex); } - } } @@ -147,42 +147,63 @@ public abstract class AbstractUndoExecutor { /** * Undo prepare. * - * @param undoPST the undo pst - * @param undoValues the undo values - * @param pkValue the pk value + * @param undoPST the undo pst + * @param undoValues the undo values + * @param pkValueList the pk value * @throws SQLException the sql exception */ - protected void undoPrepare(PreparedStatement undoPST, ArrayList<Field> undoValues, Field pkValue) - throws SQLException { + protected void undoPrepare(PreparedStatement undoPST, ArrayList<Field> undoValues, List<Field> pkValueList) + throws SQLException { int undoIndex = 0; for (Field undoValue : undoValues) { undoIndex++; - if (undoValue.getType() == JDBCType.BLOB.getVendorTypeNumber()) { - SerialBlob serialBlob = (SerialBlob) undoValue.getValue(); + int type = undoValue.getType(); + Object value = undoValue.getValue(); + if (type == JDBCType.BLOB.getVendorTypeNumber()) { + SerialBlob serialBlob = (SerialBlob) value; if (serialBlob != null) { undoPST.setBlob(undoIndex, serialBlob.getBinaryStream()); } else { undoPST.setObject(undoIndex, null); } - } else if (undoValue.getType() == JDBCType.CLOB.getVendorTypeNumber()) { - SerialClob serialClob = (SerialClob) undoValue.getValue(); + } else if (type == JDBCType.CLOB.getVendorTypeNumber()) { + SerialClob serialClob = (SerialClob) value; if (serialClob != null) { undoPST.setClob(undoIndex, serialClob.getCharacterStream()); } else { undoPST.setObject(undoIndex, null); } + } else if (type == JDBCType.DATALINK.getVendorTypeNumber()) { + SerialDatalink dataLink = (SerialDatalink) value; + if (dataLink != null) { + undoPST.setURL(undoIndex, dataLink.getDatalink()); + } else { + undoPST.setObject(undoIndex, null); + } + } else if (type == JDBCType.ARRAY.getVendorTypeNumber()) { + SerialArray array = (SerialArray) value; + if (array != null) { + Array arrayOf = undoPST.getConnection().createArrayOf(array.getBaseTypeName(), array.getElements()); + undoPST.setArray(undoIndex, arrayOf); + } else { + undoPST.setObject(undoIndex, null); + } } else if (undoValue.getType() == JDBCType.OTHER.getVendorTypeNumber()) { - undoPST.setObject(undoIndex, undoValue.getValue()); + undoPST.setObject(undoIndex, value); } else { - undoPST.setObject(undoIndex, undoValue.getValue(), undoValue.getType()); + // JDBCType.REF, JDBCType.JAVA_OBJECT etc... + undoPST.setObject(undoIndex, value, type); } } - // PK is at last one. - // INSERT INTO a (x, y, z, pk) VALUES (?, ?, ?, ?) - // UPDATE a SET x=?, y=?, z=? WHERE pk = ? - // DELETE FROM a WHERE pk = ? - undoIndex++; - undoPST.setObject(undoIndex, pkValue.getValue(), pkValue.getType()); + // PK is always at last. + // INSERT INTO a (x, y, z, pk1,pk2) VALUES (?, ?, ?, ? ,?) + // UPDATE a SET x=?, y=?, z=? WHERE pk1 in (?) and pk2 in (?) + // DELETE FROM a WHERE pk1 in (?) and pk2 in (?) + for (Field pkField : pkValueList) { + undoIndex++; + undoPST.setObject(undoIndex, pkField.getValue(), pkField.getType()); + } + } /** @@ -210,7 +231,7 @@ public abstract class AbstractUndoExecutor { if (beforeEqualsAfterResult.getResult()) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Stop rollback because there is no data change " + - "between the before data snapshot and the after data snapshot."); + "between the before data snapshot and the after data snapshot."); } // no need continue undo. return false; @@ -228,7 +249,7 @@ public abstract class AbstractUndoExecutor { if (beforeEqualsCurrentResult.getResult()) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Stop rollback because there is no data change " + - "between the before data snapshot and the current data snapshot."); + "between the before data snapshot and the current data snapshot."); } // no need continue undo. return false; @@ -240,9 +261,9 @@ public abstract class AbstractUndoExecutor { } if (LOGGER.isDebugEnabled()) { LOGGER.debug("check dirty datas failed, old and new data are not equal," + - "tableName:[" + sqlUndoLog.getTableName() + "]," + - "oldRows:[" + JSON.toJSONString(afterRecords.getRows()) + "]," + - "newRows:[" + JSON.toJSONString(currentRecords.getRows()) + "]."); + "tableName:[" + sqlUndoLog.getTableName() + "]," + + "oldRows:[" + JSON.toJSONString(afterRecords.getRows()) + "]," + + "newRows:[" + JSON.toJSONString(currentRecords.getRows()) + "]."); } throw new SQLException("Has dirty records when undo."); } @@ -260,31 +281,37 @@ public abstract class AbstractUndoExecutor { protected TableRecords queryCurrentRecords(Connection conn) throws SQLException { TableRecords undoRecords = getUndoRows(); TableMeta tableMeta = undoRecords.getTableMeta(); - String pkName = tableMeta.getPkName(); - int pkType = tableMeta.getColumnMeta(pkName).getDataType(); + //the order of element matters + List<String> pkNameList = tableMeta.getPrimaryKeyOnlyName(); // pares pk values - Object[] pkValues = parsePkValues(getUndoRows()); - if (pkValues.length == 0) { + Map<String, List<Field>> pkRowValues = parsePkValues(getUndoRows()); + if (pkRowValues.size() == 0) { return TableRecords.empty(tableMeta); } - StringBuilder replace = new StringBuilder(); - for (int i = 0; i < pkValues.length; i++) { - replace.append("?,"); - } // build check sql - String dbType = getDbType(conn); + String firstKey = pkRowValues.keySet().stream().findFirst().get(); + int pkRowSize = pkRowValues.get(firstKey).size(); String checkSQL = String.format(CHECK_SQL_TEMPLATE, sqlUndoLog.getTableName(), - tableMeta.getEscapePkName(dbType), replace.substring(0, replace.length() - 1)); + SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, pkRowSize, getDbType(conn))); PreparedStatement statement = null; ResultSet checkSet = null; TableRecords currentRecords; try { statement = conn.prepareStatement(checkSQL); - for (int i = 1; i <= pkValues.length; i++) { - statement.setObject(i, pkValues[i - 1], pkType); + int paramIndex = 1; + int rowSize = pkRowValues.get(pkNameList.get(0)).size(); + for (int r = 0; r < rowSize; r++) { + for (int c = 0; c < pkNameList.size(); c++) { + List<Field> pkColumnValueList = pkRowValues.get(pkNameList.get(c)); + Field field = pkColumnValueList.get(r); + int dataType = tableMeta.getColumnMeta(field.getName()).getDataType(); + statement.setObject(paramIndex, field.getValue(), dataType); + paramIndex++; + } } + checkSet = statement.executeQuery(); currentRecords = TableRecords.buildRecords(tableMeta, checkSet); } finally { @@ -293,27 +320,56 @@ public abstract class AbstractUndoExecutor { return currentRecords; } + protected List<Field> getOrderedPkList(TableRecords image, Row row, String dbType) { + List<Field> pkFields = new ArrayList<>(); + // To ensure the order of the pk, the order should based on getPrimaryKeyOnlyName. + List<String> pkColumnNameListByOrder = image.getTableMeta().getPrimaryKeyOnlyName(); + List<String> pkColumnNameListNoOrder = row.primaryKeys() + .stream() + .map(e -> ColumnUtils.delEscape(e.getName(), dbType)) + .collect(Collectors.toList()); + pkColumnNameListByOrder.forEach(pkName -> { + int pkIndex = pkColumnNameListNoOrder.indexOf(pkName); + if (pkIndex != -1) { + // add PK to the last of the list. + pkFields.add(row.primaryKeys().get(pkIndex)); + } + }); + return pkFields; + } + + /** - * Parse pk values object [ ]. + * Parse pk values Field List. * * @param records the records - * @return the object [ ] + * @return List<List < Field>> each element represents a row. And inside a row list contains pk columns(Field). + */ + protected Map<String, List<Field>> parsePkValues(TableRecords records) { + return parsePkValues(records.getRows(), records.getTableMeta().getPrimaryKeyOnlyName()); + } + + /** + * Parse pk values Field List. + * + * @param rows pk rows + * @param pkNameList pk column name + * @return List<List < Field>> each element represents a row. And inside a row list contains pk columns(Field). */ - protected Object[] parsePkValues(TableRecords records) { - String pkName = records.getTableMeta().getPkName(); - List<Row> undoRows = records.getRows(); - Object[] pkValues = new Object[undoRows.size()]; - for (int i = 0; i < undoRows.size(); i++) { - List<Field> fields = undoRows.get(i).getFields(); + protected Map<String, List<Field>> parsePkValues(List<Row> rows, List<String> pkNameList) { + List<Field> pkFieldList = new ArrayList<>(); + for (int i = 0; i < rows.size(); i++) { + List<Field> fields = rows.get(i).getFields(); if (fields != null) { for (Field field : fields) { - if (StringUtils.equalsIgnoreCase(pkName, field.getName())) { - pkValues[i] = field.getValue(); + if (pkNameList.stream().anyMatch(e -> field.getName().equalsIgnoreCase(e))) { + pkFieldList.add(field); } } } } - return pkValues; + Map<String, List<Field>> pkValueMap = pkFieldList.stream().collect(Collectors.groupingBy(Field::getName)); + return pkValueMap; } /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/KeywordChecker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/KeywordChecker.java index 89708259b52b52d0e34634a237a305913895a28b..1ac3e447afce8e70e0aad4b03a582c464f535ba2 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/KeywordChecker.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/KeywordChecker.java @@ -37,11 +37,4 @@ public interface KeywordChecker { */ boolean checkEscape(String fieldOrTableName); - /** - * check whether given field name and table name use keywords and,if so,will add "`" to the name. - * - * @param fieldOrTableName the field or table name - * @return string - */ - String checkAndReplace(String fieldOrTableName); } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/KeywordCheckerFactory.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/KeywordCheckerFactory.java index 65e86f0dd43c4d19094b10ab872114ea1ecab95e..e9bf2c086294e580789b0c0d77d18663ad608616 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/KeywordCheckerFactory.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/KeywordCheckerFactory.java @@ -15,11 +15,11 @@ */ package io.seata.rm.datasource.undo; +import io.seata.common.loader.EnhancedServiceLoader; + import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import io.seata.common.loader.EnhancedServiceLoader; - /** * The type Keyword checker factory. * diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutor.java index cf7c9c9479d9cfb70398adbfdc6ce0a090e152c1..56bc951d351cc7f226aba9d9d0a50ca314771da3 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutor.java @@ -67,9 +67,7 @@ public class MySQLUndoDeleteExecutor extends AbstractUndoExecutor { } Row row = beforeImageRows.get(0); List<Field> fields = new ArrayList<>(row.nonPrimaryKeys()); - Field pkField = row.primaryKeys().get(0); - // PK is at last one. - fields.add(pkField); + fields.addAll(getOrderedPkList(beforeImage,row,JdbcConstants.MYSQL)); // delete sql undo log before image all field come from table meta, need add escape. // see BaseTransactionalExecutor#buildTableRecords diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutor.java index 48f0352ba74e045a91915a91e4ed2aa255cf0a64..ae2a45c969f6793e5007e90d2250ddf57ed10b26 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutor.java @@ -15,9 +15,15 @@ */ package io.seata.rm.datasource.undo.mysql; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.util.CollectionUtils; -import io.seata.rm.datasource.ColumnUtils; +import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; import io.seata.rm.datasource.sql.struct.TableRecords; @@ -25,11 +31,6 @@ import io.seata.rm.datasource.undo.AbstractUndoExecutor; import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.util.JdbcConstants; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - /** * The type My sql undo insert executor. * @@ -40,7 +41,7 @@ public class MySQLUndoInsertExecutor extends AbstractUndoExecutor { /** * DELETE FROM a WHERE pk = ? */ - private static final String DELETE_SQL_TEMPLATE = "DELETE FROM %s WHERE %s = ?"; + private static final String DELETE_SQL_TEMPLATE = "DELETE FROM %s WHERE %s "; /** * Undo Inset. @@ -54,18 +55,24 @@ public class MySQLUndoInsertExecutor extends AbstractUndoExecutor { if (CollectionUtils.isEmpty(afterImageRows)) { throw new ShouldNeverHappenException("Invalid UNDO LOG"); } - Row row = afterImageRows.get(0); - Field pkField = row.primaryKeys().get(0); - // insert sql undo log after image all field come from table meta, need add escape. - // see BaseTransactionalExecutor#buildTableRecords - return String.format(DELETE_SQL_TEMPLATE, sqlUndoLog.getTableName(), - ColumnUtils.addEscape(pkField.getName(), JdbcConstants.MYSQL)); + return generateDeleteSql(afterImageRows,afterImage); } @Override - protected void undoPrepare(PreparedStatement undoPST, ArrayList<Field> undoValues, Field pkValue) - throws SQLException { - undoPST.setObject(1, pkValue.getValue(), pkValue.getType()); + protected void undoPrepare(PreparedStatement undoPST, ArrayList<Field> undoValues, List<Field> pkValueList) + throws SQLException { + int undoIndex = 0; + for (Field pkField:pkValueList) { + undoIndex++; + undoPST.setObject(undoIndex, pkField.getValue(), pkField.getType()); + } + } + + private String generateDeleteSql(List<Row> rows, TableRecords afterImage) { + List<String> pkNameList = getOrderedPkList(afterImage, rows.get(0), JdbcConstants.MYSQL).stream().map( + e -> e.getName()).collect(Collectors.toList()); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.MYSQL); + return String.format(DELETE_SQL_TEMPLATE, sqlUndoLog.getTableName(), whereSql); } /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManager.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManager.java index 620b5a2d07004fcfb50d29b969cacdffe5aed206..229e1814cec0adc0341ca98fa4b8ffb04979cb64 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManager.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManager.java @@ -47,7 +47,7 @@ public class MySQLUndoLogManager extends AbstractUndoLogManager { + ClientTableColumnsName.UNDO_LOG_CONTEXT + ", " + ClientTableColumnsName.UNDO_LOG_ROLLBACK_INFO + ", " + ClientTableColumnsName.UNDO_LOG_LOG_STATUS + ", " + ClientTableColumnsName.UNDO_LOG_LOG_CREATED + ", " + ClientTableColumnsName.UNDO_LOG_LOG_MODIFIED + ")" + - " VALUES (?, ?, ?, ?, ?, now(), now())"; + " VALUES (?, ?, ?, ?, ?, now(6), now(6))"; private static final String DELETE_UNDO_LOG_BY_CREATE_SQL = "DELETE FROM " + UNDO_LOG_TABLE_NAME + " WHERE log_created <= ? LIMIT ?"; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java index b5894c13b6901dc9de9f7dc35372a525ba48e353..063f831af401bfe9117b52ba7e036703f2c5baad 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java @@ -15,9 +15,13 @@ */ package io.seata.rm.datasource.undo.mysql; +import java.util.List; +import java.util.stream.Collectors; + import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.util.CollectionUtils; import io.seata.rm.datasource.ColumnUtils; +import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; import io.seata.rm.datasource.sql.struct.TableRecords; @@ -25,9 +29,6 @@ import io.seata.rm.datasource.undo.AbstractUndoExecutor; import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.util.JdbcConstants; -import java.util.List; -import java.util.stream.Collectors; - /** * The type My sql undo update executor. * @@ -36,9 +37,9 @@ import java.util.stream.Collectors; public class MySQLUndoUpdateExecutor extends AbstractUndoExecutor { /** - * UPDATE a SET x = ?, y = ?, z = ? WHERE pk = ? + * UPDATE a SET x = ?, y = ?, z = ? WHERE pk1 in (?) pk2 in (?) */ - private static final String UPDATE_SQL_TEMPLATE = "UPDATE %s SET %s WHERE %s = ?"; + private static final String UPDATE_SQL_TEMPLATE = "UPDATE %s SET %s WHERE %s "; /** * Undo Update. @@ -53,15 +54,19 @@ public class MySQLUndoUpdateExecutor extends AbstractUndoExecutor { throw new ShouldNeverHappenException("Invalid UNDO LOG"); // TODO } Row row = beforeImageRows.get(0); - Field pkField = row.primaryKeys().get(0); + List<Field> nonPkFields = row.nonPrimaryKeys(); // update sql undo log before image all field come from table meta. need add escape. // see BaseTransactionalExecutor#buildTableRecords - String updateColumns = nonPkFields.stream() - .map(field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.MYSQL) + " = ?") - .collect(Collectors.joining(", ")); - return String.format(UPDATE_SQL_TEMPLATE, sqlUndoLog.getTableName(), updateColumns, - ColumnUtils.addEscape(pkField.getName(), JdbcConstants.MYSQL)); + String updateColumns = nonPkFields.stream().map( + field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.MYSQL) + " = ?").collect( + Collectors.joining(", ")); + + List<String> pkNameList = getOrderedPkList(beforeImage, row, JdbcConstants.MYSQL).stream().map(e -> e.getName()) + .collect(Collectors.toList()); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.MYSQL); + + return String.format(UPDATE_SQL_TEMPLATE, sqlUndoLog.getTableName(), updateColumns, whereSql); } /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordChecker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordChecker.java index ff6595cf0514041c65a96424a9cd4b45b3fb7e3c..7589f468e186c37e09e630b8af21343141506f1b 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordChecker.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordChecker.java @@ -1105,7 +1105,7 @@ public class MySQLKeywordChecker implements KeywordChecker { if (keywordSet.contains(fieldOrTableName)) { return true; } - if (null != fieldOrTableName) { + if (fieldOrTableName != null) { fieldOrTableName = fieldOrTableName.toUpperCase(); } return keywordSet.contains(fieldOrTableName); @@ -1117,9 +1117,4 @@ public class MySQLKeywordChecker implements KeywordChecker { return check(fieldOrTableName); } - @Override - public String checkAndReplace(String fieldOrTableName) { - return check(fieldOrTableName) ? "`" + fieldOrTableName + "`" : fieldOrTableName; - } - } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutor.java index 5987fd84fe6f0cbe79ea1e02aec73147d61d8577..570d1941844f6bb5590170ec4a581fc12c160a53 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutor.java @@ -59,9 +59,7 @@ public class OracleUndoDeleteExecutor extends AbstractUndoExecutor { } Row row = beforeImageRows.get(0); List<Field> fields = new ArrayList<>(row.nonPrimaryKeys()); - Field pkField = row.primaryKeys().get(0); - // PK is at last one. - fields.add(pkField); + fields.addAll(getOrderedPkList(beforeImage,row,JdbcConstants.ORACLE)); // delete sql undo log before image all field come from table meta, need add escape. // see BaseTransactionalExecutor#buildTableRecords diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutor.java index 785935bd28e6ee8f2db7a7b2992a7063c10272f3..6840c0ac7b06a924607ef968d46a20b4af40b718 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutor.java @@ -15,9 +15,15 @@ */ package io.seata.rm.datasource.undo.oracle; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.util.CollectionUtils; -import io.seata.rm.datasource.ColumnUtils; +import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; import io.seata.rm.datasource.sql.struct.TableRecords; @@ -25,11 +31,6 @@ import io.seata.rm.datasource.undo.AbstractUndoExecutor; import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.util.JdbcConstants; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - /** * The type oralce undo insert executor. * @@ -40,7 +41,7 @@ public class OracleUndoInsertExecutor extends AbstractUndoExecutor { /** * DELETE FROM a WHERE pk = ? */ - private static final String DELETE_SQL_TEMPLATE = "DELETE FROM %s WHERE %s = ?"; + private static final String DELETE_SQL_TEMPLATE = "DELETE FROM %s WHERE %s "; @Override protected String buildUndoSQL() { @@ -49,18 +50,24 @@ public class OracleUndoInsertExecutor extends AbstractUndoExecutor { if (CollectionUtils.isEmpty(afterImageRows)) { throw new ShouldNeverHappenException("Invalid UNDO LOG"); } - Row row = afterImageRows.get(0); - Field pkField = row.primaryKeys().get(0); - // insert sql undo log after image all field come from table meta, need add escape. - // see BaseTransactionalExecutor#buildTableRecords - return String.format(DELETE_SQL_TEMPLATE, sqlUndoLog.getTableName(), - ColumnUtils.addEscape(pkField.getName(), JdbcConstants.ORACLE)); + return generateDeleteSql(afterImageRows,afterImage); } @Override - protected void undoPrepare(PreparedStatement undoPST, ArrayList<Field> undoValues, Field pkValue) - throws SQLException { - undoPST.setObject(1, pkValue.getValue(), pkValue.getType()); + protected void undoPrepare(PreparedStatement undoPST, ArrayList<Field> undoValues, List<Field> pkValueList) + throws SQLException { + int undoIndex = 0; + for (Field pkField:pkValueList) { + undoIndex++; + undoPST.setObject(undoIndex, pkField.getValue(), pkField.getType()); + } + } + + private String generateDeleteSql(List<Row> rows, TableRecords afterImage) { + List<String> pkNameList = getOrderedPkList(afterImage, rows.get(0), JdbcConstants.ORACLE).stream().map( + e -> e.getName()).collect(Collectors.toList()); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.ORACLE); + return String.format(DELETE_SQL_TEMPLATE, sqlUndoLog.getTableName(), whereSql); } /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutor.java index d50448086de2dd87304ff9328d8cb7d0f38dbae6..220875ce77f05c48145786574d59ef4bad491d0f 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutor.java @@ -15,9 +15,13 @@ */ package io.seata.rm.datasource.undo.oracle; +import java.util.List; +import java.util.stream.Collectors; + import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.util.CollectionUtils; import io.seata.rm.datasource.ColumnUtils; +import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; import io.seata.rm.datasource.sql.struct.TableRecords; @@ -25,9 +29,6 @@ import io.seata.rm.datasource.undo.AbstractUndoExecutor; import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.util.JdbcConstants; -import java.util.List; -import java.util.stream.Collectors; - /** * The type oracle undo update executor. * @@ -36,9 +37,9 @@ import java.util.stream.Collectors; public class OracleUndoUpdateExecutor extends AbstractUndoExecutor { /** - * UPDATE a SET x = ?, y = ?, z = ? WHERE pk = ? + * UPDATE a SET x = ?, y = ?, z = ? WHERE pk1 = ? and pk2 = ? */ - private static final String UPDATE_SQL_TEMPLATE = "UPDATE %s SET %s WHERE %s = ?"; + private static final String UPDATE_SQL_TEMPLATE = "UPDATE %s SET %s WHERE %s "; @Override protected String buildUndoSQL() { @@ -47,17 +48,20 @@ public class OracleUndoUpdateExecutor extends AbstractUndoExecutor { if (CollectionUtils.isEmpty(beforeImageRows)) { throw new ShouldNeverHappenException("Invalid UNDO LOG"); // TODO } - Row row = beforeImageRows.get(0); - Field pkField = row.primaryKeys().get(0); + List<Field> nonPkFields = row.nonPrimaryKeys(); - // update sql undo log before image all field name come from table meta, need add escape. + // update sql undo log before image all field come from table meta. need add escape. // see BaseTransactionalExecutor#buildTableRecords - String updateColumns = nonPkFields.stream() - .map(field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.ORACLE) + " = ?") - .collect(Collectors.joining(", ")); - return String.format(UPDATE_SQL_TEMPLATE, sqlUndoLog.getTableName(), updateColumns, - ColumnUtils.addEscape(pkField.getName(), JdbcConstants.ORACLE)); + String updateColumns = nonPkFields.stream().map( + field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.ORACLE) + " = ?").collect( + Collectors.joining(", ")); + + List<String> pkNameList = getOrderedPkList(beforeImage, row, JdbcConstants.ORACLE).stream().map( + e -> e.getName()).collect(Collectors.toList()); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.ORACLE); + + return String.format(UPDATE_SQL_TEMPLATE, sqlUndoLog.getTableName(), updateColumns, whereSql); } /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordChecker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordChecker.java index a22af44c206a0c8ce2134c9769bee75948596c03..6b82e72d6b4d0a3664ff17235147cd21f5f517b2 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordChecker.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordChecker.java @@ -492,7 +492,7 @@ public class OracleKeywordChecker implements KeywordChecker { if (keywordSet.contains(fieldOrTableName)) { return true; } - if (null != fieldOrTableName) { + if (fieldOrTableName != null) { fieldOrTableName = fieldOrTableName.toUpperCase(); } return keywordSet.contains(fieldOrTableName); @@ -511,12 +511,6 @@ public class OracleKeywordChecker implements KeywordChecker { return true; } - @Override - public String checkAndReplace(String fieldOrTableName) { - return check(fieldOrTableName) ? fieldOrTableName : fieldOrTableName; - // return check(fieldOrTableName)?"`" + fieldOrTableName + "`":fieldOrTableName; - } - private static boolean isUppercase(String fieldOrTableName) { if (fieldOrTableName == null) { return false; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoDeleteExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoDeleteExecutor.java index d00f117d1e58aa5e8d224cb66ad9bbbab803131f..0ed7a34f7feb3b9f60f08ba621ea49bab7ba7968 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoDeleteExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoDeleteExecutor.java @@ -59,9 +59,7 @@ public class PostgresqlUndoDeleteExecutor extends AbstractUndoExecutor { } Row row = beforeImageRows.get(0); List<Field> fields = new ArrayList<>(row.nonPrimaryKeys()); - Field pkField = row.primaryKeys().get(0); - // PK is at last one. - fields.add(pkField); + fields.addAll(getOrderedPkList(beforeImage,row,JdbcConstants.POSTGRESQL)); // delete sql undo log before image all field come from table meta, need add escape. // see BaseTransactionalExecutor#buildTableRecords diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoInsertExecutor.java index 935f39656874bcedea4964fcd53ff63a6a684c6f..47fe4fa535e622e1f7afce3f6bae06bef89f96b2 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoInsertExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoInsertExecutor.java @@ -15,9 +15,15 @@ */ package io.seata.rm.datasource.undo.postgresql; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.util.CollectionUtils; -import io.seata.rm.datasource.ColumnUtils; +import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; import io.seata.rm.datasource.sql.struct.TableRecords; @@ -25,11 +31,6 @@ import io.seata.rm.datasource.undo.AbstractUndoExecutor; import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.util.JdbcConstants; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - /** * The type postgresql undo insert executor. * @@ -40,7 +41,7 @@ public class PostgresqlUndoInsertExecutor extends AbstractUndoExecutor { /** * DELETE FROM a WHERE pk = ? */ - private static final String DELETE_SQL_TEMPLATE = "DELETE FROM %s WHERE %s = ?"; + private static final String DELETE_SQL_TEMPLATE = "DELETE FROM %s WHERE %s "; @Override protected String buildUndoSQL() { @@ -49,18 +50,23 @@ public class PostgresqlUndoInsertExecutor extends AbstractUndoExecutor { if (CollectionUtils.isEmpty(afterImageRows)) { throw new ShouldNeverHappenException("Invalid UNDO LOG"); } - Row row = afterImageRows.get(0); - Field pkField = row.primaryKeys().get(0); - // insert sql undo log after image all field come from table meta, need add escape. - // see BaseTransactionalExecutor#buildTableRecords - return String.format(DELETE_SQL_TEMPLATE, sqlUndoLog.getTableName(), - ColumnUtils.addEscape(pkField.getName(), JdbcConstants.POSTGRESQL)); + return generateDeleteSql(afterImageRows,afterImage); } @Override - protected void undoPrepare(PreparedStatement undoPST, ArrayList<Field> undoValues, - Field pkValue) throws SQLException { - undoPST.setObject(1, pkValue.getValue(), pkValue.getType()); + protected void undoPrepare(PreparedStatement undoPST, ArrayList<Field> undoValues, List<Field> pkValueList) throws SQLException { + int undoIndex = 0; + for (Field pkField:pkValueList) { + undoIndex++; + undoPST.setObject(undoIndex, pkField.getValue(), pkField.getType()); + } + } + + private String generateDeleteSql(List<Row> rows, TableRecords afterImage) { + List<String> pkNameList = getOrderedPkList(afterImage, rows.get(0), JdbcConstants.POSTGRESQL).stream().map( + e -> e.getName()).collect(Collectors.toList()); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.POSTGRESQL); + return String.format(DELETE_SQL_TEMPLATE, sqlUndoLog.getTableName(), whereSql); } /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoUpdateExecutor.java index 6f4213f321c579960918995c4b2eb9f653b8b6c7..5c6488a84752c042251568899a227864307a5a5a 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/PostgresqlUndoUpdateExecutor.java @@ -15,9 +15,13 @@ */ package io.seata.rm.datasource.undo.postgresql; +import java.util.List; +import java.util.stream.Collectors; + import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.util.CollectionUtils; import io.seata.rm.datasource.ColumnUtils; +import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; import io.seata.rm.datasource.sql.struct.TableRecords; @@ -25,18 +29,15 @@ import io.seata.rm.datasource.undo.AbstractUndoExecutor; import io.seata.rm.datasource.undo.SQLUndoLog; import io.seata.sqlparser.util.JdbcConstants; -import java.util.List; -import java.util.stream.Collectors; - /** * @author japsercloud */ public class PostgresqlUndoUpdateExecutor extends AbstractUndoExecutor { /** - * UPDATE a SET x = ?, y = ?, z = ? WHERE pk = ? + * UPDATE a SET x = ?, y = ?, z = ? WHERE pk1 = ? and pk2 = ? */ - private static final String UPDATE_SQL_TEMPLATE = "UPDATE %s SET %s WHERE %s = ?"; + private static final String UPDATE_SQL_TEMPLATE = "UPDATE %s SET %s WHERE %s "; @Override protected String buildUndoSQL() { @@ -46,15 +47,19 @@ public class PostgresqlUndoUpdateExecutor extends AbstractUndoExecutor { throw new ShouldNeverHappenException("Invalid UNDO LOG"); // TODO } Row row = beforeImageRows.get(0); - Field pkField = row.primaryKeys().get(0); + List<Field> nonPkFields = row.nonPrimaryKeys(); // update sql undo log before image all field come from table meta. need add escape. // see BaseTransactionalExecutor#buildTableRecords - String updateColumns = nonPkFields.stream() - .map(field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.POSTGRESQL) + " = ?") - .collect(Collectors.joining(", ")); - return String.format(UPDATE_SQL_TEMPLATE, sqlUndoLog.getTableName(), updateColumns, - ColumnUtils.addEscape(pkField.getName(), JdbcConstants.POSTGRESQL)); + String updateColumns = nonPkFields.stream().map( + field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.POSTGRESQL) + " = ?").collect( + Collectors.joining(", ")); + + List<String> pkNameList = getOrderedPkList(beforeImage, row, JdbcConstants.POSTGRESQL).stream().map( + e -> e.getName()).collect(Collectors.toList()); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.POSTGRESQL); + + return String.format(UPDATE_SQL_TEMPLATE, sqlUndoLog.getTableName(), updateColumns, whereSql); } /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordChecker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordChecker.java index 455a43131a1fd6e42be8f17cbf167d6f29b1167c..427244818b5762c7bbaa7e6915384fc212775793 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordChecker.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordChecker.java @@ -361,7 +361,7 @@ public class PostgresqlKeywordChecker implements KeywordChecker { if (keywordSet.contains(fieldOrTableName)) { return true; } - if (null != fieldOrTableName) { + if (fieldOrTableName != null) { fieldOrTableName = fieldOrTableName.toUpperCase(); } return keywordSet.contains(fieldOrTableName); @@ -380,18 +380,6 @@ public class PostgresqlKeywordChecker implements KeywordChecker { return true; } - @Override - public String checkAndReplace(String fieldOrTableName) { - return check(fieldOrTableName) ? replace(fieldOrTableName) : fieldOrTableName; - } - - private String replace(String fieldOrTableName) { - StringBuilder builder = new StringBuilder(); - builder.append("\"").append(fieldOrTableName).append("\""); - String name = builder.toString(); - return name; - } - private static boolean containsUppercase(String colName) { if (colName == null) { return false; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/AbstractDataSourceProxyXA.java b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/AbstractDataSourceProxyXA.java index 01c4b31e92a4512237a0be2bc45cd10e65465ced..b1656d1baf68c7a9ef845906deaafb4659dd3a21 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/AbstractDataSourceProxyXA.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/AbstractDataSourceProxyXA.java @@ -31,8 +31,8 @@ public abstract class AbstractDataSourceProxyXA extends BaseDataSourceResource<C protected static final String DEFAULT_RESOURCE_GROUP_ID = "DEFAULT_XA"; /** - * Get a ConnetionProxyXA instance for finishing XA branch(XA commit/XA rollback) - * @return ConnetionProxyXA instance + * Get a ConnectionProxyXA instance for finishing XA branch(XA commit/XA rollback) + * @return ConnectionProxyXA instance * @throws SQLException exception */ public ConnectionProxyXA getConnectionForXAFinish(XAXid xaXid) throws SQLException { diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ResourceManagerXA.java b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ResourceManagerXA.java index 0509dfde963dff0524d60f2ed05e692390865d13..b37523fd1cd869bc2268e6238d941dfa72813f9d 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ResourceManagerXA.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ResourceManagerXA.java @@ -85,7 +85,12 @@ public class ResourceManagerXA extends AbstractDataSourceCacheResourceManager { } } } else { - throw new TransactionException("Unknown Resource for XA resource " + resourceId + " " + resource); + LOGGER.error("Unknown Resource for XA resource " + resourceId + " " + resource); + if (committed) { + return BranchStatus.PhaseTwo_CommitFailed_Unretryable; + } else { + return BranchStatus.PhaseTwo_RollbackFailed_Unretryable; + } } } } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/XABranchXid.java b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/XABranchXid.java index 890ebaca884a5b808b3603f6de2298d7b65f3e3d..6a724c9bed84e3a6f156533e95d47ea6aea37477 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/XABranchXid.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/XABranchXid.java @@ -49,10 +49,12 @@ public class XABranchXid implements XAXid { decode(); } + @Override public String getGlobalXid() { return xid; } + @Override public long getBranchId() { return branchId; } diff --git a/rm-datasource/src/main/resources/META-INF/services/io.seata.rm.datasource.exec.InsertExecutor b/rm-datasource/src/main/resources/META-INF/services/io.seata.rm.datasource.exec.InsertExecutor new file mode 100644 index 0000000000000000000000000000000000000000..2169a3978d0ff55193c43c2e735855cc90cb8c86 --- /dev/null +++ b/rm-datasource/src/main/resources/META-INF/services/io.seata.rm.datasource.exec.InsertExecutor @@ -0,0 +1,19 @@ +# +# Copyright 1999-2019 Seata.io Group. +# +# Licensed under the Apache 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 +# +# http://www.apache.org/licenses/LICENSE-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. +# + +io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor +io.seata.rm.datasource.exec.oracle.OracleInsertExecutor +io.seata.rm.datasource.exec.postgresql.PostgresqlInsertExecutor \ No newline at end of file diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/ColumnUtilsTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/ColumnUtilsTest.java index 2b3f66b6f94db964378247d7d69df2ebdb0a5248..8494e24c9c718163b697e4c2445082370e6b41a6 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/ColumnUtilsTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/ColumnUtilsTest.java @@ -36,11 +36,21 @@ public class ColumnUtilsTest { Assertions.assertEquals("id", cols.get(0)); Assertions.assertEquals("name", cols.get(1)); + List<String> cols4 = new ArrayList<>(); + cols4.add("`scheme`.`id`"); + cols4 = ColumnUtils.delEscape(cols4, ColumnUtils.Escape.MYSQL); + Assertions.assertEquals("scheme.id", cols4.get(0)); + List<String> cols2 = new ArrayList<>(); cols2.add("\"id\""); cols2 = ColumnUtils.delEscape(cols2, ColumnUtils.Escape.STANDARD); Assertions.assertEquals("id", cols2.get(0)); + List<String> cols3 = new ArrayList<>(); + cols3.add("\"scheme\".\"id\""); + cols3 = ColumnUtils.delEscape(cols3, ColumnUtils.Escape.STANDARD); + Assertions.assertEquals("scheme.id", cols3.get(0)); + Assertions.assertNull(ColumnUtils.delEscape((String) null, ColumnUtils.Escape.MYSQL)); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/DataCompareUtilsTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/DataCompareUtilsTest.java index e3e90647441f48426d92a77e24a5866187d6d9bd..52ced27106cf4823552c89c461fc2688c1948151 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/DataCompareUtilsTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/DataCompareUtilsTest.java @@ -25,7 +25,9 @@ import org.mockito.Mockito; import java.sql.JDBCType; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; /** * @author Geng Zhang @@ -60,7 +62,7 @@ public class DataCompareUtilsTest { @Test public void isRecordsEquals() { TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("pk"); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{"pk"})); Mockito.when(tableMeta.getTableName()).thenReturn("table_name"); TableRecords beforeImage = new TableRecords(); @@ -127,7 +129,7 @@ public class DataCompareUtilsTest { @Test public void isRowsEquals() { TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("pk"); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{"pk"})); Mockito.when(tableMeta.getTableName()).thenReturn("table_name"); List<Row> rows = new ArrayList<>(); @@ -156,4 +158,66 @@ public class DataCompareUtilsTest { rows2.add(row3); Assertions.assertFalse(DataCompareUtils.isRowsEquals(tableMeta, rows, rows2).getResult()); } + + @Test + public void testRowListToMapWithSinglePk(){ + List<String> primaryKeyList = new ArrayList<>(); + primaryKeyList.add("id"); + + List<Row> rows = new ArrayList<>(); + Field field = new Field("id", 1, "1"); + Row row = new Row(); + row.add(field); + rows.add(row); + + Field field2 = new Field("id", 1, "2"); + Row row2 = new Row(); + row2.add(field2); + rows.add(row2); + + Field field3 = new Field("id", 1, "3"); + Row row3 = new Row(); + row3.add(field3); + rows.add(row3); + + Map<String, Map<String, Field>> result =DataCompareUtils.rowListToMap(rows,primaryKeyList); + Assertions.assertTrue(result.size()==3); + Assertions.assertEquals(result.keySet().iterator().next(),"1"); + + } + + + @Test + public void testRowListToMapWithMultipPk(){ + List<String> primaryKeyList = new ArrayList<>(); + primaryKeyList.add("id1"); + primaryKeyList.add("id2"); + + List<Row> rows = new ArrayList<>(); + Field field1 = new Field("id1", 1, "1"); + Field field11 = new Field("id2", 1, "2"); + Row row = new Row(); + row.add(field1); + row.add(field11); + rows.add(row); + + Field field2 = new Field("id1", 1, "3"); + Field field22 = new Field("id2", 1, "4"); + Row row2 = new Row(); + row2.add(field2); + row2.add(field22); + rows.add(row2); + + Field field3 = new Field("id1", 1, "5"); + Field field33 = new Field("id2", 1, "6"); + Row row3 = new Row(); + row3.add(field3); + row3.add(field33); + rows.add(row3); + + Map<String, Map<String, Field>> result =DataCompareUtils.rowListToMap(rows,primaryKeyList); + Assertions.assertTrue(result.size()==3); + Assertions.assertEquals(result.keySet().iterator().next(),"1_2"); + + } } \ No newline at end of file diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/DataSourceProxyTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/DataSourceProxyTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a889f1f5cbbb1bc40fdcb184964341d35d8610a9 --- /dev/null +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/DataSourceProxyTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.rm.datasource; + +import java.lang.reflect.Field; +import java.sql.SQLException; + +import com.alibaba.druid.pool.DruidDataSource; +import io.seata.rm.datasource.mock.MockDriver; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * @author ph3636 + */ +public class DataSourceProxyTest { + + @Test + public void getResourceIdTest() throws SQLException, NoSuchFieldException, IllegalAccessException { + MockDriver mockDriver = new MockDriver(); + String username = "username"; + + DruidDataSource dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setDriver(mockDriver); + dataSource.setUsername(username); + dataSource.setPassword("password"); + + DataSourceProxy proxy = new DataSourceProxy(dataSource); + + Field dbTypeField = proxy.getClass().getDeclaredField("dbType"); + dbTypeField.setAccessible(true); + dbTypeField.set(proxy, io.seata.sqlparser.util.JdbcConstants.ORACLE); + + String userName = dataSource.getConnection().getMetaData().getUserName(); + Assertions.assertEquals(userName, username); + + Field userNameField = proxy.getClass().getDeclaredField("userName"); + userNameField.setAccessible(true); + userNameField.set(proxy, username); + + Assertions.assertEquals(proxy.getResourceId(), "jdbc:mock:xxx/username"); + + dbTypeField.set(proxy, io.seata.sqlparser.util.JdbcConstants.MYSQL); + Assertions.assertEquals(proxy.getResourceId(), "jdbc:mock:xxx"); + } +} diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/PreparedStatementProxyTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/PreparedStatementProxyTest.java index 1b4c32936f829a813b5854b4c52673bdbfb6f72e..28352303ff05d3d06da5b39800fc4c0759f88b90 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/PreparedStatementProxyTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/PreparedStatementProxyTest.java @@ -117,202 +117,202 @@ public class PreparedStatementProxyTest { @Test public void testGetSetParamsByIndex() { preparedStatementProxy.setParamByIndex(1, "xxx"); - Assertions.assertEquals("xxx", preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals("xxx", preparedStatementProxy.getParamsByIndex(1).get(0)); } @Test public void testSetParam() throws SQLException, MalformedURLException { preparedStatementProxy.clearParameters(); preparedStatementProxy.setNull(1, JDBCType.DECIMAL.getVendorTypeNumber()); - Assertions.assertEquals(Null.get(), preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(Null.get(), preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setNull(1, JDBCType.DECIMAL.getVendorTypeNumber(), "NULL"); - Assertions.assertEquals(Null.get(), preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(Null.get(), preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setBoolean(1, true); - Assertions.assertEquals(true, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(true, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setByte(1, (byte)0); - Assertions.assertEquals((byte)0, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals((byte)0, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setShort(1, (short)0); - Assertions.assertEquals((short)0, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals((short)0, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setInt(1, 0); - Assertions.assertEquals(0, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(0, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setLong(1, 0L); - Assertions.assertEquals(0L, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(0L, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setFloat(1, 0f); - Assertions.assertEquals(0f, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(0f, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setDouble(1, 1.1); - Assertions.assertEquals(1.1, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(1.1, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setBigDecimal(1, new BigDecimal(0)); - Assertions.assertEquals(new BigDecimal(0), preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(new BigDecimal(0), preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setString(1, "x"); - Assertions.assertEquals("x", preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals("x", preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setNString(1, "x"); - Assertions.assertEquals("x", preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals("x", preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setBytes(1, "x".getBytes()); - Assertions.assertTrue(Objects.deepEquals("x".getBytes(), preparedStatementProxy.getParamsByIndex(0).get(0))); + Assertions.assertTrue(Objects.deepEquals("x".getBytes(), preparedStatementProxy.getParamsByIndex(1).get(0))); preparedStatementProxy.clearParameters(); Date date = new Date(System.currentTimeMillis()); preparedStatementProxy.setDate(1, date); - Assertions.assertEquals(date, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(date, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setDate(1, date, Calendar.getInstance()); - Assertions.assertEquals(date, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(date, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); Time time = new Time(System.currentTimeMillis()); preparedStatementProxy.setTime(1, time); - Assertions.assertEquals(time, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(time, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setTime(1, time, Calendar.getInstance()); - Assertions.assertEquals(time, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(time, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); Timestamp timestamp = new Timestamp(System.currentTimeMillis()); preparedStatementProxy.setTimestamp(1, timestamp); - Assertions.assertEquals(timestamp, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(timestamp, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setTimestamp(1, timestamp, Calendar.getInstance()); - Assertions.assertEquals(timestamp, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(timestamp, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream("x".getBytes(), 0, 1); preparedStatementProxy.setAsciiStream(1, byteArrayInputStream); - Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setAsciiStream(1, byteArrayInputStream, 1L); - Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setAsciiStream(1, byteArrayInputStream); - Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setUnicodeStream(1, byteArrayInputStream, 1); - Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setBinaryStream(1, byteArrayInputStream); - Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setBinaryStream(1, byteArrayInputStream, 1L); - Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setBinaryStream(1, byteArrayInputStream, 1); - Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setObject(1, 1, JDBCType.INTEGER.getVendorTypeNumber()); - Assertions.assertEquals(1, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(1, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setObject(1, 1, JDBCType.INTEGER.getVendorTypeNumber(), 1); - Assertions.assertEquals(1, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(1, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setObject(1, 1); - Assertions.assertEquals(1, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(1, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); Assertions.assertDoesNotThrow(() -> preparedStatementProxy.addBatch()); CharArrayReader charArrayReader = new CharArrayReader("x".toCharArray()); preparedStatementProxy.setCharacterStream(1, charArrayReader, 1); - Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setCharacterStream(1, charArrayReader, 1L); - Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setCharacterStream(1, charArrayReader); - Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setNCharacterStream(1, charArrayReader); - Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setNCharacterStream(1, charArrayReader, 1L); - Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); MockRef ref = new MockRef(); preparedStatementProxy.setRef(1, ref); - Assertions.assertEquals(ref, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(ref, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); MockBlob blob = new MockBlob(); preparedStatementProxy.setBlob(1, blob); - Assertions.assertEquals(blob, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(blob, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setBlob(1, byteArrayInputStream); - Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setBlob(1, byteArrayInputStream, 1L); - Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(byteArrayInputStream, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); MockClob clob = new MockClob(); preparedStatementProxy.setClob(1, clob); - Assertions.assertEquals(clob, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(clob, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setClob(1, charArrayReader, 1L); - Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setClob(1, charArrayReader); - Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); MockNClob nclob = new MockNClob(); preparedStatementProxy.setNClob(1, nclob); - Assertions.assertEquals(nclob, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(nclob, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setNClob(1, charArrayReader, 1L); - Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); preparedStatementProxy.setNClob(1, charArrayReader); - Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(charArrayReader, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); MockArray array = new MockArray(); preparedStatementProxy.setArray(1, array); - Assertions.assertEquals(array, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(array, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); Assertions.assertNotNull(preparedStatementProxy.getMetaData()); @@ -320,12 +320,12 @@ public class PreparedStatementProxyTest { URL url = new URL("http", "", 8080, ""); preparedStatementProxy.setURL(1, url); - Assertions.assertEquals(url, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(url, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); MockSQLXML sqlxml = new MockSQLXML(); preparedStatementProxy.setSQLXML(1, sqlxml); - Assertions.assertEquals(sqlxml, preparedStatementProxy.getParamsByIndex(0).get(0)); + Assertions.assertEquals(sqlxml, preparedStatementProxy.getParamsByIndex(1).get(0)); preparedStatementProxy.clearParameters(); Assertions.assertNotNull(preparedStatementProxy.getParameters()); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/StatementProxyTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/StatementProxyTest.java index 0274783ba4691e0a228012bd488c246f254c6d40..9e6684bfcf331d5e63a152d3a46b564db446c61b 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/StatementProxyTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/StatementProxyTest.java @@ -20,7 +20,11 @@ import java.sql.SQLFeatureNotSupportedException; import java.sql.Statement; import java.sql.Types; import java.util.List; + +import com.alibaba.druid.mock.MockResultSet; +import com.alibaba.druid.mock.MockStatement; import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.util.jdbc.ResultSetMetaDataBase; import com.google.common.collect.Lists; import io.seata.rm.datasource.mock.MockConnection; import io.seata.rm.datasource.mock.MockDriver; @@ -67,6 +71,10 @@ public class StatementProxyTest { Statement statement = mockDriver.createMockStatement((MockConnection)connectionProxy.getTargetConnection()); + MockResultSet mockResultSet = new MockResultSet(statement); + ((ResultSetMetaDataBase)mockResultSet.getMetaData()).getColumns().add(new ResultSetMetaDataBase.ColumnMetaData()); + ((MockStatement) statement).setGeneratedKeys(mockResultSet); + statementProxy = new StatementProxy(connectionProxy, statement); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java index dc95e91c7222ac1c5c8e4abcb27069e62a3ae030..a5ccdb7bea52cc05fca49bf969ca00cf5726a654 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutorTest.java @@ -15,12 +15,16 @@ */ package io.seata.rm.datasource.exec; +import io.seata.common.exception.NotSupportYetException; import io.seata.rm.datasource.ConnectionContext; import io.seata.rm.datasource.ConnectionProxy; import io.seata.rm.datasource.PreparedStatementProxy; -import io.seata.sqlparser.SQLInsertRecognizer; +import io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor; +import io.seata.rm.datasource.exec.oracle.OracleInsertExecutor; import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; +import io.seata.sqlparser.SQLInsertRecognizer; +import io.seata.sqlparser.util.JdbcConstants; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -29,6 +33,7 @@ import org.mockito.Mockito; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.sql.Connection; +import java.util.Arrays; /** * AbstractDMLBaseExecutor test @@ -68,7 +73,7 @@ public class AbstractDMLBaseExecutorTest { StatementCallback statementCallback = Mockito.mock(StatementCallback.class); SQLInsertRecognizer sqlInsertRecognizer = Mockito.mock(SQLInsertRecognizer.class); TableMeta tableMeta = Mockito.mock(TableMeta.class); - executor = Mockito.spy(new InsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + executor = Mockito.spy(new MySQLInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); Mockito.doReturn(tableMeta) .when(executor).getTableMeta(); TableRecords tableRecords = new TableRecords(); @@ -98,4 +103,21 @@ public class AbstractDMLBaseExecutorTest { Mockito.verify(connectionProxy, Mockito.never()).rollback(); branchRollbackFlagField.set(null, oldBranchRollbackFlag); } + + @Test + public void testOnlySupportMysqlWhenUseMultiPk(){ + Mockito.when(connectionProxy.getContext()) + .thenReturn(new ConnectionContext()); + PreparedStatementProxy statementProxy = Mockito.mock(PreparedStatementProxy.class); + Mockito.when(statementProxy.getConnectionProxy()) + .thenReturn(connectionProxy); + StatementCallback statementCallback = Mockito.mock(StatementCallback.class); + SQLInsertRecognizer sqlInsertRecognizer = Mockito.mock(SQLInsertRecognizer.class); + TableMeta tableMeta = Mockito.mock(TableMeta.class); + executor = Mockito.spy(new OracleInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + Mockito.when(executor.getDbType()).thenReturn(JdbcConstants.ORACLE); + Mockito.doReturn(tableMeta).when(executor).getTableMeta(); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList("id","userCode")); + Assertions.assertThrows(NotSupportYetException.class,()-> executor.executeAutoCommitFalse(null)); + } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java index f1b7bef896448ea53cca145844d20bb6412716a6..18d23bf50bf6dc018e74a7d87f89d00fb6f24c19 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java @@ -26,8 +26,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; +import java.util.*; +import java.util.concurrent.Callable; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -78,30 +78,87 @@ public class BaseTransactionalExecutorTest { public void testBuildLockKey() { //build expect data String tableName = "test_name"; - String fieldOne = "field_one"; - String fieldTwo = "field_two"; + String fieldOne = "1"; + String fieldTwo = "2"; String split1 = ":"; String split2 = ","; + String pkColumnName="id"; + //test_name:1,2 String buildLockKeyExpect = tableName + split1 + fieldOne + split2 + fieldTwo; // mock field Field field1 = mock(Field.class); when(field1.getValue()).thenReturn(fieldOne); Field field2 = mock(Field.class); when(field2.getValue()).thenReturn(fieldTwo); - List<Field> fieldList = new ArrayList<>(); - fieldList.add(field1); - fieldList.add(field2); + List<Map<String,Field>> pkRows =new ArrayList<>(); + pkRows.add(Collections.singletonMap(pkColumnName, field1)); + pkRows.add(Collections.singletonMap(pkColumnName, field2)); + + // mock tableMeta + TableMeta tableMeta = mock(TableMeta.class); + when(tableMeta.getTableName()).thenReturn(tableName); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{pkColumnName})); + // mock tableRecords + TableRecords tableRecords = mock(TableRecords.class); + when(tableRecords.getTableMeta()).thenReturn(tableMeta); + when(tableRecords.size()).thenReturn(pkRows.size()); + when(tableRecords.pkRows()).thenReturn(pkRows); + // mock executor + BaseTransactionalExecutor executor = mock(BaseTransactionalExecutor.class); + when(executor.buildLockKey(tableRecords)).thenCallRealMethod(); + when(executor.getTableMeta()).thenReturn(tableMeta); + assertThat(executor.buildLockKey(tableRecords)).isEqualTo(buildLockKeyExpect); + } + + @Test + public void testBuildLockKeyWithMultiPk() { + //build expect data + String tableName = "test_name"; + String pkOneValue1 = "1"; + String pkOneValue2 = "2"; + String pkTwoValue1 = "one"; + String pkTwoValue2 = "two"; + String split1 = ":"; + String split2 = ","; + String split3 = "_"; + String pkOneColumnName="id"; + String pkTwoColumnName="userId"; + //test_name:1_one,2_two + String buildLockKeyExpect = tableName + split1 + pkOneValue1+ split3 + pkTwoValue1 + split2 + pkOneValue2 + split3 + pkTwoValue2; + // mock field + Field pkOneField1 = mock(Field.class); + when(pkOneField1.getValue()).thenReturn(pkOneValue1); + Field pkOneField2 = mock(Field.class); + when(pkOneField2.getValue()).thenReturn(pkOneValue2); + Field pkTwoField1 = mock(Field.class); + when(pkTwoField1.getValue()).thenReturn(pkTwoValue1); + Field pkTwoField2 = mock(Field.class); + when(pkTwoField2.getValue()).thenReturn(pkTwoValue2); + List<Map<String,Field>> pkRows =new ArrayList<>(); + Map<String, Field> row1 = new HashMap<String, Field>() {{ + put(pkOneColumnName, pkOneField1); + put(pkTwoColumnName, pkTwoField1); + }}; + pkRows.add(row1); + Map<String, Field> row2 = new HashMap<String, Field>() {{ + put(pkOneColumnName, pkOneField2); + put(pkTwoColumnName, pkTwoField2); + }}; + pkRows.add(row2); + // mock tableMeta TableMeta tableMeta = mock(TableMeta.class); when(tableMeta.getTableName()).thenReturn(tableName); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{pkOneColumnName,pkTwoColumnName})); // mock tableRecords TableRecords tableRecords = mock(TableRecords.class); when(tableRecords.getTableMeta()).thenReturn(tableMeta); - when(tableRecords.pkRows()).thenReturn(fieldList); - when(tableRecords.size()).thenReturn(fieldList.size()); + when(tableRecords.size()).thenReturn(pkRows.size()); + when(tableRecords.pkRows()).thenReturn(pkRows); // mock executor BaseTransactionalExecutor executor = mock(BaseTransactionalExecutor.class); when(executor.buildLockKey(tableRecords)).thenCallRealMethod(); + when(executor.getTableMeta()).thenReturn(tableMeta); assertThat(executor.buildLockKey(tableRecords)).isEqualTo(buildLockKeyExpect); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BatchInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BatchInsertExecutorTest.java index e7e776f18678907e192998eec14fe4c05d5d5de4..4f3cddbdffb293ed38fa376a3f27b5e463851545 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BatchInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BatchInsertExecutorTest.java @@ -19,22 +19,20 @@ import com.alibaba.druid.util.JdbcConstants; import io.seata.common.exception.NotSupportYetException; import io.seata.rm.datasource.ConnectionProxy; import io.seata.rm.datasource.PreparedStatementProxy; +import io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor; +import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.struct.Null; -import io.seata.rm.datasource.sql.struct.TableMeta; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -58,7 +56,10 @@ public class BatchInsertExecutorTest { private TableMeta tableMeta; - private InsertExecutor insertExecutor; + private MySQLInsertExecutor insertExecutor; + + private final int pkIndex = 1; + private HashMap pkIndexMap; @BeforeEach public void init() { @@ -71,9 +72,13 @@ public class BatchInsertExecutorTest { StatementCallback statementCallback = mock(StatementCallback.class); sqlInsertRecognizer = mock(SQLInsertRecognizer.class); tableMeta = mock(TableMeta.class); - insertExecutor = Mockito.spy(new InsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + insertExecutor = Mockito.spy(new MySQLInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); - doReturn(1).when(insertExecutor).getPkIndex(); + pkIndexMap = new HashMap() {{ + put(ID_COLUMN, pkIndex); + }}; + + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); } @Test @@ -81,10 +86,12 @@ public class BatchInsertExecutorTest { mockInsertColumns(); mockParameters(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); - List<Object> pkValues = new ArrayList<>(PK_VALUES); - List<Integer> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); - Assertions.assertIterableEquals(pkValuesByColumn, pkValues); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); + List<Object> pkValues = new ArrayList<>(); + pkValues.addAll(PK_VALUES); + Map<String,List<Object>> pkValuesMap = insertExecutor.getPkValuesByColumn(); + Assertions.assertIterableEquals(pkValuesMap.keySet(), tableMeta.getPrimaryKeyOnlyName()); + Assertions.assertIterableEquals(pkValuesMap.get(ID_COLUMN), pkValues); } @Test @@ -92,10 +99,10 @@ public class BatchInsertExecutorTest { mockInsertColumns(); mockParametersWithAllRefOfJDBC(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(ID_COLUMN)); List<Object> pkValues = new ArrayList<>(PK_VALUES); - List<Integer> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); - Assertions.assertIterableEquals(pkValuesByColumn, pkValues); + Map<String,List<Object>> pkValuesMap = insertExecutor.getPkValuesByColumn(); + Assertions.assertIterableEquals(pkValues,pkValuesMap.get(ID_COLUMN) ); } @Test @@ -103,10 +110,12 @@ public class BatchInsertExecutorTest { mockInsertColumns(); mockParametersWithPkRefOfJDBC(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); - List<Object> pkValues = new ArrayList<>(PK_VALUES); - List<Integer> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); - Assertions.assertIterableEquals(pkValuesByColumn, pkValues); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); + List<Object> pkValues = new ArrayList<>(); + pkValues.addAll(PK_VALUES); + Map<String,List<Object>> pkValuesMap = insertExecutor.getPkValuesByColumn(); + Assertions.assertIterableEquals(pkValuesMap.keySet(), tableMeta.getPrimaryKeyOnlyName()); + Assertions.assertIterableEquals(pkValuesMap.get(ID_COLUMN), pkValues); } @Test @@ -115,11 +124,12 @@ public class BatchInsertExecutorTest { int pkId = PK_VALUES.get(0); mockParametersWithPkUnRefOfJDBC(pkId); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); List<Object> pkValues = new ArrayList<>(); pkValues.add(pkId); - List<Integer> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); - Assertions.assertIterableEquals(pkValuesByColumn, pkValues); + Map<String,List<Object>> pkValuesMap = insertExecutor.getPkValuesByColumn(); + Assertions.assertIterableEquals(pkValuesMap.keySet(), tableMeta.getPrimaryKeyOnlyName()); + Assertions.assertIterableEquals(pkValuesMap.get(ID_COLUMN), pkValues); } //----------------mysql batch values (),(),()------------------------ @@ -129,10 +139,12 @@ public class BatchInsertExecutorTest { mockInsertColumns(); mockParametersAllRefOfMysql(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); - List<Object> pkValues = new ArrayList<>(PK_VALUES); - List<Integer> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); - Assertions.assertIterableEquals(pkValuesByColumn, pkValues); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); + List<Object> pkValues = new ArrayList<>(); + pkValues.addAll(PK_VALUES); + Map<String,List<Object>> pkValuesMap = insertExecutor.getPkValuesByColumn(); + Assertions.assertIterableEquals(pkValuesMap.keySet(), tableMeta.getPrimaryKeyOnlyName()); + Assertions.assertIterableEquals(pkValuesMap.get(ID_COLUMN), pkValues); } @Test @@ -140,11 +152,12 @@ public class BatchInsertExecutorTest { mockInsertColumns(); mockParametersWithPkRefOfMysql(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); List<Object> pkValues = new ArrayList<>(); pkValues.addAll(PK_VALUES); - List<Integer> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); - Assertions.assertIterableEquals(pkValuesByColumn, pkValues); + Map<String,List<Object>> pkValuesMap = insertExecutor.getPkValuesByColumn(); + Assertions.assertIterableEquals(pkValuesMap.keySet(), tableMeta.getPrimaryKeyOnlyName()); + Assertions.assertIterableEquals(pkValuesMap.get(ID_COLUMN), pkValues); } @Test @@ -152,10 +165,12 @@ public class BatchInsertExecutorTest { mockInsertColumns(); mockParametersWithPkUnRefOfMysql(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); - List<Object> pkValues = new ArrayList<>(PK_VALUES); - List<Integer> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); - Assertions.assertIterableEquals(pkValuesByColumn, pkValues); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); + List<Object> pkValues = new ArrayList<>(); + pkValues.addAll(PK_VALUES); + Map<String,List<Object>> pkValuesMap = insertExecutor.getPkValuesByColumn(); + Assertions.assertIterableEquals(pkValuesMap.keySet(), tableMeta.getPrimaryKeyOnlyName()); + Assertions.assertIterableEquals(pkValuesMap.get(ID_COLUMN), pkValues); } @Test @@ -164,24 +179,13 @@ public class BatchInsertExecutorTest { mockInsertColumns(); mockParameters_with_number_and_insertRows_with_placeholde_null(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); insertExecutor.getPkValuesByColumn(); }); } - @Test - public void testGetPkValues_not_NotSupportYetException() throws SQLException { - mockInsertColumns(); - mockParameters_with_null_and_insertRows_with_placeholder_null(); - doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); - doReturn(new ArrayList<>()).when(insertExecutor).getPkValuesByAuto(); - insertExecutor.getPkValuesByColumn(); - verify(insertExecutor).getPkValuesByAuto(); - } - private void mockParameters_with_null_and_insertRows_with_placeholder_null() { - ArrayList<Object>[] paramters = new ArrayList[5]; + Map<Integer,ArrayList<Object>> paramters = new HashMap<>(5); ArrayList arrayList0 = new ArrayList<>(); arrayList0.add("userId1"); ArrayList arrayList1 = new ArrayList<>(); @@ -192,21 +196,21 @@ public class BatchInsertExecutorTest { arrayList3.add("userId2"); ArrayList arrayList4 = new ArrayList<>(); arrayList4.add("userName2"); - paramters[0] = arrayList0; - paramters[1] = arrayList1; - paramters[2] = arrayList2; - paramters[3] = arrayList3; - paramters[4] = arrayList4; + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); + paramters.put(5, arrayList4); when(statementProxy.getParameters()).thenReturn(paramters); List<List<Object>> insertRows = new ArrayList<>(); insertRows.add(Arrays.asList("?", "?", "?", "userStatus1")); insertRows.add(Arrays.asList("?", Null.get(), "?", "userStatus2")); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(insertRows); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(insertRows); } private void mockParameters_with_number_and_insertRows_with_placeholde_null() { - ArrayList<Object>[] paramters = new ArrayList[5]; + Map<Integer,ArrayList<Object>> paramters = new HashMap<>(5); ArrayList arrayList0 = new ArrayList<>(); arrayList0.add("userId1"); ArrayList arrayList1 = new ArrayList<>(); @@ -217,17 +221,17 @@ public class BatchInsertExecutorTest { arrayList3.add("userId2"); ArrayList arrayList4 = new ArrayList<>(); arrayList4.add("userName2"); - paramters[0] = arrayList0; - paramters[1] = arrayList1; - paramters[2] = arrayList2; - paramters[3] = arrayList3; - paramters[4] = arrayList4; + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); + paramters.put(5, arrayList4); when(statementProxy.getParameters()).thenReturn(paramters); List<List<Object>> insertRows = new ArrayList<>(); insertRows.add(Arrays.asList("?", "?", "?", "userStatus1")); insertRows.add(Arrays.asList("?", Null.get(), "?", "userStatus2")); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(insertRows); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(insertRows); } private List<String> mockInsertColumns() { @@ -242,7 +246,7 @@ public class BatchInsertExecutorTest { private void mockParameters() { int PK_INDEX = 1; - ArrayList<Object>[] paramters = new ArrayList[4]; + Map<Integer,ArrayList<Object>> paramters = new HashMap<>(); ArrayList arrayList0 = new ArrayList<>(); arrayList0.add("userId1"); arrayList0.add("userId2"); @@ -268,22 +272,22 @@ public class BatchInsertExecutorTest { arrayList3.add("userStatus4"); arrayList3.add("userStatus5"); - paramters[0] = arrayList0; - paramters[1] = arrayList1; - paramters[2] = arrayList2; - paramters[3] = arrayList3; + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); List<List<Object>> insertRows = new ArrayList<>(); insertRows.add(Arrays.asList("?", "?", "?", "?")); when(statementProxy.getParameters()).thenReturn(paramters); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(insertRows); - when(statementProxy.getParamsByIndex(PK_INDEX)).thenReturn(paramters[PK_INDEX]); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(insertRows); + when(statementProxy.getParamsByIndex(PK_INDEX)).thenReturn(paramters.get(PK_INDEX + 1)); } private void mockParametersAllRefOfMysql() { - ArrayList<Object>[] paramters = new ArrayList[20]; + Map<Integer,ArrayList<Object>> paramters = new HashMap(20); ArrayList arrayList1 = new ArrayList<>(); arrayList1.add("userId1"); ArrayList arrayList2 = new ArrayList<>(); @@ -330,26 +334,26 @@ public class BatchInsertExecutorTest { arrayList20.add("userStatus5"); - paramters[0] = arrayList1; - paramters[1] = arrayList2; - paramters[2] = arrayList3; - paramters[3] = arrayList4; - paramters[4] = arrayList5; - paramters[5] = arrayList6; - paramters[6] = arrayList7; - paramters[7] = arrayList8; - paramters[8] = arrayList9; - paramters[9] = arrayList10; - paramters[10] = arrayList11; - paramters[11] = arrayList12; - paramters[12] = arrayList13; - paramters[13] = arrayList14; - paramters[14] = arrayList15; - paramters[15] = arrayList16; - paramters[16] = arrayList17; - paramters[17] = arrayList18; - paramters[18] = arrayList19; - paramters[19] = arrayList20; + paramters.put(1,arrayList1); + paramters.put(2,arrayList2); + paramters.put(3,arrayList3); + paramters.put(4,arrayList4); + paramters.put(5,arrayList5); + paramters.put(6,arrayList6); + paramters.put(7,arrayList7); + paramters.put(8,arrayList8); + paramters.put(9,arrayList9); + paramters.put(10,arrayList10); + paramters.put(11,arrayList11); + paramters.put(12,arrayList12); + paramters.put(13,arrayList13); + paramters.put(14,arrayList14); + paramters.put(15,arrayList15); + paramters.put(16,arrayList16); + paramters.put(17,arrayList17); + paramters.put(18,arrayList18); + paramters.put(19,arrayList19); + paramters.put(20,arrayList20); List<List<Object>> insertRows = new ArrayList<>(); insertRows.add(Arrays.asList("?", "?", "?", "?")); insertRows.add(Arrays.asList("?", "?", "?", "?")); @@ -357,13 +361,13 @@ public class BatchInsertExecutorTest { insertRows.add(Arrays.asList("?", "?", "?", "?")); insertRows.add(Arrays.asList("?", "?", "?", "?")); when(statementProxy.getParameters()).thenReturn(paramters); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(insertRows); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(insertRows); when(statementProxy.getParameters()).thenReturn(paramters); } private void mockParametersWithPkRefOfMysql() { - ArrayList<Object>[] paramters = new ArrayList[10]; + Map<Integer,ArrayList<Object>> paramters = new HashMap<>(10); ArrayList arrayList1 = new ArrayList<>(); arrayList1.add("userId1"); ArrayList arrayList2 = new ArrayList<>(); @@ -384,16 +388,16 @@ public class BatchInsertExecutorTest { arrayList9.add("userId5"); ArrayList arrayList10 = new ArrayList<>(); arrayList10.add(100000005); - paramters[0] = arrayList1; - paramters[1] = arrayList2; - paramters[2] = arrayList3; - paramters[3] = arrayList4; - paramters[4] = arrayList5; - paramters[5] = arrayList6; - paramters[6] = arrayList7; - paramters[7] = arrayList8; - paramters[8] = arrayList9; - paramters[9] = arrayList10; + paramters.put(1,arrayList1); + paramters.put(2,arrayList2); + paramters.put(3,arrayList3); + paramters.put(4,arrayList4); + paramters.put(5,arrayList5); + paramters.put(6,arrayList6); + paramters.put(7,arrayList7); + paramters.put(8,arrayList8); + paramters.put(9,arrayList9); + paramters.put(10,arrayList10); List<List<Object>> insertRows = new ArrayList<>(); insertRows.add(Arrays.asList("?", "?", "1", "11")); insertRows.add(Arrays.asList("?", "?", "2", "22")); @@ -401,13 +405,13 @@ public class BatchInsertExecutorTest { insertRows.add(Arrays.asList("?", "?", "4", "44")); insertRows.add(Arrays.asList("?", "?", "5", "55")); when(statementProxy.getParameters()).thenReturn(paramters); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(insertRows); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(insertRows); when(statementProxy.getParameters()).thenReturn(paramters); } private void mockParametersWithPkUnRefOfMysql() { - ArrayList<Object>[] paramters = new ArrayList[10]; + Map<Integer,ArrayList<Object>> paramters = new HashMap<>(10); ArrayList arrayList1 = new ArrayList<>(); arrayList1.add("userId1"); ArrayList arrayList2 = new ArrayList<>(); @@ -428,16 +432,16 @@ public class BatchInsertExecutorTest { arrayList9.add("userId5"); ArrayList arrayList10 = new ArrayList<>(); arrayList10.add(100000005); - paramters[0] = arrayList1; - paramters[1] = arrayList2; - paramters[2] = arrayList3; - paramters[3] = arrayList4; - paramters[4] = arrayList5; - paramters[5] = arrayList6; - paramters[6] = arrayList7; - paramters[7] = arrayList8; - paramters[8] = arrayList9; - paramters[9] = arrayList10; + paramters.put(1,arrayList1); + paramters.put(2,arrayList2); + paramters.put(3,arrayList3); + paramters.put(4,arrayList4); + paramters.put(5,arrayList5); + paramters.put(6,arrayList6); + paramters.put(7,arrayList7); + paramters.put(8,arrayList8); + paramters.put(9,arrayList9); + paramters.put(10,arrayList10); List<List<Object>> insertRows = new ArrayList<>(); insertRows.add(Arrays.asList("?", 100000001, "?", "1")); insertRows.add(Arrays.asList("?", 100000002, "?", "2")); @@ -445,13 +449,13 @@ public class BatchInsertExecutorTest { insertRows.add(Arrays.asList("?", 100000004, "?", "4")); insertRows.add(Arrays.asList("?", 100000005, "?", "5")); when(statementProxy.getParameters()).thenReturn(paramters); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(insertRows); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(insertRows); } private void mockParametersWithAllRefOfJDBC() { int PK_INDEX = 1; - ArrayList<Object>[] paramters = new ArrayList[4]; + Map<Integer,ArrayList<Object>> paramters = new HashMap<>(4); ArrayList arrayList0 = new ArrayList<>(); arrayList0.add("userId1"); arrayList0.add("userId2"); @@ -476,21 +480,22 @@ public class BatchInsertExecutorTest { arrayList3.add("userStatus3"); arrayList3.add("userStatus4"); arrayList3.add("userStatus5"); - paramters[0] = arrayList0; - paramters[1] = arrayList1; - paramters[2] = arrayList2; - paramters[3] = arrayList3; + paramters.put(1,arrayList0); + paramters.put(2,arrayList1); + paramters.put(3,arrayList2); + paramters.put(4,arrayList3); List<List<Object>> insertRows = new ArrayList<>(); insertRows.add(Arrays.asList("?", "?", "?", "?")); when(statementProxy.getParameters()).thenReturn(paramters); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(insertRows); - when(statementProxy.getParamsByIndex(PK_INDEX)).thenReturn(paramters[PK_INDEX]); + when(statementProxy.getParamsByIndex(PK_INDEX)).thenReturn(paramters.get(PK_INDEX + 1)); + doReturn(insertRows).when(sqlInsertRecognizer).getInsertRows(pkIndexMap.values()); } + private void mockParametersWithPkRefOfJDBC() { int PK_INDEX = 1; - ArrayList<Object>[] paramters = new ArrayList[2]; + Map<Integer,ArrayList<Object>> paramters = new HashMap<>(2); ArrayList arrayList0 = new ArrayList<>(); arrayList0.add("userId1"); arrayList0.add("userId2"); @@ -503,30 +508,30 @@ public class BatchInsertExecutorTest { arrayList1.add(PK_VALUES.get(2)); arrayList1.add(PK_VALUES.get(3)); arrayList1.add(PK_VALUES.get(4)); - paramters[0] = arrayList0; - paramters[1] = arrayList1; + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); List<List<Object>> insertRows = new ArrayList<>(); insertRows.add(Arrays.asList("?", "?", "userName1", "userStatus1")); when(statementProxy.getParameters()).thenReturn(paramters); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(insertRows); - when(statementProxy.getParamsByIndex(PK_INDEX)).thenReturn(paramters[PK_INDEX]); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(insertRows); + when(statementProxy.getParamsByIndex(PK_INDEX)).thenReturn(paramters.get(PK_INDEX + 1)); } private void mockParametersWithPkUnRefOfJDBC(int pkId) { - ArrayList<Object>[] paramters = new ArrayList[2]; + Map<Integer,ArrayList<Object>> paramters = new HashMap<>(2); ArrayList arrayList0 = new ArrayList<>(); arrayList0.add("userId1"); ArrayList arrayList1 = new ArrayList<>(); arrayList1.add("userName1"); - paramters[0] = arrayList0; - paramters[1] = arrayList1; + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); List<List<Object>> insertRows = new ArrayList<>(); insertRows.add(Arrays.asList("?", pkId, "?", "userStatus")); when(statementProxy.getParameters()).thenReturn(paramters); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(insertRows); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(insertRows); } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/InsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java similarity index 52% rename from rm-datasource/src/test/java/io/seata/rm/datasource/exec/InsertExecutorTest.java rename to rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java index 8edeeea103ebf42960149aeb0b80b07031cc122a..32b9a56273923d22cf7daf3eeb05f632c2bd0829 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/InsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java @@ -15,25 +15,18 @@ */ package io.seata.rm.datasource.exec; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import io.seata.common.exception.ShouldNeverHappenException; import io.seata.rm.datasource.ConnectionProxy; import io.seata.rm.datasource.PreparedStatementProxy; import io.seata.rm.datasource.StatementProxy; -import io.seata.sqlparser.SQLInsertRecognizer; +import io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor; import io.seata.rm.datasource.sql.struct.ColumnMeta; -import io.seata.sqlparser.struct.Null; import io.seata.rm.datasource.sql.struct.Row; import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; +import io.seata.sqlparser.SQLInsertRecognizer; +import io.seata.sqlparser.struct.Null; +import io.seata.sqlparser.struct.SqlDefaultExpr; import io.seata.sqlparser.struct.SqlMethodExpr; import io.seata.sqlparser.struct.SqlSequenceExpr; import io.seata.sqlparser.util.JdbcConstants; @@ -42,6 +35,15 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -49,9 +51,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** - * @author guoyao + * @author guoyao, jsbxyyx */ -public class InsertExecutorTest { +public class MySQLInsertExecutorTest { private static final String ID_COLUMN = "id"; private static final String USER_ID_COLUMN = "user_id"; @@ -65,7 +67,10 @@ public class InsertExecutorTest { private TableMeta tableMeta; - private InsertExecutor insertExecutor; + private MySQLInsertExecutor insertExecutor; + + private final int pkIndex = 0; + private HashMap<String,Integer> pkIndexMap; @BeforeEach public void init() { @@ -78,7 +83,13 @@ public class InsertExecutorTest { StatementCallback statementCallback = mock(StatementCallback.class); sqlInsertRecognizer = mock(SQLInsertRecognizer.class); tableMeta = mock(TableMeta.class); - insertExecutor = Mockito.spy(new InsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + insertExecutor = Mockito.spy(new MySQLInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + + pkIndexMap = new HashMap<String,Integer>(){ + { + put(ID_COLUMN, pkIndex); + } + }; } @Test @@ -101,11 +112,13 @@ public class InsertExecutorTest { @Test public void testAfterImage_ByColumn() throws SQLException { doReturn(true).when(insertExecutor).containsPK(); - List<Object> pkValues = new ArrayList<>(); - pkValues.add(PK_VALUE); - doReturn(pkValues).when(insertExecutor).getPkValuesByColumn(); + Map<String,List<Object>> pkValuesMap =new HashMap<>(); + pkValuesMap.put("id",Arrays.asList(new Object[]{PK_VALUE})); + doReturn(pkValuesMap).when(insertExecutor).getPkValuesByColumn(); TableRecords tableRecords = new TableRecords(); - doReturn(tableRecords).when(insertExecutor).buildTableRecords(pkValues); + doReturn(tableRecords).when(insertExecutor).buildTableRecords(pkValuesMap); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); TableRecords resultTableRecords = insertExecutor.afterImage(new TableRecords()); Assertions.assertEquals(resultTableRecords, tableRecords); } @@ -114,11 +127,13 @@ public class InsertExecutorTest { public void testAfterImage_ByAuto() throws SQLException { doReturn(false).when(insertExecutor).containsPK(); doReturn(true).when(insertExecutor).containsColumns(); - List<Object> pkValues = new ArrayList<>(); - pkValues.add(PK_VALUE); - doReturn(pkValues).when(insertExecutor).getPkValuesByAuto(); + Map<String,List<Object>> pkValuesMap =new HashMap<>(); + pkValuesMap.put("id",Arrays.asList(new Object[]{PK_VALUE})); + doReturn(pkValuesMap).when(insertExecutor).getPkValuesByAuto(); TableRecords tableRecords = new TableRecords(); - doReturn(tableRecords).when(insertExecutor).buildTableRecords(pkValues); + doReturn(tableRecords).when(insertExecutor).buildTableRecords(pkValuesMap); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); TableRecords resultTableRecords = insertExecutor.afterImage(new TableRecords()); Assertions.assertEquals(resultTableRecords, tableRecords); } @@ -128,10 +143,12 @@ public class InsertExecutorTest { Assertions.assertThrows(SQLException.class, () -> { doReturn(false).when(insertExecutor).containsPK(); doReturn(true).when(insertExecutor).containsColumns(); - List<Object> pkValues = new ArrayList<>(); - pkValues.add(PK_VALUE); - doReturn(pkValues).when(insertExecutor).getPkValuesByAuto(); - doReturn(null).when(insertExecutor).buildTableRecords(pkValues); + Map<String,List<Object>> pkValuesMap =new HashMap<>(); + pkValuesMap.put("id",Arrays.asList(new Object[]{PK_VALUE})); + doReturn(pkValuesMap).when(insertExecutor).getPkValuesByAuto(); + doReturn(null).when(insertExecutor).buildTableRecords(pkValuesMap); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); insertExecutor.afterImage(new TableRecords()); }); } @@ -154,12 +171,12 @@ public class InsertExecutorTest { mockInsertRows(); mockParametersOfOnePk(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); List<Object> pkValues = new ArrayList<>(); pkValues.add(PK_VALUE); - doReturn(0).when(insertExecutor).getPkIndex(); - List pkValuesByColumn = insertExecutor.getPkValuesByColumn(); - Assertions.assertEquals(pkValuesByColumn, pkValues); + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); + Map<String,List<Object>> pkValuesList = insertExecutor.getPkValuesByColumn(); + Assertions.assertIterableEquals(pkValuesList.get(ID_COLUMN), pkValues); } @Test @@ -168,7 +185,7 @@ public class InsertExecutorTest { mockInsertColumns(); mockParameters(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); insertExecutor.getPkValuesByColumn(); }); } @@ -179,18 +196,23 @@ public class InsertExecutorTest { mockInsertRows(); mockParametersPkWithNull(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); + ColumnMeta cm = new ColumnMeta(); + cm.setColumnName(ID_COLUMN); + cm.setIsAutoincrement("YES"); + when(tableMeta.getPrimaryKeyMap()).thenReturn(new HashMap<String, ColumnMeta>(){{put(ID_COLUMN,cm);}}); List<Object> pkValuesAuto = new ArrayList<>(); pkValuesAuto.add(PK_VALUE); //mock getPkValuesByAuto - doReturn(pkValuesAuto).when(insertExecutor).getPkValuesByAuto(); - doReturn(0).when(insertExecutor).getPkIndex(); - List pkValuesByColumn = insertExecutor.getPkValuesByColumn(); + doReturn(new HashMap<String,List<Object>>(){{put(ID_COLUMN,pkValuesAuto);}}).when(insertExecutor).getPkValuesByAuto(); + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); + Map<String,List<Object>> pkValuesList = insertExecutor.getPkValuesByColumn(); //pk value = Null so getPkValuesByAuto verify(insertExecutor).getPkValuesByAuto(); - Assertions.assertEquals(pkValuesByColumn, pkValuesAuto); + Assertions.assertIterableEquals(pkValuesList.get(ID_COLUMN), pkValuesAuto); } + @Test public void testGetPkValuesByAuto_ShouldNeverHappenException() { Assertions.assertThrows(ShouldNeverHappenException.class, () -> { @@ -216,9 +238,7 @@ public class InsertExecutorTest { columnMetaMap.put(ID_COLUMN, columnMeta); when(columnMeta.isAutoincrement()).thenReturn(true); when(tableMeta.getPrimaryKeyMap()).thenReturn(columnMetaMap); - PreparedStatement preparedStatement = mock(PreparedStatement.class); - when(statementProxy.getTargetStatement()).thenReturn(preparedStatement); - when(preparedStatement.getGeneratedKeys()).thenThrow(new SQLException()); + when(statementProxy.getGeneratedKeys()).thenThrow(new SQLException()); insertExecutor.getPkValuesByAuto(); }); } @@ -233,11 +253,12 @@ public class InsertExecutorTest { when(tableMeta.getPrimaryKeyMap()).thenReturn(columnMetaMap); PreparedStatement preparedStatement = mock(PreparedStatement.class); when(statementProxy.getTargetStatement()).thenReturn(preparedStatement); - SQLException e = new SQLException("test warn log", InsertExecutor.ERR_SQL_STATE, 1); - when(preparedStatement.getGeneratedKeys()).thenThrow(e); + SQLException e = new SQLException("test warn log", MySQLInsertExecutor.ERR_SQL_STATE, 1); + when(statementProxy.getGeneratedKeys()).thenThrow(e); ResultSet genKeys = mock(ResultSet.class); when(statementProxy.getTargetStatement().executeQuery("SELECT LAST_INSERT_ID()")).thenReturn(genKeys); - Assertions.assertTrue(insertExecutor.getPkValuesByAuto().isEmpty()); + Map<String,List<Object>> pkValueMap=insertExecutor.getPkValuesByAuto(); + Assertions.assertTrue(pkValueMap.get(ID_COLUMN).isEmpty()); } @Test @@ -251,11 +272,11 @@ public class InsertExecutorTest { PreparedStatement preparedStatement = mock(PreparedStatement.class); when(statementProxy.getTargetStatement()).thenReturn(preparedStatement); ResultSet resultSet = mock(ResultSet.class); - when(preparedStatement.getGeneratedKeys()).thenReturn(resultSet); + when(statementProxy.getGeneratedKeys()).thenReturn(resultSet); when(resultSet.next()).thenReturn(false); when(resultSet.getObject(1)).thenReturn(PK_VALUE); - List pkValuesByAuto = insertExecutor.getPkValuesByAuto(); - Assertions.assertEquals(pkValuesByAuto.size(),0); + Map<String,List<Object>> pkValues = insertExecutor.getPkValuesByAuto(); + Assertions.assertEquals(pkValues.get(ID_COLUMN).size(),0); } @Test @@ -269,13 +290,13 @@ public class InsertExecutorTest { PreparedStatement preparedStatement = mock(PreparedStatement.class); when(statementProxy.getTargetStatement()).thenReturn(preparedStatement); ResultSet resultSet = mock(ResultSet.class); - when(preparedStatement.getGeneratedKeys()).thenReturn(resultSet); + when(statementProxy.getGeneratedKeys()).thenReturn(resultSet); when(resultSet.next()).thenReturn(true).thenReturn(false); when(resultSet.getObject(1)).thenReturn(PK_VALUE); List<Object> pkValues = new ArrayList<>(); pkValues.add(PK_VALUE); - List pkValuesByAuto = insertExecutor.getPkValuesByAuto(); - Assertions.assertEquals(pkValuesByAuto, pkValues); + Map<String,List<Object>> pkValuesList = insertExecutor.getPkValuesByAuto(); + Assertions.assertIterableEquals(pkValuesList.get(ID_COLUMN), pkValues); } @Test @@ -288,108 +309,260 @@ public class InsertExecutorTest { when(tableMeta.getPrimaryKeyMap()).thenReturn(columnMetaMap); PreparedStatement preparedStatement = mock(PreparedStatement.class); when(statementProxy.getTargetStatement()).thenReturn(preparedStatement); - when(preparedStatement.getGeneratedKeys()).thenThrow(new SQLException("", InsertExecutor.ERR_SQL_STATE)); + when(statementProxy.getGeneratedKeys()).thenThrow(new SQLException("", MySQLInsertExecutor.ERR_SQL_STATE)); ResultSet resultSet = mock(ResultSet.class); when(preparedStatement.executeQuery(anyString())).thenReturn(resultSet); when(resultSet.next()).thenReturn(true).thenReturn(false); when(resultSet.getObject(1)).thenReturn(PK_VALUE); List<Object> pkValues = new ArrayList<>(); pkValues.add(PK_VALUE); - List pkValuesByAuto = insertExecutor.getPkValuesByAuto(); - Assertions.assertEquals(pkValuesByAuto, pkValues); + Map<String,List<Object>> pkValuesList = insertExecutor.getPkValuesByAuto(); + Assertions.assertIterableEquals(pkValuesList.get(ID_COLUMN), pkValues); } @Test public void test_getPkIndex() { mockInsertColumns(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); - Assertions.assertEquals(0, insertExecutor.getPkIndex()); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); + Assertions.assertEquals(0, insertExecutor.getPkIndex().get(ID_COLUMN)); + } + + + @Test + public void test_checkPkValuesForMultiPk() + { + Map<String,List<Object>> pkValues = new HashMap<>(); + List pkValues1 = new ArrayList(); + List pkValues2 = new ArrayList(); + pkValues.put("id",pkValues1); + pkValues.put("userCode",pkValues2); + + //all pk support value + pkValues1.add(1); + pkValues2.add(2); + Assertions.assertTrue(insertExecutor.checkPkValuesForMultiPk(pkValues)); + + //supporting one pk is null + pkValues1.clear(); + pkValues2.clear(); + pkValues1.add(Null.get()); + pkValues2.add(2); + Assertions.assertTrue(insertExecutor.checkPkValuesForMultiPk(pkValues)); + + //more one pk is null is not support + pkValues1.clear(); + pkValues2.clear(); + pkValues1.add(Null.get()); + pkValues2.add(Null.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForMultiPk(pkValues)); + + //method is not support at all + pkValues1.clear(); + pkValues2.clear(); + pkValues1.add(SqlMethodExpr.get()); + pkValues2.add(2); + Assertions.assertFalse(insertExecutor.checkPkValuesForMultiPk(pkValues)); + } @Test public void test_checkPkValues() { - // one parameters. - // pk is null support + + // ps = true List<Object> pkValues = new ArrayList<>(); pkValues.add(Null.get()); - Assertions.assertTrue(insertExecutor.checkPkValues(pkValues)); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); - // pk is sequence support. pkValues = new ArrayList<>(); - pkValues.add(new SqlSequenceExpr()); - Assertions.assertTrue(insertExecutor.checkPkValues(pkValues)); + pkValues.add(Null.get()); + pkValues.add(Null.get()); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); - // pk is specify value support. pkValues = new ArrayList<>(); pkValues.add(1); - Assertions.assertTrue(insertExecutor.checkPkValues(pkValues)); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); - // pk is sql function not support. - pkValues = new ArrayList<>(); - pkValues.add(new SqlMethodExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); - - // more parameters. - // pk is specify value support. pkValues = new ArrayList<>(); pkValues.add(1); pkValues.add(2); - Assertions.assertTrue(insertExecutor.checkPkValues(pkValues)); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlMethodExpr.get()); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlMethodExpr.get()); + pkValues.add(SqlMethodExpr.get()); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlSequenceExpr()); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlDefaultExpr.get()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + // ps = false + pkValues = new ArrayList<>(); + pkValues.add(Null.get()); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); - // pk is null support. pkValues = new ArrayList<>(); pkValues.add(Null.get()); pkValues.add(Null.get()); - Assertions.assertTrue(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(2); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); - // pk is sql function not support. pkValues = new ArrayList<>(); - pkValues.add(new SqlMethodExpr()); - pkValues.add(new SqlMethodExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + pkValues.add(SqlMethodExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlMethodExpr.get()); + pkValues.add(SqlMethodExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); - // pk is sql sequence not support. pkValues = new ArrayList<>(); pkValues.add(new SqlSequenceExpr()); pkValues.add(new SqlSequenceExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertTrue(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlDefaultExpr.get()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + // not support. + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(Null.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); - // pk is specify value and null not support. pkValues = new ArrayList<>(); pkValues.add(1); pkValues.add(Null.get()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(SqlMethodExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(SqlMethodExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); - // pk is specify value and sql function not support. pkValues = new ArrayList<>(); pkValues.add(1); - pkValues.add(new SqlMethodExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); - // pk is specify value and sequence not support. pkValues = new ArrayList<>(); pkValues.add(1); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(Null.get()); + pkValues.add(SqlMethodExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(Null.get()); + pkValues.add(SqlMethodExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + + pkValues = new ArrayList<>(); + pkValues.add(Null.get()); pkValues.add(new SqlSequenceExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); - // pk is null and sql function not support. pkValues = new ArrayList<>(); pkValues.add(Null.get()); - pkValues.add(new SqlMethodExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); - // pk is null and sequence not support. pkValues = new ArrayList<>(); pkValues.add(Null.get()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(Null.get()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlMethodExpr.get()); pkValues.add(new SqlSequenceExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); - // pk is sql function and sequence not support. pkValues = new ArrayList<>(); - pkValues.add(new SqlMethodExpr()); + pkValues.add(SqlMethodExpr.get()); pkValues.add(new SqlSequenceExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlMethodExpr.get()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlMethodExpr.get()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlSequenceExpr()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlMethodExpr.get()); + pkValues.add(new SqlSequenceExpr()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false)); } private List<String> mockInsertColumns() { @@ -403,7 +576,7 @@ public class InsertExecutorTest { } private void mockParameters() { - ArrayList<Object>[] paramters = new ArrayList[4]; + Map<Integer,ArrayList<Object>> paramters = new HashMap<>(4); ArrayList arrayList0 = new ArrayList<>(); arrayList0.add(PK_VALUE); ArrayList arrayList1 = new ArrayList<>(); @@ -412,16 +585,16 @@ public class InsertExecutorTest { arrayList2.add("userName1"); ArrayList arrayList3 = new ArrayList<>(); arrayList3.add("userStatus1"); - paramters[0] = arrayList0; - paramters[1] = arrayList1; - paramters[2] = arrayList2; - paramters[3] = arrayList3; + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; when(psp.getParameters()).thenReturn(paramters); } private void mockParametersPkWithNull() { - ArrayList<Object>[] paramters = new ArrayList[4]; + Map<Integer,ArrayList<Object>> parameters = new HashMap<>(4); ArrayList arrayList0 = new ArrayList<>(); arrayList0.add(Null.get()); ArrayList arrayList1 = new ArrayList<>(); @@ -430,19 +603,19 @@ public class InsertExecutorTest { arrayList2.add("userName1"); ArrayList arrayList3 = new ArrayList<>(); arrayList3.add("userStatus1"); - paramters[0] = arrayList0; - paramters[1] = arrayList1; - paramters[2] = arrayList2; - paramters[3] = arrayList3; + parameters.put(1, arrayList0); + parameters.put(2, arrayList1); + parameters.put(3, arrayList2); + parameters.put(4, arrayList3); PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; - when(psp.getParameters()).thenReturn(paramters); + when(psp.getParameters()).thenReturn(parameters); } private void mockParametersOfOnePk() { - ArrayList<Object>[] paramters = new ArrayList[1]; + Map<Integer,ArrayList<Object>> paramters = new HashMap<>(4); ArrayList arrayList1 = new ArrayList<>(); arrayList1.add(PK_VALUE); - paramters[0] = arrayList1; + paramters.put(1, arrayList1); PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; when(psp.getParameters()).thenReturn(paramters); } @@ -450,6 +623,6 @@ public class InsertExecutorTest { private void mockInsertRows() { List<List<Object>> rows = new ArrayList<>(); rows.add(Arrays.asList("?", "?", "?", "?")); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(rows); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java index b97906a3c79c679b8c58c5e89a7c345743fd0ed6..c97b46dc904db1e62007e5cb50c5debc17b65ccf 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/OracleInsertExecutorTest.java @@ -15,19 +15,11 @@ */ package io.seata.rm.datasource.exec; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import io.seata.common.exception.NotSupportYetException; import io.seata.rm.datasource.ConnectionProxy; import io.seata.rm.datasource.PreparedStatementProxy; import io.seata.rm.datasource.StatementProxy; +import io.seata.rm.datasource.exec.oracle.OracleInsertExecutor; import io.seata.rm.datasource.sql.struct.ColumnMeta; import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.sqlparser.SQLInsertRecognizer; @@ -39,6 +31,13 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -65,7 +64,10 @@ public class OracleInsertExecutorTest { private TableMeta tableMeta; - private InsertExecutor insertExecutor; + private OracleInsertExecutor insertExecutor; + + private final int pkIndex = 0; + private HashMap<String, Integer> pkIndexMap; @BeforeEach public void init() { @@ -78,7 +80,11 @@ public class OracleInsertExecutorTest { statementCallback = mock(StatementCallback.class); sqlInsertRecognizer = mock(SQLInsertRecognizer.class); tableMeta = mock(TableMeta.class); - insertExecutor = Mockito.spy(new InsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + insertExecutor = Mockito.spy(new OracleInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + + pkIndexMap = new HashMap<String, Integer>() {{ + put(ID_COLUMN, pkIndex); + }}; } @Test @@ -86,16 +92,16 @@ public class OracleInsertExecutorTest { mockInsertColumns(); SqlSequenceExpr expr = mockParametersPkWithSeq(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); List<Object> pkValuesSeq = new ArrayList<>(); pkValuesSeq.add(PK_VALUE); doReturn(pkValuesSeq).when(insertExecutor).getPkValuesBySequence(expr); - doReturn(0).when(insertExecutor).getPkIndex(); + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); - List pkValuesByColumn = insertExecutor.getPkValuesByColumn(); + Map<String,List<Object>> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); verify(insertExecutor).getPkValuesBySequence(expr); - Assertions.assertEquals(pkValuesByColumn, pkValuesSeq); + Assertions.assertEquals(pkValuesByColumn.get(ID_COLUMN), pkValuesSeq); } @Test @@ -103,15 +109,12 @@ public class OracleInsertExecutorTest { mockInsertColumns(); mockParametersPkWithAuto(); doReturn(tableMeta).when(insertExecutor).getTableMeta(); - when(tableMeta.getPkName()).thenReturn(ID_COLUMN); - List<Object> pkValuesAuto = new ArrayList<>(); - pkValuesAuto.add(PK_VALUE); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN}));; + doReturn(Arrays.asList(new Object[]{PK_VALUE})).when(insertExecutor).getGeneratedKeys(); + Map<String,List<Object>> pkValuesByAuto = insertExecutor.getPkValues(); - doReturn(pkValuesAuto).when(insertExecutor).getPkValuesByAuto(); - List pkValuesByAuto = insertExecutor.getPkValuesByAuto(); - - verify(insertExecutor).getPkValuesByAuto(); - Assertions.assertEquals(pkValuesByAuto, pkValuesAuto); + verify(insertExecutor).getGeneratedKeys(); + Assertions.assertEquals(pkValuesByAuto.get(ID_COLUMN), Arrays.asList(new Object[]{PK_VALUE})); } @Test @@ -123,7 +126,7 @@ public class OracleInsertExecutorTest { when(statementProxy.getConnectionProxy()).thenReturn(connectionProxy); when(connectionProxy.getDbType()).thenReturn(JdbcConstants.ORACLE); - insertExecutor = Mockito.spy(new InsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + insertExecutor = Mockito.spy(new OracleInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); doReturn(tableMeta).when(insertExecutor).getTableMeta(); @@ -132,17 +135,14 @@ public class OracleInsertExecutorTest { doReturn(map).when(tableMeta).getPrimaryKeyMap(); ResultSet rs = mock(ResultSet.class); - Statement statement = mock(Statement.class); - doReturn(statement).when(statementProxy).getTargetStatement(); - doReturn(rs).when(statement).getGeneratedKeys(); + doReturn(rs).when(statementProxy).getGeneratedKeys(); doReturn(false).when(rs).next(); Assertions.assertThrows(NotSupportYetException.class, () -> { - insertExecutor.getPkValuesByAuto(); + insertExecutor.getGeneratedKeys(); }); - int pkIndex = 0; - doReturn(pkIndex).when(insertExecutor).getPkIndex(); + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); Assertions.assertThrows(NotSupportYetException.class, () -> { insertExecutor.getPkValuesByColumn(); @@ -150,20 +150,6 @@ public class OracleInsertExecutorTest { } - @Test - public void testGetPkValuesByAuto_NotSupportYetException() { - Assertions.assertThrows(NotSupportYetException.class, () -> { - doReturn(tableMeta).when(insertExecutor).getTableMeta(); - PreparedStatement preparedStatement = mock(PreparedStatement.class); - when(statementProxy.getTargetStatement()).thenReturn(preparedStatement); - when(preparedStatement.getGeneratedKeys()).thenReturn(mock(ResultSet.class)); - Map<String, ColumnMeta> columnMetaMap = new HashMap<>(); - columnMetaMap.put(ID_COLUMN, new ColumnMeta()); - columnMetaMap.put(USER_ID_COLUMN, new ColumnMeta()); - when(tableMeta.getPrimaryKeyMap()).thenReturn(columnMetaMap); - insertExecutor.getPkValuesByAuto(); - }); - } private List<String> mockInsertColumns() { @@ -178,7 +164,7 @@ public class OracleInsertExecutorTest { private SqlSequenceExpr mockParametersPkWithSeq() { SqlSequenceExpr expr = new SqlSequenceExpr("seq", "nextval"); - ArrayList<Object>[] paramters = new ArrayList[4]; + Map<Integer,ArrayList<Object>> paramters = new HashMap(4); ArrayList arrayList0 = new ArrayList<>(); arrayList0.add(expr); ArrayList arrayList1 = new ArrayList<>(); @@ -187,22 +173,22 @@ public class OracleInsertExecutorTest { arrayList2.add("userName1"); ArrayList arrayList3 = new ArrayList<>(); arrayList3.add("userStatus1"); - paramters[0] = arrayList0; - paramters[1] = arrayList1; - paramters[2] = arrayList2; - paramters[3] = arrayList3; + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; when(psp.getParameters()).thenReturn(paramters); List<List<Object>> rows = new ArrayList<>(); rows.add(Arrays.asList("?", "?", "?")); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(rows); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); return expr; } private void mockParametersPkWithAuto() { - ArrayList<Object>[] paramters = new ArrayList[4]; + Map<Integer,ArrayList<Object>> paramters = new HashMap<>(4); ArrayList arrayList0 = new ArrayList<>(); arrayList0.add(Null.get()); ArrayList arrayList1 = new ArrayList<>(); @@ -211,22 +197,22 @@ public class OracleInsertExecutorTest { arrayList2.add("userName1"); ArrayList arrayList3 = new ArrayList<>(); arrayList3.add("userStatus1"); - paramters[0] = arrayList0; - paramters[1] = arrayList1; - paramters[2] = arrayList2; - paramters[3] = arrayList3; + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; when(psp.getParameters()).thenReturn(paramters); List<List<Object>> rows = new ArrayList<>(); rows.add(Arrays.asList("?", "?", "?", "?")); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(rows); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); } private void mockStatementInsertRows() { List<List<Object>> rows = new ArrayList<>(); rows.add(Arrays.asList(Null.get(), "xx", "xx", "xx")); - when(sqlInsertRecognizer.getInsertRows()).thenReturn(rows); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/PostgresqlInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/PostgresqlInsertExecutorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e1b38381a3e0bfe5ddb3c7038379d129353c7ec2 --- /dev/null +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/PostgresqlInsertExecutorTest.java @@ -0,0 +1,141 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.rm.datasource.exec; + +import io.seata.rm.datasource.ConnectionProxy; +import io.seata.rm.datasource.PreparedStatementProxy; +import io.seata.rm.datasource.StatementProxy; +import io.seata.rm.datasource.exec.postgresql.PostgresqlInsertExecutor; +import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.sqlparser.SQLInsertRecognizer; +import io.seata.sqlparser.struct.SqlDefaultExpr; +import io.seata.sqlparser.util.JdbcConstants; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.*; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * @author jsbxyyx + */ +public class PostgresqlInsertExecutorTest { + + private static final String ID_COLUMN = "id"; + private static final String USER_ID_COLUMN = "user_id"; + private static final String USER_NAME_COLUMN = "user_name"; + private static final String USER_STATUS_COLUMN = "user_status"; + private static final Integer PK_VALUE = 100; + + private StatementProxy statementProxy; + + private SQLInsertRecognizer sqlInsertRecognizer; + + private TableMeta tableMeta; + + private PostgresqlInsertExecutor insertExecutor; + + private final int pkIndex = 0; + private HashMap<String, Integer> pkIndexMap; + + @BeforeEach + public void init() { + ConnectionProxy connectionProxy = mock(ConnectionProxy.class); + when(connectionProxy.getDbType()).thenReturn(JdbcConstants.POSTGRESQL); + + statementProxy = mock(PreparedStatementProxy.class); + when(statementProxy.getConnectionProxy()).thenReturn(connectionProxy); + + StatementCallback statementCallback = mock(StatementCallback.class); + sqlInsertRecognizer = mock(SQLInsertRecognizer.class); + tableMeta = mock(TableMeta.class); + insertExecutor = Mockito.spy(new PostgresqlInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + + pkIndexMap = new HashMap<String, Integer>() { + { + put(ID_COLUMN, pkIndex); + } + }; + } + + @Test + public void testInsertDefault_ByDefault() throws Exception { + mockInsertColumns(); + mockInsertRows(); + mockParametersPkWithDefault(); + + Map<String, ColumnMeta> pkMap = new HashMap<>(); + ColumnMeta columnMeta = mock(ColumnMeta.class); + doReturn("nextval('test_id_seq'::regclass)").when(columnMeta).getColumnDef(); + pkMap.put(ID_COLUMN, columnMeta); + doReturn(pkMap).when(tableMeta).getPrimaryKeyMap(); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + List<Object> pkValuesAuto = new ArrayList<>(); + pkValuesAuto.add(PK_VALUE); + //mock getPkValuesByAuto + doReturn(pkValuesAuto).when(insertExecutor).getGeneratedKeys(); + Map<String,List<Object>> pkValuesMap = insertExecutor.getPkValuesByColumn(); + //pk value = DEFAULT so getPkValuesByDefault + doReturn(new ArrayList<>()).when(insertExecutor).getPkValuesByDefault(); + + verify(insertExecutor).getPkValuesByDefault(); + Assertions.assertEquals(pkValuesMap.get(ID_COLUMN), pkValuesAuto); + } + + private void mockParametersPkWithDefault() { + Map<Integer,ArrayList<Object>> parameters = new HashMap<>(4); + ArrayList arrayList0 = new ArrayList<>(); + arrayList0.add(SqlDefaultExpr.get()); + ArrayList arrayList1 = new ArrayList<>(); + arrayList1.add("userId1"); + ArrayList arrayList2 = new ArrayList<>(); + arrayList2.add("userName1"); + ArrayList arrayList3 = new ArrayList<>(); + arrayList3.add("userStatus1"); + parameters.put(1, arrayList0); + parameters.put(2, arrayList1); + parameters.put(3, arrayList2); + parameters.put(4, arrayList3); + PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; + when(psp.getParameters()).thenReturn(parameters); + } + + private void mockInsertRows() { + List<List<Object>> rows = new ArrayList<>(); + rows.add(Arrays.asList("?", "?", "?")); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); + } + + private List<String> mockInsertColumns() { + List<String> columns = new ArrayList<>(); + columns.add(ID_COLUMN); + columns.add(USER_ID_COLUMN); + columns.add(USER_NAME_COLUMN); + columns.add(USER_STATUS_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); + return columns; + } + +} diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockDatabaseMetaData.java b/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockDatabaseMetaData.java index 183fececa8fc6c76603af318d53b7be5dce81956..926b89f654d3e94420cb80c10827dcef8ec8fd3f 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockDatabaseMetaData.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockDatabaseMetaData.java @@ -101,7 +101,7 @@ public class MockDatabaseMetaData implements DatabaseMetaData { @Override public String getUserName() throws SQLException { - return null; + return this.connection.getConnectProperties().getProperty("user"); } @Override diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockDriver.java b/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockDriver.java index 5d1f4efaddf178c5713fd0227d2dabf58d310583..f8c1865c60119ec0a0094705fc03d7f880589edc 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockDriver.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/mock/MockDriver.java @@ -64,6 +64,10 @@ public class MockDriver extends com.alibaba.druid.mock.MockDriver { */ private MockExecuteHandler mockExecuteHandler; + public MockDriver() { + this(Lists.newArrayList(), new Object[][]{}, new Object[][]{}, new Object[][]{}, new Object[][]{}); + } + public MockDriver(Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue) { this(Lists.newArrayList(), new Object[][]{}, mockColumnsMetasReturnValue, mockIndexMetasReturnValue, new Object[][]{}); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleDeleteRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleDeleteRecognizerTest.java index 636887731587ba3278be9b9083ac3fe3ae9fd4ba..7d3d12cb72f72bb0c9066a8bf6f15053a008dfb6 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleDeleteRecognizerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleDeleteRecognizerTest.java @@ -22,11 +22,12 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleArgumentExpr; import io.seata.sqlparser.ParametersHolder; import io.seata.sqlparser.SQLType; import io.seata.sqlparser.druid.oracle.OracleDeleteRecognizer; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; /** * @author will @@ -70,7 +71,7 @@ public class OracleDeleteRecognizerTest { OracleDeleteRecognizer recognizer = new OracleDeleteRecognizer(sql, asts.get(0)); String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { return null; } }, new ArrayList<>()); @@ -84,10 +85,12 @@ public class OracleDeleteRecognizerTest { recognizer = new OracleDeleteRecognizer(sql, asts.get(0)); whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> idParam = new ArrayList<>(); idParam.add(1); - return new ArrayList[] {idParam}; + Map result = new HashMap(); + result.put(1, idParam); + return result; } }, new ArrayList<>()); @@ -99,10 +102,12 @@ public class OracleDeleteRecognizerTest { recognizer = new OracleDeleteRecognizer(sql, asts.get(0)); whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> idParam = new ArrayList<>(); idParam.add(1); - return new ArrayList[] {idParam}; + Map result = new HashMap(); + result.put(1, idParam); + return result; } }, new ArrayList<>()); @@ -114,12 +119,15 @@ public class OracleDeleteRecognizerTest { recognizer = new OracleDeleteRecognizer(sql, asts.get(0)); whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> idParam = new ArrayList<>(); idParam.add(1); ArrayList<Object> idParam2 = new ArrayList<>(); idParam.add(2); - return new ArrayList[] {idParam, idParam2}; + Map result = new HashMap(); + result.put(1, idParam); + result.put(2, idParam2); + return result; } }, new ArrayList<>()); //test for sql with in @@ -133,8 +141,8 @@ public class OracleDeleteRecognizerTest { deleteAst.setWhere(new OracleArgumentExpr()); new OracleDeleteRecognizer(s, deleteAst).getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { - return new ArrayList[0]; + public Map<Integer,ArrayList<Object>> getParameters() { + return new HashMap<>(); } }, new ArrayList<>()); }); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleInsertRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleInsertRecognizerTest.java index d5753082edd2bd39e8ac19cfbf3678cfe6d33dbc..5afeb54524d3d89680af45ccd9a163c150bde90e 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleInsertRecognizerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleInsertRecognizerTest.java @@ -15,6 +15,7 @@ */ package io.seata.rm.datasource.sql.druid.oracle; +import java.util.Collections; import java.util.List; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; @@ -23,6 +24,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; import io.seata.sqlparser.SQLParsingException; import io.seata.sqlparser.SQLType; import io.seata.sqlparser.druid.oracle.OracleInsertRecognizer; +import io.seata.sqlparser.struct.NotPlaceholderExpr; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -93,12 +95,13 @@ public class OracleInsertRecognizerTest { @Test public void testGetInsertRows() { + final int pkIndex = 0; //test for null value String sql = "insert into t(id, no, name, age, time) values (id_seq.nextval, null, 'a', ?, now())"; List<SQLStatement> asts = SQLUtils.parseStatements(sql, DB_TYPE); OracleInsertRecognizer recognizer = new OracleInsertRecognizer(sql, asts.get(0)); - List<List<Object>> insertRows = recognizer.getInsertRows(); + List<List<Object>> insertRows = recognizer.getInsertRows(Collections.singletonList(pkIndex)); Assertions.assertEquals(1, insertRows.size()); //test for exception @@ -106,10 +109,20 @@ public class OracleInsertRecognizerTest { String s = "insert into t(a) values (?)"; List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); SQLInsertStatement sqlInsertStatement = (SQLInsertStatement)sqlStatements.get(0); - sqlInsertStatement.getValuesList().get(0).getValues().add(new OracleBinaryDoubleExpr()); + sqlInsertStatement.getValuesList().get(0).getValues().set(pkIndex, new OracleBinaryDoubleExpr()); OracleInsertRecognizer oracleInsertRecognizer = new OracleInsertRecognizer(s, sqlInsertStatement); - oracleInsertRecognizer.getInsertRows(); + oracleInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)); }); } + + @Test + public void testNotPlaceholder_giveValidPkIndex() { + String sql = "insert into test(create_time) values(sysdate)"; + List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DB_TYPE);; + + OracleInsertRecognizer oracle = new OracleInsertRecognizer(sql, sqlStatements.get(0)); + List<List<Object>> insertRows = oracle.getInsertRows(Collections.singletonList(-1)); + Assertions.assertTrue(insertRows.get(0).get(0) instanceof NotPlaceholderExpr); + } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleSelectForUpdateRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleSelectForUpdateRecognizerTest.java index c78553df04add3eb7ef753e646a96f52b122b00b..cd85c5b96021e23d2bda20426e6e6f590a13def0 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleSelectForUpdateRecognizerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleSelectForUpdateRecognizerTest.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * @author will @@ -53,7 +54,7 @@ public class OracleSelectForUpdateRecognizerTest { OracleSelectForUpdateRecognizer recognizer = new OracleSelectForUpdateRecognizer(sql, asts.get(0)); String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { return null; } }, new ArrayList<>()); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleUpdateRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleUpdateRecognizerTest.java index 13e8879bc828f41012d9a734e388a15cb67f467f..62eec43748a202d000ec905b3d14041d9f4ba0eb 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleUpdateRecognizerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/oracle/OracleUpdateRecognizerTest.java @@ -29,6 +29,7 @@ import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * @author will @@ -115,7 +116,7 @@ public class OracleUpdateRecognizerTest { OracleUpdateRecognizer recognizer = new OracleUpdateRecognizer(sql, asts.get(0)); String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { return null; } }, new ArrayList<>()); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlDeleteRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlDeleteRecognizerTest.java index 407d7b88150272b59fb3dd5470f7b650a331b1ee..2fddbcd09c0071dcf3ea04f7770c3bd0db31d479 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlDeleteRecognizerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlDeleteRecognizerTest.java @@ -21,6 +21,7 @@ import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.SQLType; import java.util.ArrayList; import java.util.List; +import java.util.Map; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; @@ -69,7 +70,7 @@ public class PostgresqlDeleteRecognizerTest { SQLDeleteRecognizer recognizer = (SQLDeleteRecognizer) sqlRecognizers.get(0); String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { return null; } }, new ArrayList<>()); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlInsertRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlInsertRecognizerTest.java index 6f0dbe356411bc48b4972dbcc43b9b9e62ce240c..905f2de5965ee502d93812b323b59447eda95c70 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlInsertRecognizerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlInsertRecognizerTest.java @@ -21,6 +21,7 @@ import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.SQLType; import io.seata.sqlparser.druid.postgresql.PostgresqlInsertRecognizer; +import java.util.Collections; import java.util.List; import com.alibaba.druid.sql.SQLUtils; @@ -97,11 +98,12 @@ public class PostgresqlInsertRecognizerTest { @Test public void testGetInsertRows() { + final int pkIndex = 0; //test for null value String sql = "insert into t(id, no, name, age, time) values (nextval('id_seq'), null, 'a', ?, now())"; SQLInsertRecognizer recognizer = (SQLInsertRecognizer) SQLVisitorFactory.get(sql, DB_TYPE).get(0); - List<List<Object>> insertRows = recognizer.getInsertRows(); + List<List<Object>> insertRows = recognizer.getInsertRows(Collections.singletonList(pkIndex)); Assertions.assertTrue(insertRows.size() == 1); //test for exception @@ -109,10 +111,10 @@ public class PostgresqlInsertRecognizerTest { String s = "insert into t(a) values (?)"; List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); SQLInsertStatement sqlInsertStatement = (SQLInsertStatement) sqlStatements.get(0); - sqlInsertStatement.getValuesList().get(0).getValues().add(new SQLBetweenExpr()); + sqlInsertStatement.getValuesList().get(0).getValues().set(pkIndex, new SQLBetweenExpr()); PostgresqlInsertRecognizer postgresqlInsertRecognizer = new PostgresqlInsertRecognizer(s, sqlInsertStatement); - postgresqlInsertRecognizer.getInsertRows(); + postgresqlInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)); }); } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlSelectForUpdateRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlSelectForUpdateRecognizerTest.java index e2295738a8bf88b7f1c8002b0e893416e846c921..11a402f63ed1e46971f8c0fecd81ed134cacbb74 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlSelectForUpdateRecognizerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlSelectForUpdateRecognizerTest.java @@ -15,11 +15,13 @@ */ package io.seata.rm.datasource.sql.druid.postgresql; +import java.util.ArrayList; +import java.util.Map; + import io.seata.rm.datasource.sql.SQLVisitorFactory; import io.seata.sqlparser.ParametersHolder; import io.seata.sqlparser.SQLSelectRecognizer; import io.seata.sqlparser.SQLType; -import java.util.ArrayList; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -45,7 +47,7 @@ public class PostgresqlSelectForUpdateRecognizerTest { SQLSelectRecognizer recognizer = (SQLSelectRecognizer) SQLVisitorFactory.get(sql, DB_TYPE).get(0); String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer, ArrayList<Object>> getParameters() { return null; } }, new ArrayList<>()); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlUpdateRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlUpdateRecognizerTest.java index c12709944ce98a411ea6ad5de45fa66a22d0199c..d48cadad8ba15be5362d8d89e5caa1eb463680b0 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlUpdateRecognizerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/postgresql/PostgresqlUpdateRecognizerTest.java @@ -15,6 +15,10 @@ */ package io.seata.rm.datasource.sql.druid.postgresql; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr; @@ -26,8 +30,6 @@ import io.seata.sqlparser.SQLParsingException; import io.seata.sqlparser.SQLType; import io.seata.sqlparser.SQLUpdateRecognizer; import io.seata.sqlparser.druid.postgresql.PostgresqlUpdateRecognizer; -import java.util.ArrayList; -import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -108,7 +110,7 @@ public class PostgresqlUpdateRecognizerTest { SQLUpdateRecognizer recognizer = (SQLUpdateRecognizer) SQLVisitorFactory.get(sql, DB_TYPE).get(0); String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer, ArrayList<Object>> getParameters() { return null; } }, new ArrayList<>()); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java index 04fff7fc578ec827ab2149a23a363f7530023db9..55ad004a203b754fcaa4d9acd67043ae60758a77 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java @@ -20,11 +20,16 @@ import io.seata.common.exception.NotSupportYetException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.List; + /** * @author will */ public class TableMetaTest { + private final String COLUMN_ID="id"; + private final String COLUMN_USERCODE="userCode"; + @Test public void testTableMeta() { TableMeta tableMeta = new TableMeta(); @@ -71,31 +76,39 @@ public class TableMetaTest { @Test public void testGetPrimaryKeyMap() { TableMeta tableMeta = new TableMeta(); + IndexMeta primary = new IndexMeta(); primary.setIndextype(IndexType.PRIMARY); primary.setValues(Lists.newArrayList(new ColumnMeta())); + tableMeta.getAllIndexes().put("id", primary); + Assertions.assertNotNull(tableMeta.getPrimaryKeyMap()); - Assertions.assertThrows(NotSupportYetException.class, () -> { - IndexMeta primary2 = new IndexMeta(); - primary2.setIndextype(IndexType.PRIMARY); - ColumnMeta columnMeta = new ColumnMeta(); - columnMeta.setColumnName("id2"); - primary2.setValues(Lists.newArrayList(columnMeta)); - tableMeta.getAllIndexes().put("id2", primary2); - tableMeta.getPrimaryKeyMap(); - }); + } @Test public void testGetPrimaryKeyOnlyName() { TableMeta tableMeta = new TableMeta(); + ColumnMeta columnIdMeta=new ColumnMeta(); + columnIdMeta.setColumnName(COLUMN_ID); IndexMeta primary = new IndexMeta(); primary.setIndextype(IndexType.PRIMARY); - primary.setValues(Lists.newArrayList(new ColumnMeta())); - tableMeta.getAllIndexes().put("id", primary); - Assertions.assertTrue(tableMeta.getPrimaryKeyOnlyName().size() >= 1); + primary.setValues(Lists.newArrayList(columnIdMeta)); + + ColumnMeta columnUserCodeMeta=new ColumnMeta(); + columnUserCodeMeta.setColumnName(COLUMN_USERCODE); + IndexMeta primary2 = new IndexMeta(); + primary2.setIndextype(IndexType.PRIMARY); + primary2.setValues(Lists.newArrayList(columnUserCodeMeta)); + + tableMeta.getAllIndexes().put(COLUMN_ID, primary); + tableMeta.getAllIndexes().put(COLUMN_USERCODE, primary2); + + List<String> pkColumnName=tableMeta.getPrimaryKeyOnlyName(); + Assertions.assertEquals("id",pkColumnName.get(0)); + Assertions.assertEquals("userCode",pkColumnName.get(1)); } @Test @@ -107,7 +120,7 @@ public class TableMetaTest { columnMeta.setColumnName("id"); primary.setValues(Lists.newArrayList(columnMeta)); tableMeta.getAllIndexes().put("id", primary); - Assertions.assertEquals("id", tableMeta.getPkName()); + Assertions.assertEquals("id", tableMeta.getPrimaryKeyOnlyName().get(0)); } @Test diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCacheTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCacheTest.java index 793389645ea73f55bab27c1281f002a147f48d77..375a8aa065bcb878cb25ff9ea16257d8c4ca7391 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCacheTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/MysqlTableMetaCacheTest.java @@ -42,12 +42,12 @@ public class MysqlTableMetaCacheTest { private static Object[][] columnMetas = new Object[][] { - new Object[] {"", "", "t1", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, - new Object[] {"", "", "t1", "name1", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", + new Object[] {"", "", "mt1", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, + new Object[] {"", "", "mt1", "name1", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, - new Object[] {"", "", "t1", "name2", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 3, "YES", + new Object[] {"", "", "mt1", "name2", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 3, "YES", "NO"}, - new Object[] {"", "", "t1", "name3", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 4, "YES", + new Object[] {"", "", "mt1", "name3", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 4, "YES", "NO"} }; @@ -84,10 +84,10 @@ public class MysqlTableMetaCacheTest { DataSourceProxy proxy = new DataSourceProxy(dataSource); - TableMeta tableMeta = getTableMetaCache().getTableMeta(proxy.getPlainConnection(), "t1", proxy.getResourceId()); + TableMeta tableMeta = getTableMetaCache().getTableMeta(proxy.getPlainConnection(), "mt1", proxy.getResourceId()); - Assertions.assertEquals("t1", tableMeta.getTableName()); - Assertions.assertEquals("id", tableMeta.getPkName()); + Assertions.assertEquals("mt1", tableMeta.getTableName()); + Assertions.assertEquals("id", tableMeta.getPrimaryKeyOnlyName().get(0)); Assertions.assertEquals("id", tableMeta.getColumnMeta("id").getColumnName()); Assertions.assertEquals("id", tableMeta.getAutoIncreaseColumn().getColumnName()); @@ -113,12 +113,12 @@ public class MysqlTableMetaCacheTest { }; mockDriver.setMockIndexMetasReturnValue(indexMetas); Assertions.assertThrows(ShouldNeverHappenException.class, () -> { - getTableMetaCache().getTableMeta(proxy.getPlainConnection(), "t2", proxy.getResourceId()); + getTableMetaCache().getTableMeta(proxy.getPlainConnection(), "mt2", proxy.getResourceId()); }); mockDriver.setMockColumnsMetasReturnValue(null); Assertions.assertThrows(ShouldNeverHappenException.class, () -> { - getTableMetaCache().getTableMeta(proxy.getPlainConnection(), "t2", proxy.getResourceId()); + getTableMetaCache().getTableMeta(proxy.getPlainConnection(), "mt2", proxy.getResourceId()); }); } @@ -138,12 +138,12 @@ public class MysqlTableMetaCacheTest { //change the columns meta columnMetas = new Object[][] { - new Object[] {"", "", "t1", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, - new Object[] {"", "", "t1", "name1", Types.VARCHAR, "VARCHAR", 65, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", + new Object[] {"", "", "mt1", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, + new Object[] {"", "", "mt1", "name1", Types.VARCHAR, "VARCHAR", 65, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, - new Object[] {"", "", "t1", "name2", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 3, "YES", + new Object[] {"", "", "mt1", "name2", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 3, "YES", "NO"}, - new Object[] {"", "", "t1", "name3", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 4, "YES", + new Object[] {"", "", "mt1", "name3", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 4, "YES", "NO"} }; mockDriver.setMockColumnsMetasReturnValue(columnMetas); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCacheTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCacheTest.java index be93c9eaceaafc3f482860c1cab0b60de81d4039..3abd6accdd59c7b85cfd1f0ceebdcaec0973a278 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCacheTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/OracleTableMetaCacheTest.java @@ -36,12 +36,12 @@ public class OracleTableMetaCacheTest { private static Object[][] columnMetas = new Object[][] { - new Object[] {"", "", "t1", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, - new Object[] {"", "", "t1", "name1", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", + new Object[] {"", "", "ot1", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, + new Object[] {"", "", "ot1", "name1", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, - new Object[] {"", "", "t1", "name2", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 3, "YES", + new Object[] {"", "", "ot1", "name2", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 3, "YES", "NO"}, - new Object[] {"", "", "t1", "name3", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 4, "YES", + new Object[] {"", "", "ot1", "name3", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 4, "YES", "NO"} }; @@ -68,11 +68,11 @@ public class OracleTableMetaCacheTest { TableMetaCache tableMetaCache = TableMetaCacheFactory.getTableMetaCache(JdbcConstants.ORACLE); - TableMeta tableMeta = tableMetaCache.getTableMeta(proxy.getPlainConnection(), "t.t1", proxy.getResourceId()); + TableMeta tableMeta = tableMetaCache.getTableMeta(proxy.getPlainConnection(), "t.ot1", proxy.getResourceId()); Assertions.assertNotNull(tableMeta); - tableMeta = tableMetaCache.getTableMeta(proxy.getPlainConnection(), "t.\"t1\"", proxy.getResourceId()); + tableMeta = tableMetaCache.getTableMeta(proxy.getPlainConnection(), "t.\"ot1\"", proxy.getResourceId()); Assertions.assertNotNull(tableMeta); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCacheTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCacheTest.java index 25a60ca9f85af5654d846c7a10cd73b80b0a64e3..a36cafe8f0943bdadcdb365d2a2abb8d8c6891ad 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCacheTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/cache/PostgresqlTableMetaCacheTest.java @@ -36,12 +36,12 @@ public class PostgresqlTableMetaCacheTest { private static Object[][] columnMetas = new Object[][] { - new Object[] {"", "", "t1", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, - new Object[] {"", "", "t1", "name1", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", + new Object[] {"", "", "pt1", "id", Types.INTEGER, "INTEGER", 64, 0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"}, + new Object[] {"", "", "pt1", "name1", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 2, "YES", "NO"}, - new Object[] {"", "", "t1", "name2", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 3, "YES", + new Object[] {"", "", "pt1", "name2", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 3, "YES", "NO"}, - new Object[] {"", "", "t1", "name3", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 4, "YES", + new Object[] {"", "", "pt1", "name3", Types.VARCHAR, "VARCHAR", 64, 0, 10, 0, "", "", 0, 0, 64, 4, "YES", "NO"} }; @@ -68,15 +68,15 @@ public class PostgresqlTableMetaCacheTest { TableMetaCache tableMetaCache = TableMetaCacheFactory.getTableMetaCache(JdbcConstants.POSTGRESQL); - TableMeta tableMeta = tableMetaCache.getTableMeta(proxy.getPlainConnection(), "t1", proxy.getResourceId()); + TableMeta tableMeta = tableMetaCache.getTableMeta(proxy.getPlainConnection(), "pt1", proxy.getResourceId()); Assertions.assertNotNull(tableMeta); - tableMeta = tableMetaCache.getTableMeta(proxy.getPlainConnection(), "t.t1", proxy.getResourceId()); + tableMeta = tableMetaCache.getTableMeta(proxy.getPlainConnection(), "t.pt1", proxy.getResourceId()); Assertions.assertNotNull(tableMeta); - tableMeta = tableMetaCache.getTableMeta(proxy.getPlainConnection(), "t.\"t1\"", proxy.getResourceId()); + tableMeta = tableMetaCache.getTableMeta(proxy.getPlainConnection(), "t.\"pt1\"", proxy.getResourceId()); Assertions.assertNotNull(tableMeta); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java index 003b7adf77488591d04fa58e80315fefeea87cd6..943b8755920091f14156ba2ebe21f6f7925526e9 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java @@ -15,6 +15,7 @@ */ package io.seata.rm.datasource.undo; +import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.sqlparser.SQLType; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; @@ -25,8 +26,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /** * @author Geng Zhang @@ -160,7 +160,7 @@ public class AbstractUndoExecutorTest extends BaseH2Test { @Test public void testParsePK() { TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("id"); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{"id"})); Mockito.when(tableMeta.getTableName()).thenReturn("table_name"); TableRecords beforeImage = new TableRecords(); @@ -186,8 +186,46 @@ public class AbstractUndoExecutorTest extends BaseH2Test { sqlUndoLog.setAfterImage(null); TestUndoExecutor executor = new TestUndoExecutor(sqlUndoLog, true); - Object[] pkValues = executor.parsePkValues(beforeImage); - Assertions.assertEquals(2, pkValues.length); + Map<String,List<Field>> pkValues = executor.parsePkValues(beforeImage); + Assertions.assertEquals(2, pkValues.get("id").size()); + } + + @Test + public void testBuildWhereConditionByPKs() throws SQLException { + List<String> pkNameList =new ArrayList<>(); + pkNameList.add("id1"); + pkNameList.add("id2"); + + Map<String,List<Field>> pkRowValues = new HashMap<>(); + List<Field> pkId1Values= new ArrayList<>(); + pkId1Values.add(new Field()); + pkId1Values.add(new Field()); + pkId1Values.add(new Field()); + List<Field> pkId2Values= new ArrayList<>(); + pkId2Values.add(new Field()); + pkId2Values.add(new Field()); + pkId2Values.add(new Field()); + pkRowValues.put("id1",pkId1Values); + pkRowValues.put("id2",pkId2Values); + + String sql=SqlGenerateUtils.buildWhereConditionByPKs(pkNameList,pkRowValues.get("id1").size(),"mysql"); + Assertions.assertEquals(" (id1,id2 ) in ( (?,?) , (?,?) , (?,?) )",sql); + } + + @Test + public void testBuildWhereConditionByPK() throws SQLException { + List<String> pkNameList =new ArrayList<>(); + pkNameList.add("id1"); + + Map<String,List<Field>> pkRowValues = new HashMap<>(); + List<Field> pkId1Values= new ArrayList<>(); + pkId1Values.add(new Field()); + List<Field> pkId2Values= new ArrayList<>(); + pkId2Values.add(new Field()); + pkRowValues.put("id1",pkId1Values); + + String sql=SqlGenerateUtils.buildWhereConditionByPKs(pkNameList,pkRowValues.get("id1").size(),"mysql"); + Assertions.assertEquals(" (id1 ) in ( (?) )",sql); } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java index 05a4a6aef45f9e0c94703bb07df32b88c7639d4a..9da87a72e07449a1907b44c5cac9d650dcd31ad6 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseH2Test.java @@ -34,6 +34,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; +import java.util.Arrays; /** @@ -105,8 +106,8 @@ public abstract class BaseH2Test { protected static TableMeta mockTableMeta() { TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("ID"); - Mockito.when(tableMeta.getEscapePkName("h2")).thenReturn("`ID`"); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{"ID"})); + Mockito.when(tableMeta.getEscapePkNameList("h2")).thenReturn(Arrays.asList(new String[]{"ID"})); Mockito.when(tableMeta.getTableName()).thenReturn("table_name"); ColumnMeta meta0 = Mockito.mock(ColumnMeta.class); Mockito.when(meta0.getDataType()).thenReturn(Types.INTEGER); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java index 29e53f3e9fef0f249b1e241dfddfe5a809429ea8..2946e9204e87084be9f6dbbfbb437e3048d6426b 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java @@ -43,9 +43,7 @@ import java.sql.Struct; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; -import java.util.Calendar; -import java.util.Map; -import java.util.Properties; +import java.util.*; import java.util.concurrent.Executor; import com.alibaba.fastjson.JSON; @@ -152,6 +150,7 @@ public class UndoExecutorTest { AbstractUndoExecutor spy = Mockito.spy(executor); // skip data validation Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); + Mockito.doReturn(JdbcConstants.MYSQL).when(spy).getDbType(connection); spy.executeOn(connection); } @@ -221,6 +220,7 @@ public class UndoExecutorTest { AbstractUndoExecutor spy = Mockito.spy(executor); // skip data validation Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); + Mockito.doReturn(JdbcConstants.MYSQL).when(spy).getDbType(connection); spy.executeOn(connection); } @@ -290,6 +290,7 @@ public class UndoExecutorTest { AbstractUndoExecutor spy = Mockito.spy(executor); // skip data validation Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); + Mockito.doReturn(JdbcConstants.MYSQL).when(spy).getDbType(connection); spy.executeOn(connection); } @@ -318,8 +319,8 @@ public class UndoExecutorTest { } @Override - public String getPkName() { - return mockPK; + public List<String> getPrimaryKeyOnlyName(){ + return Arrays.asList(new String[]{mockPK}); } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/h2/keyword/H2KeywordChecker.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/h2/keyword/H2KeywordChecker.java new file mode 100644 index 0000000000000000000000000000000000000000..6b853cb9af0efccfae00b4436f288698cc4992f7 --- /dev/null +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/h2/keyword/H2KeywordChecker.java @@ -0,0 +1,12 @@ +package io.seata.rm.datasource.undo.h2.keyword; + +import io.seata.common.loader.LoadLevel; +import io.seata.rm.datasource.undo.mysql.keyword.MySQLKeywordChecker; +import io.seata.sqlparser.util.JdbcConstants; + +/** + * @author JerryYin + */ +@LoadLevel(name = JdbcConstants.H2) +public class H2KeywordChecker extends MySQLKeywordChecker { +} diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutorTest.java index 219db45358c3853e7dba60e5e45ee7b30502bac7..7866781fa3a6770de6ce5ae1396d3bf7c216f7fe 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutorTest.java @@ -27,8 +27,11 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import static org.mockito.Mockito.when; + /** * @author Geng Zhang */ @@ -39,7 +42,7 @@ public class MySQLUndoDeleteExecutorTest extends BaseExecutorTest { @BeforeAll public static void init(){ TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("id"); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{"id"})); Mockito.when(tableMeta.getTableName()).thenReturn("table_name"); TableRecords beforeImage = new TableRecords(); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutorTest.java index 8a44f1996be460302f4597e3b8a6b6f5cab09aba..37a48dbe995622e237297fec252cf054d2f9b239 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutorTest.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -39,7 +40,7 @@ public class MySQLUndoInsertExecutorTest extends BaseExecutorTest { @BeforeAll public static void init(){ TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("id"); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{"id"})); Mockito.when(tableMeta.getTableName()).thenReturn("table_name"); TableRecords beforeImage = new TableRecords(); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManagerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManagerTest.java index 7441054ca11266d38e5add4357066b3484b14f54..7fb3a462ef0a81187becfe80790a3ba806f242fc 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManagerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoLogManagerTest.java @@ -75,7 +75,7 @@ public class MySQLUndoLogManagerTest { @Test public void testDeleteUndoLogByLogCreated() throws SQLException { Assertions.assertEquals(0, undoLogManager.deleteUndoLogByLogCreated(new Date(), 3000, dataSource.getConnection())); - Assertions.assertThrows(SQLException.class, () -> undoLogManager.deleteUndoLogByLogCreated(new Date(), 3000, connectionProxy)); + Assertions.assertDoesNotThrow(() -> undoLogManager.deleteUndoLogByLogCreated(new Date(), 3000, connectionProxy)); } @Test @@ -85,7 +85,7 @@ public class MySQLUndoLogManagerTest { Assertions.assertDoesNotThrow(() -> undoLogManager.insertUndoLogWithNormal("xid", 1L, "", new byte[]{}, dataSource.getConnection())); - Assertions.assertThrows(SQLException.class, () -> undoLogManager.deleteUndoLogByLogCreated(new Date(), 3000, connectionProxy)); + Assertions.assertDoesNotThrow(() -> undoLogManager.deleteUndoLogByLogCreated(new Date(), 3000, connectionProxy)); } @@ -101,14 +101,14 @@ public class MySQLUndoLogManagerTest { public void testDeleteUndoLog() { Assertions.assertDoesNotThrow(() -> undoLogManager.deleteUndoLog("xid", 1L, dataSource.getConnection())); - Assertions.assertThrows(SQLException.class, () -> undoLogManager.deleteUndoLog("xid", 1L, connectionProxy)); + Assertions.assertDoesNotThrow(() -> undoLogManager.deleteUndoLog("xid", 1L, connectionProxy)); } @Test public void testBatchDeleteUndoLog() { Assertions.assertDoesNotThrow(() -> undoLogManager.batchDeleteUndoLog(Sets.newHashSet("xid"), Sets.newHashSet(1L), dataSource.getConnection())); - Assertions.assertThrows(SQLException.class, () -> undoLogManager.batchDeleteUndoLog(Sets.newHashSet("xid"), Sets.newHashSet(1L), connectionProxy)); + Assertions.assertDoesNotThrow(() -> undoLogManager.batchDeleteUndoLog(Sets.newHashSet("xid"), Sets.newHashSet(1L), connectionProxy)); } @Test diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutorTest.java index 6b8567bb37f0141303a4a400ec767463230b0a98..11c6ffc41954d42107a4672a5a6c40302f8587b0 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutorTest.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -39,7 +40,7 @@ public class MySQLUndoUpdateExecutorTest extends BaseExecutorTest { @BeforeAll public static void init(){ TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("id"); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{"id"})); Mockito.when(tableMeta.getTableName()).thenReturn("table_name"); TableRecords beforeImage = new TableRecords(); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java index 74d8a6012df70a1f6390877dca3cb19dfe5f8462..72fb6d0f1c1ad387208600f8c73756d013a5b664 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java @@ -15,6 +15,7 @@ */ package io.seata.rm.datasource.undo.mysql.keyword; +import java.sql.SQLException; import java.sql.Types; import io.seata.rm.datasource.undo.KeywordChecker; @@ -50,16 +51,6 @@ public class MySQLKeywordCheckerTest { Assertions.assertTrue(keywordChecker.check("desc")); } - /** - * Test check and replace - */ - @Test - public void testCheckAndReplace() { - KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.MYSQL); - Assertions.assertEquals("`desc`", keywordChecker.checkAndReplace("desc")); - - } - /** * Test keyword check with UPDATE case */ @@ -125,7 +116,7 @@ public class MySQLKeywordCheckerTest { MySQLUndoUpdateExecutorExtension mySQLUndoUpdateExecutor = new MySQLUndoUpdateExecutorExtension(sqlUndoLog); Assertions.assertEquals("UPDATE `lock` SET `desc` = ?, since = ? WHERE `key` = ?", - mySQLUndoUpdateExecutor.getSql()); + mySQLUndoUpdateExecutor.getSql().trim()); } @@ -212,7 +203,7 @@ public class MySQLKeywordCheckerTest { MySQLUndoInsertExecutorExtension mySQLUndoInsertExecutor = new MySQLUndoInsertExecutorExtension(sqlUndoLog); - Assertions.assertEquals("DELETE FROM `lock` WHERE `key` = ?", mySQLUndoInsertExecutor.getSql()); + Assertions.assertEquals("DELETE FROM `lock` WHERE `key` = ?", mySQLUndoInsertExecutor.getSql().trim()); } @@ -245,9 +236,9 @@ public class MySQLKeywordCheckerTest { sqlUndoLog.setTableName("`lock`"); sqlUndoLog.setSqlType(SQLType.DELETE); - TableRecords afterImage = TableRecords.empty(new UndoExecutorTest.MockTableMeta("product", "id")); + TableRecords afterImage = TableRecords.empty(new UndoExecutorTest.MockTableMeta("product", "key")); - TableRecords beforeImage = new TableRecords(new UndoExecutorTest.MockTableMeta("product", "id")); + TableRecords beforeImage = new TableRecords(new UndoExecutorTest.MockTableMeta("product", "key")); Row afterRow1 = new Row(); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutorTest.java index 0f95364169d4cf8288523f868bb83edbec57993c..279a33cb8537b5c794d0f66474f3d5d1bab260d5 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoDeleteExecutorTest.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -53,7 +54,7 @@ public class OracleUndoDeleteExecutorTest extends BaseExecutorTest { private OracleUndoDeleteExecutor upperCase() { TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("ID"); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{"ID"})); Mockito.when(tableMeta.getTableName()).thenReturn("TABLE_NAME"); TableRecords beforeImage = new TableRecords(); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutorTest.java index 9dd88ff81541d760a12fb33fbfb1e8cbe1183dd2..74e67da6e307644050822a482a35d2a592eb2a05 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoInsertExecutorTest.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -52,7 +53,7 @@ public class OracleUndoInsertExecutorTest extends BaseExecutorTest { public OracleUndoInsertExecutor upperCase() { TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("ID"); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{"ID"})); Mockito.when(tableMeta.getTableName()).thenReturn("TABLE_NAME"); TableRecords beforeImage = new TableRecords(); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutorTest.java index c6ffcd9dcc853059cd15da8823321ecf87d3e7fd..3848669843b2222a4cf126be849e9680c9f784ab 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/OracleUndoUpdateExecutorTest.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -54,7 +55,7 @@ public class OracleUndoUpdateExecutorTest extends BaseExecutorTest { private OracleUndoUpdateExecutor upperCaseSQL() { TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("ID"); + Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{"ID"})); Mockito.when(tableMeta.getTableName()).thenReturn("TABLE_NAME"); TableRecords beforeImage = new TableRecords(); diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordCheckerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordCheckerTest.java index d7f622f814108676373efa9b3a3a695c47f43e75..04d505b6a76a2a6077eacb04050f0dbccaec5e50 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordCheckerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/oracle/keyword/OracleKeywordCheckerTest.java @@ -33,11 +33,4 @@ public class OracleKeywordCheckerTest { Assertions.assertNotNull(keywordChecker); } - @Test - public void testCheckAndReplate() { - KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.ORACLE); - Assertions.assertNull(keywordChecker.checkAndReplace(null)); - Assertions.assertEquals("undo_log", keywordChecker.checkAndReplace("undo_log")); - Assertions.assertEquals("TABLE", keywordChecker.checkAndReplace("TABLE")); - } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordCheckerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordCheckerTest.java index 9179d0c78ec61d51a5e4d9c90ae080f0a0f2c218..77d7f2f92920eb9e5e1e9ee1ff78f98692642973 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordCheckerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/postgresql/keyword/PostgresqlKeywordCheckerTest.java @@ -33,11 +33,4 @@ public class PostgresqlKeywordCheckerTest { Assertions.assertNotNull(keywordChecker); } - @Test - public void testCheckAndReplate() { - KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.POSTGRESQL); - Assertions.assertEquals(null, keywordChecker.checkAndReplace(null)); - Assertions.assertEquals("undo_log", keywordChecker.checkAndReplace("undo_log")); - Assertions.assertEquals("\"TABLE\"", keywordChecker.checkAndReplace("TABLE")); - } } diff --git a/rm-datasource/src/test/java/io/seata/rm/xa/ConnectionProxyXATest.java b/rm-datasource/src/test/java/io/seata/rm/xa/ConnectionProxyXATest.java index fec7828f8b45ab254453cb7667038d88a6a2e48d..8960a70023068b4300add11f670686179949331a 100644 --- a/rm-datasource/src/test/java/io/seata/rm/xa/ConnectionProxyXATest.java +++ b/rm-datasource/src/test/java/io/seata/rm/xa/ConnectionProxyXATest.java @@ -24,10 +24,7 @@ import io.seata.rm.datasource.xa.ConnectionProxyXA; import io.seata.rm.datasource.xa.StatementProxyXA; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.function.Executable; import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import javax.sql.XAConnection; import javax.transaction.xa.XAResource; @@ -36,6 +33,7 @@ import java.sql.Connection; import java.sql.Statement; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; /** * Tests for ConnectionProxyXA @@ -44,18 +42,6 @@ import static org.mockito.ArgumentMatchers.any; */ public class ConnectionProxyXATest { - private class ValueHolder<T> { - public T value; - - public ValueHolder(T value) { - this.value = value; - } - - public ValueHolder() { - - } - } - @Test public void testInit() throws Throwable { Connection connection = Mockito.mock(Connection.class); @@ -65,67 +51,18 @@ public class ConnectionProxyXATest { String xid = "xxx"; ConnectionProxyXA connectionProxyXA = new ConnectionProxyXA(connection, xaConnection, baseDataSourceResource, xid); - Assertions.assertThrows(IllegalStateException.class, new Executable() { - @Override - public void execute() throws Throwable { - try { - connectionProxyXA.init(); - } catch (Throwable ex) { - Assertions.assertTrue(ex.getMessage().startsWith("Connection[autocommit=false]")); - throw ex; - } - } - }); + + Assertions.assertThrows(IllegalStateException.class, + connectionProxyXA::init, + "Connection[autocommit=false] as default is NOT supported"); } @Test public void testXABranchCommit() throws Throwable { Connection connection = Mockito.mock(Connection.class); - ValueHolder<Boolean> autoCommitOnConnection = new ValueHolder<>(); - autoCommitOnConnection.value = true; - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - autoCommitOnConnection.value = (boolean)invocationOnMock.getArguments()[0]; - return null; - } - }).when(connection).setAutoCommit(any(Boolean.class)); - - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - return autoCommitOnConnection.value; - } - }).when(connection).getAutoCommit(); + Mockito.when(connection.getAutoCommit()).thenReturn(true); XAResource xaResource = Mockito.mock(XAResource.class); - ValueHolder<Boolean> xaStarted = new ValueHolder<>(); - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - xaStarted.value = true; - return null; - } - }).when(xaResource).start(any(Xid.class), any(Integer.class)); - - ValueHolder<Boolean> xaEnded = new ValueHolder<>(); - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - xaEnded.value = true; - return null; - } - }).when(xaResource).end(any(Xid.class), any(Integer.class)); - - ValueHolder<Boolean> xaPrepared = new ValueHolder<>(false); - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - xaPrepared.value = true; - return null; - } - }).when(xaResource).prepare(any(Xid.class)); - XAConnection xaConnection = Mockito.mock(XAConnection.class); Mockito.when(xaConnection.getXAResource()).thenReturn(xaResource); BaseDataSourceResource<ConnectionProxyXA> baseDataSourceResource = Mockito.mock(BaseDataSourceResource.class); @@ -140,65 +77,23 @@ public class ConnectionProxyXATest { connectionProxyXA.setAutoCommit(false); - Assertions.assertFalse(connectionProxyXA.getAutoCommit()); // Assert setAutoCommit = false was NEVER invoked on the wrapped connection - Assertions.assertTrue(connection.getAutoCommit()); + Mockito.verify(connection, times(0)).setAutoCommit(false); // Assert XA start was invoked - Assertions.assertTrue(xaStarted.value); + Mockito.verify(xaResource).start(any(Xid.class), any(Integer.class)); connectionProxyXA.commit(); - Assertions.assertTrue(xaEnded.value); - Assertions.assertTrue(xaPrepared.value); + + Mockito.verify(xaResource).end(any(Xid.class), any(Integer.class)); + Mockito.verify(xaResource).prepare(any(Xid.class)); } @Test public void testXABranchRollback() throws Throwable { Connection connection = Mockito.mock(Connection.class); - ValueHolder<Boolean> autoCommitOnConnection = new ValueHolder<>(); - autoCommitOnConnection.value = true; - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - autoCommitOnConnection.value = (boolean)invocationOnMock.getArguments()[0]; - return null; - } - }).when(connection).setAutoCommit(any(Boolean.class)); - - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - return autoCommitOnConnection.value; - } - }).when(connection).getAutoCommit(); + Mockito.when(connection.getAutoCommit()).thenReturn(true); XAResource xaResource = Mockito.mock(XAResource.class); - ValueHolder<Boolean> xaStarted = new ValueHolder<>(); - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - xaStarted.value = true; - return null; - } - }).when(xaResource).start(any(Xid.class), any(Integer.class)); - - ValueHolder<Boolean> xaEnded = new ValueHolder<>(); - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - xaEnded.value = true; - return null; - } - }).when(xaResource).end(any(Xid.class), any(Integer.class)); - - ValueHolder<Boolean> xaPrepared = new ValueHolder<>(false); - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - xaPrepared.value = true; - return null; - } - }).when(xaResource).prepare(any(Xid.class)); - XAConnection xaConnection = Mockito.mock(XAConnection.class); Mockito.when(xaConnection.getXAResource()).thenReturn(xaResource); BaseDataSourceResource<ConnectionProxyXA> baseDataSourceResource = Mockito.mock(BaseDataSourceResource.class); @@ -213,31 +108,25 @@ public class ConnectionProxyXATest { connectionProxyXA.setAutoCommit(false); - Assertions.assertFalse(connectionProxyXA.getAutoCommit()); // Assert setAutoCommit = false was NEVER invoked on the wrapped connection - Assertions.assertTrue(connection.getAutoCommit()); + Mockito.verify(connection, times(0)).setAutoCommit(false); + // Assert XA start was invoked - Assertions.assertTrue(xaStarted.value); + Mockito.verify(xaResource).start(any(Xid.class), any(Integer.class)); connectionProxyXA.rollback(); - Assertions.assertTrue(xaEnded.value); + + Mockito.verify(xaResource).end(any(Xid.class), any(Integer.class)); + // Not prepared - Assertions.assertFalse(xaPrepared.value); + Mockito.verify(xaResource, times(0)).prepare(any(Xid.class)); } @Test public void testClose() throws Throwable { Connection connection = Mockito.mock(Connection.class); Mockito.when(connection.getAutoCommit()).thenReturn(true); - ValueHolder<Boolean> closed = new ValueHolder<>(); - closed.value = false; - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - closed.value = true; - return null; - } - }).when(connection).close(); + XAConnection xaConnection = Mockito.mock(XAConnection.class); BaseDataSourceResource<ConnectionProxyXA> baseDataSourceResource = Mockito.mock(BaseDataSourceResource.class); String xid = "xxx"; @@ -249,7 +138,7 @@ public class ConnectionProxyXATest { // call close on proxy connectionProxyXA1.close(); // Assert the original connection was NOT closed - Assertions.assertFalse(closed.value); + Mockito.verify(connection, times(0)).close(); ConnectionProxyXA connectionProxyXA2 = new ConnectionProxyXA(connection, xaConnection, baseDataSourceResource, xid); connectionProxyXA2.init(); @@ -258,7 +147,7 @@ public class ConnectionProxyXATest { // call close on proxy connectionProxyXA2.close(); // Assert the original connection was ALSO closed - Assertions.assertTrue(closed.value); + Mockito.verify(connection).close(); } @Test @@ -267,24 +156,6 @@ public class ConnectionProxyXATest { Mockito.when(connection.getAutoCommit()).thenReturn(true); XAResource xaResource = Mockito.mock(XAResource.class); - ValueHolder<Boolean> xaCommitted = new ValueHolder<>(false); - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - xaCommitted.value = true; - return null; - } - }).when(xaResource).commit(any(Xid.class), any(Boolean.class)); - - ValueHolder<Boolean> xaRolledback = new ValueHolder<>(false); - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - xaRolledback.value = true; - return null; - } - }).when(xaResource).rollback(any(Xid.class)); - XAConnection xaConnection = Mockito.mock(XAConnection.class); Mockito.when(xaConnection.getXAResource()).thenReturn(xaResource); BaseDataSourceResource<ConnectionProxyXA> baseDataSourceResource = Mockito.mock(BaseDataSourceResource.class); @@ -294,8 +165,9 @@ public class ConnectionProxyXATest { connectionProxyXA.init(); connectionProxyXA.xaCommit("xxx", 123L, null); - Assertions.assertTrue(xaCommitted.value); - Assertions.assertFalse(xaRolledback.value); + + Mockito.verify(xaResource).commit(any(Xid.class), any(Boolean.class)); + Mockito.verify(xaResource, times(0)).rollback(any(Xid.class)); } @Test @@ -304,23 +176,6 @@ public class ConnectionProxyXATest { Mockito.when(connection.getAutoCommit()).thenReturn(true); XAResource xaResource = Mockito.mock(XAResource.class); - ValueHolder<Boolean> xaCommitted = new ValueHolder<>(false); - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - xaCommitted.value = true; - return null; - } - }).when(xaResource).commit(any(Xid.class), any(Boolean.class)); - - ValueHolder<Boolean> xaRolledback = new ValueHolder<>(false); - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - xaRolledback.value = true; - return null; - } - }).when(xaResource).rollback(any(Xid.class)); XAConnection xaConnection = Mockito.mock(XAConnection.class); Mockito.when(xaConnection.getXAResource()).thenReturn(xaResource); @@ -331,8 +186,9 @@ public class ConnectionProxyXATest { connectionProxyXA.init(); connectionProxyXA.xaRollback("xxx", 123L, null); - Assertions.assertFalse(xaCommitted.value); - Assertions.assertTrue(xaRolledback.value); + + Mockito.verify(xaResource, times(0)).commit(any(Xid.class), any(Boolean.class)); + Mockito.verify(xaResource).rollback(any(Xid.class)); } @Test diff --git a/rm-datasource/src/test/resources/META-INF/services/io.seata.rm.datasource.undo.KeywordChecker b/rm-datasource/src/test/resources/META-INF/services/io.seata.rm.datasource.undo.KeywordChecker new file mode 100644 index 0000000000000000000000000000000000000000..de389691db18b0b8bd4a204c7f4867523a984c59 --- /dev/null +++ b/rm-datasource/src/test/resources/META-INF/services/io.seata.rm.datasource.undo.KeywordChecker @@ -0,0 +1 @@ +io.seata.rm.datasource.undo.h2.keyword.H2KeywordChecker \ No newline at end of file diff --git a/rm/pom.xml b/rm/pom.xml index 136824879f66ce1835418b9a45019f5221ce90da..64c78aea1ba1012ca023cafa9692a51e4762d163 100644 --- a/rm/pom.xml +++ b/rm/pom.xml @@ -33,6 +33,10 @@ <artifactId>seata-core</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> </dependencies> diff --git a/rm/src/main/java/io/seata/rm/AbstractRMHandler.java b/rm/src/main/java/io/seata/rm/AbstractRMHandler.java index 1cbb163ede55e61d51da07a5bb1a21e1124ff078..5e21b8a1c9de02c0fb7a76eb1b8771235178c644 100644 --- a/rm/src/main/java/io/seata/rm/AbstractRMHandler.java +++ b/rm/src/main/java/io/seata/rm/AbstractRMHandler.java @@ -15,7 +15,6 @@ */ package io.seata.rm; -import io.seata.common.exception.ShouldNeverHappenException; import io.seata.core.exception.AbstractExceptionHandler; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; @@ -153,7 +152,7 @@ public abstract class AbstractRMHandler extends AbstractExceptionHandler @Override public void onResponse(AbstractResultMessage response, RpcContext context) { - throw new ShouldNeverHappenException(); + LOGGER.info("the rm client received response msg [{}] from tc server.", response.toString()); } public abstract BranchType getBranchType(); diff --git a/rm/src/main/java/io/seata/rm/AbstractResourceManager.java b/rm/src/main/java/io/seata/rm/AbstractResourceManager.java index 644c4bbfa8de1c44f49108dd740922c3b466c2a5..29ddad2026a6e82ea8e799cce31d77ab40bc67ba 100644 --- a/rm/src/main/java/io/seata/rm/AbstractResourceManager.java +++ b/rm/src/main/java/io/seata/rm/AbstractResourceManager.java @@ -15,8 +15,6 @@ */ package io.seata.rm; -import java.util.concurrent.TimeoutException; - import io.seata.common.exception.NotSupportYetException; import io.seata.core.exception.RmTransactionException; import io.seata.core.exception.TransactionException; @@ -30,11 +28,12 @@ import io.seata.core.protocol.transaction.BranchRegisterRequest; import io.seata.core.protocol.transaction.BranchRegisterResponse; import io.seata.core.protocol.transaction.BranchReportRequest; import io.seata.core.protocol.transaction.BranchReportResponse; -import io.seata.core.rpc.netty.RmRpcClient; - +import io.seata.core.rpc.netty.RmNettyRemotingClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.concurrent.TimeoutException; + /** * abstract ResourceManager * @@ -46,6 +45,7 @@ public abstract class AbstractResourceManager implements ResourceManager { /** * registry branch record + * * @param branchType the branch type * @param resourceId the resource id * @param clientId the client id @@ -64,7 +64,7 @@ public abstract class AbstractResourceManager implements ResourceManager { request.setBranchType(branchType); request.setApplicationData(applicationData); - BranchRegisterResponse response = (BranchRegisterResponse) RmRpcClient.getInstance().sendMsgWithResponse(request); + BranchRegisterResponse response = (BranchRegisterResponse) RmNettyRemotingClient.getInstance().sendSyncRequest(request); if (response.getResultCode() == ResultCode.Failed) { throw new RmTransactionException(response.getTransactionExceptionCode(), String.format("Response[ %s ]", response.getMsg())); } @@ -78,6 +78,7 @@ public abstract class AbstractResourceManager implements ResourceManager { /** * report branch status + * * @param branchType the branch type * @param xid the xid * @param branchId the branch id @@ -94,7 +95,7 @@ public abstract class AbstractResourceManager implements ResourceManager { request.setStatus(status); request.setApplicationData(applicationData); - BranchReportResponse response = (BranchReportResponse) RmRpcClient.getInstance().sendMsgWithResponse(request); + BranchReportResponse response = (BranchReportResponse) RmNettyRemotingClient.getInstance().sendSyncRequest(request); if (response.getResultCode() == ResultCode.Failed) { throw new RmTransactionException(response.getTransactionExceptionCode(), String.format("Response[ %s ]", response.getMsg())); } @@ -117,6 +118,6 @@ public abstract class AbstractResourceManager implements ResourceManager { @Override public void registerResource(Resource resource) { - RmRpcClient.getInstance().registerResource(resource.getResourceGroupId(), resource.getResourceId()); + RmNettyRemotingClient.getInstance().registerResource(resource.getResourceGroupId(), resource.getResourceId()); } } diff --git a/rm/src/main/java/io/seata/rm/RMClient.java b/rm/src/main/java/io/seata/rm/RMClient.java index cc8b2ec0242b29211a73bb00d780a5b8af16aa11..96600094f89fcf3392d18cc35689d8e05e57bfe2 100644 --- a/rm/src/main/java/io/seata/rm/RMClient.java +++ b/rm/src/main/java/io/seata/rm/RMClient.java @@ -15,8 +15,7 @@ */ package io.seata.rm; -import io.seata.core.rpc.netty.RmMessageListener; -import io.seata.core.rpc.netty.RmRpcClient; +import io.seata.core.rpc.netty.RmNettyRemotingClient; /** * The Rm client Initiator. @@ -32,10 +31,10 @@ public class RMClient { * @param transactionServiceGroup the transaction service group */ public static void init(String applicationId, String transactionServiceGroup) { - RmRpcClient rmRpcClient = RmRpcClient.getInstance(applicationId, transactionServiceGroup); - rmRpcClient.setResourceManager(DefaultResourceManager.get()); - rmRpcClient.setClientMessageListener(new RmMessageListener(DefaultRMHandler.get(), rmRpcClient)); - rmRpcClient.init(); + RmNettyRemotingClient rmNettyRemotingClient = RmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup); + rmNettyRemotingClient.setResourceManager(DefaultResourceManager.get()); + rmNettyRemotingClient.setTransactionMessageHandler(DefaultRMHandler.get()); + rmNettyRemotingClient.init(); } } diff --git a/saga/pom.xml b/saga/pom.xml index a134a00d86772d68ca68f2493a3416b480fa224a..b90c548bad878fc16ac726b618a100d46bc7b8d5 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -47,6 +47,18 @@ <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-all</artifactId> </dependency> </dependencies> </project> diff --git a/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/config/DbStateMachineConfig.java b/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/config/DbStateMachineConfig.java index 2b8b393b163c5256c21af75f6bbb5259fca3a045..cb098c9b2861ca4ee329ca9bfe87976f99467548 100644 --- a/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/config/DbStateMachineConfig.java +++ b/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/config/DbStateMachineConfig.java @@ -20,17 +20,23 @@ import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; +import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; import io.seata.saga.engine.impl.DefaultStateMachineConfig; +import io.seata.saga.engine.serializer.impl.ParamsSerializer; import io.seata.saga.engine.store.db.DbAndReportTcStateLogStore; import io.seata.saga.engine.store.db.DbStateLangStore; import io.seata.saga.tm.DefaultSagaTransactionalTemplate; import io.seata.saga.tm.SagaTransactionalTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; +import org.springframework.util.StringUtils; import static io.seata.core.constants.DefaultValues.DEFAULT_CLIENT_REPORT_SUCCESS_ENABLE; import static io.seata.core.constants.DefaultValues.DEFAULT_CLIENT_SAGA_BRANCH_REGISTER_ENABLE; +import static io.seata.core.constants.DefaultValues.DEFAULT_SAGA_JSON_PARSER; /** * DbStateMachineConfig @@ -39,14 +45,33 @@ import static io.seata.core.constants.DefaultValues.DEFAULT_CLIENT_SAGA_BRANCH_R */ public class DbStateMachineConfig extends DefaultStateMachineConfig implements DisposableBean { + private static final Logger LOGGER = LoggerFactory.getLogger(DbStateMachineConfig.class); + private DataSource dataSource; private String applicationId; private String txServiceGroup; private String tablePrefix = "seata_"; private String dbType; private SagaTransactionalTemplate sagaTransactionalTemplate; - private boolean rmReportSuccessEnable = ConfigurationFactory.getInstance().getBoolean(ConfigurationKeys.CLIENT_REPORT_SUCCESS_ENABLE, DEFAULT_CLIENT_REPORT_SUCCESS_ENABLE); - private boolean sagaBranchRegisterEnable = ConfigurationFactory.getInstance().getBoolean(ConfigurationKeys.CLIENT_SAGA_BRANCH_REGISTER_ENABLE, DEFAULT_CLIENT_SAGA_BRANCH_REGISTER_ENABLE); + private boolean rmReportSuccessEnable = DEFAULT_CLIENT_REPORT_SUCCESS_ENABLE; + private boolean sagaBranchRegisterEnable = DEFAULT_CLIENT_SAGA_BRANCH_REGISTER_ENABLE; + private String sagaJsonParser = DEFAULT_SAGA_JSON_PARSER; + + + public DbStateMachineConfig() { + try { + Configuration configuration = ConfigurationFactory.getInstance(); + if (configuration != null) { + this.rmReportSuccessEnable = configuration.getBoolean(ConfigurationKeys.CLIENT_REPORT_SUCCESS_ENABLE, DEFAULT_CLIENT_REPORT_SUCCESS_ENABLE); + this.sagaBranchRegisterEnable = configuration.getBoolean(ConfigurationKeys.CLIENT_SAGA_BRANCH_REGISTER_ENABLE, DEFAULT_CLIENT_SAGA_BRANCH_REGISTER_ENABLE); + this.sagaJsonParser = configuration.getConfig(ConfigurationKeys.CLIENT_SAGA_JSON_PARSER, DEFAULT_SAGA_JSON_PARSER); + this.applicationId = configuration.getConfig(ConfigurationKeys.APPLICATION_ID); + this.txServiceGroup = configuration.getConfig(ConfigurationKeys.TX_SERVICE_GROUP); + } + } catch (Exception e) { + LOGGER.warn("Load SEATA configuration failed, use default configuration instead.", e); + } + } public static String getDbTypeFromDataSource(DataSource dataSource) throws SQLException { try (Connection con = dataSource.getConnection()) { @@ -68,6 +93,12 @@ public class DbStateMachineConfig extends DefaultStateMachineConfig implements D dbStateLogStore.setDefaultTenantId(getDefaultTenantId()); dbStateLogStore.setSeqGenerator(getSeqGenerator()); + if (StringUtils.hasLength(sagaJsonParser)) { + ParamsSerializer paramsSerializer = new ParamsSerializer(); + paramsSerializer.setJsonParserName(sagaJsonParser); + dbStateLogStore.setParamsSerializer(paramsSerializer); + } + if (sagaTransactionalTemplate == null) { DefaultSagaTransactionalTemplate defaultSagaTransactionalTemplate = new DefaultSagaTransactionalTemplate(); @@ -161,4 +192,12 @@ public class DbStateMachineConfig extends DefaultStateMachineConfig implements D public void setRmReportSuccessEnable(boolean rmReportSuccessEnable) { this.rmReportSuccessEnable = rmReportSuccessEnable; } + + public String getSagaJsonParser() { + return sagaJsonParser; + } + + public void setSagaJsonParser(String sagaJsonParser) { + this.sagaJsonParser = sagaJsonParser; + } } diff --git a/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/serializer/impl/ParamsFastjsonSerializer.java b/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/serializer/impl/ParamsFastjsonSerializer.java deleted file mode 100644 index 89aa33d59e7fb5451d15e35710fccbe229454491..0000000000000000000000000000000000000000 --- a/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/serializer/impl/ParamsFastjsonSerializer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache 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 - * - * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.engine.serializer.impl; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.parser.Feature; -import com.alibaba.fastjson.serializer.SerializerFeature; - -import io.seata.saga.engine.serializer.Serializer; - -/** - * Parameter serializer based on Fastjson - * - * @author lorne.cl - */ -public class ParamsFastjsonSerializer implements Serializer<Object, String> { - - private static final SerializerFeature[] SERIALIZER_FEATURES = new SerializerFeature[] { - SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteDateUseDateFormat, - SerializerFeature.WriteClassName}; - - @Override - public String serialize(Object params) { - if (params != null) { - return JSON.toJSONString(params, SERIALIZER_FEATURES); - } - return null; - } - - @Override - public Object deserialize(String json) { - if (json != null) { - return JSON.parse(json, Feature.SupportAutoType); - - } - return null; - } -} \ No newline at end of file diff --git a/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/serializer/impl/ParamsSerializer.java b/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/serializer/impl/ParamsSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..bce52e954c50df0dd82754ed53bead3465923b04 --- /dev/null +++ b/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/serializer/impl/ParamsSerializer.java @@ -0,0 +1,63 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.engine.serializer.impl; + +import io.seata.saga.engine.serializer.Serializer; +import io.seata.saga.statelang.domain.DomainConstants; +import io.seata.saga.statelang.parser.JsonParser; +import io.seata.saga.statelang.parser.JsonParserFactory; + +/** + * Parameter serializer based on Fastjson + * + * @author lorne.cl + */ +public class ParamsSerializer implements Serializer<Object, String> { + + private String jsonParserName = DomainConstants.DEFAULT_JSON_PARSER; + + @Override + public String serialize(Object params) { + if (params != null) { + JsonParser jsonParser = JsonParserFactory.getJsonParser(jsonParserName); + if (jsonParser == null) { + throw new RuntimeException("Cannot find JsonParer by name: " + jsonParserName); + } + return jsonParser.toJsonString(params, false); + } + return null; + } + + @Override + public Object deserialize(String json) { + if (json != null) { + JsonParser jsonParser = JsonParserFactory.getJsonParser(jsonParserName); + if (jsonParser == null) { + throw new RuntimeException("Cannot find JsonParer by name: " + jsonParserName); + } + return jsonParser.parse(json, Object.class, false); + } + return null; + } + + public String getJsonParserName() { + return jsonParserName; + } + + public void setJsonParserName(String jsonParserName) { + this.jsonParserName = jsonParserName; + } +} \ No newline at end of file diff --git a/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/store/db/DbAndReportTcStateLogStore.java b/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/store/db/DbAndReportTcStateLogStore.java index 54551eef993ad54321b97ac0df923839e41381df..fcd09c6cdd83b1dd4e413affbbfa8f833f0079c7 100644 --- a/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/store/db/DbAndReportTcStateLogStore.java +++ b/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/store/db/DbAndReportTcStateLogStore.java @@ -37,7 +37,7 @@ import io.seata.saga.engine.pcext.utils.EngineUtils; import io.seata.saga.engine.sequence.SeqGenerator; import io.seata.saga.engine.serializer.Serializer; import io.seata.saga.engine.serializer.impl.ExceptionSerializer; -import io.seata.saga.engine.serializer.impl.ParamsFastjsonSerializer; +import io.seata.saga.engine.serializer.impl.ParamsSerializer; import io.seata.saga.engine.store.StateLogStore; import io.seata.saga.proctrl.ProcessContext; import io.seata.saga.statelang.domain.DomainConstants; @@ -75,7 +75,7 @@ public class DbAndReportTcStateLogStore extends AbstractStore implements StateLo = new StateInstanceToStatementForUpdate(); private static final ResultSetToStateInstance RESULT_SET_TO_STATE_INSTANCE = new ResultSetToStateInstance(); private SagaTransactionalTemplate sagaTransactionalTemplate; - private Serializer<Object, String> paramsSerializer = new ParamsFastjsonSerializer(); + private Serializer<Object, String> paramsSerializer = new ParamsSerializer(); private Serializer<Exception, byte[]> exceptionSerializer = new ExceptionSerializer(); private StateLogStoreSqls stateLogStoreSqls; private String defaultTenantId; @@ -155,6 +155,11 @@ public class DbAndReportTcStateLogStore extends AbstractStore implements StateLo endParams.remove(DomainConstants.VAR_NAME_GLOBAL_TX); } + // if success, clear exception + if (ExecutionStatus.SU.equals(machineInstance.getStatus()) && machineInstance.getException() != null) { + machineInstance.setException(null); + } + machineInstance.setSerializedEndParams(paramsSerializer.serialize(machineInstance.getEndParams())); machineInstance.setSerializedException(exceptionSerializer.serialize(machineInstance.getException())); int effect = executeUpdate(stateLogStoreSqls.getRecordStateMachineFinishedSql(dbType), diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/StateMachineConfig.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/StateMachineConfig.java index 749a298abcd99a768d57dd463b1eea39dc340c46..6249cfe4523527be5b88cefb82e74f32f0c1baaf 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/StateMachineConfig.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/StateMachineConfig.java @@ -29,6 +29,8 @@ import io.seata.saga.engine.strategy.StatusDecisionStrategy; import io.seata.saga.proctrl.eventing.impl.ProcessCtrlEventPublisher; import org.springframework.context.ApplicationContext; +import javax.script.ScriptEngineManager; + /** * StateMachineConfig * @@ -159,4 +161,11 @@ public interface StateMachineConfig { * @return */ int getServiceInvokeTimeout(); + + /** + * get ScriptEngineManager + * + * @return + */ + ScriptEngineManager getScriptEngineManager(); } \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/DefaultStateMachineConfig.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/DefaultStateMachineConfig.java index d3a7e5ee2412ffd7fe2717eceaeffddf10e15894..f136d930e0033347707c41a519f95659037e7a8b 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/DefaultStateMachineConfig.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/DefaultStateMachineConfig.java @@ -17,9 +17,11 @@ package io.seata.saga.engine.impl; import java.io.IOException; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.ThreadPoolExecutor; +import io.seata.common.loader.EnhancedServiceLoader; import io.seata.saga.engine.StateMachineConfig; import io.seata.saga.engine.evaluation.EvaluatorFactoryManager; import io.seata.saga.engine.evaluation.exception.ExceptionMatchEvaluatorFactory; @@ -29,8 +31,14 @@ import io.seata.saga.engine.expression.seq.SequenceExpressionFactory; import io.seata.saga.engine.expression.spel.SpringELExpressionFactory; import io.seata.saga.engine.invoker.ServiceInvokerManager; import io.seata.saga.engine.invoker.impl.SpringBeanServiceInvoker; +import io.seata.saga.engine.pcext.InterceptableStateHandler; +import io.seata.saga.engine.pcext.InterceptableStateRouter; +import io.seata.saga.engine.pcext.StateHandler; +import io.seata.saga.engine.pcext.StateHandlerInterceptor; import io.seata.saga.engine.pcext.StateMachineProcessHandler; import io.seata.saga.engine.pcext.StateMachineProcessRouter; +import io.seata.saga.engine.pcext.StateRouter; +import io.seata.saga.engine.pcext.StateRouterInterceptor; import io.seata.saga.engine.repo.StateLogRepository; import io.seata.saga.engine.repo.StateMachineRepository; import io.seata.saga.engine.repo.impl.StateLogRepositoryImpl; @@ -60,6 +68,8 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.io.Resource; +import javax.script.ScriptEngineManager; + /** * Default state machine configuration * @@ -94,6 +104,7 @@ public class DefaultStateMachineConfig implements StateMachineConfig, Applicatio private Resource[] resources = new Resource[0]; private String charset = "UTF-8"; private String defaultTenantId = "000001"; + private ScriptEngineManager scriptEngineManager; protected void init() throws Exception { @@ -192,15 +203,21 @@ public class DefaultStateMachineConfig implements StateMachineConfig, Applicatio this.serviceInvokerManager.putServiceInvoker(DomainConstants.SERVICE_TYPE_SPRING_BEAN, springBeanServiceInvoker); } + + if (this.scriptEngineManager == null) { + this.scriptEngineManager = new ScriptEngineManager(); + } } - private ProcessControllerImpl createProcessorController(ProcessCtrlEventPublisher eventPublisher) throws Exception { + protected ProcessControllerImpl createProcessorController(ProcessCtrlEventPublisher eventPublisher) throws Exception { StateMachineProcessRouter stateMachineProcessRouter = new StateMachineProcessRouter(); stateMachineProcessRouter.initDefaultStateRouters(); + loadStateRouterInterceptors(stateMachineProcessRouter.getStateRouters()); StateMachineProcessHandler stateMachineProcessHandler = new StateMachineProcessHandler(); stateMachineProcessHandler.initDefaultHandlers(); + loadStateHandlerInterceptors(stateMachineProcessHandler.getStateHandlers()); DefaultRouterHandler defaultRouterHandler = new DefaultRouterHandler(); defaultRouterHandler.setEventPublisher(eventPublisher); @@ -225,6 +242,42 @@ public class DefaultStateMachineConfig implements StateMachineConfig, Applicatio return processorController; } + protected void loadStateHandlerInterceptors(Map<String, StateHandler> stateHandlerMap) { + for (StateHandler stateHandler : stateHandlerMap.values()) { + if (stateHandler instanceof InterceptableStateHandler) { + InterceptableStateHandler interceptableStateHandler = (InterceptableStateHandler) stateHandler; + List<StateHandlerInterceptor> interceptorList = EnhancedServiceLoader.loadAll(StateHandlerInterceptor.class); + for (StateHandlerInterceptor interceptor : interceptorList) { + if (interceptor.match(interceptableStateHandler.getClass())) { + interceptableStateHandler.addInterceptor(interceptor); + } + + if (interceptor instanceof ApplicationContextAware) { + ((ApplicationContextAware) interceptor).setApplicationContext(getApplicationContext()); + } + } + } + } + } + + protected void loadStateRouterInterceptors(Map<String, StateRouter> stateRouterMap) { + for (StateRouter stateRouter : stateRouterMap.values()) { + if (stateRouter instanceof InterceptableStateRouter) { + InterceptableStateRouter interceptableStateRouter = (InterceptableStateRouter) stateRouter; + List<StateRouterInterceptor> interceptorList = EnhancedServiceLoader.loadAll(StateRouterInterceptor.class); + for (StateRouterInterceptor interceptor : interceptorList) { + if (interceptor.match(interceptableStateRouter.getClass())) { + interceptableStateRouter.addInterceptor(interceptor); + } + + if (interceptor instanceof ApplicationContextAware) { + ((ApplicationContextAware) interceptor).setApplicationContext(getApplicationContext()); + } + } + } + } + } + @Override public void afterPropertiesSet() throws Exception { init(); @@ -403,4 +456,13 @@ public class DefaultStateMachineConfig implements StateMachineConfig, Applicatio public void setServiceInvokeTimeout(int serviceInvokeTimeout) { this.serviceInvokeTimeout = serviceInvokeTimeout; } + + @Override + public ScriptEngineManager getScriptEngineManager() { + return scriptEngineManager; + } + + public void setScriptEngineManager(ScriptEngineManager scriptEngineManager) { + this.scriptEngineManager = scriptEngineManager; + } } \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/ProcessCtrlStateMachineEngine.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/ProcessCtrlStateMachineEngine.java index 18ac42eb95b6ec6f406d2c50311d30867c143bfb..e6a359c3c6f66b8c4ba199edf9e4e3c893e1ec7a 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/ProcessCtrlStateMachineEngine.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/impl/ProcessCtrlStateMachineEngine.java @@ -28,8 +28,8 @@ import io.seata.saga.engine.StateMachineEngine; import io.seata.saga.engine.exception.EngineExecutionException; import io.seata.saga.engine.exception.ForwardInvalidException; import io.seata.saga.engine.pcext.StateInstruction; -import io.seata.saga.engine.pcext.interceptors.ServiceTaskHandlerInterceptor; import io.seata.saga.engine.pcext.utils.EngineUtils; +import io.seata.saga.engine.pcext.utils.ParameterUtils; import io.seata.saga.engine.utils.ProcessContextBuilder; import io.seata.saga.proctrl.ProcessContext; import io.seata.saga.proctrl.ProcessType; @@ -350,7 +350,7 @@ public class ProcessCtrlStateMachineEngine implements StateMachineEngine { if (state.getOutput() != null && state.getOutput().size() > 0) { try { - Map<String, Object> outputVariablesToContext = ServiceTaskHandlerInterceptor + Map<String, Object> outputVariablesToContext = ParameterUtils .createOutputParams(stateMachineConfig.getExpressionFactoryManager(), state, serviceOutputParams); if (outputVariablesToContext != null && outputVariablesToContext.size() > 0) { diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptibleStateHandler.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptableStateHandler.java similarity index 86% rename from saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptibleStateHandler.java rename to saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptableStateHandler.java index 8d2ff4c9d92c045e1135a4b381e6d56a41c6ce1c..33c70f20c9a6eaff6e96391fb797cd16cc0a4ecf 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptibleStateHandler.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptableStateHandler.java @@ -22,7 +22,9 @@ import java.util.List; * * @author lorne.cl */ -public interface InterceptibleStateHandler extends StateHandler { +public interface InterceptableStateHandler extends StateHandler { List<StateHandlerInterceptor> getInterceptors(); + + void addInterceptor(StateHandlerInterceptor interceptor); } \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptibleStateRouter.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptableStateRouter.java similarity index 82% rename from saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptibleStateRouter.java rename to saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptableStateRouter.java index 289165d035c98c4ebf7804a0f0d8e999f296f1d7..96d8d4f130b505e6f808c36b5e68e5dd97c5cc32 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptibleStateRouter.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/InterceptableStateRouter.java @@ -18,11 +18,13 @@ package io.seata.saga.engine.pcext; import java.util.List; /** - * Interceptible State Router + * Interceptable State Router * * @author lorne.cl */ -public interface InterceptibleStateRouter extends StateRouter { +public interface InterceptableStateRouter extends StateRouter { List<StateRouterInterceptor> getInterceptors(); + + void addInterceptor(StateRouterInterceptor interceptor); } \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateHandlerInterceptor.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateHandlerInterceptor.java index 00f4fce6ef604276b08bf807551f3fe47f2cd624..8243b4c6be79865f92dc9c55008d7ab1148f42a2 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateHandlerInterceptor.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateHandlerInterceptor.java @@ -28,4 +28,6 @@ public interface StateHandlerInterceptor { void preProcess(ProcessContext context) throws EngineExecutionException; void postProcess(ProcessContext context, Exception e) throws EngineExecutionException; + + boolean match(Class<? extends InterceptableStateHandler> clazz); } \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateMachineProcessHandler.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateMachineProcessHandler.java index f7f383d474797ec1d7de1748aa83949d4779e21c..acc2f1d05059c4bd9b32fed598209c8b4da129d6 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateMachineProcessHandler.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateMachineProcessHandler.java @@ -24,10 +24,10 @@ import io.seata.common.exception.FrameworkException; import io.seata.saga.engine.pcext.handlers.ChoiceStateHandler; import io.seata.saga.engine.pcext.handlers.CompensationTriggerStateHandler; import io.seata.saga.engine.pcext.handlers.FailEndStateHandler; +import io.seata.saga.engine.pcext.handlers.ScriptTaskStateHandler; import io.seata.saga.engine.pcext.handlers.ServiceTaskStateHandler; import io.seata.saga.engine.pcext.handlers.SubStateMachineHandler; import io.seata.saga.engine.pcext.handlers.SucceedEndStateHandler; -import io.seata.saga.engine.pcext.interceptors.ServiceTaskHandlerInterceptor; import io.seata.saga.proctrl.ProcessContext; import io.seata.saga.proctrl.handler.ProcessHandler; import io.seata.saga.statelang.domain.DomainConstants; @@ -52,8 +52,8 @@ public class StateMachineProcessHandler implements ProcessHandler { StateHandler stateHandler = stateHandlers.get(stateType); List<StateHandlerInterceptor> interceptors = null; - if (stateHandler instanceof InterceptibleStateHandler) { - interceptors = ((InterceptibleStateHandler)stateHandler).getInterceptors(); + if (stateHandler instanceof InterceptableStateHandler) { + interceptors = ((InterceptableStateHandler)stateHandler).getInterceptors(); } List<StateHandlerInterceptor> executedInterceptors = null; @@ -87,18 +87,13 @@ public class StateMachineProcessHandler implements ProcessHandler { public void initDefaultHandlers() { if (stateHandlers.size() == 0) { - //ServiceTask - ServiceTaskStateHandler serviceTaskStateHandler = new ServiceTaskStateHandler(); - List<StateHandlerInterceptor> stateHandlerInterceptors = new ArrayList<>(1); - stateHandlerInterceptors.add(new ServiceTaskHandlerInterceptor()); - serviceTaskStateHandler.setInterceptors(stateHandlerInterceptors); - stateHandlers.put(DomainConstants.STATE_TYPE_SERVICE_TASK, serviceTaskStateHandler); + stateHandlers.put(DomainConstants.STATE_TYPE_SERVICE_TASK, new ServiceTaskStateHandler()); - stateHandlers.put(DomainConstants.STATE_TYPE_SUB_MACHINE_COMPENSATION, serviceTaskStateHandler); + stateHandlers.put(DomainConstants.STATE_TYPE_SCRIPT_TASK, new ScriptTaskStateHandler()); - SubStateMachineHandler subStateMachineHandler = new SubStateMachineHandler(); - subStateMachineHandler.setInterceptors(stateHandlerInterceptors); - stateHandlers.put(DomainConstants.STATE_TYPE_SUB_STATE_MACHINE, subStateMachineHandler); + stateHandlers.put(DomainConstants.STATE_TYPE_SUB_MACHINE_COMPENSATION, new ServiceTaskStateHandler()); + + stateHandlers.put(DomainConstants.STATE_TYPE_SUB_STATE_MACHINE, new SubStateMachineHandler()); stateHandlers.put(DomainConstants.STATE_TYPE_CHOICE, new ChoiceStateHandler()); stateHandlers.put(DomainConstants.STATE_TYPE_SUCCEED, new SucceedEndStateHandler()); diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateMachineProcessRouter.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateMachineProcessRouter.java index 7541508e50afe51851cdc6631ae58960eacaf742..d3e68adcc41e7f8ff72032f4ca97bcb3862d87f0 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateMachineProcessRouter.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateMachineProcessRouter.java @@ -22,7 +22,6 @@ import java.util.concurrent.ConcurrentHashMap; import io.seata.common.exception.FrameworkException; import io.seata.saga.engine.StateMachineConfig; -import io.seata.saga.engine.pcext.interceptors.EndStateRouterInterceptor; import io.seata.saga.engine.pcext.routers.EndStateRouter; import io.seata.saga.engine.pcext.routers.TaskStateRouter; import io.seata.saga.engine.pcext.utils.EngineUtils; @@ -67,8 +66,8 @@ public class StateMachineProcessRouter implements ProcessRouter { Instruction instruction = null; List<StateRouterInterceptor> interceptors = null; - if (router instanceof InterceptibleStateRouter) { - interceptors = ((InterceptibleStateRouter)router).getInterceptors(); + if (router instanceof InterceptableStateRouter) { + interceptors = ((InterceptableStateRouter)router).getInterceptors(); } List<StateRouterInterceptor> executedInterceptors = null; @@ -109,18 +108,14 @@ public class StateMachineProcessRouter implements ProcessRouter { if (this.stateRouters.size() == 0) { TaskStateRouter taskStateRouter = new TaskStateRouter(); this.stateRouters.put(DomainConstants.STATE_TYPE_SERVICE_TASK, taskStateRouter); + this.stateRouters.put(DomainConstants.STATE_TYPE_SCRIPT_TASK, taskStateRouter); this.stateRouters.put(DomainConstants.STATE_TYPE_CHOICE, taskStateRouter); this.stateRouters.put(DomainConstants.STATE_TYPE_COMPENSATION_TRIGGER, taskStateRouter); this.stateRouters.put(DomainConstants.STATE_TYPE_SUB_STATE_MACHINE, taskStateRouter); this.stateRouters.put(DomainConstants.STATE_TYPE_SUB_MACHINE_COMPENSATION, taskStateRouter); - EndStateRouter endStateRouter = new EndStateRouter(); - List<StateRouterInterceptor> stateRouterInterceptors = new ArrayList<>(1); - stateRouterInterceptors.add(new EndStateRouterInterceptor()); - endStateRouter.setInterceptors(stateRouterInterceptors); - - this.stateRouters.put(DomainConstants.STATE_TYPE_SUCCEED, endStateRouter); - this.stateRouters.put(DomainConstants.STATE_TYPE_FAIL, endStateRouter); + this.stateRouters.put(DomainConstants.STATE_TYPE_SUCCEED, new EndStateRouter()); + this.stateRouters.put(DomainConstants.STATE_TYPE_FAIL, new EndStateRouter()); } } diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateRouterInterceptor.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateRouterInterceptor.java index 2a829575e98a2da24e76fc895642a6d9f9ffa32c..0a1b205fbe02b3b140dc115aa29482c1e0541153 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateRouterInterceptor.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/StateRouterInterceptor.java @@ -48,4 +48,7 @@ public interface StateRouterInterceptor { */ void postRoute(ProcessContext context, State state, Instruction instruction, Exception e) throws EngineExecutionException; + + + boolean match(Class<? extends InterceptableStateRouter> clazz); } \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/CompensationTriggerStateHandler.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/CompensationTriggerStateHandler.java index bd696714b464c049af2cc8d3d1b174f95504e88e..20d3055e3003bb2af4892354e98828385bb5763f 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/CompensationTriggerStateHandler.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/CompensationTriggerStateHandler.java @@ -60,7 +60,10 @@ public class CompensationTriggerStateHandler implements StateHandler { if (stateListToBeCompensated != null && stateListToBeCompensated.size() > 0) { //Clear exceptions that occur during forward execution - context.removeVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION); + Exception e = (Exception)context.removeVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION); + if (e != null) { + stateMachineInstance.setException(e); + } Stack<StateInstance> stateStackToBeCompensated = CompensationHolder.getCurrent(context, true) .getStateStackNeedCompensation(); diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/ScriptTaskStateHandler.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/ScriptTaskStateHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..087b169abb4fdf92017687cd296a5636dbdc7606 --- /dev/null +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/ScriptTaskStateHandler.java @@ -0,0 +1,164 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.engine.pcext.handlers; + +import io.seata.common.exception.FrameworkErrorCode; +import io.seata.saga.engine.StateMachineConfig; +import io.seata.saga.engine.exception.EngineExecutionException; +import io.seata.saga.engine.pcext.InterceptableStateHandler; +import io.seata.saga.engine.pcext.StateHandler; +import io.seata.saga.engine.pcext.StateHandlerInterceptor; +import io.seata.saga.engine.pcext.StateInstruction; +import io.seata.saga.engine.pcext.utils.EngineUtils; +import io.seata.saga.proctrl.HierarchicalProcessContext; +import io.seata.saga.proctrl.ProcessContext; +import io.seata.saga.statelang.domain.DomainConstants; +import io.seata.saga.statelang.domain.impl.ScriptTaskStateImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.script.Bindings; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.SimpleBindings; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * ScriptTaskState Handler + * + * @author lorne.cl + */ +public class ScriptTaskStateHandler implements StateHandler, InterceptableStateHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(ScriptTaskStateHandler.class); + + private List<StateHandlerInterceptor> interceptors = new ArrayList<>(); + + private volatile Map<String, ScriptEngine> scriptEngineCache = new ConcurrentHashMap<>(); + + @Override + public void process(ProcessContext context) throws EngineExecutionException { + + StateInstruction instruction = context.getInstruction(StateInstruction.class); + ScriptTaskStateImpl state = (ScriptTaskStateImpl) instruction.getState(context); + + String scriptType = state.getScriptType(); + String scriptContent = state.getScriptContent(); + + Object result; + try { + + List<Object> input = (List<Object>) context.getVariable(DomainConstants.VAR_NAME_INPUT_PARAMS); + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(">>>>>>>>>>>>>>>>>>>>>> Start to execute ScriptTaskState[{}], ScriptType[{}], Input:{}", + state.getName(), scriptType, input); + } + + StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable( + DomainConstants.VAR_NAME_STATEMACHINE_CONFIG); + + ScriptEngine scriptEngine = getScriptEngineFromCache(scriptType, stateMachineConfig.getScriptEngineManager()); + if (scriptEngine == null) { + throw new EngineExecutionException("No such ScriptType[" + scriptType + "]", + FrameworkErrorCode.ObjectNotExists); + } + + Bindings bindings = null; + Map<String, Object> inputMap = null; + if (input != null && input.size() > 0 && input.get(0) instanceof Map) { + inputMap = (Map<String, Object>) input.get(0); + } + List<Object> inputExps = state.getInput(); + if (inputExps != null && inputExps.size() > 0 && inputExps.get(0) instanceof Map) { + Map<String, Object> inputExpMap = (Map<String, Object>) inputExps.get(0); + if (inputExpMap.size() > 0) { + bindings = new SimpleBindings(); + for (String property : inputExpMap.keySet()) { + if (inputMap != null && inputMap.containsKey(property)) { + bindings.put(property, inputMap.get(property)); + } + else { + //if we do not bind the null value property, groovy will throw MissingPropertyException + bindings.put(property, null); + } + } + } + } + if (bindings != null) { + result = scriptEngine.eval(scriptContent, bindings); + } + else { + result = scriptEngine.eval(scriptContent); + } + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("<<<<<<<<<<<<<<<<<<<<<< ScriptTaskState[{}], ScriptType[{}], Execute finish. result: {}", + state.getName(), scriptType, result); + } + + if (result != null) { + ((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_OUTPUT_PARAMS, + result); + } + + } catch (Throwable e) { + + LOGGER.error("<<<<<<<<<<<<<<<<<<<<<< ScriptTaskState[{}], ScriptTaskState[{}] Execute failed.", + state.getName(), scriptType, e); + + ((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_CURRENT_EXCEPTION, e); + + EngineUtils.handleException(context, state, e); + } + + } + + protected ScriptEngine getScriptEngineFromCache(String scriptType, ScriptEngineManager scriptEngineManager) { + ScriptEngine scriptEngine = this.scriptEngineCache.get(scriptType); + if (scriptEngine == null) { + synchronized (this.scriptEngineCache) { + scriptEngine = this.scriptEngineCache.get(scriptType); + if (scriptEngine == null) { + scriptEngine = scriptEngineManager.getEngineByName(scriptType); + if (scriptEngine != null) { + this.scriptEngineCache.put(scriptType, scriptEngine); + } + } + } + } + return scriptEngine; + } + + @Override + public List<StateHandlerInterceptor> getInterceptors() { + return interceptors; + } + + @Override + public void addInterceptor(StateHandlerInterceptor interceptor) { + if (interceptors != null && !interceptors.contains(interceptor)) { + interceptors.add(interceptor); + } + } + + public void setInterceptors(List<StateHandlerInterceptor> interceptors) { + this.interceptors = interceptors; + } +} \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/ServiceTaskStateHandler.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/ServiceTaskStateHandler.java index f6cc45112ba684cb5614e4f6c5ef61496adbff58..e47106fee1a52d0cb3a08f9e409ad1a2ba84d621 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/ServiceTaskStateHandler.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/ServiceTaskStateHandler.java @@ -25,10 +25,11 @@ import io.seata.saga.engine.StateMachineConfig; import io.seata.saga.engine.StateMachineEngine; import io.seata.saga.engine.exception.EngineExecutionException; import io.seata.saga.engine.invoker.ServiceInvoker; -import io.seata.saga.engine.pcext.InterceptibleStateHandler; +import io.seata.saga.engine.pcext.InterceptableStateHandler; import io.seata.saga.engine.pcext.StateHandler; import io.seata.saga.engine.pcext.StateHandlerInterceptor; import io.seata.saga.engine.pcext.StateInstruction; +import io.seata.saga.engine.pcext.utils.EngineUtils; import io.seata.saga.proctrl.HierarchicalProcessContext; import io.seata.saga.proctrl.ProcessContext; import io.seata.saga.statelang.domain.CompensateSubStateMachineState; @@ -37,8 +38,6 @@ import io.seata.saga.statelang.domain.ExecutionStatus; import io.seata.saga.statelang.domain.ServiceTaskState; import io.seata.saga.statelang.domain.StateInstance; import io.seata.saga.statelang.domain.StateMachineInstance; -import io.seata.saga.statelang.domain.TaskState; -import io.seata.saga.statelang.domain.impl.AbstractTaskState; import io.seata.saga.statelang.domain.impl.ServiceTaskStateImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,72 +49,11 @@ import org.springframework.util.StringUtils; * * @author lorne.cl */ -public class ServiceTaskStateHandler implements StateHandler, InterceptibleStateHandler { +public class ServiceTaskStateHandler implements StateHandler, InterceptableStateHandler { private static final Logger LOGGER = LoggerFactory.getLogger(ServiceTaskStateHandler.class); - private List<StateHandlerInterceptor> interceptors; - - public static void handleException(ProcessContext context, AbstractTaskState state, Throwable e) { - List<TaskState.ExceptionMatch> catches = state.getCatches(); - if (catches != null && catches.size() > 0) { - for (TaskState.ExceptionMatch exceptionMatch : catches) { - - List<String> exceptions = exceptionMatch.getExceptions(); - List<Class<? extends Exception>> exceptionClasses = exceptionMatch.getExceptionClasses(); - if (exceptions != null && exceptions.size() > 0) { - - if (exceptionClasses == null) { - synchronized (exceptionMatch) { - exceptionClasses = exceptionMatch.getExceptionClasses(); - if (exceptionClasses == null) { - - exceptionClasses = new ArrayList<>(exceptions.size()); - for (String expStr : exceptions) { - - Class<? extends Exception> expClass = null; - try { - expClass = (Class<? extends Exception>) ServiceTaskStateHandler.class - .getClassLoader().loadClass(expStr); - } catch (Exception e1) { - - LOGGER.warn("Cannot Load Exception Class by getClass().getClassLoader()", e1); - - try { - expClass = (Class<? extends Exception>) Thread.currentThread() - .getContextClassLoader().loadClass(expStr); - } catch (Exception e2) { - LOGGER.warn( - "Cannot Load Exception Class by Thread.currentThread()" - + ".getContextClassLoader()", - e2); - } - } - - if (expClass != null) { - exceptionClasses.add(expClass); - } - } - exceptionMatch.setExceptionClasses(exceptionClasses); - } - } - } - - for (Class<? extends Exception> expClass : exceptionClasses) { - if (expClass.isAssignableFrom(e.getClass())) { - ((HierarchicalProcessContext) context).setVariableLocally( - DomainConstants.VAR_NAME_CURRENT_EXCEPTION_ROUTE, exceptionMatch.getNext()); - return; - } - } - - } - } - } - - LOGGER.error("Task execution failed and no catches configured"); - ((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_IS_EXCEPTION_NOT_CATCH, true); - } + private List<StateHandlerInterceptor> interceptors = new ArrayList<>(); @Override public void process(ProcessContext context) throws EngineExecutionException { @@ -181,7 +119,7 @@ public class ServiceTaskStateHandler implements StateHandler, InterceptibleState ((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_CURRENT_EXCEPTION, e); - handleException(context, state, e); + EngineUtils.handleException(context, state, e); } } @@ -239,6 +177,13 @@ public class ServiceTaskStateHandler implements StateHandler, InterceptibleState return interceptors; } + @Override + public void addInterceptor(StateHandlerInterceptor interceptor) { + if (interceptors != null && !interceptors.contains(interceptor)) { + interceptors.add(interceptor); + } + } + public void setInterceptors(List<StateHandlerInterceptor> interceptors) { this.interceptors = interceptors; } diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/SubStateMachineHandler.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/SubStateMachineHandler.java index e508264972c47b09f1b29ec8e073e1c32f062a2e..d87c0d053f81677be5c9d91ab43d21527777f258 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/SubStateMachineHandler.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/handlers/SubStateMachineHandler.java @@ -15,6 +15,7 @@ */ package io.seata.saga.engine.pcext.handlers; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -24,7 +25,7 @@ import io.seata.saga.engine.StateMachineConfig; import io.seata.saga.engine.StateMachineEngine; import io.seata.saga.engine.exception.EngineExecutionException; import io.seata.saga.engine.exception.ForwardInvalidException; -import io.seata.saga.engine.pcext.InterceptibleStateHandler; +import io.seata.saga.engine.pcext.InterceptableStateHandler; import io.seata.saga.engine.pcext.StateHandler; import io.seata.saga.engine.pcext.StateHandlerInterceptor; import io.seata.saga.engine.pcext.StateInstruction; @@ -46,11 +47,11 @@ import org.springframework.util.StringUtils; * * @author lorne.cl */ -public class SubStateMachineHandler implements StateHandler, InterceptibleStateHandler { +public class SubStateMachineHandler implements StateHandler, InterceptableStateHandler { private static final Logger LOGGER = LoggerFactory.getLogger(SubStateMachineHandler.class); - private List<StateHandlerInterceptor> interceptors; + private List<StateHandlerInterceptor> interceptors = new ArrayList<>(); private static ExecutionStatus decideStatus(StateMachineInstance stateMachineInstance, boolean isForward) { @@ -99,7 +100,7 @@ public class SubStateMachineHandler implements StateHandler, InterceptibleStateH stateInstance, subStateMachine); Map<String, Object> outputParams = subStateMachineInstance.getEndParams(); - boolean isForward = DomainConstants.VAR_NAME_OPERATION_NAME.equals( + boolean isForward = DomainConstants.OPERATION_NAME_FORWARD.equals( context.getVariable(DomainConstants.VAR_NAME_OPERATION_NAME)); ExecutionStatus callSubMachineStatus = decideStatus(subStateMachineInstance, isForward); stateInstance.setStatus(callSubMachineStatus); @@ -136,7 +137,7 @@ public class SubStateMachineHandler implements StateHandler, InterceptibleStateH context.setVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION, e); - ServiceTaskStateHandler.handleException(context, subStateMachine, e); + EngineUtils.handleException(context, subStateMachine, e); } } @@ -200,6 +201,13 @@ public class SubStateMachineHandler implements StateHandler, InterceptibleStateH return interceptors; } + @Override + public void addInterceptor(StateHandlerInterceptor interceptor) { + if (interceptors != null && !interceptors.contains(interceptor)) { + interceptors.add(interceptor); + } + } + public void setInterceptors(List<StateHandlerInterceptor> interceptors) { this.interceptors = interceptors; } diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/interceptors/EndStateRouterInterceptor.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/interceptors/EndStateRouterInterceptor.java index b94777bc434b2692a018c341c83d0026f8531bdd..d9b967454ae05a451b3aa321cdae5f0e32c09898 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/interceptors/EndStateRouterInterceptor.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/interceptors/EndStateRouterInterceptor.java @@ -15,8 +15,11 @@ */ package io.seata.saga.engine.pcext.interceptors; +import io.seata.common.loader.LoadLevel; import io.seata.saga.engine.exception.EngineExecutionException; +import io.seata.saga.engine.pcext.InterceptableStateRouter; import io.seata.saga.engine.pcext.StateRouterInterceptor; +import io.seata.saga.engine.pcext.routers.EndStateRouter; import io.seata.saga.engine.pcext.utils.EngineUtils; import io.seata.saga.proctrl.Instruction; import io.seata.saga.proctrl.ProcessContext; @@ -27,6 +30,7 @@ import io.seata.saga.statelang.domain.State; * * @author lorne.cl */ +@LoadLevel(name = "EndState", order = 100) public class EndStateRouterInterceptor implements StateRouterInterceptor { @Override @@ -39,4 +43,9 @@ public class EndStateRouterInterceptor implements StateRouterInterceptor { throws EngineExecutionException { EngineUtils.endStateMachine(context); } + + @Override + public boolean match(Class<? extends InterceptableStateRouter> clazz) { + return clazz != null && EndStateRouter.class.isAssignableFrom(clazz); + } } \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/interceptors/ScriptTaskHandlerInterceptor.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/interceptors/ScriptTaskHandlerInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..fe6e5fdd5b90c192b5465a170d9656a83016a650 --- /dev/null +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/interceptors/ScriptTaskHandlerInterceptor.java @@ -0,0 +1,139 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.engine.pcext.interceptors; + +import io.seata.common.exception.FrameworkErrorCode; +import io.seata.common.loader.LoadLevel; +import io.seata.saga.engine.StateMachineConfig; +import io.seata.saga.engine.exception.EngineExecutionException; +import io.seata.saga.engine.pcext.InterceptableStateHandler; +import io.seata.saga.engine.pcext.StateHandlerInterceptor; +import io.seata.saga.engine.pcext.StateInstruction; +import io.seata.saga.engine.pcext.handlers.ScriptTaskStateHandler; +import io.seata.saga.engine.pcext.utils.EngineUtils; +import io.seata.saga.engine.pcext.utils.ParameterUtils; +import io.seata.saga.engine.utils.ExceptionUtils; +import io.seata.saga.proctrl.HierarchicalProcessContext; +import io.seata.saga.proctrl.ProcessContext; +import io.seata.saga.statelang.domain.DomainConstants; +import io.seata.saga.statelang.domain.StateMachineInstance; +import io.seata.saga.statelang.domain.impl.ScriptTaskStateImpl; + +import java.util.List; +import java.util.Map; + +/** + * StateInterceptor for ScriptTask + * + * @author lorne.cl + */ +@LoadLevel(name = "ScriptTask", order = 100) +public class ScriptTaskHandlerInterceptor implements StateHandlerInterceptor { + + @Override + public boolean match(Class<? extends InterceptableStateHandler> clazz) { + return clazz != null && + ScriptTaskStateHandler.class.isAssignableFrom(clazz); + } + + @Override + public void preProcess(ProcessContext context) throws EngineExecutionException { + + StateInstruction instruction = context.getInstruction(StateInstruction.class); + + StateMachineInstance stateMachineInstance = (StateMachineInstance)context.getVariable( + DomainConstants.VAR_NAME_STATEMACHINE_INST); + StateMachineConfig stateMachineConfig = (StateMachineConfig)context.getVariable( + DomainConstants.VAR_NAME_STATEMACHINE_CONFIG); + + Map<String, Object> contextVariables = (Map<String, Object>)context.getVariable( + DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT); + ScriptTaskStateImpl state = (ScriptTaskStateImpl)instruction.getState(context); + List<Object> serviceInputParams = null; + if (contextVariables != null) { + try { + serviceInputParams = ParameterUtils.createInputParams(stateMachineConfig.getExpressionFactoryManager(), null, + state, contextVariables); + } catch (Exception e) { + + String message = "Task [" + state.getName() + + "] input parameters assign failed, please check 'Input' expression:" + e.getMessage(); + + EngineExecutionException exception = ExceptionUtils.createEngineExecutionException(e, + FrameworkErrorCode.VariablesAssignError, message, stateMachineInstance, state.getName()); + + EngineUtils.failStateMachine(context, exception); + + throw exception; + } + } + + ((HierarchicalProcessContext)context).setVariableLocally(DomainConstants.VAR_NAME_INPUT_PARAMS, + serviceInputParams); + } + + @Override + public void postProcess(ProcessContext context, Exception exp) throws EngineExecutionException { + + StateInstruction instruction = context.getInstruction(StateInstruction.class); + ScriptTaskStateImpl state = (ScriptTaskStateImpl)instruction.getState(context); + + StateMachineInstance stateMachineInstance = (StateMachineInstance)context.getVariable( + DomainConstants.VAR_NAME_STATEMACHINE_INST); + + StateMachineConfig stateMachineConfig = (StateMachineConfig)context.getVariable( + DomainConstants.VAR_NAME_STATEMACHINE_CONFIG); + + if (exp == null) { + exp = (Exception)context.getVariable(DomainConstants.VAR_NAME_CURRENT_EXCEPTION); + } + + Map<String, Object> contextVariables = (Map<String, Object>)context.getVariable( + DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT); + Object serviceOutputParams = context.getVariable(DomainConstants.VAR_NAME_OUTPUT_PARAMS); + if (serviceOutputParams != null) { + try { + Map<String, Object> outputVariablesToContext = ParameterUtils.createOutputParams( + stateMachineConfig.getExpressionFactoryManager(), state, serviceOutputParams); + if (outputVariablesToContext != null && outputVariablesToContext.size() > 0) { + contextVariables.putAll(outputVariablesToContext); + } + } catch (Exception e) { + String message = "Task [" + state.getName() + + "] output parameters assign failed, please check 'Output' expression:" + e.getMessage(); + + EngineExecutionException exception = ExceptionUtils.createEngineExecutionException(e, + FrameworkErrorCode.VariablesAssignError, message, stateMachineInstance, state.getName()); + + EngineUtils.failStateMachine(context, exception); + + throw exception; + } + } + + context.removeVariable(DomainConstants.VAR_NAME_OUTPUT_PARAMS); + context.removeVariable(DomainConstants.VAR_NAME_INPUT_PARAMS); + + if (exp != null && context.getVariable(DomainConstants.VAR_NAME_IS_EXCEPTION_NOT_CATCH) != null + && (Boolean)context.getVariable(DomainConstants.VAR_NAME_IS_EXCEPTION_NOT_CATCH)) { + //If there is an exception and there is no catch, need to exit the state machine to execute. + + context.removeVariable(DomainConstants.VAR_NAME_IS_EXCEPTION_NOT_CATCH); + EngineUtils.failStateMachine(context, exp); + } + + } +} diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/interceptors/ServiceTaskHandlerInterceptor.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/interceptors/ServiceTaskHandlerInterceptor.java index 66c331794534940fc5bf21e9dcb9009288504a0a..52e1107c65309d6ae97b7c1678a1dd66783a8533 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/interceptors/ServiceTaskHandlerInterceptor.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/interceptors/ServiceTaskHandlerInterceptor.java @@ -15,27 +15,27 @@ */ package io.seata.saga.engine.pcext.interceptors; -import java.util.ArrayList; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import io.seata.common.exception.FrameworkErrorCode; +import io.seata.common.loader.LoadLevel; import io.seata.saga.engine.StateMachineConfig; import io.seata.saga.engine.evaluation.Evaluator; import io.seata.saga.engine.evaluation.EvaluatorFactory; import io.seata.saga.engine.evaluation.EvaluatorFactoryManager; import io.seata.saga.engine.evaluation.expression.ExpressionEvaluator; import io.seata.saga.engine.exception.EngineExecutionException; -import io.seata.saga.engine.expression.Expression; -import io.seata.saga.engine.expression.ExpressionFactory; -import io.seata.saga.engine.expression.ExpressionFactoryManager; -import io.seata.saga.engine.expression.seq.SequenceExpression; +import io.seata.saga.engine.pcext.InterceptableStateHandler; import io.seata.saga.engine.pcext.StateHandlerInterceptor; import io.seata.saga.engine.pcext.StateInstruction; +import io.seata.saga.engine.pcext.handlers.ServiceTaskStateHandler; +import io.seata.saga.engine.pcext.handlers.SubStateMachineHandler; import io.seata.saga.engine.pcext.utils.CompensationHolder; import io.seata.saga.engine.pcext.utils.EngineUtils; +import io.seata.saga.engine.pcext.utils.ParameterUtils; import io.seata.saga.engine.utils.ExceptionUtils; import io.seata.saga.proctrl.HierarchicalProcessContext; import io.seata.saga.proctrl.ProcessContext; @@ -50,152 +50,20 @@ import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; /** - * ServiceTaskHandler Interceptor + * StateInterceptor for ServiceTask, SubStateMachine, CompensateState * * @author lorne.cl */ +@LoadLevel(name = "ServiceTask", order = 100) public class ServiceTaskHandlerInterceptor implements StateHandlerInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(ServiceTaskHandlerInterceptor.class); - private static List<Object> createInputParams(ExpressionFactoryManager expressionFactoryManager, - StateInstanceImpl stateInstance, - ServiceTaskStateImpl serviceTaskState, Object variablesFrom) { - - List<Object> inputAssignments = serviceTaskState.getInput(); - if (inputAssignments == null || inputAssignments.size() == 0) { - return new ArrayList<>(0); - } - - List<Object> inputExpressions = serviceTaskState.getInputExpressions(); - if (inputExpressions == null) { - synchronized (serviceTaskState) { - inputExpressions = serviceTaskState.getInputExpressions(); - if (inputExpressions == null) { - inputExpressions = new ArrayList<>(inputAssignments.size()); - for (Object inputAssignment : inputAssignments) { - inputExpressions.add(createValueExpression(expressionFactoryManager, inputAssignment)); - } - } - serviceTaskState.setInputExpressions(inputExpressions); - } - } - List<Object> inputValues = new ArrayList<>(inputExpressions.size()); - for (Object valueExpression : inputExpressions) { - Object value = getValue(valueExpression, variablesFrom, stateInstance); - inputValues.add(value); - } - - return inputValues; - } - - public static Map<String, Object> createOutputParams(ExpressionFactoryManager expressionFactoryManager, - ServiceTaskStateImpl serviceTaskState, Object variablesFrom) { - - Map<String, Object> outputAssignments = serviceTaskState.getOutput(); - if (outputAssignments == null || outputAssignments.size() == 0) { - return new LinkedHashMap<>(0); - } - - Map<String, Object> outputExpressions = serviceTaskState.getOutputExpressions(); - if (outputExpressions == null) { - synchronized (serviceTaskState) { - outputExpressions = serviceTaskState.getOutputExpressions(); - if (outputExpressions == null) { - outputExpressions = new LinkedHashMap<>(outputAssignments.size()); - for (String paramName : outputAssignments.keySet()) { - outputExpressions.put(paramName, - createValueExpression(expressionFactoryManager, outputAssignments.get(paramName))); - } - } - serviceTaskState.setOutputExpressions(outputExpressions); - } - } - Map<String, Object> outputValues = new LinkedHashMap<>(outputExpressions.size()); - for (String paramName : outputExpressions.keySet()) { - outputValues.put(paramName, getValue(outputExpressions.get(paramName), variablesFrom, null)); - } - return outputValues; - } - - private static Object getValue(Object valueExpression, Object variablesFrom, StateInstance stateInstance) { - if (valueExpression instanceof Expression) { - Object value = ((Expression)valueExpression).getValue(variablesFrom); - if (value != null && stateInstance != null && StringUtils.isEmpty(stateInstance.getBusinessKey()) - && valueExpression instanceof SequenceExpression) { - stateInstance.setBusinessKey(String.valueOf(value)); - } - return value; - } else if (valueExpression instanceof Map) { - Map<String, Object> mapValueExpression = (Map<String, Object>)valueExpression; - Map<String, Object> mapValue = new LinkedHashMap<>(); - for (String paramName : mapValueExpression.keySet()) { - Object value = getValue(mapValueExpression.get(paramName), variablesFrom, stateInstance); - if (value != null) { - mapValue.put(paramName, value); - } - } - return mapValue; - } else if (valueExpression instanceof List) { - List<Object> listValueExpression = (List<Object>)valueExpression; - List<Object> listValue = new ArrayList<>(listValueExpression.size()); - for (Object aValueExpression : listValueExpression) { - listValue.add(getValue(aValueExpression, variablesFrom, stateInstance)); - } - return listValue; - } else { - return valueExpression; - } - } - - private static Object createValueExpression(ExpressionFactoryManager expressionFactoryManager, - Object paramAssignment) { - - Object valueExpression; - - if (paramAssignment instanceof Expression) { - valueExpression = paramAssignment; - } else if (paramAssignment instanceof Map) { - Map<String, Object> paramMapAssignment = (Map<String, Object>)paramAssignment; - Map<String, Object> paramMap = new LinkedHashMap<>(paramMapAssignment.size()); - for (String paramName : paramMapAssignment.keySet()) { - Object valueAssignment = paramMapAssignment.get(paramName); - paramMap.put(paramName, createValueExpression(expressionFactoryManager, valueAssignment)); - } - valueExpression = paramMap; - } else if (paramAssignment instanceof List) { - List<Object> paramListAssignment = (List<Object>)paramAssignment; - List<Object> paramList = new ArrayList<>(paramListAssignment.size()); - for (Object aParamAssignment : paramListAssignment) { - paramList.add(createValueExpression(expressionFactoryManager, aParamAssignment)); - } - valueExpression = paramList; - } else if (paramAssignment instanceof String && ((String)paramAssignment).startsWith("$")) { - - String expressionStr = (String)paramAssignment; - int expTypeStart = expressionStr.indexOf("$"); - int expTypeEnd = expressionStr.indexOf(".", expTypeStart); - - String expressionType = null; - if (expTypeStart >= 0 && expTypeEnd > expTypeStart) { - expressionType = expressionStr.substring(expTypeStart + 1, expTypeEnd); - } - - int expEnd = expressionStr.length(); - String expressionContent = null; - if (expTypeEnd > 0 && expEnd > expTypeEnd) { - expressionContent = expressionStr.substring(expTypeEnd + 1, expEnd); - } - - ExpressionFactory expressionFactory = expressionFactoryManager.getExpressionFactory(expressionType); - if (expressionFactory == null) { - throw new IllegalArgumentException("Cannot get ExpressionFactory by Type[" + expressionType + "]"); - } - valueExpression = expressionFactory.createExpression(expressionContent); - } else { - valueExpression = paramAssignment; - } - return valueExpression; + @Override + public boolean match(Class<? extends InterceptableStateHandler> clazz) { + return clazz != null && + (ServiceTaskStateHandler.class.isAssignableFrom(clazz) + || SubStateMachineHandler.class.isAssignableFrom(clazz)); } @Override @@ -230,12 +98,12 @@ public class ServiceTaskHandlerInterceptor implements StateHandlerInterceptor { List<Object> serviceInputParams = null; if (contextVariables != null) { try { - serviceInputParams = createInputParams(stateMachineConfig.getExpressionFactoryManager(), stateInstance, + serviceInputParams = ParameterUtils.createInputParams(stateMachineConfig.getExpressionFactoryManager(), stateInstance, state, contextVariables); } catch (Exception e) { String message = "Task [" + state.getName() - + "] input parameters assign failed, please check from/to expression:" + e.getMessage(); + + "] input parameters assign failed, please check 'Input' expression:" + e.getMessage(); EngineExecutionException exception = ExceptionUtils.createEngineExecutionException(e, FrameworkErrorCode.VariablesAssignError, message, stateMachineInstance, state.getName()); @@ -371,14 +239,14 @@ public class ServiceTaskHandlerInterceptor implements StateHandlerInterceptor { Object serviceOutputParams = context.getVariable(DomainConstants.VAR_NAME_OUTPUT_PARAMS); if (serviceOutputParams != null) { try { - Map<String, Object> outputVariablesToContext = createOutputParams( + Map<String, Object> outputVariablesToContext = ParameterUtils.createOutputParams( stateMachineConfig.getExpressionFactoryManager(), state, serviceOutputParams); if (outputVariablesToContext != null && outputVariablesToContext.size() > 0) { contextVariables.putAll(outputVariablesToContext); } } catch (Exception e) { String message = "Task [" + state.getName() - + "] output parameters assign failed, please check from/to expression:" + e.getMessage(); + + "] output parameters assign failed, please check 'Output' expression:" + e.getMessage(); EngineExecutionException exception = ExceptionUtils.createEngineExecutionException(e, FrameworkErrorCode.VariablesAssignError, message, stateMachineInstance, stateInstance); diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/routers/EndStateRouter.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/routers/EndStateRouter.java index fdf8d3824638d666d4d5b6f371fc72d91282e1e0..a3b8c2cafe2d18d85e46c29dc8d9173374abbafd 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/routers/EndStateRouter.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/routers/EndStateRouter.java @@ -15,10 +15,11 @@ */ package io.seata.saga.engine.pcext.routers; +import java.util.ArrayList; import java.util.List; import io.seata.saga.engine.exception.EngineExecutionException; -import io.seata.saga.engine.pcext.InterceptibleStateRouter; +import io.seata.saga.engine.pcext.InterceptableStateRouter; import io.seata.saga.engine.pcext.StateRouter; import io.seata.saga.engine.pcext.StateRouterInterceptor; import io.seata.saga.proctrl.Instruction; @@ -30,9 +31,9 @@ import io.seata.saga.statelang.domain.State; * * @author lorne.cl */ -public class EndStateRouter implements StateRouter, InterceptibleStateRouter { +public class EndStateRouter implements StateRouter, InterceptableStateRouter { - private List<StateRouterInterceptor> interceptors; + private List<StateRouterInterceptor> interceptors = new ArrayList<>(); @Override public Instruction route(ProcessContext context, State state) throws EngineExecutionException { @@ -44,6 +45,13 @@ public class EndStateRouter implements StateRouter, InterceptibleStateRouter { return interceptors; } + @Override + public void addInterceptor(StateRouterInterceptor interceptor) { + if (interceptors != null && !interceptors.contains(interceptor)) { + interceptors.add(interceptor); + } + } + public void setInterceptors(List<StateRouterInterceptor> interceptors) { this.interceptors = interceptors; } diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/utils/EngineUtils.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/utils/EngineUtils.java index c6b6050264887316c3c35d68e636466ca88f3721..6e5c19aa302d48c840a210aea7c9ad836edbb692 100644 --- a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/utils/EngineUtils.java +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/utils/EngineUtils.java @@ -15,17 +15,24 @@ */ package io.seata.saga.engine.pcext.utils; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import java.util.Map; import io.seata.saga.engine.AsyncCallback; import io.seata.saga.engine.StateMachineConfig; import io.seata.saga.engine.pcext.StateInstruction; +import io.seata.saga.engine.pcext.handlers.ScriptTaskStateHandler; import io.seata.saga.engine.utils.ExceptionUtils; +import io.seata.saga.proctrl.HierarchicalProcessContext; import io.seata.saga.proctrl.ProcessContext; import io.seata.saga.statelang.domain.DomainConstants; import io.seata.saga.statelang.domain.StateInstance; import io.seata.saga.statelang.domain.StateMachineInstance; +import io.seata.saga.statelang.domain.TaskState; +import io.seata.saga.statelang.domain.TaskState.ExceptionMatch; +import io.seata.saga.statelang.domain.impl.AbstractTaskState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -142,4 +149,72 @@ public class EngineUtils { } return System.currentTimeMillis() - gmtUpdated.getTime() > timeoutMillis; } + + /** + * Handle exceptions while ServiceTask or ScriptTask Executing + * + * @param context + * @param state + * @param e + */ + public static void handleException(ProcessContext context, AbstractTaskState state, Throwable e) { + List<ExceptionMatch> catches = state.getCatches(); + if (catches != null && catches.size() > 0) { + for (TaskState.ExceptionMatch exceptionMatch : catches) { + + List<String> exceptions = exceptionMatch.getExceptions(); + List<Class<? extends Exception>> exceptionClasses = exceptionMatch.getExceptionClasses(); + if (exceptions != null && exceptions.size() > 0) { + + if (exceptionClasses == null) { + synchronized (exceptionMatch) { + exceptionClasses = exceptionMatch.getExceptionClasses(); + if (exceptionClasses == null) { + + exceptionClasses = new ArrayList<>(exceptions.size()); + for (String expStr : exceptions) { + + Class<? extends Exception> expClass = null; + try { + expClass = (Class<? extends Exception>) ScriptTaskStateHandler.class + .getClassLoader().loadClass(expStr); + } catch (Exception e1) { + + LOGGER.warn("Cannot Load Exception Class by getClass().getClassLoader()", e1); + + try { + expClass = (Class<? extends Exception>) Thread.currentThread() + .getContextClassLoader().loadClass(expStr); + } catch (Exception e2) { + LOGGER.warn( + "Cannot Load Exception Class by Thread.currentThread()" + + ".getContextClassLoader()", + e2); + } + } + + if (expClass != null) { + exceptionClasses.add(expClass); + } + } + exceptionMatch.setExceptionClasses(exceptionClasses); + } + } + } + + for (Class<? extends Exception> expClass : exceptionClasses) { + if (expClass.isAssignableFrom(e.getClass())) { + ((HierarchicalProcessContext) context).setVariableLocally( + DomainConstants.VAR_NAME_CURRENT_EXCEPTION_ROUTE, exceptionMatch.getNext()); + return; + } + } + + } + } + } + + LOGGER.error("Task execution failed and no catches configured"); + ((HierarchicalProcessContext) context).setVariableLocally(DomainConstants.VAR_NAME_IS_EXCEPTION_NOT_CATCH, true); + } } \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/utils/ParameterUtils.java b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/utils/ParameterUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..b7a586dc2efcf2c093f647c0088240ba179c3fd9 --- /dev/null +++ b/saga/seata-saga-engine/src/main/java/io/seata/saga/engine/pcext/utils/ParameterUtils.java @@ -0,0 +1,179 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.engine.pcext.utils; + +import io.seata.saga.engine.expression.Expression; +import io.seata.saga.engine.expression.ExpressionFactory; +import io.seata.saga.engine.expression.ExpressionFactoryManager; +import io.seata.saga.engine.expression.seq.SequenceExpression; +import io.seata.saga.statelang.domain.StateInstance; +import io.seata.saga.statelang.domain.impl.AbstractTaskState; +import io.seata.saga.statelang.domain.impl.StateInstanceImpl; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * + * ParameterUtils + * + * @author lorne.cl + */ +public class ParameterUtils { + + public static List<Object> createInputParams(ExpressionFactoryManager expressionFactoryManager, + StateInstanceImpl stateInstance, + AbstractTaskState serviceTaskState, Object variablesFrom) { + + List<Object> inputAssignments = serviceTaskState.getInput(); + if (inputAssignments == null || inputAssignments.size() == 0) { + return new ArrayList<>(0); + } + + List<Object> inputExpressions = serviceTaskState.getInputExpressions(); + if (inputExpressions == null) { + synchronized (serviceTaskState) { + inputExpressions = serviceTaskState.getInputExpressions(); + if (inputExpressions == null) { + inputExpressions = new ArrayList<>(inputAssignments.size()); + for (Object inputAssignment : inputAssignments) { + inputExpressions.add(createValueExpression(expressionFactoryManager, inputAssignment)); + } + } + serviceTaskState.setInputExpressions(inputExpressions); + } + } + List<Object> inputValues = new ArrayList<>(inputExpressions.size()); + for (Object valueExpression : inputExpressions) { + Object value = getValue(valueExpression, variablesFrom, stateInstance); + inputValues.add(value); + } + + return inputValues; + } + + public static Map<String, Object> createOutputParams(ExpressionFactoryManager expressionFactoryManager, + AbstractTaskState serviceTaskState, Object variablesFrom) { + + Map<String, Object> outputAssignments = serviceTaskState.getOutput(); + if (outputAssignments == null || outputAssignments.size() == 0) { + return new LinkedHashMap<>(0); + } + + Map<String, Object> outputExpressions = serviceTaskState.getOutputExpressions(); + if (outputExpressions == null) { + synchronized (serviceTaskState) { + outputExpressions = serviceTaskState.getOutputExpressions(); + if (outputExpressions == null) { + outputExpressions = new LinkedHashMap<>(outputAssignments.size()); + for (String paramName : outputAssignments.keySet()) { + outputExpressions.put(paramName, + createValueExpression(expressionFactoryManager, outputAssignments.get(paramName))); + } + } + serviceTaskState.setOutputExpressions(outputExpressions); + } + } + Map<String, Object> outputValues = new LinkedHashMap<>(outputExpressions.size()); + for (String paramName : outputExpressions.keySet()) { + outputValues.put(paramName, getValue(outputExpressions.get(paramName), variablesFrom, null)); + } + return outputValues; + } + + public static Object getValue(Object valueExpression, Object variablesFrom, StateInstance stateInstance) { + if (valueExpression instanceof Expression) { + Object value = ((Expression)valueExpression).getValue(variablesFrom); + if (value != null && stateInstance != null && StringUtils.isEmpty(stateInstance.getBusinessKey()) + && valueExpression instanceof SequenceExpression) { + stateInstance.setBusinessKey(String.valueOf(value)); + } + return value; + } else if (valueExpression instanceof Map) { + Map<String, Object> mapValueExpression = (Map<String, Object>)valueExpression; + Map<String, Object> mapValue = new LinkedHashMap<>(); + for (String paramName : mapValueExpression.keySet()) { + Object value = getValue(mapValueExpression.get(paramName), variablesFrom, stateInstance); + if (value != null) { + mapValue.put(paramName, value); + } + } + return mapValue; + } else if (valueExpression instanceof List) { + List<Object> listValueExpression = (List<Object>)valueExpression; + List<Object> listValue = new ArrayList<>(listValueExpression.size()); + for (Object aValueExpression : listValueExpression) { + listValue.add(getValue(aValueExpression, variablesFrom, stateInstance)); + } + return listValue; + } else { + return valueExpression; + } + } + + public static Object createValueExpression(ExpressionFactoryManager expressionFactoryManager, + Object paramAssignment) { + + Object valueExpression; + + if (paramAssignment instanceof Expression) { + valueExpression = paramAssignment; + } else if (paramAssignment instanceof Map) { + Map<String, Object> paramMapAssignment = (Map<String, Object>)paramAssignment; + Map<String, Object> paramMap = new LinkedHashMap<>(paramMapAssignment.size()); + for (String paramName : paramMapAssignment.keySet()) { + Object valueAssignment = paramMapAssignment.get(paramName); + paramMap.put(paramName, createValueExpression(expressionFactoryManager, valueAssignment)); + } + valueExpression = paramMap; + } else if (paramAssignment instanceof List) { + List<Object> paramListAssignment = (List<Object>)paramAssignment; + List<Object> paramList = new ArrayList<>(paramListAssignment.size()); + for (Object aParamAssignment : paramListAssignment) { + paramList.add(createValueExpression(expressionFactoryManager, aParamAssignment)); + } + valueExpression = paramList; + } else if (paramAssignment instanceof String && ((String)paramAssignment).startsWith("$")) { + + String expressionStr = (String)paramAssignment; + int expTypeStart = expressionStr.indexOf("$"); + int expTypeEnd = expressionStr.indexOf(".", expTypeStart); + + String expressionType = null; + if (expTypeStart >= 0 && expTypeEnd > expTypeStart) { + expressionType = expressionStr.substring(expTypeStart + 1, expTypeEnd); + } + + int expEnd = expressionStr.length(); + String expressionContent = null; + if (expTypeEnd > 0 && expEnd > expTypeEnd) { + expressionContent = expressionStr.substring(expTypeEnd + 1, expEnd); + } + + ExpressionFactory expressionFactory = expressionFactoryManager.getExpressionFactory(expressionType); + if (expressionFactory == null) { + throw new IllegalArgumentException("Cannot get ExpressionFactory by Type[" + expressionType + "]"); + } + valueExpression = expressionFactory.createExpression(expressionContent); + } else { + valueExpression = paramAssignment; + } + return valueExpression; + } +} \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/resources/META-INF/services/io.seata.saga.engine.pcext.StateHandlerInterceptor b/saga/seata-saga-engine/src/main/resources/META-INF/services/io.seata.saga.engine.pcext.StateHandlerInterceptor new file mode 100644 index 0000000000000000000000000000000000000000..f55c75b9589d2c6327779e27aaf1c978f1d3b082 --- /dev/null +++ b/saga/seata-saga-engine/src/main/resources/META-INF/services/io.seata.saga.engine.pcext.StateHandlerInterceptor @@ -0,0 +1,2 @@ +io.seata.saga.engine.pcext.interceptors.ServiceTaskHandlerInterceptor +io.seata.saga.engine.pcext.interceptors.ScriptTaskHandlerInterceptor \ No newline at end of file diff --git a/saga/seata-saga-engine/src/main/resources/META-INF/services/io.seata.saga.engine.pcext.StateRouterInterceptor b/saga/seata-saga-engine/src/main/resources/META-INF/services/io.seata.saga.engine.pcext.StateRouterInterceptor new file mode 100644 index 0000000000000000000000000000000000000000..7085ba797313e4a64f892d00186ea7a6ad8b4f37 --- /dev/null +++ b/saga/seata-saga-engine/src/main/resources/META-INF/services/io.seata.saga.engine.pcext.StateRouterInterceptor @@ -0,0 +1 @@ +io.seata.saga.engine.pcext.interceptors.EndStateRouterInterceptor \ No newline at end of file diff --git a/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/HierarchicalProcessContext.java b/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/HierarchicalProcessContext.java index e768dfb8816ff96a2c51f5eb2fd90cbd73f7ad2d..bb21fa36cb6a1b8f9ae73fdbf5df64b1934e726a 100644 --- a/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/HierarchicalProcessContext.java +++ b/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/HierarchicalProcessContext.java @@ -66,8 +66,9 @@ public interface HierarchicalProcessContext extends ProcessContext { * Remove variable locally. * * @param name the name + * @return the removed variable or null */ - void removeVariableLocally(String name); + Object removeVariableLocally(String name); /** * Clear locally. diff --git a/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/ProcessContext.java b/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/ProcessContext.java index 118f8d20598e44c364aff6e97af9c129bb0bb2fe..48e98869041f6b01800abc9585706bbe9118d559 100644 --- a/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/ProcessContext.java +++ b/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/ProcessContext.java @@ -61,8 +61,9 @@ public interface ProcessContext { * Remove variable. * * @param name the name + * @return the removed variable or null */ - void removeVariable(String name); + Object removeVariable(String name); /** * Has variable boolean. diff --git a/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/handler/DefaultRouterHandler.java b/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/handler/DefaultRouterHandler.java index 5df3fad9af7e35b5b21a2fd07183d96d5ed24060..793f6ca29d9230880c9053d26fe7fe16b9c227c4 100644 --- a/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/handler/DefaultRouterHandler.java +++ b/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/handler/DefaultRouterHandler.java @@ -68,7 +68,7 @@ public class DefaultRouterHandler implements RouterHandler { Instruction instruction = processRouter.route(context); if (instruction == null) { - LOGGER.warn("route instruction is null, process end"); + LOGGER.info("route instruction is null, process end"); } else { context.setInstruction(instruction); diff --git a/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/impl/ProcessContextImpl.java b/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/impl/ProcessContextImpl.java index 2952737b0e76204e145735a2a73547c751732b3d..a2fe419e91340e8234c28f8911df9e57e99af7e3 100644 --- a/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/impl/ProcessContextImpl.java +++ b/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/impl/ProcessContextImpl.java @@ -137,21 +137,21 @@ public class ProcessContextImpl implements HierarchicalProcessContext, ProcessCo } @Override - public void removeVariable(String name) { + public Object removeVariable(String name) { if (variables.containsKey(name)) { - variables.remove(name); - return; + return variables.remove(name); } if (parent != null) { - parent.removeVariable(name); - return; + return parent.removeVariable(name); } + + return null; } @Override - public void removeVariableLocally(String name) { - variables.remove(name); + public Object removeVariableLocally(String name) { + return variables.remove(name); } @Override diff --git a/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/process/impl/CustomizeBusinessProcessor.java b/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/process/impl/CustomizeBusinessProcessor.java index 1362fe147a977b3b72ede6513adb84d047c11951..26b4b57a02a42d43199760cc0499f5aa9a5e852e 100644 --- a/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/process/impl/CustomizeBusinessProcessor.java +++ b/saga/seata-saga-processctrl/src/main/java/io/seata/saga/proctrl/process/impl/CustomizeBusinessProcessor.java @@ -23,7 +23,6 @@ import io.seata.saga.proctrl.ProcessContext; import io.seata.saga.proctrl.ProcessType; import io.seata.saga.proctrl.handler.ProcessHandler; import io.seata.saga.proctrl.handler.RouterHandler; -import io.seata.saga.proctrl.impl.ProcessControllerImpl; import io.seata.saga.proctrl.process.BusinessProcessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,7 +35,7 @@ import org.slf4j.LoggerFactory; */ public class CustomizeBusinessProcessor implements BusinessProcessor { - private static final Logger LOGGER = LoggerFactory.getLogger(ProcessControllerImpl.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CustomizeBusinessProcessor.class); private Map<String, ProcessHandler> processHandlers; diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/DomainConstants.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/DomainConstants.java index 05f368712ad24877c342382a15443f3c7ed4ccb3..85e4967233d9fe42aed6c7b61ae18d2a3ba4bcd7 100644 --- a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/DomainConstants.java +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/DomainConstants.java @@ -32,6 +32,7 @@ public class DomainConstants { public static final String STATE_TYPE_COMPENSATION_TRIGGER = "CompensationTrigger"; public static final String STATE_TYPE_SUB_STATE_MACHINE = "SubStateMachine"; public static final String STATE_TYPE_SUB_MACHINE_COMPENSATION = "CompensateSubMachine"; + public static final String STATE_TYPE_SCRIPT_TASK = "ScriptTask"; /** * State Types **/ @@ -89,4 +90,6 @@ public class DomainConstants { public static final String SEPERATOR_PARENT_ID = ":"; + public static final String DEFAULT_JSON_PARSER = "fastjson"; + } \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/ScriptTaskState.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/ScriptTaskState.java new file mode 100644 index 0000000000000000000000000000000000000000..8cac732ac2c664e71907868e43cc1909cb86038a --- /dev/null +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/ScriptTaskState.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.statelang.domain; + +/** + * ScriptTask State, execute scripts + * + * @author lorne.cl + */ +public interface ScriptTaskState extends TaskState { + + /** + * get ScriptType such as groovy + * + * @return + */ + String getScriptType(); + + /** + * get ScriptContent + * + * @return + */ + String getScriptContent(); +} \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/impl/AbstractTaskState.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/impl/AbstractTaskState.java index 6bdb056e08bea80251f8aace26568fe0d8f164e5..487eed9841780c32872aad009a115dfff94c6cbb 100644 --- a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/impl/AbstractTaskState.java +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/impl/AbstractTaskState.java @@ -36,6 +36,8 @@ public abstract class AbstractTaskState extends BaseState implements TaskState { private List<Object> input; private Map<String, Object> output; private Map<String, String> status;//Map<String/* expression */, String /* status */> + private List<Object> inputExpressions; + private Map<String, Object> outputExpressions; private boolean isPersist = true; @Override @@ -111,6 +113,23 @@ public abstract class AbstractTaskState extends BaseState implements TaskState { isPersist = persist; } + public List<Object> getInputExpressions() { + return inputExpressions; + } + + public void setInputExpressions(List<Object> inputExpressions) { + this.inputExpressions = inputExpressions; + } + + public Map<String, Object> getOutputExpressions() { + return outputExpressions; + } + + public void setOutputExpressions(Map<String, Object> outputExpressions) { + this.outputExpressions = outputExpressions; + } + + @Override public Map<String, String> getStatus() { return status; diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/impl/ScriptTaskStateImpl.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/impl/ScriptTaskStateImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..99a395acbbd34a6f3e8d55e19d63465cb3f0b94f --- /dev/null +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/impl/ScriptTaskStateImpl.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.statelang.domain.impl; + +import io.seata.saga.statelang.domain.DomainConstants; +import io.seata.saga.statelang.domain.ScriptTaskState; + +/** + * A state used to execute script such as groovy + * + * @author lorne.cl + */ +public class ScriptTaskStateImpl extends AbstractTaskState implements ScriptTaskState { + + private static final String DEFAULT_SCRIPT_TYPE = "groovy"; + + private String scriptType = DEFAULT_SCRIPT_TYPE; + + private String scriptContent; + + public ScriptTaskStateImpl() { + setType(DomainConstants.STATE_TYPE_SCRIPT_TASK); + } + + @Override + public String getScriptType() { + return this.scriptType; + } + + @Override + public String getScriptContent() { + return this.scriptContent; + } + + public void setScriptType(String scriptType) { + this.scriptType = scriptType; + } + + public void setScriptContent(String scriptContent) { + this.scriptContent = scriptContent; + } +} \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/impl/ServiceTaskStateImpl.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/impl/ServiceTaskStateImpl.java index 856142163298bf1e7cc57371bf84e92b2df8c2a2..b012487de464cf45a2f0141772457ca6f97d0ed6 100644 --- a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/impl/ServiceTaskStateImpl.java +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/domain/impl/ServiceTaskStateImpl.java @@ -34,8 +34,6 @@ public class ServiceTaskStateImpl extends AbstractTaskState implements ServiceTa private String serviceMethod; private List<String> parameterTypes; private Method method; - private List<Object> inputExpressions; - private Map<String, Object> outputExpressions; private Map<Object, String> statusEvaluators; private boolean isAsync; @@ -87,22 +85,6 @@ public class ServiceTaskStateImpl extends AbstractTaskState implements ServiceTa this.method = method; } - public List<Object> getInputExpressions() { - return inputExpressions; - } - - public void setInputExpressions(List<Object> inputExpressions) { - this.inputExpressions = inputExpressions; - } - - public Map<String, Object> getOutputExpressions() { - return outputExpressions; - } - - public void setOutputExpressions(Map<String, Object> outputExpressions) { - this.outputExpressions = outputExpressions; - } - public Map<Object, String> getStatusEvaluators() { return statusEvaluators; } diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/JsonParser.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/JsonParser.java new file mode 100644 index 0000000000000000000000000000000000000000..37fef5c258e41174d2b9944a19090781d7f74e7b --- /dev/null +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/JsonParser.java @@ -0,0 +1,51 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.statelang.parser; + +/** + * + * Json Parser + * + * @author lorne.cl + */ +public interface JsonParser { + + /** + * get Name + * + * @return + */ + String getName(); + + /** + * Object to Json string + * + * @param o + * @param prettyPrint + * @return + */ + String toJsonString(Object o, boolean prettyPrint); + + /** + * parse json string to Object + * + * @param json + * @param type + * @param <T> + * @return + */ + <T> T parse(String json, Class<T> type, boolean ignoreAutoType); +} \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/JsonParserFactory.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/JsonParserFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..00183119bff5d76cebd836129ab36943a52c378a --- /dev/null +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/JsonParserFactory.java @@ -0,0 +1,54 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.statelang.parser; + +import io.seata.common.loader.EnhancedServiceLoader; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * JsonParserFactory + * + * @author lorne.cl + */ +public class JsonParserFactory { + + private JsonParserFactory() { + } + + private static final ConcurrentMap<String, JsonParser> INSTANCES = new ConcurrentHashMap<>(); + + /** + * Gets JsonParser by name + * + * @param name parser name + * @return the JsonParser + */ + public static JsonParser getJsonParser(String name) { + JsonParser parser = INSTANCES.get(name); + if (parser == null) { + synchronized (JsonParserFactory.class) { + parser = INSTANCES.get(name); + if (parser == null) { + parser = EnhancedServiceLoader.load(JsonParser.class, name, Thread.currentThread().getContextClassLoader()); + INSTANCES.putIfAbsent(name, parser); + } + } + } + return parser; + } +} \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/StateParserFactory.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/StateParserFactory.java index fba3be973a14ba27895dd945d8ba335789db86e9..1f39042087b6ea0ba23b5a532df2a5415b54a674 100644 --- a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/StateParserFactory.java +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/StateParserFactory.java @@ -23,6 +23,7 @@ import io.seata.saga.statelang.parser.impl.ChoiceStateParser; import io.seata.saga.statelang.parser.impl.CompensateSubStateMachineStateParser; import io.seata.saga.statelang.parser.impl.CompensationTriggerStateParser; import io.seata.saga.statelang.parser.impl.FailEndStateParser; +import io.seata.saga.statelang.parser.impl.ScriptTaskStateParser; import io.seata.saga.statelang.parser.impl.ServiceTaskStateParser; import io.seata.saga.statelang.parser.impl.SubStateMachineParser; import io.seata.saga.statelang.parser.impl.SucceedEndStateParser; @@ -45,6 +46,7 @@ public class StateParserFactory { stateParserMap.put(DomainConstants.STATE_TYPE_SUB_STATE_MACHINE, new SubStateMachineParser()); stateParserMap.put(DomainConstants.STATE_TYPE_SUB_MACHINE_COMPENSATION, new CompensateSubStateMachineStateParser()); + stateParserMap.put(DomainConstants.STATE_TYPE_SCRIPT_TASK, new ScriptTaskStateParser()); } public static StateParser getStateParser(String stateType) { diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/FastjsonParser.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/FastjsonParser.java new file mode 100644 index 0000000000000000000000000000000000000000..04efa8eed97009166b9a1c758479587bfa6497ba --- /dev/null +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/FastjsonParser.java @@ -0,0 +1,69 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.statelang.parser.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.Feature; +import com.alibaba.fastjson.serializer.SerializerFeature; +import io.seata.common.loader.LoadLevel; +import io.seata.saga.statelang.parser.JsonParser; + +/** + * JsonParser implement by Fastjson + * + * @author lorne.cl + */ +@LoadLevel(name = FastjsonParser.NAME) +public class FastjsonParser implements JsonParser { + + private static final SerializerFeature[] SERIALIZER_FEATURES = new SerializerFeature[] { + SerializerFeature.DisableCircularReferenceDetect, + SerializerFeature.WriteDateUseDateFormat, + SerializerFeature.WriteClassName }; + + private static final SerializerFeature[] SERIALIZER_FEATURES_PRETTY = new SerializerFeature[] { + SerializerFeature.DisableCircularReferenceDetect, + SerializerFeature.WriteDateUseDateFormat, + SerializerFeature.WriteClassName, + SerializerFeature.PrettyFormat }; + + public static final String NAME = "fastjson"; + + @Override + public String getName() { + return NAME; + } + + @Override + public String toJsonString(Object o, boolean prettyPrint) { + if (prettyPrint) { + return JSON.toJSONString(o, SERIALIZER_FEATURES_PRETTY); + } + else { + return JSON.toJSONString(o, SERIALIZER_FEATURES); + } + } + + @Override + public <T> T parse(String json, Class<T> type, boolean ignoreAutoType) { + if (ignoreAutoType) { + return JSON.parseObject(json, type, Feature.IgnoreAutoType, Feature.OrderedField); + } + else { + return JSON.parseObject(json, type, Feature.SupportAutoType, Feature.OrderedField); + } + } +} \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/JacksonJsonParser.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/JacksonJsonParser.java new file mode 100644 index 0000000000000000000000000000000000000000..7056969224aad2a516998ac081105d8ccb008902 --- /dev/null +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/JacksonJsonParser.java @@ -0,0 +1,95 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.statelang.parser.impl; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; +import io.seata.common.loader.LoadLevel; +import io.seata.saga.statelang.parser.JsonParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * JsonParser implement by Jackson + * + * @author lorne.cl + */ +@LoadLevel(name = JacksonJsonParser.NAME) +public class JacksonJsonParser implements JsonParser { + + private static final Logger LOGGER = LoggerFactory.getLogger(JacksonJsonParser.class); + + private ObjectMapper objectMapperWithAutoType = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .enableDefaultTypingAsProperty(DefaultTyping.NON_FINAL, "@type") + .enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER) + .setSerializationInclusion(Include.NON_NULL); + + private ObjectMapper objectMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .disableDefaultTyping() + .enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER) + .setSerializationInclusion(Include.NON_NULL); + + public static final String NAME = "jackson"; + + @Override + public String getName() { + return NAME; + } + + @Override + public String toJsonString(Object o, boolean prettyPrint) { + try { + if (o instanceof List && ((List) o).size() == 0) { + return "[]"; + } + if (prettyPrint) { + return objectMapperWithAutoType.writerWithDefaultPrettyPrinter().writeValueAsString(o); + } + else { + return objectMapperWithAutoType.writeValueAsString(o); + } + } catch (JsonProcessingException e) { + throw new RuntimeException("Parse object to json error", e); + } + } + + @Override + public <T> T parse(String json, Class<T> type, boolean ignoreAutoType) { + try { + if (json != null && "[]".equals(json)) { + return (T) (new ArrayList(0)); + } + if (ignoreAutoType) { + return objectMapper.readValue(json, type); + } + else { + return objectMapperWithAutoType.readValue(json, type); + } + } catch (IOException e) { + throw new RuntimeException("Parse json to object error", e); + } + } +} \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/ScriptTaskStateParser.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/ScriptTaskStateParser.java new file mode 100644 index 0000000000000000000000000000000000000000..12e132720659f235c70acf1b472bc1309cef626a --- /dev/null +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/ScriptTaskStateParser.java @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.statelang.parser.impl; + +import io.seata.common.util.StringUtils; +import io.seata.saga.statelang.domain.ScriptTaskState; +import io.seata.saga.statelang.domain.impl.ScriptTaskStateImpl; +import io.seata.saga.statelang.parser.StateParser; + +import java.util.Map; + +/** + * ScriptTaskState parser + * + * @author lorne.cl + */ +public class ScriptTaskStateParser extends AbstractTaskStateParser implements StateParser<ScriptTaskState> { + + @Override + public ScriptTaskState parse(Object node) { + + ScriptTaskStateImpl scriptTaskState = new ScriptTaskStateImpl(); + + parseTaskAttributes(scriptTaskState, node); + + Map<String, Object> nodeMap = (Map<String, Object>)node; + String scriptType = (String) nodeMap.get("ScriptType"); + if (StringUtils.isNotBlank(scriptType)) { + scriptTaskState.setScriptType(scriptType); + } + scriptTaskState.setScriptContent((String)nodeMap.get("ScriptContent")); + + scriptTaskState.setForCompensation(false); + scriptTaskState.setForUpdate(false); + scriptTaskState.setPersist(false); + + return scriptTaskState; + } +} \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/StateMachineParserImpl.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/StateMachineParserImpl.java index b6fb8ae0ee372fc83b18fd5f1b2d7a2f76b0121a..fc9347c7701f9d92f1da832a958c08b15f7a19ac 100644 --- a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/StateMachineParserImpl.java +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/impl/StateMachineParserImpl.java @@ -16,18 +16,16 @@ package io.seata.saga.statelang.parser.impl; import java.util.Map; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.parser.Feature; - -import com.alibaba.fastjson.serializer.SerializerFeature; import io.seata.common.util.StringUtils; +import io.seata.saga.statelang.domain.DomainConstants; import io.seata.saga.statelang.domain.RecoverStrategy; import io.seata.saga.statelang.domain.State; import io.seata.saga.statelang.domain.StateMachine; import io.seata.saga.statelang.domain.impl.AbstractTaskState; import io.seata.saga.statelang.domain.impl.BaseState; import io.seata.saga.statelang.domain.impl.StateMachineImpl; +import io.seata.saga.statelang.parser.JsonParser; +import io.seata.saga.statelang.parser.JsonParserFactory; import io.seata.saga.statelang.parser.StateMachineParser; import io.seata.saga.statelang.parser.StateParser; import io.seata.saga.statelang.parser.StateParserFactory; @@ -44,16 +42,23 @@ public class StateMachineParserImpl implements StateMachineParser { private static final Logger LOGGER = LoggerFactory.getLogger(StateMachineParserImpl.class); + private String jsonParserName = DomainConstants.DEFAULT_JSON_PARSER; + @Override public StateMachine parse(String json) { - Map<String, Object> node = JSON.parseObject(json, Map.class, Feature.IgnoreAutoType, Feature.OrderedField); + JsonParser jsonParser = JsonParserFactory.getJsonParser(jsonParserName); + if (jsonParser == null) { + throw new RuntimeException("Cannot find JsonParer by name: " + jsonParserName); + } + Map<String, Object> node = jsonParser.parse(json, Map.class, true); if (DesignerJsonTransformer.isDesignerJson(node)) { node = DesignerJsonTransformer.toStandardJson(node); if (LOGGER.isDebugEnabled()) { - LOGGER.debug("===== Transformed standard state language:\n{}", JSON.toJSONString(node, SerializerFeature.PrettyFormat)); + LOGGER.debug("===== Transformed standard state language:\n{}", jsonParser.toJsonString(node, true)); } } + StateMachineImpl stateMachine = new StateMachineImpl(); stateMachine.setName((String) node.get("Name")); stateMachine.setComment((String) node.get("Comment")); @@ -104,4 +109,12 @@ public class StateMachineParserImpl implements StateMachineParser { } return stateMachine; } + + public String getJsonParserName() { + return jsonParserName; + } + + public void setJsonParserName(String jsonParserName) { + this.jsonParserName = jsonParserName; + } } \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/utils/DesignerJsonTransformer.java b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/utils/DesignerJsonTransformer.java index 155dea825313bde5b210aaef5b873e0d5a1369a0..1415abc4bc8882fabfa9a6f3d1798c53de5d7653 100644 --- a/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/utils/DesignerJsonTransformer.java +++ b/saga/seata-saga-statelang/src/main/java/io/seata/saga/statelang/parser/utils/DesignerJsonTransformer.java @@ -15,20 +15,17 @@ */ package io.seata.saga.statelang.parser.utils; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.parser.Feature; -import com.alibaba.fastjson.serializer.SerializerFeature; import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.exception.FrameworkException; import io.seata.saga.statelang.domain.ExecutionStatus; import io.seata.saga.statelang.domain.StateInstance; import io.seata.saga.statelang.domain.StateMachineInstance; +import io.seata.saga.statelang.parser.JsonParser; import org.springframework.util.StringUtils; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -44,16 +41,15 @@ public class DesignerJsonTransformer { if (!isDesignerJson(designerJsonObject)) { return designerJsonObject; } - - JSONObject machineJsonObject = new JSONObject(true); + Map<String, Object> machineJsonObject = new LinkedHashMap<>(); List<Object> nodes = (List) designerJsonObject.get("nodes"); if (nodes != null && nodes.size() > 0) { - Map<String, JSONObject> nodeMap = new HashMap<>(nodes.size()); + Map<String, Object> nodeMap = new LinkedHashMap<>(nodes.size()); for (Object node : nodes) { - JSONObject nodeObj = (JSONObject) node; + Map<String, Object> nodeObj = (Map<String, Object>) node; transformNode(machineJsonObject, nodeMap, nodeObj); } @@ -61,7 +57,7 @@ public class DesignerJsonTransformer { List<Object> edges = (List) designerJsonObject.get("edges"); if (edges != null && edges.size() > 0) { for (Object edge : edges) { - JSONObject edgeObj = (JSONObject) edge; + Map<String, Object> edgeObj = (Map<String, Object>) edge; transformEdge(machineJsonObject, nodes, nodeMap, edgeObj); } } @@ -69,31 +65,31 @@ public class DesignerJsonTransformer { return machineJsonObject; } - private static void transformNode(JSONObject machineJsonObject, Map<String, JSONObject> nodeMap, JSONObject nodeObj) { - nodeMap.put(nodeObj.getString("id"), nodeObj); + private static void transformNode(Map<String, Object> machineJsonObject, Map<String, Object> nodeMap, Map<String, Object> nodeObj) { + nodeMap.put((String) nodeObj.get("id"), nodeObj); - String type = nodeObj.getString("stateType"); - JSONObject propsObj = (JSONObject) nodeObj.get("stateProps"); + String type = (String) nodeObj.get("stateType"); + Map<String, Object> propsObj = (Map<String, Object>) nodeObj.get("stateProps"); if ("Start".equals(type)) { if (propsObj != null && propsObj.containsKey("StateMachine")) { - machineJsonObject.putAll(propsObj.getJSONObject("StateMachine")); + machineJsonObject.putAll((Map<String, Object>) propsObj.get("StateMachine")); } } else if (!"Catch".equals(type)) { - JSONObject states = machineJsonObject.getJSONObject("States"); + Map<String, Object> states = (Map<String, Object>) machineJsonObject.get("States"); if (states == null) { - states = new JSONObject(true); + states = new LinkedHashMap<>(); machineJsonObject.put("States", states); } - JSONObject stateJsonObject = new JSONObject(true); - String stateId = nodeObj.getString("stateId"); + Map<String, Object> stateJsonObject = new LinkedHashMap<>(); + String stateId = (String) nodeObj.get("stateId"); if (states.containsKey(stateId)) { throw new RuntimeException( "Transform designer json to standard json failed, stateId[" + stateId + "] already exists, pls rename it."); } - String comment = nodeObj.getString("label"); + String comment = (String) nodeObj.get("label"); if (StringUtils.hasLength(comment)) { stateJsonObject.put("Comment", comment); } @@ -103,7 +99,7 @@ public class DesignerJsonTransformer { states.put(stateId, stateJsonObject); - String stateType = nodeObj.getString("stateType"); + String stateType = (String) nodeObj.get("stateType"); if ("Compensation".equals(stateType)) { stateJsonObject.put("Type", "ServiceTask"); } else { @@ -112,64 +108,64 @@ public class DesignerJsonTransformer { } } - private static void transformEdge(JSONObject machineJsonObject, List<Object> nodes, Map<String, JSONObject> nodeMap, - JSONObject edgeObj) { - String sourceId = edgeObj.getString("source"); - String targetId = edgeObj.getString("target"); + private static void transformEdge(Map<String, Object> machineJsonObject, List<Object> nodes, Map<String, Object> nodeMap, Map<String, Object> edgeObj) { + String sourceId = (String) edgeObj.get("source"); + String targetId = (String) edgeObj.get("target"); if (StringUtils.hasLength(sourceId)) { - JSONObject sourceNode = nodeMap.get(sourceId); - JSONObject targetNode = nodeMap.get(targetId); + Map<String, Object> sourceNode = (Map<String, Object>) nodeMap.get(sourceId); + Map<String, Object> targetNode = (Map<String, Object>) nodeMap.get(targetId); if (sourceNode != null) { - JSONObject states = machineJsonObject.getJSONObject("States"); - JSONObject sourceState = states.getJSONObject(sourceNode.getString("stateId")); - String targetStateId = targetNode.getString("stateId"); + Map<String, Object> states = (Map<String, Object>) machineJsonObject.get("States"); + Map<String, Object> sourceState = (Map<String, Object>) states.get((String) sourceNode.get("stateId")); + String targetStateId = (String) targetNode.get("stateId"); - String sourceType = sourceNode.getString("stateType"); + String sourceType = (String) sourceNode.get("stateType"); if ("Start".equals(sourceType)) { machineJsonObject.put("StartState", targetStateId); //Make sure 'StartState' is before 'States' machineJsonObject.put("States", machineJsonObject.remove("States")); } else if ("ServiceTask".equals(sourceType)) { - if (targetNode != null && "Compensation".equals(targetNode.getString("stateType"))) { + if (targetNode != null && "Compensation".equals(targetNode.get("stateType"))) { sourceState.put("CompensateState", targetStateId); } else { sourceState.put("Next", targetStateId); } } else if ("Catch".equals(sourceType)) { - JSONObject catchAttachedNode = getCatchAttachedNode(sourceNode, nodes); + Map<String, Object> catchAttachedNode = getCatchAttachedNode(sourceNode, nodes); if (catchAttachedNode == null) { - throw new RuntimeException("'Catch' node[" + sourceNode.get("id") + "] is not attached on a 'ServiceTask'"); + throw new RuntimeException("'Catch' node[" + sourceNode.get("id") + "] is not attached on a 'ServiceTask' or 'ScriptTask'"); } - JSONObject catchAttachedState = (JSONObject) states.get(catchAttachedNode.getString("stateId")); - JSONArray catches = catchAttachedState.getJSONArray("Catch"); + Map<String, Object> catchAttachedState = (Map<String, Object>) states.get(catchAttachedNode.get("stateId")); + List<Object> catches = (List<Object>) catchAttachedState.get("Catch"); if (catches == null) { - catches = new JSONArray(); + catches = new ArrayList<>(); catchAttachedState.put("Catch", catches); } - JSONObject edgeProps = (JSONObject) edgeObj.get("stateProps"); + Map<String, Object> edgeProps = (Map<String, Object>) edgeObj.get("stateProps"); if (edgeProps != null) { - JSONObject catchObj = new JSONObject(true); + Map<String, Object> catchObj = new LinkedHashMap<>(); catchObj.put("Exceptions", edgeProps.get("Exceptions")); catchObj.put("Next", targetStateId); catches.add(catchObj); } } else if ("Choice".equals(sourceType)) { - JSONArray choices = sourceState.getJSONArray("Choices"); + List<Object> choices = (List<Object>) sourceState.get("Choices"); if (choices == null) { - choices = new JSONArray(); + choices = new ArrayList<>(); sourceState.put("Choices", choices); } - JSONObject edgeProps = (JSONObject) edgeObj.get("stateProps"); + Map<String, Object> edgeProps = (Map<String, Object>) edgeObj.get("stateProps"); if (edgeProps != null) { - if (Boolean.TRUE.equals(edgeProps.getBoolean("Default"))) { + if (Boolean.TRUE.equals(edgeProps.get("Default"))) { sourceState.put("Default", targetStateId); } else { - JSONObject choiceObj = new JSONObject(true); + //JSONObject choiceObj = new JSONObject(true); + Map<String, Object> choiceObj = new LinkedHashMap<>(); choiceObj.put("Expression", edgeProps.get("Expression")); choiceObj.put("Next", targetStateId); choices.add(choiceObj); @@ -186,22 +182,24 @@ public class DesignerJsonTransformer { return jsonObject != null && jsonObject.containsKey("nodes") && jsonObject.containsKey("edges"); } - private static JSONObject getCatchAttachedNode(JSONObject catchNode, List<Object> nodes) { - int catchNodeX = catchNode.getInteger("x"); - int catchNodeY = catchNode.getInteger("y"); - String catchSize = catchNode.getString("size"); + private static Map<String, Object> getCatchAttachedNode(Map<String, Object> catchNode, List<Object> nodes) { + Number catchNodeX = (Number) catchNode.get("x"); + Number catchNodeY = (Number) catchNode.get("y"); + String catchSize = (String) catchNode.get("size"); String[] catchSizes = catchSize.split("\\*"); int catchWidth = Integer.parseInt(catchSizes[0]); int catchHeight = Integer.parseInt(catchSizes[1]); for (Object node : nodes) { - JSONObject nodeObj = (JSONObject) node; - if (catchNode != nodeObj && "ServiceTask".equals(nodeObj.get("stateType"))) { + Map<String, Object> nodeObj = (Map<String, Object>) node; + if (catchNode != nodeObj && + ("ServiceTask".equals(nodeObj.get("stateType")) + || "ScriptTask".equals(nodeObj.get("stateType")))) { - int nodeX = nodeObj.getInteger("x"); - int nodeY = nodeObj.getInteger("y"); + Number nodeX = (Number) nodeObj.get("x"); + Number nodeY = (Number) nodeObj.get("y"); - String nodeSize = nodeObj.getString("size"); + String nodeSize = (String) nodeObj.get("size"); String[] nodeSizes = nodeSize.split("\\*"); int nodeWidth = Integer.parseInt(nodeSizes[0]); int nodeHeight = Integer.parseInt(nodeSizes[1]); @@ -216,9 +214,9 @@ public class DesignerJsonTransformer { return null; } - private static boolean isBordersCoincided(int xyA, int xyB, int lengthA, int lengthB) { - int centerPointLength = xyA > xyB ? xyA - xyB : xyB - xyA; - return ((lengthA + lengthB) / 2) > centerPointLength; + private static boolean isBordersCoincided(Number xyA, Number xyB, Number lengthA, Number lengthB) { + double centerPointLength = xyA.doubleValue() > xyB.doubleValue() ? xyA.doubleValue() - xyB.doubleValue() : xyB.doubleValue() - xyA.doubleValue(); + return ((lengthA.doubleValue() + lengthB.doubleValue()) / 2) > centerPointLength; } /** @@ -226,7 +224,7 @@ public class DesignerJsonTransformer { * @param stateMachineInstance * @return */ - public static String generateTracingGraphJson(StateMachineInstance stateMachineInstance) { + public static String generateTracingGraphJson(StateMachineInstance stateMachineInstance, JsonParser jsonParser) { if (stateMachineInstance == null) { throw new FrameworkException("StateMachineInstance is not exits", @@ -237,7 +235,8 @@ public class DesignerJsonTransformer { throw new FrameworkException("Cannot get StateMachine Json", FrameworkErrorCode.ObjectNotExists); } - JSONObject stateMachineJsonObj = JSON.parseObject(stateMachineJson, Feature.IgnoreAutoType, Feature.OrderedField); + + Map<String, Object> stateMachineJsonObj = jsonParser.parse(stateMachineJson, Map.class, true); if (!DesignerJsonTransformer.isDesignerJson(stateMachineJsonObj)) { throw new FrameworkException("StateMachine Json is not generated by Designer", FrameworkErrorCode.InvalidConfiguration); @@ -252,11 +251,11 @@ public class DesignerJsonTransformer { } stateInstanceList.add(stateInstance); } - JSONArray nodesArray = stateMachineJsonObj.getJSONArray("nodes"); + List<Object> nodesArray = (List<Object>) stateMachineJsonObj.get("nodes"); for (Object nodeObj : nodesArray) { - JSONObject node = (JSONObject) nodeObj; - String stateId = node.getString("stateId"); - String stateType = node.getString("stateType"); + Map<String, Object> node = (Map<String, Object>) nodeObj; + String stateId = (String) node.get("stateId"); + String stateType = (String) node.get("stateType"); if ("ServiceTask".equals(stateType) || "SubStateMachine".equals(stateType) || "Compensation".equals(stateType)) { @@ -282,19 +281,23 @@ public class DesignerJsonTransformer { node.put("stateInstanceStatus", stateInstance.getStatus()); if (ExecutionStatus.SU.equals(stateInstance.getStatus())) { node.put("color", "green"); - JSONObject style = new JSONObject(); + Map<String, Object> style = new LinkedHashMap<>(); style.put("fill", "#00D73E"); style.put("lineWidth", 2); node.put("style", style); } else { node.put("color", "red"); - JSONObject style = new JSONObject(); + Map<String, Object> style = new LinkedHashMap<>(); style.put("fill", "#FF7777"); style.put("lineWidth", 2); node.put("style", style); } } } - return stateMachineJsonObj.toString(SerializerFeature.PrettyFormat); + + if (stateMachineJsonObj != null) { + return jsonParser.toJsonString(stateMachineJsonObj, true); + } + return ""; } } \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/main/resources/META-INF/services/io.seata.saga.statelang.parser.JsonParser b/saga/seata-saga-statelang/src/main/resources/META-INF/services/io.seata.saga.statelang.parser.JsonParser new file mode 100644 index 0000000000000000000000000000000000000000..84fe046ffe1f7eb6823a184a06c4b027fa39b422 --- /dev/null +++ b/saga/seata-saga-statelang/src/main/resources/META-INF/services/io.seata.saga.statelang.parser.JsonParser @@ -0,0 +1,2 @@ +io.seata.saga.statelang.parser.impl.FastjsonParser +io.seata.saga.statelang.parser.impl.JacksonJsonParser \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/test/java/io/seata/saga/statelang/parser/StateParserTests.java b/saga/seata-saga-statelang/src/test/java/io/seata/saga/statelang/parser/StateParserTests.java index 785de7f7221d720690c2f340a78f4aa5a6c0370c..1f2159628185928f9b088c0dabc9bfcbf364c123 100644 --- a/saga/seata-saga-statelang/src/test/java/io/seata/saga/statelang/parser/StateParserTests.java +++ b/saga/seata-saga-statelang/src/test/java/io/seata/saga/statelang/parser/StateParserTests.java @@ -16,12 +16,9 @@ package io.seata.saga.statelang.parser; import java.io.IOException; +import java.util.Date; import java.util.Map; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.parser.Feature; -import com.alibaba.fastjson.serializer.SerializerFeature; - import io.seata.saga.statelang.domain.StateMachine; import io.seata.saga.statelang.parser.utils.DesignerJsonTransformer; import org.junit.jupiter.api.Assertions; @@ -41,11 +38,18 @@ public class StateParserTests { ClassPathResource resource = new ClassPathResource("statelang/simple_statemachine.json"); String json = io.seata.saga.statelang.parser.utils.IOUtils.toString(resource.getInputStream(), "UTF-8"); StateMachine stateMachine = StateMachineParserFactory.getStateMachineParser().parse(json); + stateMachine.setGmtCreate(new Date()); Assertions.assertNotNull(stateMachine); - String outputJson = JSON.toJSONString(stateMachine, SerializerFeature.PrettyFormat); + JsonParser jsonParser = JsonParserFactory.getJsonParser("jackson"); + String outputJson = jsonParser.toJsonString(stateMachine, true); System.out.println(outputJson); + + JsonParser fastjsonParser = JsonParserFactory.getJsonParser("fastjson"); + String fastjsonOutputJson = fastjsonParser.toJsonString(stateMachine, true); + System.out.println(fastjsonOutputJson); + Assertions.assertEquals(stateMachine.getName(), "simpleTestStateMachine"); Assertions.assertTrue(stateMachine.getStates().size() > 0); } @@ -55,10 +59,19 @@ public class StateParserTests { ClassPathResource resource = new ClassPathResource("statelang/simple_statemachine_with_layout.json"); String json = io.seata.saga.statelang.parser.utils.IOUtils.toString(resource.getInputStream(), "UTF-8"); - Map<String, Object> parsedObj = DesignerJsonTransformer.toStandardJson(JSON.parseObject(json, Feature.OrderedField)); + JsonParser jsonParser = JsonParserFactory.getJsonParser("jackson"); + Map<String, Object> parsedObj = DesignerJsonTransformer.toStandardJson(jsonParser.parse(json, Map.class, true)); Assertions.assertNotNull(parsedObj); - String outputJson = JSON.toJSONString(parsedObj, SerializerFeature.PrettyFormat); + String outputJson = jsonParser.toJsonString(parsedObj, true); System.out.println(outputJson); + + + JsonParser fastjsonParser = JsonParserFactory.getJsonParser("fastjson"); + Map<String, Object> fastjsonParsedObj = DesignerJsonTransformer.toStandardJson(fastjsonParser.parse(json, Map.class, true)); + Assertions.assertNotNull(fastjsonParsedObj); + + String fastjsonOutputJson = fastjsonParser.toJsonString(fastjsonParsedObj, true); + System.out.println(fastjsonOutputJson); } } \ No newline at end of file diff --git a/saga/seata-saga-statelang/src/test/resources/statelang/simple_statemachine.json b/saga/seata-saga-statelang/src/test/resources/statelang/simple_statemachine.json index 32168f5b7dd9f5512fb9c4a56516060f7799c404..417d3b5b8dec304afcecbb7a762791ab0ff49c4c 100644 --- a/saga/seata-saga-statelang/src/test/resources/statelang/simple_statemachine.json +++ b/saga/seata-saga-statelang/src/test/resources/statelang/simple_statemachine.json @@ -9,6 +9,20 @@ "ServiceName": "is.seata.saga.DemoService", "ServiceMethod": "foo", "IsPersist": false, + "Next": "ScriptState" + }, + "ScriptState": { + "Type": "ScriptTask", + "ScriptType": "groovy", + "ScriptContent": "return 'hello ' + inputA", + "Input": [ + { + "inputA": "$.data1" + } + ], + "Output": { + "scriptStateResult": "$.#root" + }, "Next": "ChoiceState" }, "ChoiceState": { diff --git a/saga/seata-saga-statemachine-designer/.babelrc b/saga/seata-saga-statemachine-designer/.babelrc index e092e89971f12815ecfa9eb5746bdc6b437128ce..d9ea09a607e5781420183827fa7fb23735f4ef3d 100644 --- a/saga/seata-saga-statemachine-designer/.babelrc +++ b/saga/seata-saga-statemachine-designer/.babelrc @@ -25,7 +25,8 @@ "@common": "./ggeditor/common", "@components": "./ggeditor/components", "@helpers": "./ggeditor/helpers", - "@utils": "./ggeditor/utils" + "@utils": "./ggeditor/utils", + "@gg-editor-core": "./ggeditor/gg-editor-core" } } ], diff --git a/saga/seata-saga-statemachine-designer/ggeditor/components/Base/Editor.js b/saga/seata-saga-statemachine-designer/ggeditor/components/Base/Editor.js index 579dfe780ec27495c0c71de1678a905bc014a205..d84afbf0e551a389e21bed4404156ca65524c8ed 100644 --- a/saga/seata-saga-statemachine-designer/ggeditor/components/Base/Editor.js +++ b/saga/seata-saga-statemachine-designer/ggeditor/components/Base/Editor.js @@ -1,4 +1,4 @@ -import GGEditorCore from 'gg-editor-core'; +import GGEditorCore from '@gg-editor-core/bundle'; import { EVENT_BEFORE_ADD_PAGE } from '@common/constants'; import track from '@helpers/track'; import { uniqueId } from '@utils'; diff --git a/saga/seata-saga-statemachine-designer/ggeditor/gg-editor-core/bundle.js b/saga/seata-saga-statemachine-designer/ggeditor/gg-editor-core/bundle.js new file mode 100644 index 0000000000000000000000000000000000000000..facde7f6a3184c294a8150109d4a677d97f8e05e --- /dev/null +++ b/saga/seata-saga-statemachine-designer/ggeditor/gg-editor-core/bundle.js @@ -0,0 +1,19 @@ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.GGEditorCore=e():t.GGEditorCore=e()}(window,(function(){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=25)}([function(t,e,n){"use strict";function r(t,e,n){return t.addShape("path",{attrs:{...n,path:e}})}function i(t){return[{x:t.centerX,y:t.minY},{x:t.maxX,y:t.centerY},{x:t.centerX,y:t.maxY},{x:t.minX,y:t.centerY}]}function o(t,e){const n=i(e);let r,o,a=1/0;return n.forEach((e,n)=>{const i=(s=t,c=e,Math.sqrt(Math.pow(s.x-c.x,2)+Math.pow(s.y-c.y,2)));var s,c;i<a&&(r=e,a=i,o=n)}),{point:r,index:o}}function a(t,e){return{x:(t[e].x+t[e+1].x)/2,y:(t[e].y+t[e+1].y)/2}}function s({point:t,index:e},{point:n,index:r}){return t.x===n.x||t.y===n.y?[t,n]:2===e&&0===r||0===e&&2===r?[t,{x:t.x,y:(t.y+n.y)/2},{x:n.x,y:(t.y+n.y)/2},n]:2!==e&&0!==e||3!==r&&1!==r?1!==e&&3!==e||2!==r&&0!==r?[t,{x:(t.x+n.x)/2,y:t.y},{x:(t.x+n.x)/2,y:n.y},n]:[t,{x:n.x,y:t.y},n]:[t,{x:t.x,y:n.y},n]}function c(t,e){return t[e].x===t[e+1].x}function u(t,e,n){return c(e,n)?t.x===e[n].x&&(t.y-e[n].y)*(t.y-e[n+1].y)<=0:t.y===e[n].y&&(t.x-e[n].x)*(t.x-e[n+1].x)<=0}function h(t,e){let n,r,i,o=1/0;for(let h=0;h<e.length-1;h++){const l=c(e,h);let d;if(d=l?{x:e[h].x,y:t.y}:{x:t.x,y:e[h].y},u(d,e,h)){const e=(a=t,s=d,Math.pow(a.x-s.x,2)+Math.pow(a.y-s.y,2));o>e&&(o=e,n=h,r=d,i=l)}}var a,s;return{verticalPoint:r,index:n,vertical:i}}function l(t,e,n){const r=function(t){if(!t)return{x:void 0,y:void 0};const e=t.getBBox();return{x:e.centerX,y:e.centerY}}(e);let a=t.getLinkPoints(r)[0];if(n){const r=i(t.getBBox())[n];s=t.getBBox(),c=r,u={x:e.getBBox().centerX,y:e.getBBox().centerY},((s.centerX-c.x)*(s.centerX-u.x)>0||(s.centerY-c.y)*(s.centerY-u.y)>0)&&(a=r)}var s,c,u;a=o(a,t.getBBox());let h=e.getLinkPoints(a.point)[0];return h=o(h,e.getBBox()),{sourcePoint:a,targetPoint:h}}function d(t,e,n){return c(e,n)?t.minX>e[n].x?1:t.maxX<e[n].x?-1:0:t.minY>e[n].y?1:t.maxY<e.y?-1:0}function f(t,e,n){return c(e,n)?{x:e[n].x,y:t.y}:{x:t.x,y:e[n].y}}function g(t){let e;switch(t){case 0:e=2;break;case 1:e=3;break;case 3:e=1;break;default:e=0}return e}n.d(e,"b",(function(){return r})),n.d(e,"c",(function(){return i})),n.d(e,"f",(function(){return o})),n.d(e,"j",(function(){return a})),n.d(e,"h",(function(){return s})),n.d(e,"i",(function(){return c})),n.d(e,"l",(function(){return u})),n.d(e,"e",(function(){return h})),n.d(e,"d",(function(){return l})),n.d(e,"a",(function(){return d})),n.d(e,"g",(function(){return f})),n.d(e,"k",(function(){return g}))},function(t,e,n){const r=n(7),i=n(3),o=n(4),a={getActivedStyle(){},getSelectedStyle(){},getStyle(){},getPath(){}};function s(t,e,n){let r=[];return o.isString(t)?r=[e,t]:o.isArray(t)?(t.unshift(e),r=t):r=[e],n&&r.unshift(n+"-base"),r}r.registerNode("page-base",{...a}),r.registerEdge("page-base",{...a}),r.registerGroup("page-base",{...a}),r.registerGuide("page-base",{...a}),i.setRegister=(t,e,n)=>{t.registerNode=(t,i,o)=>{r.registerNode(t,i,s(o,e+"-base",n))},t.registerEdge=(t,i,o)=>{r.registerEdge(t,i,s(o,e+"-base",n))},t.registerGroup=(t,i,o)=>{r.registerGroup(t,i,s(o,e+"-base",n))},t.registerGuide=(t,i,o)=>{r.registerGuide(t,i,s(o,e+"-base",n))},t.registerBehaviour=(t,e,n)=>{r.registerBehaviour(t,t=>{const n=t.get("page");n.set("_graph",t),e(n)},n)}},i.setRegister(i,"page"),n(44),t.exports=i},function(t,e,n){const r=n(7),i=n(22),o=n(63),a=n(64),s={...r.Util,...i,...o,...a};t.exports=s},function(t,e,n){const r=n(21),i=n(4),o=n(14),a=n(34),s=n(35),c=n(37),u=[a,n(38),n(39),s,c,n(40),n(42),n(43)];class h extends r{constructor(t){const e={defaultData:null,shortcut:{redo:!0,undo:!0,delete:!0,resetZoom:!0,autoZoom:!0,zoomIn:!0,zoomOut:!0},_controllers:{},_signals:{}};i.each(u,t=>{i.mix(e,t.CFG)}),i.mix(!0,e,t),super(e),this.isPage=!0,this.type="page",this._init()}getDelegation(t,e){if(!e){e=this.getGraph().getRootGroup()}let n;if(1!==t.length||t[0].isNode||t[0].isGroup){const r=i.getTotalBBox(t.map(t=>t.getBBox()));n=i.getRectByBox(r,e,o.nodeDelegationStyle),n.set("capture",!1)}else t[0].isEdge?n=e.addShape("path",{attrs:{path:"M0 0L 1 1",...o.edgeDelegationStyle},capture:!1}):(n=i.getRectByBox(t[0],e,o.nodeDelegationStyle),n.set("capture",!1));return n}focusGraphWrapper(){this.getGraph().getKeyboardEventWrapper().focus()}saveImage(t){const e=this.getGraph(),n=e.getBBox(),r=e.getFitViewPadding();let i,o;return e.saveImage({width:n.width+r[1]+r[3],height:n.height+r[0]+r[2],beforeTransform:()=>{i=this.getSelected().map(t=>t.id),o=this.getSelected().map(t=>t.id),this.clearSelected(),this.clearActived()},afterTransform:()=>{this.setSelected(i,!0),this.setActived(o,!0)},...t})}_init(){i.each(u,t=>{t.INIT&&this[t.INIT]()}),this.bindEvent(),this._cacheBBox()}executeCommand(t,e){const n=this.editor;n?n.executeCommand(t,e):t()}_cacheBBox(){const t=this.getGraph();this.set("bboxCache",t.getBBox())}bindEvent(){this.getGraph().on("afterchange",()=>{this._cacheBBox()})}translateLimt(t){const e=this.getGraph(),n=this.get("bboxCache"),r=e.getWidth(),o=e.getHeight(),a=[n.minX,n.minY,1],s=[n.maxX,n.maxY,1];return i.vec3.transformMat3(a,a,t),i.vec3.transformMat3(s,s,t),s[0]<100&&i.mat3.translate(t,t,[100-s[0],0]),s[1]<100&&i.mat3.translate(t,t,[0,100-s[1]]),a[1]>o-100&&i.mat3.translate(t,t,[0,o-100-a[1]]),a[0]>r-100&&i.mat3.translate(t,t,[r-100-a[0],0]),!0}setSignal(t,e){this.get("_signals")[t]=e}getSignal(t){return this.get("_signals")[t]}setController(t,e){this.get("_controllers")[t]=e}getController(t){return this.get("_controllers")[t]}destroy(){const t=this.get("_graph"),e=this.get("_controllers");i.each(e,t=>{t.destroy()}),t.destroy()}}i.each(u,t=>{i.mix(h.prototype,t.AUGMENT)}),t.exports=h},function(t,e,n){const r=n(6),i=n(14),o=r.createDOM("<canvas>").getContext("2d");t.exports={...r,getPanCanvasBehaviour:t=>e=>{const n=e.getGraph();let o,a;n.behaviourOn("canvas:mouseenter",()=>{e.css({cursor:i.cursor.beforePanCanvas})}),n.behaviourOn("mouseleave",t=>{t.toShape||e.css({cursor:i.cursor.beforePanCanvas})}),n.behaviourOn("mousedown",r=>{(2!==r.button&&!t||!r.shape||r.item&&!1===r.item.dragable&&"mind-root"!==r.item.shapeObj.type&&!e.getSignal("dragEdge"))&&(o={x:r.domX,y:r.domY},e.css({cursor:i.cursor.panningCanvas}),a=n.getMatrix(),e.setCapture(!1))}),n.behaviourOn("drag",t=>{if(o){const i=t.domX-o.x,s=t.domY-o.y,c=[];r.mat3.translate(c,a,[i,s]),e.translateLimt(c)&&(n.updateMatrix(c),n.draw())}}),n.behaviourOn("mouseup",()=>{o&&(o=void 0,a=void 0,e.setCapture(!0),e.css({cursor:i.cursor.beforePanCanvas}))})},getLabelTextByTextLineWidth(t,e,n=320){o.font=e;let r=o.measureText(t).width;if(r>n){r=0;for(let e=1;e<t.length;e++)r+=o.measureText(t[e]).width,r>=n&&(t=t.substring(0,e)+"\n"+t.substring(e,t.length),e+=1,r=0)}return t}}},function(t,e){t.exports={orbitGap:10,nodeDefaultShape:"flow-node",edgeDefaultShape:"flow-smooth",groupDefaultShape:"flow-group",nodeActivedOutterStyle:{lineWidth:0},groupSelectedOutterStyle:{stroke:"#E0F0FF",lineWidth:2},nodeSelectedOutterStyle:{stroke:"#E0F0FF",lineWidth:2},edgeActivedStyle:{stroke:"#1890FF",strokeOpacity:.92},nodeActivedStyle:{fill:"#F3F9FF",stroke:"#1890FF"},groupActivedStyle:{stroke:"#1890FF"},edgeSelectedStyle:{lineWidth:2,strokeOpacity:.92,stroke:"#A3B1BF"},nodeSelectedStyle:{fill:"#F3F9FF",stroke:"#1890FF"},groupSelectedStyle:{stroke:"#1890FF",fillOpacity:.92},nodeStyle:{stroke:"#CED4D9",fill:"#FFFFFF",shadowOffsetX:0,shadowOffsetY:4,shadowBlur:10,shadowColor:"rgba(13, 26, 38, 0.08)",lineWidth:1,radius:4,fillOpacity:.92},edgeStyle:{stroke:"#A3B1BF",strokeOpacity:.92,lineWidth:1,lineAppendWidth:8,endArrow:!0},groupBackgroundPadding:[40,10,10,10],groupLabelOffsetX:10,groupLabelOffsetY:10,edgeLabelStyle:{fill:"#666",textAlign:"center",textBaseline:"middle"},edgeLabelRectPadding:4,edgeLabelRectStyle:{fill:"white"},nodeLabelStyle:{fill:"#666",textAlign:"center",textBaseline:"middle"},groupStyle:{stroke:"#CED4D9",radius:4},groupLabelStyle:{fill:"#666",textAlign:"left",textBaseline:"top"},multiSelectRectStyle:{fill:"#1890FF",fillOpacity:.08,stroke:"#1890FF",opacity:.1},dragNodeHoverToGroupStyle:{stroke:"#1890FF",lineWidth:2},dragNodeLeaveFromGroupStyle:{stroke:"#BAE7FF",lineWidth:2},anchorPointStyle:{radius:3.5,fill:"#fff",stroke:"#1890FF",lineAppendWidth:12},anchorHotsoptStyle:{radius:12,fill:"#1890FF",fillOpacity:.25},anchorHotsoptActivedStyle:{radius:14},anchorPointHoverStyle:{radius:4,fill:"#1890FF",fillOpacity:1,stroke:"#1890FF"},nodeControlPointStyle:{radius:4,fill:"#fff",shadowBlur:4,shadowColor:"#666"},edgeControlPointStyle:{radius:6,symbol:"square",lineAppendWidth:6,fillOpacity:0,strokeOpacity:0},nodeSelectedBoxStyle:{stroke:"#C2C2C2"},cursor:{panningCanvas:"-webkit-grabbing",beforePanCanvas:"-webkit-grab",hoverNode:"move",hoverEffectiveAnchor:"crosshair",hoverEdge:"default",hoverGroup:"move",hoverUnEffectiveAnchor:"default",hoverEdgeControllPoint:"crosshair",multiSelect:"crosshair"},zIndex:{anchorPoint:3,anchorHotsopt:2,selectedBox:1,controlPoint:4},polylineEdgeStyle:{offset:10,borderRadius:5},addToGroupDelayTime:400,outFromGroupDelayTime:400}},function(t,e,n){const r=n(7),i=n(28),o=n(29),a={whitespace:{9:"Tab",13:"Enter",32:"Space"},fn:{112:"f1 ",113:"f2 ",114:"f3 ",115:"f4 ",116:"f5 ",117:"f6 ",118:"f7 ",119:"f8 ",120:"f9 ",121:"f10",122:"f11",123:"f12"},letter:{65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z"},number:{48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9"},navigation:{37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown"},symbol:{110:"decimal point",186:"semi-colon",187:"=",188:"comma",189:"-",190:"period ",191:"/",192:"grave accent",219:"open bracket ",220:"back slash ",221:"close bracket ",222:"single quote "},smallNumberKey:{96:"numpad 0 ",97:"numpad 1 ",98:"numpad 2 ",99:"numpad 3 ",100:"numpad 4 ",101:"numpad 5 ",102:"numpad 6 ",103:"numpad 7 ",104:"numpad 8 ",105:"numpad 9 "},modifierKey:{16:"Shift",17:"Ctrl ",18:"Alt",20:"caps lock"},escKey:{8:"Backspace",46:"Delete",27:"Escape"},homeKey:{91:"Windows Key / Left command",92:"right window key ",93:"Windows Menu"},computeKey:{106:"multiply ",107:"add",109:"subtract ",111:"divide "}},s={...r.Util,...i,getNodeSize(t){if(t){if(r.Util.isNumber(t))return[t,t];if(r.Util.isString(t)){if(-1===t.indexOf("*")){const e=Number(t);return[e,e]}return t.split("*")}return t}return[96,48]},getTypeAndChar(t){let e,n;t=""+t;for(const r in a){e=r;for(const i in a[r])if(i===t)return n=a[r][i],{type:e,character:n}}return{}},getKeyboradKey:t=>t.key||s.getTypeAndChar(t.keyCode).character,getIndex:t=>t.getParent().get("children").indexOf(t),setId(t){t.id||(t.id=r.Util.guid())},pointLineDistance(t,e,n,i,o,a){const s=[n-t,i-e];if(r.Util.vec2.exactEquals(s,[0,0]))return NaN;const c=[-s[1],s[0]];r.Util.vec2.normalize(c,c);const u=[o-t,a-e];return Math.abs(r.Util.vec2.dot(u,c))},getRectByBox:(t,e,n)=>e.addShape("rect",{attrs:{...n,x:t.minX,y:t.minY,width:t.maxX-t.minX,height:t.maxY-t.minY}}),objectToValues(t){const e=[];let n;for(n in t)t.hasOwnProperty(n)&&e.push(t[n]);return e},getValue:t=>r.Util.isFunction(t)?t():t,getContrast(t,e){const n={};return r.Util.each(e,(e,r)=>{n[r]=t[r]}),n},arrowTo(t,e,n,i,o,a,s){const c=[a-i,s-o],u=r.Util.vec2.angleTo(c,[1,0],!0);return t.transform([["r",u],["t",e,n]]),t},setEndOfContenteditable(t){let e,n;document.createRange?(e=document.createRange(),e.selectNodeContents(t),e.collapse(!1),n=window.getSelection(),n.removeAllRanges(),n.addRange(e)):document.selection&&(e=document.body.createTextRange(),e.moveToElementText(t),e.collapse(!1),e.select())},matches:(t,e)=>(Element.prototype.matches||Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector||function(t){const e=(this.document||this.ownerDocument).querySelectorAll(t);let n=e.length;for(;--n>=0&&e.item(n)!==this;);return n>-1}).call(t,e),delegateEvent:(t,e,n,r)=>s.addEventListener(t,e,(function(e){let i=e.target||e.srcElement;for(;i!==t;)s.matches(i,n)&&r.call(i,Array.prototype.slice.call(arguments)),i=i.parentNode})),Palettes:o};t.exports=s},function(t,e,n){window,t.exports=function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=820)}([,function(t,e,n){"use strict";var r=function(t,e,n){t.prototype=e.prototype=n,n.constructor=t};function i(t,e){var n=Object.create(t.prototype);for(var r in e)n[r]=e[r];return n}function o(){}var a="\\s*([+-]?\\d+)\\s*",s="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",c="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",u=/^#([0-9a-f]{3})$/,h=/^#([0-9a-f]{6})$/,l=new RegExp("^rgb\\("+[a,a,a]+"\\)$"),d=new RegExp("^rgb\\("+[c,c,c]+"\\)$"),f=new RegExp("^rgba\\("+[a,a,a,s]+"\\)$"),g=new RegExp("^rgba\\("+[c,c,c,s]+"\\)$"),p=new RegExp("^hsl\\("+[s,c,c]+"\\)$"),m=new RegExp("^hsla\\("+[s,c,c,s]+"\\)$"),v={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function x(t){var e;return t=(t+"").trim().toLowerCase(),(e=u.exec(t))?new _((e=parseInt(e[1],16))>>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):(e=h.exec(t))?y(parseInt(e[1],16)):(e=l.exec(t))?new _(e[1],e[2],e[3],1):(e=d.exec(t))?new _(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=f.exec(t))?b(e[1],e[2],e[3],e[4]):(e=g.exec(t))?b(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=p.exec(t))?A(e[1],e[2]/100,e[3]/100,1):(e=m.exec(t))?A(e[1],e[2]/100,e[3]/100,e[4]):v.hasOwnProperty(t)?y(v[t]):"transparent"===t?new _(NaN,NaN,NaN,0):null}function y(t){return new _(t>>16&255,t>>8&255,255&t,1)}function b(t,e,n,r){return r<=0&&(t=e=n=NaN),new _(t,e,n,r)}function w(t){return t instanceof o||(t=x(t)),t?new _((t=t.rgb()).r,t.g,t.b,t.opacity):new _}function M(t,e,n,r){return 1===arguments.length?w(t):new _(t,e,n,null==r?1:r)}function _(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function S(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function A(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new P(t,e,n,r)}function E(t,e,n,r){return 1===arguments.length?function(t){if(t instanceof P)return new P(t.h,t.s,t.l,t.opacity);if(t instanceof o||(t=x(t)),!t)return new P;if(t instanceof P)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),s=NaN,c=a-i,u=(a+i)/2;return c?(s=e===a?(n-r)/c+6*(n<r):n===a?(r-e)/c+2:(e-n)/c+4,c/=u<.5?a+i:2-a-i,s*=60):c=u>0&&u<1?0:s,new P(s,c,u,t.opacity)}(t):new P(t,e,n,null==r?1:r)}function P(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function C(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}r(o,x,{displayable:function(){return this.rgb().displayable()},hex:function(){return this.rgb().hex()},toString:function(){return this.rgb()+""}}),r(_,M,i(o,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new _(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new _(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return 0<=this.r&&this.r<=255&&0<=this.g&&this.g<=255&&0<=this.b&&this.b<=255&&0<=this.opacity&&this.opacity<=1},hex:function(){return"#"+S(this.r)+S(this.g)+S(this.b)},toString:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}})),r(P,E,i(o,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new P(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new P(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new _(C(t>=240?t-240:t+120,i,r),C(t,i,r),C(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1}}));var O=Math.PI/180,I=180/Math.PI,k=.96422,B=.82521,T=6/29,N=3*T*T;function L(t){if(t instanceof G)return new G(t.l,t.a,t.b,t.opacity);if(t instanceof U){if(isNaN(t.h))return new G(t.l,0,0,t.opacity);var e=t.h*O;return new G(t.l,Math.cos(e)*t.c,Math.sin(e)*t.c,t.opacity)}t instanceof _||(t=w(t));var n,r,i=R(t.r),o=R(t.g),a=R(t.b),s=D((.2225045*i+.7168786*o+.0606169*a)/1);return i===o&&o===a?n=r=s:(n=D((.4360747*i+.3850649*o+.1430804*a)/k),r=D((.0139322*i+.0971045*o+.7141733*a)/B)),new G(116*s-16,500*(n-s),200*(s-r),t.opacity)}function Y(t,e){return new G(t,0,0,null==e?1:e)}function X(t,e,n,r){return 1===arguments.length?L(t):new G(t,e,n,null==r?1:r)}function G(t,e,n,r){this.l=+t,this.a=+e,this.b=+n,this.opacity=+r}function D(t){return t>.008856451679035631?Math.pow(t,1/3):t/N+4/29}function F(t){return t>T?t*t*t:N*(t-4/29)}function j(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function R(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function H(t){if(t instanceof U)return new U(t.h,t.c,t.l,t.opacity);if(t instanceof G||(t=L(t)),0===t.a&&0===t.b)return new U(NaN,0,t.l,t.opacity);var e=Math.atan2(t.b,t.a)*I;return new U(e<0?e+360:e,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}function q(t,e,n,r){return 1===arguments.length?H(t):new U(n,e,t,null==r?1:r)}function z(t,e,n,r){return 1===arguments.length?H(t):new U(t,e,n,null==r?1:r)}function U(t,e,n,r){this.h=+t,this.c=+e,this.l=+n,this.opacity=+r}r(G,X,i(o,{brighter:function(t){return new G(this.l+18*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new G(this.l-18*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,e=isNaN(this.a)?t:t+this.a/500,n=isNaN(this.b)?t:t-this.b/200;return new _(j(3.1338561*(e=k*F(e))-1.6168667*(t=1*F(t))-.4906146*(n=B*F(n))),j(-.9787684*e+1.9161415*t+.033454*n),j(.0719453*e-.2289914*t+1.4052427*n),this.opacity)}})),r(U,z,i(o,{brighter:function(t){return new U(this.h,this.c,this.l+18*(null==t?1:t),this.opacity)},darker:function(t){return new U(this.h,this.c,this.l-18*(null==t?1:t),this.opacity)},rgb:function(){return L(this).rgb()}}));var W=-.14861,V=1.78277,K=-.29227,Z=-.90649,Q=1.97294,$=Q*Z,J=Q*V,tt=V*K-Z*W;function et(t,e,n,r){return 1===arguments.length?function(t){if(t instanceof nt)return new nt(t.h,t.s,t.l,t.opacity);t instanceof _||(t=w(t));var e=t.r/255,n=t.g/255,r=t.b/255,i=(tt*r+$*e-J*n)/(tt+$-J),o=r-i,a=(Q*(n-i)-K*o)/Z,s=Math.sqrt(a*a+o*o)/(Q*i*(1-i)),c=s?Math.atan2(a,o)*I-120:NaN;return new nt(c<0?c+360:c,s,i,t.opacity)}(t):new nt(t,e,n,null==r?1:r)}function nt(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}r(nt,et,i(o,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new nt(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new nt(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=isNaN(this.h)?0:(this.h+120)*O,e=+this.l,n=isNaN(this.s)?0:this.s*e*(1-e),r=Math.cos(t),i=Math.sin(t);return new _(255*(e+n*(W*r+V*i)),255*(e+n*(K*r+Z*i)),255*(e+n*(Q*r)),this.opacity)}})),n.d(e,"a",(function(){return x})),n.d(e,"h",(function(){return M})),n.d(e,"e",(function(){return E})),n.d(e,"f",(function(){return X})),n.d(e,"d",(function(){return z})),n.d(e,"g",(function(){return q})),n.d(e,"c",(function(){return Y})),n.d(e,"b",(function(){return et}))},,,,,,,,,,,,,,,function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,n){"use strict";n.r(e);var r,i,o=0,a=0,s=0,c=0,u=0,h=0,l="object"==typeof performance&&performance.now?performance:Date,d="object"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};function f(){return u||(d(g),u=l.now()+h)}function g(){u=0}function p(){this._call=this._time=this._next=null}function m(t,e,n){var r=new p;return r.restart(t,e,n),r}function v(){f(),++o;for(var t,e=r;e;)(t=u-e._time)>=0&&e._call.call(null,t),e=e._next;--o}function x(){u=(c=l.now())+h,o=a=0;try{v()}finally{o=0,function(){for(var t,e,n=r,o=1/0;n;)n._call?(o>n._time&&(o=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:r=e);i=t,b(o)}(),u=0}}function y(){var t=l.now(),e=t-c;e>1e3&&(h-=e,c=t)}function b(t){o||(a&&(a=clearTimeout(a)),t-u>24?(t<1/0&&(a=setTimeout(x,t-l.now()-h)),s&&(s=clearInterval(s))):(s||(c=l.now(),s=setInterval(y,1e3)),o=1,d(x)))}p.prototype=m.prototype={constructor:p,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?f():+n)+(null==e?0:+e),this._next||i===this||(i?i._next=this:r=this,i=this),this._call=t,this._time=n,b()},stop:function(){this._call&&(this._call=null,this._time=1/0,b())}};var w=function(t,e,n){var r=new p;return e=null==e?0:+e,r.restart((function(n){r.stop(),t(n+e)}),e,n),r},M=function(t,e,n){var r=new p,i=e;return null==e?(r.restart(t,e,n),r):(e=+e,n=null==n?f():+n,r.restart((function o(a){a+=i,r.restart(o,i+=e,n),t(a)}),e,n),r)};n.d(e,"now",(function(){return f})),n.d(e,"timer",(function(){return m})),n.d(e,"timerFlush",(function(){return v})),n.d(e,"timeout",(function(){return w})),n.d(e,"interval",(function(){return M}))},,function(t,e,n){var r=n(644),i={};r.merge(i,r,{mixin:function(t,e){var n=t.CFG?"CFG":"ATTRS";if(t&&e){t._mixins=e,t[n]=t[n]||{};var r={};i.each(e,(function(e){i.augment(t,e);var o=e[n];o&&i.merge(r,o)})),t[n]=i.merge(r,t[n])}}}),t.exports=i},function(t,e,n){var r=n(117),i="object"==typeof self&&self&&self.Object===Object&&self,o=r||i||Function("return this")();t.exports=o},,,function(t,e){t.exports=function(t){return null!=t&&"object"==typeof t}},,,function(t,e,n){var r={},i=n(682),o=n(748),a=n(257),s=n(727),c=n(726),u=n(725);a.mix(r,a,c,u,s,o,i),t.exports=r},,,,,,,,function(t,e,n){var r=n(38),i=n(250),o=n(249),a=r?r.toStringTag:void 0;t.exports=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":a&&a in Object(t)?i(t):o(t)}},,,,function(t,e,n){var r=n(20).Symbol;t.exports=r},function(t,e,n){var r=n(34),i=n(23);t.exports=function(t){return"symbol"==typeof t||i(t)&&"[object Symbol]"==r(t)}},,,,,function(t,e,n){"use strict";function r(t){return+t}function i(t){return t*t}function o(t){return t*(2-t)}function a(t){return((t*=2)<=1?t*t:--t*(2-t)+1)/2}function s(t){return t*t*t}function c(t){return--t*t*t+1}function u(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}n.r(e);var h=function t(e){function n(t){return Math.pow(t,e)}return e=+e,n.exponent=t,n}(3),l=function t(e){function n(t){return 1-Math.pow(1-t,e)}return e=+e,n.exponent=t,n}(3),d=function t(e){function n(t){return((t*=2)<=1?Math.pow(t,e):2-Math.pow(2-t,e))/2}return e=+e,n.exponent=t,n}(3),f=Math.PI,g=f/2;function p(t){return 1-Math.cos(t*g)}function m(t){return Math.sin(t*g)}function v(t){return(1-Math.cos(f*t))/2}function x(t){return Math.pow(2,10*t-10)}function y(t){return 1-Math.pow(2,-10*t)}function b(t){return((t*=2)<=1?Math.pow(2,10*t-10):2-Math.pow(2,10-10*t))/2}function w(t){return 1-Math.sqrt(1-t*t)}function M(t){return Math.sqrt(1- --t*t)}function _(t){return((t*=2)<=1?1-Math.sqrt(1-t*t):Math.sqrt(1-(t-=2)*t)+1)/2}var S=4/11,A=7.5625;function E(t){return 1-P(1-t)}function P(t){return(t=+t)<S?A*t*t:t<8/11?A*(t-=6/11)*t+.75:t<10/11?A*(t-=9/11)*t+.9375:A*(t-=21/22)*t+63/64}function C(t){return((t*=2)<=1?1-P(1-t):P(t-1)+1)/2}var O=function t(e){function n(t){return t*t*((e+1)*t-e)}return e=+e,n.overshoot=t,n}(1.70158),I=function t(e){function n(t){return--t*t*((e+1)*t+e)+1}return e=+e,n.overshoot=t,n}(1.70158),k=function t(e){function n(t){return((t*=2)<1?t*t*((e+1)*t-e):(t-=2)*t*((e+1)*t+e)+2)/2}return e=+e,n.overshoot=t,n}(1.70158),B=2*Math.PI,T=function t(e,n){var r=Math.asin(1/(e=Math.max(1,e)))*(n/=B);function i(t){return e*Math.pow(2,10*--t)*Math.sin((r-t)/n)}return i.amplitude=function(e){return t(e,n*B)},i.period=function(n){return t(e,n)},i}(1,.3),N=function t(e,n){var r=Math.asin(1/(e=Math.max(1,e)))*(n/=B);function i(t){return 1-e*Math.pow(2,-10*(t=+t))*Math.sin((t+r)/n)}return i.amplitude=function(e){return t(e,n*B)},i.period=function(n){return t(e,n)},i}(1,.3),L=function t(e,n){var r=Math.asin(1/(e=Math.max(1,e)))*(n/=B);function i(t){return((t=2*t-1)<0?e*Math.pow(2,10*t)*Math.sin((r-t)/n):2-e*Math.pow(2,-10*t)*Math.sin((r+t)/n))/2}return i.amplitude=function(e){return t(e,n*B)},i.period=function(n){return t(e,n)},i}(1,.3);n.d(e,"easeLinear",(function(){return r})),n.d(e,"easeQuad",(function(){return a})),n.d(e,"easeQuadIn",(function(){return i})),n.d(e,"easeQuadOut",(function(){return o})),n.d(e,"easeQuadInOut",(function(){return a})),n.d(e,"easeCubic",(function(){return u})),n.d(e,"easeCubicIn",(function(){return s})),n.d(e,"easeCubicOut",(function(){return c})),n.d(e,"easeCubicInOut",(function(){return u})),n.d(e,"easePoly",(function(){return d})),n.d(e,"easePolyIn",(function(){return h})),n.d(e,"easePolyOut",(function(){return l})),n.d(e,"easePolyInOut",(function(){return d})),n.d(e,"easeSin",(function(){return v})),n.d(e,"easeSinIn",(function(){return p})),n.d(e,"easeSinOut",(function(){return m})),n.d(e,"easeSinInOut",(function(){return v})),n.d(e,"easeExp",(function(){return b})),n.d(e,"easeExpIn",(function(){return x})),n.d(e,"easeExpOut",(function(){return y})),n.d(e,"easeExpInOut",(function(){return b})),n.d(e,"easeCircle",(function(){return _})),n.d(e,"easeCircleIn",(function(){return w})),n.d(e,"easeCircleOut",(function(){return M})),n.d(e,"easeCircleInOut",(function(){return _})),n.d(e,"easeBounce",(function(){return P})),n.d(e,"easeBounceIn",(function(){return E})),n.d(e,"easeBounceOut",(function(){return P})),n.d(e,"easeBounceInOut",(function(){return C})),n.d(e,"easeBack",(function(){return k})),n.d(e,"easeBackIn",(function(){return O})),n.d(e,"easeBackOut",(function(){return I})),n.d(e,"easeBackInOut",(function(){return k})),n.d(e,"easeElastic",(function(){return N})),n.d(e,"easeElasticIn",(function(){return T})),n.d(e,"easeElasticOut",(function(){return N})),n.d(e,"easeElasticInOut",(function(){return L}))},function(t,e,n){var r=n(115),i=Array.isArray?Array.isArray:function(t){return r(t,"Array")};t.exports=i},function(t,e,n){var r=n(621),i=n(45);t.exports=function(t,e){if(t)if(i(t))for(var n=0,o=t.length;n<o&&!1!==e(t[n],n);n++);else if(r(t))for(var a in t)if(t.hasOwnProperty(a)&&!1===e(t[a],a))break}},,,,,,,,,,,,function(t,e,n){var r=n(19),i=n(742),o=n(641),a=n(613),s=function t(e){t.superclass.constructor.call(this,e)};s.ATTRS={},r.extend(s,o);var c={matrix:"matrix",path:"path",points:"points",lineDash:"lineDash"};r.augment(s,i,{isShape:!0,drawInner:function(t){var e=this._attrs;this.createPath(t);var n=t.globalAlpha;if(this.hasFill()){var i=e.fillOpacity;r.isNil(i)||1===i?t.fill():(t.globalAlpha=i,t.fill(),t.globalAlpha=n)}if(this.hasStroke()&&this._attrs.lineWidth>0){var o=e.strokeOpacity;r.isNil(o)||1===o||(t.globalAlpha=o),t.stroke()}this.afterPath(t)},afterPath:function(){},isHitBox:function(){return!0},isHit:function(t,e){var n=[t,e,1];if(this.invert(n),this.isHitBox()){var r=this.getBBox();if(r&&!a.box(r.minX,r.maxX,r.minY,r.maxY,n[0],n[1]))return!1}var i=this._attrs.clip;return i?(i.invert(n,this.get("canvas")),!!i.isPointInPath(n[0],n[1])&&this.isPointInPath(n[0],n[1])):this.isPointInPath(n[0],n[1])},calculateBox:function(){return null},getHitLineWidth:function(){var t=this._attrs,e=t.lineAppendWidth||0;return(t.lineWidth||0)+e},clearTotalMatrix:function(){this._cfg.totalMatrix=null,this._cfg.region=null},clearBBox:function(){this._cfg.box=null,this._cfg.region=null},getBBox:function(){var t=this._cfg.box;return t||((t=this.calculateBox())&&(t.x=t.minX,t.y=t.minY,t.width=t.maxX-t.minX,t.height=t.maxY-t.minY),this._cfg.box=t),t},clone:function(){var t=null,e=this._attrs,n={};return r.each(e,(function(t,i){c[i]&&r.isArray(e[i])?n[i]=function(t){for(var e=[],n=0;n<t.length;n++)r.isArray(t[n])?e.push([].concat(t[n])):e.push(t[n]);return e}(e[i]):n[i]=e[i]})),(t=new this.constructor({attrs:n}))._cfg.zIndex=this._cfg.zIndex,t}}),t.exports=s},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setMatrixArrayType=function(t){e.ARRAY_TYPE=t},e.toRadian=function(t){return t*i},e.equals=function(t,e){return Math.abs(t-e)<=r*Math.max(1,Math.abs(t),Math.abs(e))};var r=e.EPSILON=1e-6;e.ARRAY_TYPE="undefined"!=typeof Float32Array?Float32Array:Array,e.RANDOM=Math.random;var i=Math.PI/180},,,,,,,,,,,,,,,,,,,,,,,,,function(t,e,n){var r=n(115);t.exports=function(t){return r(t,"Function")}},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,function(t,e){var n={}.toString;t.exports=function(t,e){return n.call(t)==="[object "+e+"]"}},function(t,e,n){var r; +/*! + * EventEmitter v5.1.0 - git.io/ee + * Unlicense - http://unlicense.org/ + * Oliver Caldwell - http://oli.me.uk/ + * @preserve + */!function(e){"use strict";function i(){}var o=i.prototype,a=e.EventEmitter;function s(t,e){for(var n=t.length;n--;)if(t[n].listener===e)return n;return-1}function c(t){return function(){return this[t].apply(this,arguments)}}o.getListeners=function(t){var e,n,r=this._getEvents();if(t instanceof RegExp)for(n in e={},r)r.hasOwnProperty(n)&&t.test(n)&&(e[n]=r[n]);else e=r[t]||(r[t]=[]);return e},o.flattenListeners=function(t){var e,n=[];for(e=0;e<t.length;e+=1)n.push(t[e].listener);return n},o.getListenersAsObject=function(t){var e,n=this.getListeners(t);return n instanceof Array&&((e={})[t]=n),e||n},o.addListener=function(t,e){if(!function t(e){return"function"==typeof e||e instanceof RegExp||!(!e||"object"!=typeof e)&&t(e.listener)}(e))throw new TypeError("listener must be a function");var n,r=this.getListenersAsObject(t),i="object"==typeof e;for(n in r)r.hasOwnProperty(n)&&-1===s(r[n],e)&&r[n].push(i?e:{listener:e,once:!1});return this},o.on=c("addListener"),o.addOnceListener=function(t,e){return this.addListener(t,{listener:e,once:!0})},o.once=c("addOnceListener"),o.defineEvent=function(t){return this.getListeners(t),this},o.defineEvents=function(t){for(var e=0;e<t.length;e+=1)this.defineEvent(t[e]);return this},o.removeListener=function(t,e){var n,r,i=this.getListenersAsObject(t);for(r in i)i.hasOwnProperty(r)&&-1!==(n=s(i[r],e))&&i[r].splice(n,1);return this},o.off=c("removeListener"),o.addListeners=function(t,e){return this.manipulateListeners(!1,t,e)},o.removeListeners=function(t,e){return this.manipulateListeners(!0,t,e)},o.manipulateListeners=function(t,e,n){var r,i,o=t?this.removeListener:this.addListener,a=t?this.removeListeners:this.addListeners;if("object"!=typeof e||e instanceof RegExp)for(r=n.length;r--;)o.call(this,e,n[r]);else for(r in e)e.hasOwnProperty(r)&&(i=e[r])&&("function"==typeof i?o.call(this,r,i):a.call(this,r,i));return this},o.removeEvent=function(t){var e,n=typeof t,r=this._getEvents();if("string"===n)delete r[t];else if(t instanceof RegExp)for(e in r)r.hasOwnProperty(e)&&t.test(e)&&delete r[e];else delete this._events;return this},o.removeAllListeners=c("removeEvent"),o.emitEvent=function(t,e){var n,r,i,o,a=this.getListenersAsObject(t);for(o in a)if(a.hasOwnProperty(o))for(n=a[o].slice(0),i=0;i<n.length;i++)!0===(r=n[i]).once&&this.removeListener(t,r.listener),r.listener.apply(this,e||[])===this._getOnceReturnValue()&&this.removeListener(t,r.listener);return this},o.trigger=c("emitEvent"),o.emit=function(t){var e=Array.prototype.slice.call(arguments,1);return this.emitEvent(t,e)},o.setOnceReturnValue=function(t){return this._onceReturnValue=t,this},o._getOnceReturnValue=function(){return!this.hasOwnProperty("_onceReturnValue")||this._onceReturnValue},o._getEvents=function(){return this._events||(this._events={})},i.noConflict=function(){return e.EventEmitter=a,i},void 0===(r=function(){return i}.call(e,n,e,t))||(t.exports=r)}(this||{})},function(t,e,n){(function(e){var n="object"==typeof e&&e&&e.Object===Object&&e;t.exports=n}).call(this,n(252))},function(t,e){t.exports=function(t){return null!==t&&"function"!=typeof t&&isFinite(t.length)}},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,function(t,e,n){var r=n(115);t.exports=function(t){return r(t,"Number")}},function(t,e){t.exports=function(t){return null==t}},function(t,e,n){"use strict";n.r(e);var r=n(1);function i(t,e,n,r,i){var o=t*t,a=o*t;return((1-3*t+3*o-a)*e+(4-6*o+3*a)*n+(1+3*t+3*o-3*a)*r+a*i)/6}var o=function(t){var e=t.length-1;return function(n){var r=n<=0?n=0:n>=1?(n=1,e-1):Math.floor(n*e),o=t[r],a=t[r+1],s=r>0?t[r-1]:2*o-a,c=r<e-1?t[r+2]:2*a-o;return i((n-r/e)*e,s,o,a,c)}},a=function(t){var e=t.length;return function(n){var r=Math.floor(((n%=1)<0?++n:n)*e),o=t[(r+e-1)%e],a=t[r%e],s=t[(r+1)%e],c=t[(r+2)%e];return i((n-r/e)*e,o,a,s,c)}},s=function(t){return function(){return t}};function c(t,e){return function(n){return t+n*e}}function u(t,e){var n=e-t;return n?c(t,n>180||n<-180?n-360*Math.round(n/360):n):s(isNaN(t)?e:t)}function h(t,e){var n=e-t;return n?c(t,n):s(isNaN(t)?e:t)}var l=function t(e){var n=function(t){return 1==(t=+t)?h:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):s(isNaN(e)?n:e)}}(e);function i(t,e){var i=n((t=Object(r.h)(t)).r,(e=Object(r.h)(e)).r),o=n(t.g,e.g),a=n(t.b,e.b),s=h(t.opacity,e.opacity);return function(e){return t.r=i(e),t.g=o(e),t.b=a(e),t.opacity=s(e),t+""}}return i.gamma=t,i}(1);function d(t){return function(e){var n,i,o=e.length,a=new Array(o),s=new Array(o),c=new Array(o);for(n=0;n<o;++n)i=Object(r.h)(e[n]),a[n]=i.r||0,s[n]=i.g||0,c[n]=i.b||0;return a=t(a),s=t(s),c=t(c),i.opacity=1,function(t){return i.r=a(t),i.g=s(t),i.b=c(t),i+""}}}var f,g,p,m,v=d(o),x=d(a),y=function(t,e){var n,r=e?e.length:0,i=t?Math.min(r,t.length):0,o=new Array(i),a=new Array(r);for(n=0;n<i;++n)o[n]=E(t[n],e[n]);for(;n<r;++n)a[n]=e[n];return function(t){for(n=0;n<i;++n)a[n]=o[n](t);return a}},b=function(t,e){var n=new Date;return e-=t=+t,function(r){return n.setTime(t+e*r),n}},w=function(t,e){return e-=t=+t,function(n){return t+e*n}},M=function(t,e){var n,r={},i={};for(n in null!==t&&"object"==typeof t||(t={}),null!==e&&"object"==typeof e||(e={}),e)n in t?r[n]=E(t[n],e[n]):i[n]=e[n];return function(t){for(n in r)i[n]=r[n](t);return i}},_=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,S=new RegExp(_.source,"g"),A=function(t,e){var n,r,i,o=_.lastIndex=S.lastIndex=0,a=-1,s=[],c=[];for(t+="",e+="";(n=_.exec(t))&&(r=S.exec(e));)(i=r.index)>o&&(i=e.slice(o,i),s[a]?s[a]+=i:s[++a]=i),(n=n[0])===(r=r[0])?s[a]?s[a]+=r:s[++a]=r:(s[++a]=null,c.push({i:a,x:w(n,r)})),o=S.lastIndex;return o<e.length&&(i=e.slice(o),s[a]?s[a]+=i:s[++a]=i),s.length<2?c[0]?function(t){return function(e){return t(e)+""}}(c[0].x):function(t){return function(){return t}}(e):(e=c.length,function(t){for(var n,r=0;r<e;++r)s[(n=c[r]).i]=n.x(t);return s.join("")})},E=function(t,e){var n,i=typeof e;return null==e||"boolean"===i?s(e):("number"===i?w:"string"===i?(n=Object(r.a)(e))?(e=n,l):A:e instanceof r.a?l:e instanceof Date?b:Array.isArray(e)?y:"function"!=typeof e.valueOf&&"function"!=typeof e.toString||isNaN(e)?M:w)(t,e)},P=function(t,e){return e-=t=+t,function(n){return Math.round(t+e*n)}},C=180/Math.PI,O={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1},I=function(t,e,n,r,i,o){var a,s,c;return(a=Math.sqrt(t*t+e*e))&&(t/=a,e/=a),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r<e*n&&(t=-t,e=-e,c=-c,a=-a),{translateX:i,translateY:o,rotate:Math.atan2(e,t)*C,skewX:Math.atan(c)*C,scaleX:a,scaleY:s}};function k(t,e,n,r){function i(t){return t.length?t.pop()+" ":""}return function(o,a){var s=[],c=[];return o=t(o),a=t(a),function(t,r,i,o,a,s){if(t!==i||r!==o){var c=a.push("translate(",null,e,null,n);s.push({i:c-4,x:w(t,i)},{i:c-2,x:w(r,o)})}else(i||o)&&a.push("translate("+i+e+o+n)}(o.translateX,o.translateY,a.translateX,a.translateY,s,c),function(t,e,n,o){t!==e?(t-e>180?e+=360:e-t>180&&(t+=360),o.push({i:n.push(i(n)+"rotate(",null,r)-2,x:w(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(o.rotate,a.rotate,s,c),function(t,e,n,o){t!==e?o.push({i:n.push(i(n)+"skewX(",null,r)-2,x:w(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(o.skewX,a.skewX,s,c),function(t,e,n,r,o,a){if(t!==n||e!==r){var s=o.push(i(o)+"scale(",null,",",null,")");a.push({i:s-4,x:w(t,n)},{i:s-2,x:w(e,r)})}else 1===n&&1===r||o.push(i(o)+"scale("+n+","+r+")")}(o.scaleX,o.scaleY,a.scaleX,a.scaleY,s,c),o=a=null,function(t){for(var e,n=-1,r=c.length;++n<r;)s[(e=c[n]).i]=e.x(t);return s.join("")}}}var B=k((function(t){return"none"===t?O:(f||(f=document.createElement("DIV"),g=document.documentElement,p=document.defaultView),f.style.transform=t,t=p.getComputedStyle(g.appendChild(f),null).getPropertyValue("transform"),g.removeChild(f),t=t.slice(7,-1).split(","),I(+t[0],+t[1],+t[2],+t[3],+t[4],+t[5]))}),"px, ","px)","deg)"),T=k((function(t){return null==t?O:(m||(m=document.createElementNS("http://www.w3.org/2000/svg","g")),m.setAttribute("transform",t),(t=m.transform.baseVal.consolidate())?(t=t.matrix,I(t.a,t.b,t.c,t.d,t.e,t.f)):O)}),", ",")",")"),N=Math.SQRT2;function L(t){return((t=Math.exp(t))+1/t)/2}var Y=function(t,e){var n,r,i=t[0],o=t[1],a=t[2],s=e[0],c=e[1],u=e[2],h=s-i,l=c-o,d=h*h+l*l;if(d<1e-12)r=Math.log(u/a)/N,n=function(t){return[i+t*h,o+t*l,a*Math.exp(N*t*r)]};else{var f=Math.sqrt(d),g=(u*u-a*a+4*d)/(2*a*2*f),p=(u*u-a*a-4*d)/(2*u*2*f),m=Math.log(Math.sqrt(g*g+1)-g),v=Math.log(Math.sqrt(p*p+1)-p);r=(v-m)/N,n=function(t){var e=t*r,n=L(m),s=a/(2*f)*(n*function(t){return((t=Math.exp(2*t))-1)/(t+1)}(N*e+m)-function(t){return((t=Math.exp(t))-1/t)/2}(m));return[i+s*h,o+s*l,a*n/L(N*e+m)]}}return n.duration=1e3*r,n};function X(t){return function(e,n){var i=t((e=Object(r.e)(e)).h,(n=Object(r.e)(n)).h),o=h(e.s,n.s),a=h(e.l,n.l),s=h(e.opacity,n.opacity);return function(t){return e.h=i(t),e.s=o(t),e.l=a(t),e.opacity=s(t),e+""}}}var G=X(u),D=X(h);function F(t,e){var n=h((t=Object(r.f)(t)).l,(e=Object(r.f)(e)).l),i=h(t.a,e.a),o=h(t.b,e.b),a=h(t.opacity,e.opacity);return function(e){return t.l=n(e),t.a=i(e),t.b=o(e),t.opacity=a(e),t+""}}function j(t){return function(e,n){var i=t((e=Object(r.d)(e)).h,(n=Object(r.d)(n)).h),o=h(e.c,n.c),a=h(e.l,n.l),s=h(e.opacity,n.opacity);return function(t){return e.h=i(t),e.c=o(t),e.l=a(t),e.opacity=s(t),e+""}}}var R=j(u),H=j(h);function q(t){return function e(n){function i(e,i){var o=t((e=Object(r.b)(e)).h,(i=Object(r.b)(i)).h),a=h(e.s,i.s),s=h(e.l,i.l),c=h(e.opacity,i.opacity);return function(t){return e.h=o(t),e.s=a(t),e.l=s(Math.pow(t,n)),e.opacity=c(t),e+""}}return n=+n,i.gamma=e,i}(1)}var z=q(u),U=q(h),W=function(t,e){for(var n=new Array(e),r=0;r<e;++r)n[r]=t(r/(e-1));return n};n.d(e,"interpolate",(function(){return E})),n.d(e,"interpolateArray",(function(){return y})),n.d(e,"interpolateBasis",(function(){return o})),n.d(e,"interpolateBasisClosed",(function(){return a})),n.d(e,"interpolateDate",(function(){return b})),n.d(e,"interpolateNumber",(function(){return w})),n.d(e,"interpolateObject",(function(){return M})),n.d(e,"interpolateRound",(function(){return P})),n.d(e,"interpolateString",(function(){return A})),n.d(e,"interpolateTransformCss",(function(){return B})),n.d(e,"interpolateTransformSvg",(function(){return T})),n.d(e,"interpolateZoom",(function(){return Y})),n.d(e,"interpolateRgb",(function(){return l})),n.d(e,"interpolateRgbBasis",(function(){return v})),n.d(e,"interpolateRgbBasisClosed",(function(){return x})),n.d(e,"interpolateHsl",(function(){return G})),n.d(e,"interpolateHslLong",(function(){return D})),n.d(e,"interpolateLab",(function(){return F})),n.d(e,"interpolateHcl",(function(){return R})),n.d(e,"interpolateHclLong",(function(){return H})),n.d(e,"interpolateCubehelix",(function(){return z})),n.d(e,"interpolateCubehelixLong",(function(){return U})),n.d(e,"quantize",(function(){return W}))},,,,,,,,,function(t,e,n){var r=n(609);t.exports={track:!1,defaultNodeSize:40,labelStyle:{fill:"#595959",textAlign:"center",textBaseline:"middle"},groupStyle:{stroke:"#CED4D9",fill:"#F2F4F5",radius:2},groupBackgroundPadding:[40,10,10,10],updateDuration:450,enterDuration:450,leaveDuration:450,updateEasing:"easeQuadOut",enterEasing:"easeQuadOut",leaveEasing:"easeQuadOut",version:r}},function(t,e,n){t.exports={Canvas:n(747),Group:n(642),Shape:n(58),Arc:n(638),Circle:n(637),Dom:n(636),Ellipse:n(635),Fan:n(634),Image:n(633),Line:n(632),Marker:n(611),Path:n(631),Polygon:n(630),Polyline:n(629),Rect:n(628),Text:n(627),PathSegment:n(600),PathUtil:n(610),Event:n(643),version:"3.3.5"}},function(t,e){var n=Object.prototype.toString;t.exports=function(t){return n.call(t)}},function(t,e,n){var r=n(38),i=Object.prototype,o=i.hasOwnProperty,a=i.toString,s=r?r.toStringTag:void 0;t.exports=function(t){var e=o.call(t,s),n=t[s];try{t[s]=void 0;var r=!0}catch(t){}var i=a.call(t);return r&&(e?t[s]=n:delete t[s]),i}},function(t,e,n){var r=n(16),i=n(39),o=/^\s+|\s+$/g,a=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,c=/^0o[0-7]+$/i,u=parseInt;t.exports=function(t){if("number"==typeof t)return t;if(i(t))return NaN;if(r(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=r(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(o,"");var n=s.test(t);return n||c.test(t)?u(t.slice(2),n?2:8):a.test(t)?NaN:+t}},function(t,e){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){var r=n(20);t.exports=function(){return r.Date.now()}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.forEach=e.sqrLen=e.len=e.sqrDist=e.dist=e.div=e.mul=e.sub=void 0,e.create=i,e.clone=function(t){var e=new r.ARRAY_TYPE(3);return e[0]=t[0],e[1]=t[1],e[2]=t[2],e},e.length=o,e.fromValues=a,e.copy=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t},e.set=function(t,e,n,r){return t[0]=e,t[1]=n,t[2]=r,t},e.add=function(t,e,n){return t[0]=e[0]+n[0],t[1]=e[1]+n[1],t[2]=e[2]+n[2],t},e.subtract=s,e.multiply=c,e.divide=u,e.ceil=function(t,e){return t[0]=Math.ceil(e[0]),t[1]=Math.ceil(e[1]),t[2]=Math.ceil(e[2]),t},e.floor=function(t,e){return t[0]=Math.floor(e[0]),t[1]=Math.floor(e[1]),t[2]=Math.floor(e[2]),t},e.min=function(t,e,n){return t[0]=Math.min(e[0],n[0]),t[1]=Math.min(e[1],n[1]),t[2]=Math.min(e[2],n[2]),t},e.max=function(t,e,n){return t[0]=Math.max(e[0],n[0]),t[1]=Math.max(e[1],n[1]),t[2]=Math.max(e[2],n[2]),t},e.round=function(t,e){return t[0]=Math.round(e[0]),t[1]=Math.round(e[1]),t[2]=Math.round(e[2]),t},e.scale=function(t,e,n){return t[0]=e[0]*n,t[1]=e[1]*n,t[2]=e[2]*n,t},e.scaleAndAdd=function(t,e,n,r){return t[0]=e[0]+n[0]*r,t[1]=e[1]+n[1]*r,t[2]=e[2]+n[2]*r,t},e.distance=h,e.squaredDistance=l,e.squaredLength=d,e.negate=function(t,e){return t[0]=-e[0],t[1]=-e[1],t[2]=-e[2],t},e.inverse=function(t,e){return t[0]=1/e[0],t[1]=1/e[1],t[2]=1/e[2],t},e.normalize=f,e.dot=g,e.cross=function(t,e,n){var r=e[0],i=e[1],o=e[2],a=n[0],s=n[1],c=n[2];return t[0]=i*c-o*s,t[1]=o*a-r*c,t[2]=r*s-i*a,t},e.lerp=function(t,e,n,r){var i=e[0],o=e[1],a=e[2];return t[0]=i+r*(n[0]-i),t[1]=o+r*(n[1]-o),t[2]=a+r*(n[2]-a),t},e.hermite=function(t,e,n,r,i,o){var a=o*o,s=a*(2*o-3)+1,c=a*(o-2)+o,u=a*(o-1),h=a*(3-2*o);return t[0]=e[0]*s+n[0]*c+r[0]*u+i[0]*h,t[1]=e[1]*s+n[1]*c+r[1]*u+i[1]*h,t[2]=e[2]*s+n[2]*c+r[2]*u+i[2]*h,t},e.bezier=function(t,e,n,r,i,o){var a=1-o,s=a*a,c=o*o,u=s*a,h=3*o*s,l=3*c*a,d=c*o;return t[0]=e[0]*u+n[0]*h+r[0]*l+i[0]*d,t[1]=e[1]*u+n[1]*h+r[1]*l+i[1]*d,t[2]=e[2]*u+n[2]*h+r[2]*l+i[2]*d,t},e.random=function(t,e){e=e||1;var n=2*r.RANDOM()*Math.PI,i=2*r.RANDOM()-1,o=Math.sqrt(1-i*i)*e;return t[0]=Math.cos(n)*o,t[1]=Math.sin(n)*o,t[2]=i*e,t},e.transformMat4=function(t,e,n){var r=e[0],i=e[1],o=e[2],a=n[3]*r+n[7]*i+n[11]*o+n[15];return a=a||1,t[0]=(n[0]*r+n[4]*i+n[8]*o+n[12])/a,t[1]=(n[1]*r+n[5]*i+n[9]*o+n[13])/a,t[2]=(n[2]*r+n[6]*i+n[10]*o+n[14])/a,t},e.transformMat3=function(t,e,n){var r=e[0],i=e[1],o=e[2];return t[0]=r*n[0]+i*n[3]+o*n[6],t[1]=r*n[1]+i*n[4]+o*n[7],t[2]=r*n[2]+i*n[5]+o*n[8],t},e.transformQuat=function(t,e,n){var r=n[0],i=n[1],o=n[2],a=n[3],s=e[0],c=e[1],u=e[2],h=i*u-o*c,l=o*s-r*u,d=r*c-i*s,f=i*d-o*l,g=o*h-r*d,p=r*l-i*h,m=2*a;return h*=m,l*=m,d*=m,f*=2,g*=2,p*=2,t[0]=s+h+f,t[1]=c+l+g,t[2]=u+d+p,t},e.rotateX=function(t,e,n,r){var i=[],o=[];return i[0]=e[0]-n[0],i[1]=e[1]-n[1],i[2]=e[2]-n[2],o[0]=i[0],o[1]=i[1]*Math.cos(r)-i[2]*Math.sin(r),o[2]=i[1]*Math.sin(r)+i[2]*Math.cos(r),t[0]=o[0]+n[0],t[1]=o[1]+n[1],t[2]=o[2]+n[2],t},e.rotateY=function(t,e,n,r){var i=[],o=[];return i[0]=e[0]-n[0],i[1]=e[1]-n[1],i[2]=e[2]-n[2],o[0]=i[2]*Math.sin(r)+i[0]*Math.cos(r),o[1]=i[1],o[2]=i[2]*Math.cos(r)-i[0]*Math.sin(r),t[0]=o[0]+n[0],t[1]=o[1]+n[1],t[2]=o[2]+n[2],t},e.rotateZ=function(t,e,n,r){var i=[],o=[];return i[0]=e[0]-n[0],i[1]=e[1]-n[1],i[2]=e[2]-n[2],o[0]=i[0]*Math.cos(r)-i[1]*Math.sin(r),o[1]=i[0]*Math.sin(r)+i[1]*Math.cos(r),o[2]=i[2],t[0]=o[0]+n[0],t[1]=o[1]+n[1],t[2]=o[2]+n[2],t},e.angle=function(t,e){var n=a(t[0],t[1],t[2]),r=a(e[0],e[1],e[2]);f(n,n),f(r,r);var i=g(n,r);return i>1?0:i<-1?Math.PI:Math.acos(i)},e.str=function(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"},e.exactEquals=function(t,e){return t[0]===e[0]&&t[1]===e[1]&&t[2]===e[2]},e.equals=function(t,e){var n=t[0],i=t[1],o=t[2],a=e[0],s=e[1],c=e[2];return Math.abs(n-a)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(a))&&Math.abs(i-s)<=r.EPSILON*Math.max(1,Math.abs(i),Math.abs(s))&&Math.abs(o-c)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(c))};var r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}(n(59));function i(){var t=new r.ARRAY_TYPE(3);return r.ARRAY_TYPE!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t}function o(t){var e=t[0],n=t[1],r=t[2];return Math.sqrt(e*e+n*n+r*r)}function a(t,e,n){var i=new r.ARRAY_TYPE(3);return i[0]=t,i[1]=e,i[2]=n,i}function s(t,e,n){return t[0]=e[0]-n[0],t[1]=e[1]-n[1],t[2]=e[2]-n[2],t}function c(t,e,n){return t[0]=e[0]*n[0],t[1]=e[1]*n[1],t[2]=e[2]*n[2],t}function u(t,e,n){return t[0]=e[0]/n[0],t[1]=e[1]/n[1],t[2]=e[2]/n[2],t}function h(t,e){var n=e[0]-t[0],r=e[1]-t[1],i=e[2]-t[2];return Math.sqrt(n*n+r*r+i*i)}function l(t,e){var n=e[0]-t[0],r=e[1]-t[1],i=e[2]-t[2];return n*n+r*r+i*i}function d(t){var e=t[0],n=t[1],r=t[2];return e*e+n*n+r*r}function f(t,e){var n=e[0],r=e[1],i=e[2],o=n*n+r*r+i*i;return o>0&&(o=1/Math.sqrt(o),t[0]=e[0]*o,t[1]=e[1]*o,t[2]=e[2]*o),t}function g(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}e.sub=s,e.mul=c,e.div=u,e.dist=h,e.sqrDist=l,e.len=o,e.sqrLen=d,e.forEach=function(){var t=i();return function(e,n,r,i,o,a){var s,c=void 0;for(n||(n=3),r||(r=0),s=i?Math.min(i*n+r,e.length):e.length,c=r;c<s;c+=n)t[0]=e[c],t[1]=e[c+1],t[2]=e[c+2],o(t,t,a),e[c]=t[0],e[c+1]=t[1],e[c+2]=t[2];return e}}()},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.forEach=e.sqrLen=e.sqrDist=e.dist=e.div=e.mul=e.sub=e.len=void 0,e.create=i,e.clone=function(t){var e=new r.ARRAY_TYPE(2);return e[0]=t[0],e[1]=t[1],e},e.fromValues=function(t,e){var n=new r.ARRAY_TYPE(2);return n[0]=t,n[1]=e,n},e.copy=function(t,e){return t[0]=e[0],t[1]=e[1],t},e.set=function(t,e,n){return t[0]=e,t[1]=n,t},e.add=function(t,e,n){return t[0]=e[0]+n[0],t[1]=e[1]+n[1],t},e.subtract=o,e.multiply=a,e.divide=s,e.ceil=function(t,e){return t[0]=Math.ceil(e[0]),t[1]=Math.ceil(e[1]),t},e.floor=function(t,e){return t[0]=Math.floor(e[0]),t[1]=Math.floor(e[1]),t},e.min=function(t,e,n){return t[0]=Math.min(e[0],n[0]),t[1]=Math.min(e[1],n[1]),t},e.max=function(t,e,n){return t[0]=Math.max(e[0],n[0]),t[1]=Math.max(e[1],n[1]),t},e.round=function(t,e){return t[0]=Math.round(e[0]),t[1]=Math.round(e[1]),t},e.scale=function(t,e,n){return t[0]=e[0]*n,t[1]=e[1]*n,t},e.scaleAndAdd=function(t,e,n,r){return t[0]=e[0]+n[0]*r,t[1]=e[1]+n[1]*r,t},e.distance=c,e.squaredDistance=u,e.length=h,e.squaredLength=l,e.negate=function(t,e){return t[0]=-e[0],t[1]=-e[1],t},e.inverse=function(t,e){return t[0]=1/e[0],t[1]=1/e[1],t},e.normalize=function(t,e){var n=e[0],r=e[1],i=n*n+r*r;return i>0&&(i=1/Math.sqrt(i),t[0]=e[0]*i,t[1]=e[1]*i),t},e.dot=function(t,e){return t[0]*e[0]+t[1]*e[1]},e.cross=function(t,e,n){var r=e[0]*n[1]-e[1]*n[0];return t[0]=t[1]=0,t[2]=r,t},e.lerp=function(t,e,n,r){var i=e[0],o=e[1];return t[0]=i+r*(n[0]-i),t[1]=o+r*(n[1]-o),t},e.random=function(t,e){e=e||1;var n=2*r.RANDOM()*Math.PI;return t[0]=Math.cos(n)*e,t[1]=Math.sin(n)*e,t},e.transformMat2=function(t,e,n){var r=e[0],i=e[1];return t[0]=n[0]*r+n[2]*i,t[1]=n[1]*r+n[3]*i,t},e.transformMat2d=function(t,e,n){var r=e[0],i=e[1];return t[0]=n[0]*r+n[2]*i+n[4],t[1]=n[1]*r+n[3]*i+n[5],t},e.transformMat3=function(t,e,n){var r=e[0],i=e[1];return t[0]=n[0]*r+n[3]*i+n[6],t[1]=n[1]*r+n[4]*i+n[7],t},e.transformMat4=function(t,e,n){var r=e[0],i=e[1];return t[0]=n[0]*r+n[4]*i+n[12],t[1]=n[1]*r+n[5]*i+n[13],t},e.rotate=function(t,e,n,r){var i=e[0]-n[0],o=e[1]-n[1],a=Math.sin(r),s=Math.cos(r);return t[0]=i*s-o*a+n[0],t[1]=i*a+o*s+n[1],t},e.angle=function(t,e){var n=t[0],r=t[1],i=e[0],o=e[1],a=n*n+r*r;a>0&&(a=1/Math.sqrt(a));var s=i*i+o*o;s>0&&(s=1/Math.sqrt(s));var c=(n*i+r*o)*a*s;return c>1?0:c<-1?Math.PI:Math.acos(c)},e.str=function(t){return"vec2("+t[0]+", "+t[1]+")"},e.exactEquals=function(t,e){return t[0]===e[0]&&t[1]===e[1]},e.equals=function(t,e){var n=t[0],i=t[1],o=e[0],a=e[1];return Math.abs(n-o)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(o))&&Math.abs(i-a)<=r.EPSILON*Math.max(1,Math.abs(i),Math.abs(a))};var r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}(n(59));function i(){var t=new r.ARRAY_TYPE(2);return r.ARRAY_TYPE!=Float32Array&&(t[0]=0,t[1]=0),t}function o(t,e,n){return t[0]=e[0]-n[0],t[1]=e[1]-n[1],t}function a(t,e,n){return t[0]=e[0]*n[0],t[1]=e[1]*n[1],t}function s(t,e,n){return t[0]=e[0]/n[0],t[1]=e[1]/n[1],t}function c(t,e){var n=e[0]-t[0],r=e[1]-t[1];return Math.sqrt(n*n+r*r)}function u(t,e){var n=e[0]-t[0],r=e[1]-t[1];return n*n+r*r}function h(t){var e=t[0],n=t[1];return Math.sqrt(e*e+n*n)}function l(t){var e=t[0],n=t[1];return e*e+n*n}e.len=h,e.sub=o,e.mul=a,e.div=s,e.dist=c,e.sqrDist=u,e.sqrLen=l,e.forEach=function(){var t=i();return function(e,n,r,i,o,a){var s,c=void 0;for(n||(n=2),r||(r=0),s=i?Math.min(i*n+r,e.length):e.length,c=r;c<s;c+=n)t[0]=e[c],t[1]=e[c+1],o(t,t,a),e[c]=t[0],e[c+1]=t[1];return e}}()},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.sub=e.mul=void 0,e.create=function(){var t=new r.ARRAY_TYPE(9);return r.ARRAY_TYPE!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[5]=0,t[6]=0,t[7]=0),t[0]=1,t[4]=1,t[8]=1,t},e.fromMat4=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[4],t[4]=e[5],t[5]=e[6],t[6]=e[8],t[7]=e[9],t[8]=e[10],t},e.clone=function(t){var e=new r.ARRAY_TYPE(9);return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e},e.copy=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t[6]=e[6],t[7]=e[7],t[8]=e[8],t},e.fromValues=function(t,e,n,i,o,a,s,c,u){var h=new r.ARRAY_TYPE(9);return h[0]=t,h[1]=e,h[2]=n,h[3]=i,h[4]=o,h[5]=a,h[6]=s,h[7]=c,h[8]=u,h},e.set=function(t,e,n,r,i,o,a,s,c,u){return t[0]=e,t[1]=n,t[2]=r,t[3]=i,t[4]=o,t[5]=a,t[6]=s,t[7]=c,t[8]=u,t},e.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.transpose=function(t,e){if(t===e){var n=e[1],r=e[2],i=e[5];t[1]=e[3],t[2]=e[6],t[3]=n,t[5]=e[7],t[6]=r,t[7]=i}else t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8];return t},e.invert=function(t,e){var n=e[0],r=e[1],i=e[2],o=e[3],a=e[4],s=e[5],c=e[6],u=e[7],h=e[8],l=h*a-s*u,d=-h*o+s*c,f=u*o-a*c,g=n*l+r*d+i*f;return g?(g=1/g,t[0]=l*g,t[1]=(-h*r+i*u)*g,t[2]=(s*r-i*a)*g,t[3]=d*g,t[4]=(h*n-i*c)*g,t[5]=(-s*n+i*o)*g,t[6]=f*g,t[7]=(-u*n+r*c)*g,t[8]=(a*n-r*o)*g,t):null},e.adjoint=function(t,e){var n=e[0],r=e[1],i=e[2],o=e[3],a=e[4],s=e[5],c=e[6],u=e[7],h=e[8];return t[0]=a*h-s*u,t[1]=i*u-r*h,t[2]=r*s-i*a,t[3]=s*c-o*h,t[4]=n*h-i*c,t[5]=i*o-n*s,t[6]=o*u-a*c,t[7]=r*c-n*u,t[8]=n*a-r*o,t},e.determinant=function(t){var e=t[0],n=t[1],r=t[2],i=t[3],o=t[4],a=t[5],s=t[6],c=t[7],u=t[8];return e*(u*o-a*c)+n*(-u*i+a*s)+r*(c*i-o*s)},e.multiply=i,e.translate=function(t,e,n){var r=e[0],i=e[1],o=e[2],a=e[3],s=e[4],c=e[5],u=e[6],h=e[7],l=e[8],d=n[0],f=n[1];return t[0]=r,t[1]=i,t[2]=o,t[3]=a,t[4]=s,t[5]=c,t[6]=d*r+f*a+u,t[7]=d*i+f*s+h,t[8]=d*o+f*c+l,t},e.rotate=function(t,e,n){var r=e[0],i=e[1],o=e[2],a=e[3],s=e[4],c=e[5],u=e[6],h=e[7],l=e[8],d=Math.sin(n),f=Math.cos(n);return t[0]=f*r+d*a,t[1]=f*i+d*s,t[2]=f*o+d*c,t[3]=f*a-d*r,t[4]=f*s-d*i,t[5]=f*c-d*o,t[6]=u,t[7]=h,t[8]=l,t},e.scale=function(t,e,n){var r=n[0],i=n[1];return t[0]=r*e[0],t[1]=r*e[1],t[2]=r*e[2],t[3]=i*e[3],t[4]=i*e[4],t[5]=i*e[5],t[6]=e[6],t[7]=e[7],t[8]=e[8],t},e.fromTranslation=function(t,e){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=e[0],t[7]=e[1],t[8]=1,t},e.fromRotation=function(t,e){var n=Math.sin(e),r=Math.cos(e);return t[0]=r,t[1]=n,t[2]=0,t[3]=-n,t[4]=r,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.fromScaling=function(t,e){return t[0]=e[0],t[1]=0,t[2]=0,t[3]=0,t[4]=e[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.fromMat2d=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=0,t[3]=e[2],t[4]=e[3],t[5]=0,t[6]=e[4],t[7]=e[5],t[8]=1,t},e.fromQuat=function(t,e){var n=e[0],r=e[1],i=e[2],o=e[3],a=n+n,s=r+r,c=i+i,u=n*a,h=r*a,l=r*s,d=i*a,f=i*s,g=i*c,p=o*a,m=o*s,v=o*c;return t[0]=1-l-g,t[3]=h-v,t[6]=d+m,t[1]=h+v,t[4]=1-u-g,t[7]=f-p,t[2]=d-m,t[5]=f+p,t[8]=1-u-l,t},e.normalFromMat4=function(t,e){var n=e[0],r=e[1],i=e[2],o=e[3],a=e[4],s=e[5],c=e[6],u=e[7],h=e[8],l=e[9],d=e[10],f=e[11],g=e[12],p=e[13],m=e[14],v=e[15],x=n*s-r*a,y=n*c-i*a,b=n*u-o*a,w=r*c-i*s,M=r*u-o*s,_=i*u-o*c,S=h*p-l*g,A=h*m-d*g,E=h*v-f*g,P=l*m-d*p,C=l*v-f*p,O=d*v-f*m,I=x*O-y*C+b*P+w*E-M*A+_*S;return I?(I=1/I,t[0]=(s*O-c*C+u*P)*I,t[1]=(c*E-a*O-u*A)*I,t[2]=(a*C-s*E+u*S)*I,t[3]=(i*C-r*O-o*P)*I,t[4]=(n*O-i*E+o*A)*I,t[5]=(r*E-n*C-o*S)*I,t[6]=(p*_-m*M+v*w)*I,t[7]=(m*b-g*_-v*y)*I,t[8]=(g*M-p*b+v*x)*I,t):null},e.projection=function(t,e,n){return t[0]=2/e,t[1]=0,t[2]=0,t[3]=0,t[4]=-2/n,t[5]=0,t[6]=-1,t[7]=1,t[8]=1,t},e.str=function(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"},e.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2))},e.add=function(t,e,n){return t[0]=e[0]+n[0],t[1]=e[1]+n[1],t[2]=e[2]+n[2],t[3]=e[3]+n[3],t[4]=e[4]+n[4],t[5]=e[5]+n[5],t[6]=e[6]+n[6],t[7]=e[7]+n[7],t[8]=e[8]+n[8],t},e.subtract=o,e.multiplyScalar=function(t,e,n){return t[0]=e[0]*n,t[1]=e[1]*n,t[2]=e[2]*n,t[3]=e[3]*n,t[4]=e[4]*n,t[5]=e[5]*n,t[6]=e[6]*n,t[7]=e[7]*n,t[8]=e[8]*n,t},e.multiplyScalarAndAdd=function(t,e,n,r){return t[0]=e[0]+n[0]*r,t[1]=e[1]+n[1]*r,t[2]=e[2]+n[2]*r,t[3]=e[3]+n[3]*r,t[4]=e[4]+n[4]*r,t[5]=e[5]+n[5]*r,t[6]=e[6]+n[6]*r,t[7]=e[7]+n[7]*r,t[8]=e[8]+n[8]*r,t},e.exactEquals=function(t,e){return t[0]===e[0]&&t[1]===e[1]&&t[2]===e[2]&&t[3]===e[3]&&t[4]===e[4]&&t[5]===e[5]&&t[6]===e[6]&&t[7]===e[7]&&t[8]===e[8]},e.equals=function(t,e){var n=t[0],i=t[1],o=t[2],a=t[3],s=t[4],c=t[5],u=t[6],h=t[7],l=t[8],d=e[0],f=e[1],g=e[2],p=e[3],m=e[4],v=e[5],x=e[6],y=e[7],b=e[8];return Math.abs(n-d)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(d))&&Math.abs(i-f)<=r.EPSILON*Math.max(1,Math.abs(i),Math.abs(f))&&Math.abs(o-g)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(g))&&Math.abs(a-p)<=r.EPSILON*Math.max(1,Math.abs(a),Math.abs(p))&&Math.abs(s-m)<=r.EPSILON*Math.max(1,Math.abs(s),Math.abs(m))&&Math.abs(c-v)<=r.EPSILON*Math.max(1,Math.abs(c),Math.abs(v))&&Math.abs(u-x)<=r.EPSILON*Math.max(1,Math.abs(u),Math.abs(x))&&Math.abs(h-y)<=r.EPSILON*Math.max(1,Math.abs(h),Math.abs(y))&&Math.abs(l-b)<=r.EPSILON*Math.max(1,Math.abs(l),Math.abs(b))};var r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}(n(59));function i(t,e,n){var r=e[0],i=e[1],o=e[2],a=e[3],s=e[4],c=e[5],u=e[6],h=e[7],l=e[8],d=n[0],f=n[1],g=n[2],p=n[3],m=n[4],v=n[5],x=n[6],y=n[7],b=n[8];return t[0]=d*r+f*a+g*u,t[1]=d*i+f*s+g*h,t[2]=d*o+f*c+g*l,t[3]=p*r+m*a+v*u,t[4]=p*i+m*s+v*h,t[5]=p*o+m*c+v*l,t[6]=x*r+y*a+b*u,t[7]=x*i+y*s+b*h,t[8]=x*o+y*c+b*l,t}function o(t,e,n){return t[0]=e[0]-n[0],t[1]=e[1]-n[1],t[2]=e[2]-n[2],t[3]=e[3]-n[3],t[4]=e[4]-n[4],t[5]=e[5]-n[5],t[6]=e[6]-n[6],t[7]=e[7]-n[7],t[8]=e[8]-n[8],t}e.mul=i,e.sub=o},function(t,e,n){function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var i=n(819);Math.sign=function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1};var o=function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},i=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(i=i.concat(Object.getOwnPropertySymbols(n).filter((function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable})))),i.forEach((function(e){r(t,e,n[e])}))}return t}({},i,{throttle:n(749),debounce:n(645),omit:function(t,e){var n={};return i.each(t,(function(t,r){-1===e.indexOf(r)&&(n[r]=t)})),n},traverseTree:function(t,e,n,r){void 0===r&&(r=!1);var i=n(t);r&&e(t,null,null),i&&o.each(i,(function(r,i){e(r,t,i),o.traverseTree(r,e,n)}))},toAllPadding:function(t){var e=0,n=0,r=0,i=0;return o.isNumber(t)||o.isString(t)?e=n=r=i=t:o.isArray(t)&&(e=t[0],r=o.isNil(t[1])?t[0]:t[1],i=o.isNil(t[2])?t[0]:t[2],n=o.isNil(t[3])?r:t[3]),[e,r,i,n]},guid:function(){return"xxxxxxxx".replace(/[xy]/g,(function(t){var e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)}))},mix:function(){var t,e,n=o.toArray(arguments),r=n[0];if(!0===r)for(r=n[1],e=2;e<n.length;e++)a(r,t=n[e]);else for(e=1;e<n.length;e++)for(var i in t=n[e])t.hasOwnProperty(i)&&"constructor"!==i&&(r[i]=t[i]);return r},mixin:function(t,e){t&&e&&(t._mixins=e,t.ATTRS=t.ATTRS||{},o.each(e,(function(e){o.augment(t,e)})),t.ATTRS=o.mix({},t.ATTRS))}});function a(t,e,n){for(var r in n=n||0,e)if(e.hasOwnProperty(r)){var i=e[r];null!==i&&o.isPlainObject(i)?(o.isPlainObject(t[r])||(t[r]={}),n<5?a(t[r],e[r],n+1):t[r]=e[r]):o.isArray(i)?(t[r]=[],t[r]=t[r].concat(i)):void 0!==i&&(t[r]=e[r])}}o.Array={remove:function(t,e){var n=o.indexOf(t,e);-1!==n&&t.splice(n,1)}},t.exports=o},function(t,e,n){var r=n(26),i={},o={draw:function(){}},a={defaultShapeType:null,getShape:function(t,e){return this[t]||this[e]||this[this.defaultShapeType]||o},getExtendShape:function(t,e){var n=this;if(r.isArray(t)){var i={};return t.forEach((function(t){n[t]&&(i=r.mix({},i,n.getShape(t,e)))})),i}return this.getShape(t,e)}};i.registerShapeManager=function(t,e){var n=r.mix({},a,e),o=r.upperFirst(t);return i[o]=n,i["register"+o]=function(t,e,i,o){r.isNil(i)&&r.isNil(o)&&(i=t);var a=n.getExtendShape(i,o),s=r.mix(!0,{},a,e);return s.type=t,n[t]=s,s},n},t.exports=i},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,function(t,e,n){var r=n(19),i=/[MLHVQTCSAZ]([^MLHVQTCSAZ]*)/gi,o=/[^\s\,]+/gi;t.exports={parseRadius:function(t){var e=0,n=0,i=0,o=0;return r.isArray(t)?1===t.length?e=n=i=o=t[0]:2===t.length?(e=i=t[0],n=o=t[1]):3===t.length?(e=t[0],n=o=t[1],i=t[2]):(e=t[0],n=t[1],i=t[2],o=t[3]):e=n=i=o=t,{r1:e,r2:n,r3:i,r4:o}},parsePath:function(t){return t=t||[],r.isArray(t)?t:r.isString(t)?(t=t.match(i),r.each(t,(function(e,n){if((e=e.match(o))[0].length>1){var i=e[0].charAt(0);e.splice(1,0,e[0].substr(1)),e[0]=i}r.each(e,(function(t,n){isNaN(t)||(e[n]=+t)})),t[n]=e})),t):void 0}}},function(t,e,n){var r=n(237);t.exports=function(t){return r(t)?"":t.toString()}},function(t,e,n){var r=n(115);t.exports=function(t){return r(t,"String")}},function(t,e,n){var r=n(619),i=n(115);t.exports=function(t){if(!r(t)||!i(t,"Object"))return!1;if(null===Object.getPrototypeOf(t))return!0;for(var e=t;null!==Object.getPrototypeOf(e);)e=Object.getPrototypeOf(e);return Object.getPrototypeOf(t)===e}},function(t,e,n){var r=function(t){function e(e){var n;return(n=t.call(this)||this).options=e,n}return function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t),e.prototype.execute=function(){var t=this,e=this.options;this.roots.forEach((function(n){t.layout(n,e).eachNode((function(t){t.data.x=t.x+t.data.width/2+t.hgap,t.data.y=t.y+t.data.height/2+t.vgap}))}))},e}(n(622));t.exports=r},function(t,e,n){"undefined"!=typeof self&&self,t.exports=function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=5)}([function(t,e,n){var r=n(7);t.exports={assign:r}},function(t,e,n){var r=n(3),i=function(){function t(t,e){void 0===e&&(e={}),this.options=e,this.rootNode=r(t,e)}return t.prototype.execute=function(){throw new Error("please override this method")},t}();t.exports=i},function(t,e,n){var r=n(4),i=["LR","RL","TB","BT","H","V"],o=["LR","RL","H"],a=i[0];t.exports=function(t,e,n){var s=e.direction||a;if(e.isHorizontal=function(t){return o.indexOf(t)>-1}(s),s&&-1===i.indexOf(s))throw new TypeError("Invalid direction: "+s);if(s===i[0])n(t,e);else if(s===i[1])n(t,e),t.right2left();else if(s===i[2])n(t,e);else if(s===i[3])n(t,e),t.bottom2top();else if(s===i[4]||s===i[5]){var c=r(t,e),u=c.left,h=c.right;n(u,e),n(h,e),e.isHorizontal?u.right2left():u.bottom2top(),h.translate(u.x-h.x,u.y-h.y),t.x=u.x,t.y=h.y;var l=t.getBoundingBox();e.isHorizontal?l.top<0&&t.translate(0,-l.top):l.left<0&&t.translate(-l.left,0)}return t.translate(-(t.x+t.width/2+t.hgap),-(t.y+t.height/2+t.vgap)),t}},function(t,e,n){var r=n(0),i={getId:function(t){return t.id||t.name},getHGap:function(t){return t.hgap||18},getVGap:function(t){return t.vgap||18},getChildren:function(t){return t.children},getHeight:function(t){return t.height||36},getWidth:function(t){var e=t.name||" ";return t.width||18*e.split("").length}};function o(t,e){var n=this;if(n.vgap=n.hgap=0,t instanceof o)return t;n.data=t;var r=e.getHGap(t),i=e.getVGap(t);return n.width=e.getWidth(t),n.height=e.getHeight(t),n.id=e.getId(t),n.x=n.y=0,n.depth=0,n.children||(n.children=[]),n.addGap(r,i),n}r.assign(o.prototype,{isRoot:function(){return 0===this.depth},isLeaf:function(){return 0===this.children.length},addGap:function(t,e){this.hgap+=t,this.vgap+=e,this.width+=2*t,this.height+=2*e},eachNode:function(t){for(var e,n=[this];e=n.pop();)t(e),n=n.concat(e.children)},DFTraverse:function(t){this.eachNode(t)},BFTraverse:function(t){for(var e,n=[this];e=n.shift();)t(e),n=n.concat(e.children)},getBoundingBox:function(){var t={left:Number.MAX_VALUE,top:Number.MAX_VALUE,width:0,height:0};return this.eachNode((function(e){t.left=Math.min(t.left,e.x),t.top=Math.min(t.top,e.y),t.width=Math.max(t.width,e.x+e.width),t.height=Math.max(t.height,e.y+e.height)})),t},translate:function(t,e){void 0===t&&(t=0),void 0===e&&(e=0),this.eachNode((function(n){n.x+=t,n.y+=e}))},right2left:function(){var t=this.getBoundingBox();this.eachNode((function(e){e.x=e.x-2*(e.x-t.left)-e.width})),this.translate(t.width,0)},bottom2top:function(){var t=this.getBoundingBox();this.eachNode((function(e){e.y=e.y-2*(e.y-t.top)-e.height})),this.translate(0,t.height)}}),t.exports=function(t,e,n){void 0===e&&(e={});var a,s=new o(t,e=r.assign({},i,e)),c=[s];if(!n&&!t.collapsed)for(;a=c.pop();)if(!a.data.collapsed){var u=e.getChildren(a.data),h=u?u.length:0;if(a.children=new Array(h),u&&h)for(var l=0;l<h;l++){var d=new o(u[l],e);a.children[l]=d,c.push(d),d.parent=a,d.depth=a.depth+1}}return s}},function(t,e,n){var r=n(3);t.exports=function(t,e){for(var n=r(t.data,e,!0),i=r(t.data,e,!0),o=t.children.length,a=Math.round(o/2),s=e.getSide||function(t,e){return e<a?"right":"left"},c=0;c<o;c++){var u=t.children[c];"right"===s(u,c)?i.children.push(u):n.children.push(u)}return n.eachNode((function(t){t.isRoot()||(t.side="left")})),i.eachNode((function(t){t.isRoot()||(t.side="right")})),{left:n,right:i}}},function(t,e,n){var r={compactBox:n(6),dendrogram:n(9),indented:n(11),mindmap:n(13)};t.exports=r},function(t,e,n){var r=n(1),i=n(8),o=n(2),a=n(0),s=function(t){function e(){return t.apply(this,arguments)||this}return function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t),e.prototype.execute=function(){return o(this.rootNode,this.options,i)},e}(r),c={};t.exports=function(t,e){return e=a.assign({},c,e),new s(t,e).execute()}},function(t,e){function n(t,e){for(var n in e)e.hasOwnProperty(n)&&"constructor"!==n&&void 0!==e[n]&&(t[n]=e[n])}t.exports=function(t,e,r,i){return e&&n(t,e),r&&n(t,r),i&&n(t,i),t}},function(t,e){function n(t,e,n,r){void 0===r&&(r=[]);var i=this;i.w=t||0,i.h=e||0,i.y=n||0,i.x=0,i.c=r||[],i.cs=r.length,i.prelim=0,i.mod=0,i.shift=0,i.change=0,i.tl=null,i.tr=null,i.el=null,i.er=null,i.msel=0,i.mser=0}n.fromNode=function(t,e){if(!t)return null;var r=[];return t.children.forEach((function(t){r.push(n.fromNode(t,e))})),e?new n(t.height,t.width,t.x,r):new n(t.width,t.height,t.y,r)},t.exports=function(t,e){void 0===e&&(e={});var r=e.isHorizontal;function i(t){0===t.cs?(t.el=t,t.er=t,t.msel=t.mser=0):(t.el=t.c[0].el,t.msel=t.c[0].msel,t.er=t.c[t.cs-1].er,t.mser=t.c[t.cs-1].mser)}function o(t,e,n){for(var r=t.c[e-1],i=r.mod,o=t.c[e],h=o.mod;null!==r&&null!==o;){u(r)>n.low&&(n=n.nxt);var l=i+r.prelim+r.w-(h+o.prelim);l>0&&(h+=l,a(t,e,n.index,l));var d=u(r),f=u(o);d<=f&&null!==(r=c(r))&&(i+=r.mod),d>=f&&null!==(o=s(o))&&(h+=o.mod)}!r&&o?function(t,e,n,r){var i=t.c[0].el;i.tl=n;var o=r-n.mod-t.c[0].msel;i.mod+=o,i.prelim-=o,t.c[0].el=t.c[e].el,t.c[0].msel=t.c[e].msel}(t,e,o,h):r&&!o&&function(t,e,n,r){var i=t.c[e].er;i.tr=n;var o=r-n.mod-t.c[e].mser;i.mod+=o,i.prelim-=o,t.c[e].er=t.c[e-1].er,t.c[e].mser=t.c[e-1].mser}(t,e,r,i)}function a(t,e,n,r){t.c[e].mod+=r,t.c[e].msel+=r,t.c[e].mser+=r,function(t,e,n,r){if(n!==e-1){var i=e-n;t.c[n+1].shift+=r/i,t.c[e].shift-=r/i,t.c[e].change-=r-r/i}}(t,e,n,r)}function s(t){return 0===t.cs?t.tl:t.c[0]}function c(t){return 0===t.cs?t.tr:t.c[t.cs-1]}function u(t){return t.y+t.h}function h(t,e,n){for(;null!==n&&t>=n.low;)n=n.nxt;return{low:t,index:e,nxt:n}}!function t(e,n,r){void 0===r&&(r=0),n?(e.x=r,r+=e.width):(e.y=r,r+=e.height),e.children.forEach((function(e){t(e,n,r)}))}(t,r);var l=n.fromNode(t,r);return function t(e){if(0!==e.cs){t(e.c[0]);for(var n=h(u(e.c[0].el),0,null),r=1;r<e.cs;++r){t(e.c[r]);var a=u(e.c[r].er);o(e,r,n),n=h(a,r,n)}!function(t){t.prelim=(t.c[0].prelim+t.c[0].mod+t.c[t.cs-1].mod+t.c[t.cs-1].prelim+t.c[t.cs-1].w)/2-t.w/2}(e),i(e)}else i(e)}(l),function t(e,n){n+=e.mod,e.x=e.prelim+n,function(t){for(var e=0,n=0,r=0;r<t.cs;r++)n+=(e+=t.c[r].shift)+t.c[r].change,t.c[r].mod+=n}(e);for(var r=0;r<e.cs;r++)t(e.c[r],n)}(l,0),function t(e,n,r){r?n.y=e.x:n.x=e.x,e.c.forEach((function(e,i){t(e,n.children[i],r)}))}(l,t,r),function(t,e){!function t(e,n,r){r?e.y+=n:e.x+=n,e.children.forEach((function(e){t(e,n,r)}))}(t,-function t(e,n){var r=n?e.y:e.x;return e.children.forEach((function(e){r=Math.min(t(e,n),r)})),r}(t,e),e)}(t,r),t}},function(t,e,n){var r=n(1),i=n(10),o=n(2),a=n(0),s=function(t){function e(){return t.apply(this,arguments)||this}return function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t),e.prototype.execute=function(){return this.rootNode.width=0,o(this.rootNode,this.options,i)},e}(r),c={};t.exports=function(t,e){return e=a.assign({},c,e),new s(t,e).execute()}},function(t,e,n){var r=n(0),i={isHorizontal:!0,nodeSep:20,nodeSize:20,rankSep:200,subTreeSep:10};t.exports=function(t,e){void 0===e&&(e={}),e=r.assign({},i,e);var n,o=0,a=function t(e){if(!e)return null;e.width=0,e.depth&&e.depth>o&&(o=e.depth);var n=e.children,r=n.length,i=new function(t,e){void 0===t&&(t=0),void 0===e&&(e=[]);var n=this;n.x=n.y=0,n.leftChild=n.rightChild=null,n.height=0,n.children=e}(e.height,[]);return n.forEach((function(e,n){var o=t(e);i.children.push(o),0===n&&(i.leftChild=o),n===r-1&&(i.rightChild=o)})),i.originNode=e,i.isLeaf=e.isLeaf(),i}(t);return function t(e){if(e.isLeaf||0===e.children.length)e.drawingDepth=o;else{var n=e.children.map((function(e){return t(e)})),r=Math.min.apply(null,n);e.drawingDepth=r-1}return e.drawingDepth}(a),function t(r){r.x=r.drawingDepth*e.rankSep,r.isLeaf?(r.y=0,n&&(r.y=n.y+n.height+e.nodeSep,r.originNode.parent!==n.originNode.parent&&(r.y+=e.subTreeSep)),n=r):(r.children.forEach((function(e){t(e)})),r.y=(r.leftChild.y+r.rightChild.y)/2)}(a),function t(e,n,r){r?(n.x=e.x,n.y=e.y):(n.x=e.y,n.y=e.x),e.children.forEach((function(e,i){t(e,n.children[i],r)}))}(a,t,e.isHorizontal),t}},function(t,e,n){var r=n(1),i=n(12),o=n(4),a=n(0),s=["LR","RL","H"],c=s[0],u=function(t){function e(){return t.apply(this,arguments)||this}return function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t),e.prototype.execute=function(){var t=this.options,e=this.rootNode;t.isHorizontal=!0;var n=t.indent,r=t.direction||c;if(r&&-1===s.indexOf(r))throw new TypeError("Invalid direction: "+r);if(r===s[0])i(e,n);else if(r===s[1])i(e,n),e.right2left();else if(r===s[2]){var a=o(e,t),u=a.left,h=a.right;i(u,n),u.right2left(),i(h,n);var l=u.getBoundingBox();h.translate(l.width,0),e.x=h.x-e.width/2}return e},e}(r),h={};t.exports=function(t,e){return e=a.assign({},h,e),new u(t,e).execute()}},function(t,e){t.exports=function(t,e){void 0===e&&(e=20);var n=null;t.eachNode((function(t){!function(t,e,n){t.x+=n*t.depth,t.y=e?e.y+e.height:0}(t,n,e),n=t}))}},function(t,e,n){var r=n(1),i=n(14),o=n(2),a=n(0),s=function(t){function e(){return t.apply(this,arguments)||this}return function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t),e.prototype.execute=function(){return o(this.rootNode,this.options,i)},e}(r),c={};t.exports=function(t,e){return e=a.assign({},c,e),new s(t,e).execute()}},function(t,e,n){var r=n(0),i={getSubTreeSep:function(){return 0}};t.exports=function(t,e){void 0===e&&(e={}),e=r.assign({},i,e),t.parent={x:0,width:0,height:0,y:0},t.BFTraverse((function(t){t.x=t.parent.x+t.parent.width})),t.parent=null,function t(e,n){var r=0;return e.children.length?e.children.forEach((function(e){r+=t(e,n)})):r=e.height,e._subTreeSep=n.getSubTreeSep(e.data),e.totalHeight=Math.max(e.height,r)+2*e._subTreeSep,e.totalHeight}(t,e),t.startY=0,t.y=t.totalHeight/2-t.height/2,t.eachNode((function(t){var e=t.children,n=e.length;if(n){var r=e[0];if(r.startY=t.startY+t._subTreeSep,1===n)r.y=t.y+t.height/2-r.height/2;else{r.y=r.startY+r.totalHeight/2-r.height/2;for(var i=1;i<n;i++){var o=e[i];o.startY=e[i-1].startY+e[i-1].totalHeight,o.y=o.startY+o.totalHeight/2-o.height/2}}}})),function t(e){var n=e.children,r=n.length;if(r){n.forEach((function(e){t(e)}));var i=n[0],o=n[r-1],a=o.y-i.y+o.height,s=0;if(n.forEach((function(t){s+=t.totalHeight})),a>e.height)e.y=i.y+a/2-e.height/2;else if(1!==n.length||e.height>s){var c=e.y+(e.height-a)/2-i.y;n.forEach((function(t){t.translate(0,c)}))}else e.y=(i.y+i.height/2+o.y+o.height/2)/2-e.height/2}}(t)}}])},function(t,e,n){var r=n(26),i=function(){var t=e.prototype;function e(t){var e=this.getDefaultCfg();r.mix(this,e,t),this._init()}return t.getDefaultCfg=function(){return{}},t._init=function(){},t.destroy=function(){},e}();t.exports=i},function(t,e,n){var r=n(19),i=n(613),o=n(612),a=n(640),s=n(639),c=r.vec3,u=r.mat3,h=["m","l","c","a","q","h","v","t","s","z"];function l(t,e,n){return{x:n.x+t,y:n.y+e}}function d(t,e){return{x:e.x+(e.x-t.x),y:e.y+(e.y-t.y)}}function f(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1])}function g(t,e){return(t[0]*e[0]+t[1]*e[1])/(f(t)*f(e))}function p(t,e){return(t[0]*e[1]<t[1]*e[0]?-1:1)*Math.acos(g(t,e))}var m=function(t,e,n){this.preSegment=e,this.isLast=n,this.init(t,e)};r.augment(m,{init:function(t,e){var n=t[0];e=e||{endPoint:{x:0,y:0}};var i,o,a,s,c=h.indexOf(n)>=0,u=c?n.toUpperCase():n,f=t,m=e.endPoint,v=f[1],x=f[2];switch(u){default:break;case"M":s=c?l(v,x,m):{x:v,y:x},this.command="M",this.params=[m,s],this.subStart=s,this.endPoint=s;break;case"L":s=c?l(v,x,m):{x:v,y:x},this.command="L",this.params=[m,s],this.subStart=e.subStart,this.endPoint=s,this.endTangent=function(){return[s.x-m.x,s.y-m.y]},this.startTangent=function(){return[m.x-s.x,m.y-s.y]};break;case"H":s=c?l(v,0,m):{x:v,y:m.y},this.command="L",this.params=[m,s],this.subStart=e.subStart,this.endPoint=s,this.endTangent=function(){return[s.x-m.x,s.y-m.y]},this.startTangent=function(){return[m.x-s.x,m.y-s.y]};break;case"V":s=c?l(0,v,m):{x:m.x,y:v},this.command="L",this.params=[m,s],this.subStart=e.subStart,this.endPoint=s,this.endTangent=function(){return[s.x-m.x,s.y-m.y]},this.startTangent=function(){return[m.x-s.x,m.y-s.y]};break;case"Q":c?(i=l(v,x,m),o=l(f[3],f[4],m)):(i={x:v,y:x},o={x:f[3],y:f[4]}),this.command="Q",this.params=[m,i,o],this.subStart=e.subStart,this.endPoint=o,this.endTangent=function(){return[o.x-i.x,o.y-i.y]},this.startTangent=function(){return[m.x-i.x,m.y-i.y]};break;case"T":o=c?l(v,x,m):{x:v,y:x},"Q"===e.command?(i=d(e.params[1],m),this.command="Q",this.params=[m,i,o],this.subStart=e.subStart,this.endPoint=o,this.endTangent=function(){return[o.x-i.x,o.y-i.y]},this.startTangent=function(){return[m.x-i.x,m.y-i.y]}):(this.command="TL",this.params=[m,o],this.subStart=e.subStart,this.endPoint=o,this.endTangent=function(){return[o.x-m.x,o.y-m.y]},this.startTangent=function(){return[m.x-o.x,m.y-o.y]});break;case"C":c?(i=l(v,x,m),o=l(f[3],f[4],m),a=l(f[5],f[6],m)):(i={x:v,y:x},o={x:f[3],y:f[4]},a={x:f[5],y:f[6]}),this.command="C",this.params=[m,i,o,a],this.subStart=e.subStart,this.endPoint=a,this.endTangent=function(){return[a.x-o.x,a.y-o.y]},this.startTangent=function(){return[m.x-i.x,m.y-i.y]};break;case"S":c?(o=l(v,x,m),a=l(f[3],f[4],m)):(o={x:v,y:x},a={x:f[3],y:f[4]}),"C"===e.command?(i=d(e.params[2],m),this.command="C",this.params=[m,i,o,a],this.subStart=e.subStart,this.endPoint=a,this.endTangent=function(){return[a.x-o.x,a.y-o.y]},this.startTangent=function(){return[m.x-i.x,m.y-i.y]}):(this.command="SQ",this.params=[m,o,a],this.subStart=e.subStart,this.endPoint=a,this.endTangent=function(){return[a.x-o.x,a.y-o.y]},this.startTangent=function(){return[m.x-o.x,m.y-o.y]});break;case"A":var y=v,b=x,w=f[3],M=f[4],_=f[5];s=c?l(f[6],f[7],m):{x:f[6],y:f[7]},this.command="A";var S=function(t,e,n,i,o,a,s){var c=r.mod(r.toRadian(s),2*Math.PI),u=t.x,h=t.y,l=e.x,d=e.y,f=Math.cos(c)*(u-l)/2+Math.sin(c)*(h-d)/2,m=-1*Math.sin(c)*(u-l)/2+Math.cos(c)*(h-d)/2,v=f*f/(o*o)+m*m/(a*a);v>1&&(o*=Math.sqrt(v),a*=Math.sqrt(v));var x=o*o*(m*m)+a*a*(f*f),y=Math.sqrt((o*o*(a*a)-x)/x);n===i&&(y*=-1),isNaN(y)&&(y=0);var b=y*o*m/a,w=y*-a*f/o,M=(u+l)/2+Math.cos(c)*b-Math.sin(c)*w,_=(h+d)/2+Math.sin(c)*b+Math.cos(c)*w,S=p([1,0],[(f-b)/o,(m-w)/a]),A=[(f-b)/o,(m-w)/a],E=[(-1*f-b)/o,(-1*m-w)/a],P=p(A,E);return g(A,E)<=-1&&(P=Math.PI),g(A,E)>=1&&(P=0),0===i&&P>0&&(P-=2*Math.PI),1===i&&P<0&&(P+=2*Math.PI),[t,M,_,o,a,S,P,c,i]}(m,s,M,_,y,b,w);this.params=S;var A=e.subStart;this.subStart=A,this.endPoint=s;var E=S[5]%(2*Math.PI);r.isNumberEqual(E,2*Math.PI)&&(E=0);var P=S[6]%(2*Math.PI);r.isNumberEqual(P,2*Math.PI)&&(P=0);var C=.001;this.startTangent=function(){0===_&&(C*=-1);var t=S[3]*Math.cos(E-C)+S[1],e=S[4]*Math.sin(E-C)+S[2];return[t-A.x,e-A.y]},this.endTangent=function(){var t=S[6];t-2*Math.PI<1e-4&&(t=0);var e=S[3]*Math.cos(E+t+C)+S[1],n=S[4]*Math.sin(E+t-C)+S[2];return[m.x-e,m.y-n]};break;case"Z":this.command="Z",this.params=[m,e.subStart],this.subStart=e.subStart,this.endPoint=e.subStart}},isInside:function(t,e,n){var r=this.command,o=this.params,a=this.box;if(a&&!i.box(a.minX,a.maxX,a.minY,a.maxY,t,e))return!1;switch(r){default:break;case"M":return!1;case"TL":case"L":case"Z":return i.line(o[0].x,o[0].y,o[1].x,o[1].y,n,t,e);case"SQ":case"Q":return i.quadraticline(o[0].x,o[0].y,o[1].x,o[1].y,o[2].x,o[2].y,n,t,e);case"C":return i.cubicline(o[0].x,o[0].y,o[1].x,o[1].y,o[2].x,o[2].y,o[3].x,o[3].y,n,t,e);case"A":var s=o,h=s[1],l=s[2],d=s[3],f=s[4],g=s[5],p=s[6],m=s[7],v=s[8],x=d>f?d:f,y=d>f?1:d/f,b=d>f?f/d:1;s=[t,e,1];var w=[1,0,0,0,1,0,0,0,1];return u.translate(w,w,[-h,-l]),u.rotate(w,w,-m),u.scale(w,w,[1/y,1/b]),c.transformMat3(s,s,w),i.arcline(0,0,x,g,g+p,1-v,n,s[0],s[1])}return!1},draw:function(t){var e,n,r,i=this.command,o=this.params;switch(i){default:break;case"M":t.moveTo(o[1].x,o[1].y);break;case"TL":case"L":t.lineTo(o[1].x,o[1].y);break;case"SQ":case"Q":e=o[1],n=o[2],t.quadraticCurveTo(e.x,e.y,n.x,n.y);break;case"C":e=o[1],n=o[2],r=o[3],t.bezierCurveTo(e.x,e.y,n.x,n.y,r.x,r.y);break;case"A":var a=o,s=a[1],c=a[2],u=a[3],h=a[4],l=a[5],d=a[6],f=a[7],g=a[8],p=u>h?u:h,m=u>h?1:u/h,v=u>h?h/u:1;t.translate(s,c),t.rotate(f),t.scale(m,v),t.arc(0,0,p,l,l+d,1-g),t.scale(1/m,1/v),t.rotate(-f),t.translate(-s,-c);break;case"Z":t.closePath()}},getBBox:function(t){var e,n,r,i,c=t/2,u=this.params;switch(this.command){default:case"M":case"Z":break;case"TL":case"L":this.box={minX:Math.min(u[0].x,u[1].x)-c,maxX:Math.max(u[0].x,u[1].x)+c,minY:Math.min(u[0].y,u[1].y)-c,maxY:Math.max(u[0].y,u[1].y)+c};break;case"SQ":case"Q":for(r=0,i=(n=a.extrema(u[0].x,u[1].x,u[2].x)).length;r<i;r++)n[r]=a.at(u[0].x,u[1].x,u[2].x,n[r]);for(n.push(u[0].x,u[2].x),r=0,i=(e=a.extrema(u[0].y,u[1].y,u[2].y)).length;r<i;r++)e[r]=a.at(u[0].y,u[1].y,u[2].y,e);e.push(u[0].y,u[2].y),this.box={minX:Math.min.apply(Math,n)-c,maxX:Math.max.apply(Math,n)+c,minY:Math.min.apply(Math,e)-c,maxY:Math.max.apply(Math,e)+c};break;case"C":for(r=0,i=(n=o.extrema(u[0].x,u[1].x,u[2].x,u[3].x)).length;r<i;r++)n[r]=o.at(u[0].x,u[1].x,u[2].x,u[3].x,n[r]);for(r=0,i=(e=o.extrema(u[0].y,u[1].y,u[2].y,u[3].y)).length;r<i;r++)e[r]=o.at(u[0].y,u[1].y,u[2].y,u[3].y,e[r]);n.push(u[0].x,u[3].x),e.push(u[0].y,u[3].y),this.box={minX:Math.min.apply(Math,n)-c,maxX:Math.max.apply(Math,n)+c,minY:Math.min.apply(Math,e)-c,maxY:Math.max.apply(Math,e)+c};break;case"A":var h=u,l=h[1],d=h[2],f=h[3],g=h[4],p=h[5],m=h[6],v=h[7],x=h[8],y=p,b=p+m,w=s.xExtrema(v,f,g),M=1/0,_=-1/0,S=[y,b];for(r=2*-Math.PI;r<=2*Math.PI;r+=Math.PI){var A=w+r;1===x?y<A&&A<b&&S.push(A):b<A&&A<y&&S.push(A)}for(r=0,i=S.length;r<i;r++){var E=s.xAt(v,f,g,l,S[r]);E<M&&(M=E),E>_&&(_=E)}var P=s.yExtrema(v,f,g),C=1/0,O=-1/0,I=[y,b];for(r=2*-Math.PI;r<=2*Math.PI;r+=Math.PI){var k=P+r;1===x?y<k&&k<b&&I.push(k):b<k&&k<y&&I.push(k)}for(r=0,i=I.length;r<i;r++){var B=s.yAt(v,f,g,d,I[r]);B<C&&(C=B),B>O&&(O=B)}this.box={minX:M-c,maxX:_+c,minY:C-c,maxY:O+c}}}}),t.exports=m},function(t,e,n){var r=n(593),i=n(600),o=Math.PI,a=Math.sin,s=Math.cos,c=Math.atan2,u=o/3;function h(t,e,n,r,i,h,l){var d,f,g,p,m,v,x;if(!e.fill){var y=e.arrowLength||10,b=e.arrowAngle?e.arrowAngle*o/180:u;x=c(r-h,n-i),m=Math.abs(e.lineWidth*s(x))/2,v=Math.abs(e.lineWidth*a(x))/2,l&&(m=-m,v=-v),d=i+y*s(x+b/2),f=h+y*a(x+b/2),g=i+y*s(x-b/2),p=h+y*a(x-b/2),t.beginPath(),t.moveTo(d-m,f-v),t.lineTo(i-m,h-v),t.lineTo(g-m,p-v),t.moveTo(i-m,h-v),t.lineTo(i+m,h+v),t.moveTo(i,h),t.stroke()}}function l(t,e,n,o,a,s,c){var u=c?e.startArrow:e.endArrow,h=u.d,l=0,d=a-n,f=s-o,g=Math.atan(d/f);0===f&&d<0?l=Math.PI:d>0&&f>0?l=Math.PI/2-g:d<0&&f<0?l=-Math.PI/2-g:d>=0&&f<0?l=-g-Math.PI/2:d<=0&&f>0&&(l=Math.PI/2-g);var p=function(t){var e,n=[],o=r.parsePath(t.path);if(!Array.isArray(o)||0===o.length||"M"!==o[0][0]&&"m"!==o[0][0])return!1;for(var a=o.length,s=0;s<o.length;s++){var c=o[s];e=new i(c,e,s===a-1),n.push(e)}return n}(u);if(p){h&&(c?(a+=Math.sin(Math.abs(g))*h,s=s+Math.cos(Math.abs(g))*h-.5*t.lineWidth):(a-=Math.sin(Math.abs(g))*h,s=s-Math.cos(Math.abs(g))*h+.5*t.lineWidth)),t.save(),t.beginPath(),t.translate(a,s),t.rotate(l);for(var m=0;m<p.length;m++)p[m].draw(t);t.setTransform(1,0,0,1,0,0),t.fillStyle=t.strokeStyle,t.fill(),t.restore()}}t.exports={addStartArrow:function(t,e,n,r,i,o){"object"==typeof e.startArrow?l(t,e,n,r,i,o,!0):e.startArrow&&h(t,e,n,r,i,o,!0)},addEndArrow:function(t,e,n,r,i,o){"object"==typeof e.endArrow?l(t,e,n,r,i,o,!1):e.endArrow&&h(t,e,n,r,i,o,!1)}}},function(t,e,n){var r=n(19);function i(t,e,n,r){return{x:Math.cos(r)*n+t,y:Math.sin(r)*n+e}}function o(t,e,n,r){var i,o;return r?t<e?(i=e-t,o=2*Math.PI-n+t):t>n&&(i=2*Math.PI-t+e,o=t-n):(i=t-e,o=n-t),i>o?n:e}function a(t,e,n,i){var a=0;return n-e>=2*Math.PI&&(a=2*Math.PI),e=r.mod(e,2*Math.PI),n=r.mod(n,2*Math.PI)+a,t=r.mod(t,2*Math.PI),i?e>=n?t>n&&t<e?t:o(t,n,e,!0):t<e||t>n?t:o(t,e,n):e<=n?e<t&&t<n?t:o(t,e,n,!0):t>e||t<n?t:o(t,n,e)}function s(t,e,n,i,o,s,c,u,h){var l=[c,u],d=[t,e],f=r.vec2.subtract([],l,d),g=r.vec2.angleTo([1,0],f);g=a(g,i,o,s);var p=[n*Math.cos(g)+t,n*Math.sin(g)+e];return h&&(h.x=p[0],h.y=p[1]),r.vec2.distance(p,l)}t.exports={nearAngle:a,projectPoint:function(t,e,n,r,i,o,a,c){var u={};return s(t,e,n,r,i,o,a,c,u),u},pointDistance:s,box:function(t,e,n,o,s,c){var u=Math.PI/2,h=Math.PI,l=3*Math.PI/2,d=[],f=a(0,o,s,c);0===f&&d.push(i(t,e,n,0)),(f=a(u,o,s,c))===u&&d.push(i(t,e,n,u)),(f=a(h,o,s,c))===h&&d.push(i(t,e,n,h)),(f=a(l,o,s,c))===l&&d.push(i(t,e,n,l)),d.push(i(t,e,n,o)),d.push(i(t,e,n,s));var g=1/0,p=-1/0,m=1/0,v=-1/0;return r.each(d,(function(t){g>t.x&&(g=t.x),p<t.x&&(p=t.x),m>t.y&&(m=t.y),v<t.y&&(v=t.y)})),{minX:g,minY:m,maxX:p,maxY:v}}}},function(t,e,n){var r=n(19).vec2;t.exports={at:function(t,e,n){return(e-t)*n+t},pointDistance:function(t,e,n,i,o,a){var s=[n-t,i-e];if(r.exactEquals(s,[0,0]))return NaN;var c=[-s[1],s[0]];r.normalize(c,c);var u=[o-t,a-e];return Math.abs(r.dot(u,c))},box:function(t,e,n,r,i){var o=i/2,a=Math.min(t,n),s=Math.max(t,n);return{minX:a-o,minY:Math.min(e,r)-o,maxX:s+o,maxY:Math.max(e,r)+o}},len:function(t,e,n,r){return Math.sqrt((n-t)*(n-t)+(r-e)*(r-e))}}},function(t,e,n){var r=n(118);t.exports=function(t){return r(t)?Array.prototype.slice.call(t):[]}},function(t,e,n){var r=n(118),i=Array.prototype.indexOf;t.exports=function(t,e){return!!r(t)&&i.call(t,e)>-1}},function(t,e){function n(t,e){for(var n in e)e.hasOwnProperty(n)&&"constructor"!==n&&void 0!==e[n]&&(t[n]=e[n])}t.exports=function(t,e,r,i){return e&&n(t,e),r&&n(t,r),i&&n(t,i),t}},,function(t,e,n){var r=n(26),i=function(){function t(t){r.mix(this,{id:"",type:null,model:{},group:null,animate:!1,modelCache:{},isItem:!0,visible:!0},t),this._init()}var e=t.prototype;return e._init=function(){this._initGroup(),this.draw()},e._mapping=function(){var t=this.mapper,e=this.model;t.mapping(e)},e._initGroup=function(){var t=this.group,e=this.model,n=this.type;t.isItemContainer=!0,t.id=e.id,t.itemType=n,t.model=e,t.item=this},e._calculateBBox=function(){var t=this.keyShape,e=this.group,n=r.getBBox(t,e);return n.width=n.maxX-n.minX,n.height=n.maxY-n.minY,n.centerX=(n.minX+n.maxX)/2,n.centerY=(n.minY+n.maxY)/2,n},e.getLabel=function(){return this.group.findByClass("label")[0]},e.getGraph=function(){return this.graph},e._setShapeObj=function(){var t=this.graph,e=this.type,n=this.getModel();this.shapeObj=t.getShapeObj(e,n)},e._afterDraw=function(){var t=this.graph;this._setGId(),this._cacheModel(),t.emit("afteritemdraw",{item:this})},e._cacheModel=function(){this.modelCache=r.mix({},this.model)},e._setGId=function(){var t=this.group,e=this.id,n=this.type;t.gid=e,t.deepEach((function(t,r,i){var o=r.gid;if(t.id=e,t.eventPreFix=n,t.gid=o+"-"+i,t.isShape){var a=t.get("type");t.gid+="-"+a}}))},e._beforeDraw=function(){var t=this.graph,e=this.group;t.emit("beforeitemdraw",{item:this}),e.resetMatrix(),this.updateCollapsedParent()},e._shouldDraw=function(){return!0},e._getDiff=function(){var t=[],e=this.model,n=this.modelCache;return r.each(e,(function(e,i){r.isEqual(e,n[i])||t.push(i)})),0!==t.length&&t},e._drawInner=function(){var t=this.animate;this.group.clear(!t),this._mapping(),this._setShapeObj();var e=this.shapeObj,n=e.draw(this);n&&(n.isKeyShape=!0,this.keyShape=n),e.afterDraw&&e.afterDraw(this)},e.deepEach=function(t,e){r.traverseTree(this,t,e||function(t){return t.getChildren()})},e.getShapeObj=function(){return this.shapeObj},e.updateCollapsedParent=function(){var t=this.dataMap;this.collapsedParent=function t(e,n){var r=n[e.parent];if(!r)return!1;if(r){var i=t(r,n);if(i)return i}return r.collapsed?r:void 0}(this.model,t)},e.isVisible=function(){return this.visible},e.hide=function(){var t=this.group,e=this.graph;e.emit("beforeitemhide",{item:this}),t.hide(),this.visible=!1,e.emit("afteritemhide",{item:this})},e.show=function(){var t=this.group,e=this.graph;e.emit("beforeitemshow",{item:this}),t.show(),this.visible=!0,e.emit("afteritemshow",{item:this})},e.draw=function(){this._beforeDraw(),this._shouldDraw()&&this._drawInner(),this._afterDraw()},e.forceUpdate=function(){this._beforeDraw(),this._drawInner(),this._afterDraw()},e.getCenter=function(){var t=this.getBBox();return{x:t.centerX,y:t.centerY}},e.getBBox=function(){return this.bbox||this._calculateBBox()},e.layoutUpdate=function(){this.isVisible()&&this.draw()},e.update=function(){this.draw()},e.getModel=function(){return this.model},e.getKeyShape=function(){return this.keyShape},e.getGraphicGroup=function(){return this.group},e.getHierarchy=function(){return this.graph.getHierarchy(this)},e.getParent=function(){var t=this.model;return this.itemMap[t.parent]},e.getAllParents=function(){for(var t=this.model,e=this.itemMap,n=[],r=t.parent;r&&e[r];){var i=e[r],o=i.getModel();n.push(i),r=o.parent}return n},e.getAllChildren=function(){var t=[];return this.deepEach((function(e){t.push(e)})),t},e.getChildren=function(){var t=this.id;return this.graph.getItems().filter((function(e){return e.model.parent===t}))},e.toFront=function(){this.group.toFront()},e.toBack=function(){this.group.toBack()},e.destroy=function(){if(!this.destroyed){var t=this.animate,e=this.graph;e.emit("beforeitemdestroy",{item:this}),this.group.remove(!t),this.destroyed=!0,e.emit("afteritemdestroy",{item:this})}},t}();t.exports=i},function(t,e){t.exports="2.2.6"},function(t,e,n){var r=n(644),i="\t\n\v\f\r \u2028\u2029",o=new RegExp("([a-z])["+i+",]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?["+i+"]*,?["+i+"]*)+)","ig"),a=new RegExp("(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)["+i+"]*,?["+i+"]*","ig"),s=function(t){if(!t)return null;if(typeof t==typeof[])return t;var e={a:7,c:6,o:2,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,u:3,z:0},n=[];return String(t).replace(o,(function(t,r,i){var o=[],s=r.toLowerCase();if(i.replace(a,(function(t,e){e&&o.push(+e)})),"m"===s&&o.length>2&&(n.push([r].concat(o.splice(0,2))),s="l",r="m"===r?"l":"L"),"o"===s&&1===o.length&&n.push([r,o[0]]),"r"===s)n.push([r].concat(o));else for(;o.length>=e[s]&&(n.push([r].concat(o.splice(0,e[s]))),e[s]););})),n},c=function(t,e){for(var n=[],r=0,i=t.length;i-2*!e>r;r+=2){var o=[{x:+t[r-2],y:+t[r-1]},{x:+t[r],y:+t[r+1]},{x:+t[r+2],y:+t[r+3]},{x:+t[r+4],y:+t[r+5]}];e?r?i-4===r?o[3]={x:+t[0],y:+t[1]}:i-2===r&&(o[2]={x:+t[0],y:+t[1]},o[3]={x:+t[2],y:+t[3]}):o[0]={x:+t[i-2],y:+t[i-1]}:i-4===r?o[3]=o[2]:r||(o[0]={x:+t[r],y:+t[r+1]}),n.push(["C",(-o[0].x+6*o[1].x+o[2].x)/6,(-o[0].y+6*o[1].y+o[2].y)/6,(o[1].x+6*o[2].x-o[3].x)/6,(o[1].y+6*o[2].y-o[3].y)/6,o[2].x,o[2].y])}return n},u=function(t,e,n,r,i){var o=[];if(null===i&&null===r&&(r=n),t=+t,e=+e,n=+n,r=+r,null!==i){var a=Math.PI/180,s=t+n*Math.cos(-r*a),c=t+n*Math.cos(-i*a);o=[["M",s,e+n*Math.sin(-r*a)],["A",n,n,0,+(i-r>180),0,c,e+n*Math.sin(-i*a)]]}else o=[["M",t,e],["m",0,-r],["a",n,r,0,1,1,0,2*r],["a",n,r,0,1,1,0,-2*r],["z"]];return o},h=function(t){if(!(t=s(t))||!t.length)return[["M",0,0]];var e,n,r=[],i=0,o=0,a=0,h=0,l=0;"M"===t[0][0]&&(a=i=+t[0][1],h=o=+t[0][2],l++,r[0]=["M",i,o]);for(var d,f,g=3===t.length&&"M"===t[0][0]&&"R"===t[1][0].toUpperCase()&&"Z"===t[2][0].toUpperCase(),p=l,m=t.length;p<m;p++){if(r.push(d=[]),(e=(f=t[p])[0])!==e.toUpperCase())switch(d[0]=e.toUpperCase(),d[0]){case"A":d[1]=f[1],d[2]=f[2],d[3]=f[3],d[4]=f[4],d[5]=f[5],d[6]=+f[6]+i,d[7]=+f[7]+o;break;case"V":d[1]=+f[1]+o;break;case"H":d[1]=+f[1]+i;break;case"R":for(var v=2,x=(n=[i,o].concat(f.slice(1))).length;v<x;v++)n[v]=+n[v]+i,n[++v]=+n[v]+o;r.pop(),r=r.concat(c(n,g));break;case"O":r.pop(),(n=u(i,o,f[1],f[2])).push(n[0]),r=r.concat(n);break;case"U":r.pop(),r=r.concat(u(i,o,f[1],f[2],f[3])),d=["U"].concat(r[r.length-1].slice(-2));break;case"M":a=+f[1]+i,h=+f[2]+o;break;default:for(var y=1,b=f.length;y<b;y++)d[y]=+f[y]+(y%2?i:o)}else if("R"===e)n=[i,o].concat(f.slice(1)),r.pop(),r=r.concat(c(n,g)),d=["R"].concat(f.slice(-2));else if("O"===e)r.pop(),(n=u(i,o,f[1],f[2])).push(n[0]),r=r.concat(n);else if("U"===e)r.pop(),r=r.concat(u(i,o,f[1],f[2],f[3])),d=["U"].concat(r[r.length-1].slice(-2));else for(var w=0,M=f.length;w<M;w++)d[w]=f[w];if("O"!==(e=e.toUpperCase()))switch(d[0]){case"Z":i=+a,o=+h;break;case"H":i=d[1];break;case"V":o=d[1];break;case"M":a=d[d.length-2],h=d[d.length-1];break;default:i=d[d.length-2],o=d[d.length-1]}}return r},l=function(t,e,n,r){return[t,e,n,r,n,r]},d=function(t,e,n,r,i,o){return[1/3*t+2/3*n,1/3*e+2/3*r,1/3*i+2/3*n,1/3*o+2/3*r,i,o]},f=function(t,e){var n,r=h(t),i=e&&h(e),o={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},a={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},s=[],c=[],u="",f="",g=function(t,e,n){var r,i;if(!t)return["C",e.x,e.y,e.x,e.y,e.x,e.y];switch(!(t[0]in{T:1,Q:1})&&(e.qx=e.qy=null),t[0]){case"M":e.X=t[1],e.Y=t[2];break;case"A":t=["C"].concat(function t(e,n,r,i,o,a,s,c,u,h){r===i&&(r+=1);var l,d,f,g,p,m=120*Math.PI/180,v=Math.PI/180*(+o||0),x=[],y=function(t,e,n){return{x:t*Math.cos(n)-e*Math.sin(n),y:t*Math.sin(n)+e*Math.cos(n)}};if(h)d=h[0],f=h[1],g=h[2],p=h[3];else{e=(l=y(e,n,-v)).x,n=l.y,c=(l=y(c,u,-v)).x,u=l.y,e===c&&n===u&&(c+=1,u+=1);var b=(e-c)/2,w=(n-u)/2,M=b*b/(r*r)+w*w/(i*i);M>1&&(r*=M=Math.sqrt(M),i*=M);var _=r*r,S=i*i,A=(a===s?-1:1)*Math.sqrt(Math.abs((_*S-_*w*w-S*b*b)/(_*w*w+S*b*b)));g=A*r*w/i+(e+c)/2,p=A*-i*b/r+(n+u)/2,d=Math.asin(((n-p)/i).toFixed(9)),f=Math.asin(((u-p)/i).toFixed(9)),d=e<g?Math.PI-d:d,f=c<g?Math.PI-f:f,d<0&&(d=2*Math.PI+d),f<0&&(f=2*Math.PI+f),s&&d>f&&(d-=2*Math.PI),!s&&f>d&&(f-=2*Math.PI)}var E=f-d;if(Math.abs(E)>m){var P=f,C=c,O=u;f=d+m*(s&&f>d?1:-1),x=t(c=g+r*Math.cos(f),u=p+i*Math.sin(f),r,i,o,0,s,C,O,[f,P,g,p])}E=f-d;var I=Math.cos(d),k=Math.sin(d),B=Math.cos(f),T=Math.sin(f),N=Math.tan(E/4),L=4/3*r*N,Y=4/3*i*N,X=[e,n],G=[e+L*k,n-Y*I],D=[c+L*T,u-Y*B],F=[c,u];if(G[0]=2*X[0]-G[0],G[1]=2*X[1]-G[1],h)return[G,D,F].concat(x);for(var j=[],R=0,H=(x=[G,D,F].concat(x).join().split(",")).length;R<H;R++)j[R]=R%2?y(x[R-1],x[R],v).y:y(x[R],x[R+1],v).x;return j}.apply(0,[e.x,e.y].concat(t.slice(1))));break;case"S":"C"===n||"S"===n?(r=2*e.x-e.bx,i=2*e.y-e.by):(r=e.x,i=e.y),t=["C",r,i].concat(t.slice(1));break;case"T":"Q"===n||"T"===n?(e.qx=2*e.x-e.qx,e.qy=2*e.y-e.qy):(e.qx=e.x,e.qy=e.y),t=["C"].concat(d(e.x,e.y,e.qx,e.qy,t[1],t[2]));break;case"Q":e.qx=t[1],e.qy=t[2],t=["C"].concat(d(e.x,e.y,t[1],t[2],t[3],t[4]));break;case"L":t=["C"].concat(l(e.x,e.y,t[1],t[2]));break;case"H":t=["C"].concat(l(e.x,e.y,t[1],e.y));break;case"V":t=["C"].concat(l(e.x,e.y,e.x,t[1]));break;case"Z":t=["C"].concat(l(e.x,e.y,e.X,e.Y))}return t},p=function(t,e){if(t[e].length>7){t[e].shift();for(var o=t[e];o.length;)s[e]="A",i&&(c[e]="A"),t.splice(e++,0,["C"].concat(o.splice(0,6)));t.splice(e,1),n=Math.max(r.length,i&&i.length||0)}},m=function(t,e,o,a,s){t&&e&&"M"===t[s][0]&&"M"!==e[s][0]&&(e.splice(s,0,["M",a.x,a.y]),o.bx=0,o.by=0,o.x=t[s][1],o.y=t[s][2],n=Math.max(r.length,i&&i.length||0))};n=Math.max(r.length,i&&i.length||0);for(var v=0;v<n;v++){r[v]&&(u=r[v][0]),"C"!==u&&(s[v]=u,v&&(f=s[v-1])),r[v]=g(r[v],o,f),"A"!==s[v]&&"C"===u&&(s[v]="C"),p(r,v),i&&(i[v]&&(u=i[v][0]),"C"!==u&&(c[v]=u,v&&(f=c[v-1])),i[v]=g(i[v],a,f),"A"!==c[v]&&"C"===u&&(c[v]="C"),p(i,v)),m(r,i,o,a,v),m(i,r,a,o,v);var x=r[v],y=i&&i[v],b=x.length,w=i&&y.length;o.x=x[b-2],o.y=x[b-1],o.bx=parseFloat(x[b-4])||o.x,o.by=parseFloat(x[b-3])||o.y,a.bx=i&&(parseFloat(y[w-4])||a.x),a.by=i&&(parseFloat(y[w-3])||a.y),a.x=i&&y[w-2],a.y=i&&y[w-1]}return i?[r,i]:r},g=/,?([a-z]),?/gi,p=function(t){return t.join(",").replace(g,"$1")},m=function(t,e,n,r,i){return t*(t*(-3*e+9*n-9*r+3*i)+6*e-12*n+6*r)-3*e+3*n},v=function(t,e,n,r,i,o,a,s,c){null===c&&(c=1);for(var u=(c=c>1?1:c<0?0:c)/2,h=[-.1252,.1252,-.3678,.3678,-.5873,.5873,-.7699,.7699,-.9041,.9041,-.9816,.9816],l=[.2491,.2491,.2335,.2335,.2032,.2032,.1601,.1601,.1069,.1069,.0472,.0472],d=0,f=0;f<12;f++){var g=u*h[f]+u,p=m(g,t,n,i,a),v=m(g,e,r,o,s),x=p*p+v*v;d+=l[f]*Math.sqrt(x)}return u*d},x=function(t,e,n,r,i,o,a,s){if(!(Math.max(t,n)<Math.min(i,a)||Math.min(t,n)>Math.max(i,a)||Math.max(e,r)<Math.min(o,s)||Math.min(e,r)>Math.max(o,s))){var c=(t-n)*(o-s)-(e-r)*(i-a);if(c){var u=((t*r-e*n)*(i-a)-(t-n)*(i*s-o*a))/c,h=((t*r-e*n)*(o-s)-(e-r)*(i*s-o*a))/c,l=+u.toFixed(2),d=+h.toFixed(2);if(!(l<+Math.min(t,n).toFixed(2)||l>+Math.max(t,n).toFixed(2)||l<+Math.min(i,a).toFixed(2)||l>+Math.max(i,a).toFixed(2)||d<+Math.min(e,r).toFixed(2)||d>+Math.max(e,r).toFixed(2)||d<+Math.min(o,s).toFixed(2)||d>+Math.max(o,s).toFixed(2)))return{x:u,y:h}}}},y=function(t,e,n){return e>=t.x&&e<=t.x+t.width&&n>=t.y&&n<=t.y+t.height},b=function(t,e,n,r,i){if(i)return[["M",+t+ +i,e],["l",n-2*i,0],["a",i,i,0,0,1,i,i],["l",0,r-2*i],["a",i,i,0,0,1,-i,i],["l",2*i-n,0],["a",i,i,0,0,1,-i,-i],["l",0,2*i-r],["a",i,i,0,0,1,i,-i],["z"]];var o=[["M",t,e],["l",n,0],["l",0,r],["l",-n,0],["z"]];return o.parsePathArray=p,o},w=function(t,e,n,r){return null===t&&(t=e=n=r=0),null===e&&(e=t.y,n=t.width,r=t.height,t=t.x),{x:t,y:e,width:n,w:n,height:r,h:r,x2:t+n,y2:e+r,cx:t+n/2,cy:e+r/2,r1:Math.min(n,r)/2,r2:Math.max(n,r)/2,r0:Math.sqrt(n*n+r*r)/2,path:b(t,e,n,r),vb:[t,e,n,r].join(" ")}},M=function(t,e,n,i,o,a,s,c){r.isArray(t)||(t=[t,e,n,i,o,a,s,c]);var u=function(t,e,n,r,i,o,a,s){for(var c,u,h,l,d=[],f=[[],[]],g=0;g<2;++g)if(0===g?(u=6*t-12*n+6*i,c=-3*t+9*n-9*i+3*a,h=3*n-3*t):(u=6*e-12*r+6*o,c=-3*e+9*r-9*o+3*s,h=3*r-3*e),Math.abs(c)<1e-12){if(Math.abs(u)<1e-12)continue;(l=-h/u)>0&&l<1&&d.push(l)}else{var p=u*u-4*h*c,m=Math.sqrt(p);if(!(p<0)){var v=(-u+m)/(2*c);v>0&&v<1&&d.push(v);var x=(-u-m)/(2*c);x>0&&x<1&&d.push(x)}}for(var y,b=d.length,w=b;b--;)y=1-(l=d[b]),f[0][b]=y*y*y*t+3*y*y*l*n+3*y*l*l*i+l*l*l*a,f[1][b]=y*y*y*e+3*y*y*l*r+3*y*l*l*o+l*l*l*s;return f[0][w]=t,f[1][w]=e,f[0][w+1]=a,f[1][w+1]=s,f[0].length=f[1].length=w+2,{min:{x:Math.min.apply(0,f[0]),y:Math.min.apply(0,f[1])},max:{x:Math.max.apply(0,f[0]),y:Math.max.apply(0,f[1])}}}.apply(null,t);return w(u.min.x,u.min.y,u.max.x-u.min.x,u.max.y-u.min.y)},_=function(t,e,n,r,i,o,a,s,c){var u=1-c,h=Math.pow(u,3),l=Math.pow(u,2),d=c*c,f=d*c,g=t+2*c*(n-t)+d*(i-2*n+t),p=e+2*c*(r-e)+d*(o-2*r+e),m=n+2*c*(i-n)+d*(a-2*i+n),v=r+2*c*(o-r)+d*(s-2*o+r);return{x:h*t+3*l*c*n+3*u*c*c*i+f*a,y:h*e+3*l*c*r+3*u*c*c*o+f*s,m:{x:g,y:p},n:{x:m,y:v},start:{x:u*t+c*n,y:u*e+c*r},end:{x:u*i+c*a,y:u*o+c*s},alpha:90-180*Math.atan2(g-m,p-v)/Math.PI}},S=function(t,e,n){if(!function(t,e){return t=w(t),e=w(e),y(e,t.x,t.y)||y(e,t.x2,t.y)||y(e,t.x,t.y2)||y(e,t.x2,t.y2)||y(t,e.x,e.y)||y(t,e.x2,e.y)||y(t,e.x,e.y2)||y(t,e.x2,e.y2)||(t.x<e.x2&&t.x>e.x||e.x<t.x2&&e.x>t.x)&&(t.y<e.y2&&t.y>e.y||e.y<t.y2&&e.y>t.y)}(M(t),M(e)))return n?0:[];for(var r=~~(v.apply(0,t)/8),i=~~(v.apply(0,e)/8),o=[],a=[],s={},c=n?0:[],u=0;u<r+1;u++){var h=_.apply(0,t.concat(u/r));o.push({x:h.x,y:h.y,t:u/r})}for(var l=0;l<i+1;l++){var d=_.apply(0,e.concat(l/i));a.push({x:d.x,y:d.y,t:l/i})}for(var f=0;f<r;f++)for(var g=0;g<i;g++){var p=o[f],m=o[f+1],b=a[g],S=a[g+1],A=Math.abs(m.x-p.x)<.001?"y":"x",E=Math.abs(S.x-b.x)<.001?"y":"x",P=x(p.x,p.y,m.x,m.y,b.x,b.y,S.x,S.y);if(P){if(s[P.x.toFixed(4)]===P.y.toFixed(4))continue;s[P.x.toFixed(4)]=P.y.toFixed(4);var C=p.t+Math.abs((P[A]-p[A])/(m[A]-p[A]))*(m.t-p.t),O=b.t+Math.abs((P[E]-b[E])/(S[E]-b[E]))*(S.t-b.t);C>=0&&C<=1&&O>=0&&O<=1&&(n?c++:c.push({x:P.x,y:P.y,t1:C,t2:O}))}}return c};function A(t,e){var n=[],r=[];return t.length&&function t(e,i){if(1===e.length)n.push(e[0]),r.push(e[0]);else{for(var o=[],a=0;a<e.length-1;a++)0===a&&n.push(e[0]),a===e.length-2&&r.push(e[a+1]),o[a]=[(1-i)*e[a][0]+i*e[a+1][0],(1-i)*e[a][1]+i*e[a+1][1]];t(o,i)}}(t,e),{left:n,right:r.reverse()}}var E=function(t,e){if(t.length!==e.length)return!1;var n=!0;return r.each(t,(function(t,r){if(t!==e[r])return n=!1,!1})),n};function P(t,e,n){var r=null,i=n;return e<i&&(i=e,r="add"),t<i&&(i=t,r="del"),{type:r,min:i}}function C(t,e,n){for(var r,i=[].concat(t),o=1/(n+1),a=O(e)[0],s=1;s<=n;s++)o*=s,0===(r=Math.floor(t.length*o))?i.unshift([a[0]*o+t[r][0]*(1-o),a[1]*o+t[r][1]*(1-o)]):i.splice(r,0,[a[0]*o+t[r][0]*(1-o),a[1]*o+t[r][1]*(1-o)]);return i}function O(t){var e=[];switch(t[0]){case"M":case"L":e.push([t[1],t[2]]);break;case"A":e.push([t[6],t[7]]);break;case"Q":e.push([t[3],t[4]]),e.push([t[1],t[2]]);break;case"T":e.push([t[1],t[2]]);break;case"C":e.push([t[5],t[6]]),e.push([t[1],t[2]]),e.push([t[3],t[4]]);break;case"S":e.push([t[3],t[4]]),e.push([t[1],t[2]]);break;case"H":case"V":e.push([t[1],t[1]])}return e}t.exports={parsePathString:s,parsePathArray:p,pathTocurve:f,pathToAbsolute:h,catmullRomToBezier:c,rectPath:b,fillPath:function(t,e){if(1===t.length)return t;var n=t.length-1,r=e.length-1,i=n/r,o=[];if(1===t.length&&"M"===t[0][0]){for(var a=0;a<r-n;a++)t.push(t[0]);return t}for(var s=0;s<r;s++){var c=Math.floor(i*s);o[c]=(o[c]||0)+1}var u=o.reduce((function(e,r,i){return i===n?e.concat(t[n]):e.concat(function(t,e,n){if(1===n)return[[].concat(t)];var r=[];if("L"===e[0]||"C"===e[0]||"Q"===e[0])r=r.concat(function(t,e,n){var r=[[t[1],t[2]]];n=n||2;var i=[];"A"===e[0]?(r.push(e[6]),r.push(e[7])):"C"===e[0]?(r.push([e[1],e[2]]),r.push([e[3],e[4]]),r.push([e[5],e[6]])):"S"===e[0]||"Q"===e[0]?(r.push([e[1],e[2]]),r.push([e[3],e[4]])):r.push([e[1],e[2]]);for(var o=r,a=1/n,s=0;s<n-1;s++){var c=A(o,a/(1-a*s));i.push(c.left),o=c.right}return i.push(o),i.map((function(t){var e=[];return 4===t.length&&(e.push("C"),e=e.concat(t[2])),t.length>=3&&(3===t.length&&e.push("Q"),e=e.concat(t[1])),2===t.length&&e.push("L"),e.concat(t[t.length-1])}))}(t,e,n));else{var i=[].concat(t);"M"===i[0]&&(i[0]="L");for(var o=0;o<=n-1;o++)r.push(i)}return r}(t[i],t[i+1],r))}),[]);return u.unshift(t[0]),"Z"!==e[r]&&"z"!==e[r]||u.push("Z"),u},fillPathByDiff:function(t,e){var n=function(t,e){var n,r,i=t.length,o=e.length,a=0;if(0===i||0===o)return null;for(var s=[],c=0;c<=i;c++)s[c]=[],s[c][0]={min:c};for(var u=0;u<=o;u++)s[0][u]={min:u};for(var h=1;h<=i;h++){n=t[h-1];for(var l=1;l<=o;l++){r=e[l-1],a=E(n,r)?0:1;var d=s[h-1][l].min+1,f=s[h][l-1].min+1,g=s[h-1][l-1].min+a;s[h][l]=P(d,f,g)}}return s}(t,e),r=t.length,i=e.length,o=[],a=1,s=1;if(n[r][i]!==r){for(var c=1;c<=r;c++){var u=n[c][c].min;s=c;for(var h=a;h<=i;h++)n[c][h].min<u&&(u=n[c][h].min,s=h);a=s,n[c][a].type&&o.push({index:c-1,type:n[c][a].type})}for(var l=o.length-1;l>=0;l--)a=o[l].index,"add"===o[l].type?t.splice(a,0,[].concat(t[a])):t.splice(a,1)}var d=i-(r=t.length);if(r<i)for(var f=0;f<d;f++)"z"===t[r-1][0]||"Z"===t[r-1][0]?t.splice(r-2,0,t[r-2]):t.push(t[r-1]),r+=1;return t},formatPath:function(t,e){if(t.length<=1)return t;for(var n,r=0;r<e.length;r++)if(t[r][0]!==e[r][0])switch(n=O(t[r]),e[r][0]){case"M":t[r]=["M"].concat(n[0]);break;case"L":t[r]=["L"].concat(n[0]);break;case"A":t[r]=[].concat(e[r]),t[r][6]=n[0][0],t[r][7]=n[0][1];break;case"Q":if(n.length<2){if(!(r>0)){t[r]=e[r];break}n=C(n,t[r-1],1)}t[r]=["Q"].concat(n.reduce((function(t,e){return t.concat(e)}),[]));break;case"T":t[r]=["T"].concat(n[0]);break;case"C":if(n.length<3){if(!(r>0)){t[r]=e[r];break}n=C(n,t[r-1],2)}t[r]=["C"].concat(n.reduce((function(t,e){return t.concat(e)}),[]));break;case"S":if(n.length<2){if(!(r>0)){t[r]=e[r];break}n=C(n,t[r-1],1)}t[r]=["S"].concat(n.reduce((function(t,e){return t.concat(e)}),[]));break;default:t[r]=e[r]}return t},intersection:function(t,e){return function(t,e,n){var r,i,o,a,s,c,u,h,l,d;t=f(t),e=f(e);for(var g=[],p=0,m=t.length;p<m;p++){var v=t[p];if("M"===v[0])r=s=v[1],i=c=v[2];else{"C"===v[0]?(r=(l=[r,i].concat(v.slice(1)))[6],i=l[7]):(l=[r,i,r,i,s,c,s,c],r=s,i=c);for(var x=0,y=e.length;x<y;x++){var b=e[x];if("M"===b[0])o=u=b[1],a=h=b[2];else{"C"===b[0]?(o=(d=[o,a].concat(b.slice(1)))[6],a=d[7]):(d=[o,a,o,a,u,h,u,h],o=u,a=h);for(var w=S(l,d,n),M=0,_=w.length;M<_;M++)w[M].segment1=p,w[M].segment2=x,w[M].bez1=l,w[M].bez2=d;g=g.concat(w)}}}}return g}(t,e)}}},function(t,e,n){var r=n(19),i=n(58),o=n(593),a=n(600),s=function t(e){t.superclass.constructor.call(this,e)};s.Symbols={circle:function(t,e,n){return[["M",t,e],["m",-n,0],["a",n,n,0,1,0,2*n,0],["a",n,n,0,1,0,2*-n,0]]},square:function(t,e,n){return[["M",t-n,e-n],["L",t+n,e-n],["L",t+n,e+n],["L",t-n,e+n],["Z"]]},diamond:function(t,e,n){return[["M",t-n,e],["L",t,e-n],["L",t+n,e],["L",t,e+n],["Z"]]},triangle:function(t,e,n){var r=n*Math.sin(1/3*Math.PI);return[["M",t-n,e+r],["L",t,e-r],["L",t+n,e+r],["z"]]},"triangle-down":function(t,e,n){var r=n*Math.sin(1/3*Math.PI);return[["M",t-n,e-r],["L",t+n,e-r],["L",t,e+r],["Z"]]}},s.ATTRS={path:null,lineWidth:1},r.extend(s,i),r.augment(s,{type:"marker",canFill:!0,canStroke:!0,getDefaultAttrs:function(){return{x:0,y:0,lineWidth:1}},calculateBox:function(){var t=this._attrs,e=t.x,n=t.y,r=t.radius,i=this.getHitLineWidth()/2+r;return{minX:e-i,minY:n-i,maxX:e+i,maxY:n+i}},_getPath:function(){var t=this._attrs,e=t.x,n=t.y,i=t.radius||t.r,o=t.symbol||"circle";return(r.isFunction(o)?o:s.Symbols[o])(e,n,i)},createPath:function(t){var e=this._cfg.segments;if(!e||this._cfg.hasUpdate){var n,r=o.parsePath(this._getPath());t.beginPath(),e=[];for(var i=0;i<r.length;i++){var s=r[i];n=new a(s,n,i===r.length-1),e.push(n),n.draw(t)}this._cfg.segments=e,this._cfg.hasUpdate=!1}else{t.beginPath();for(var c=0;c<e.length;c++)e[c].draw(t)}}}),t.exports=s},function(t,e,n){var r=n(19),i=r.vec2;function o(t,e,n,r,i){var o=1-i;return o*o*(o*r+3*i*n)+i*i*(i*t+3*o*e)}function a(t,e,n,r,a,s,c,u,h,l,d){var f,g,p,m,v,x,y,b,w=.005,M=1/0,_=[h,l];for(g=0;g<1;g+=.05)p=[o(t,n,a,c,g),o(e,r,s,u,g)],(m=i.squaredDistance(_,p))<M&&(f=g,M=m);M=1/0;for(var S=0;S<32&&!(w<1e-4);S++)b=f+w,p=[o(t,n,a,c,y=f-w),o(e,r,s,u,y)],m=i.squaredDistance(_,p),y>=0&&m<M?(f=y,M=m):(x=[o(t,n,a,c,b),o(e,r,s,u,b)],v=i.squaredDistance(_,x),b<=1&&v<M?(f=b,M=v):w*=.5);return d&&(d.x=o(t,n,a,c,f),d.y=o(e,r,s,u,f)),Math.sqrt(M)}function s(t,e,n,r,i){return t*(t*(-3*e+9*n-9*r+3*i)+6*e-12*n+6*r)-3*e+3*n}t.exports={at:o,derivativeAt:function(t,e,n,r,i){var o=1-i;return 3*(((e-t)*o+2*(n-e)*i)*o+(r-n)*i*i)},projectPoint:function(t,e,n,r,i,o,s,c,u,h){var l={};return a(t,e,n,r,i,o,s,c,u,h,l),l},pointDistance:a,extrema:function(t,e,n,i){var o,a,s,c=3*t-9*e+9*n-3*i,u=6*e-12*n+6*i,h=3*n-3*i,l=[];if(r.isNumberEqual(c,0))r.isNumberEqual(u,0)||(o=-h/u)>=0&&o<=1&&l.push(o);else{var d=u*u-4*c*h;r.isNumberEqual(d,0)?l.push(-u/(2*c)):d>0&&(a=(-u-(s=Math.sqrt(d)))/(2*c),(o=(-u+s)/(2*c))>=0&&o<=1&&l.push(o),a>=0&&a<=1&&l.push(a))}return l},len:function(t,e,n,i,o,a,c,u,h){r.isNil(h)&&(h=1);for(var l=(h=h>1?1:h<0?0:h)/2,d=[-.1252,.1252,-.3678,.3678,-.5873,.5873,-.7699,.7699,-.9041,.9041,-.9816,.9816],f=[.2491,.2491,.2335,.2335,.2032,.2032,.1601,.1601,.1069,.1069,.0472,.0472],g=0,p=0;p<12;p++){var m=l*d[p]+l,v=s(m,t,n,o,c),x=s(m,e,i,a,u),y=v*v+x*x;g+=f[p]*Math.sqrt(y)}return l*g}}},function(t,e,n){var r=n(603),i=n(640),o=n(612),a=n(602);t.exports={line:function(t,e,n,i,o,a,s){var c=r.box(t,e,n,i,o);if(!this.box(c.minX,c.maxX,c.minY,c.maxY,a,s))return!1;var u=r.pointDistance(t,e,n,i,a,s);return!isNaN(u)&&u<=o/2},polyline:function(t,e,n,r){var i=t.length-1;if(i<1)return!1;for(var o=0;o<i;o++){var a=t[o][0],s=t[o][1],c=t[o+1][0],u=t[o+1][1];if(this.line(a,s,c,u,e,n,r))return!0}return!1},cubicline:function(t,e,n,r,i,a,s,c,u,h,l){return o.pointDistance(t,e,n,r,i,a,s,c,h,l)<=u/2},quadraticline:function(t,e,n,r,o,a,s,c,u){return i.pointDistance(t,e,n,r,o,a,c,u)<=s/2},arcline:function(t,e,n,r,i,o,s,c,u){return a.pointDistance(t,e,n,r,i,o,c,u)<=s/2},rect:function(t,e,n,r,i,o){return t<=i&&i<=t+n&&e<=o&&o<=e+r},circle:function(t,e,n,r,i){return Math.pow(r-t,2)+Math.pow(i-e,2)<=Math.pow(n,2)},box:function(t,e,n,r,i,o){return t<=i&&i<=e&&n<=o&&o<=r}}},function(t,e,n){var r=n(619),i=n(118),o=n(595);t.exports=function t(e,n){if(e===n)return!0;if(!e||!n)return!1;if(o(e)||o(n))return!1;if(i(e)||i(n)){if(e.length!==n.length)return!1;for(var a=!0,s=0;s<e.length&&(a=t(e[s],n[s]));s++);return a}if(r(e)||r(n)){var c=Object.keys(e),u=Object.keys(n);if(c.length!==u.length)return!1;for(var h=!0,l=0;l<c.length&&(h=t(e[c[l]],n[c[l]]));l++);return h}return!1}},function(t,e,n){var r=n(596),i=n(45);function o(t,e,n,a){for(var s in n=n||0,a=a||5,e)if(e.hasOwnProperty(s)){var c=e[s];null!==c&&r(c)?(r(t[s])||(t[s]={}),n<a?o(t[s],c,n+1,a):t[s]=e[s]):i(c)?(t[s]=[],t[s]=t[s].concat(c)):void 0!==c&&(t[s]=c)}}t.exports=function(){for(var t=new Array(arguments.length),e=t.length,n=0;n<e;n++)t[n]=arguments[n];for(var r=t[0],i=1;i<e;i++)o(r,t[i]);return r}},function(t,e,n){var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=n(45);t.exports=function t(e){if("object"!==(void 0===e?"undefined":r(e))||null===e)return e;var n=void 0;if(i(e)){n=[];for(var o=0,a=e.length;o<a;o++)"object"===r(e[o])&&null!=e[o]?n[o]=t(e[o]):n[o]=e[o]}else for(var s in n={},e)"object"===r(e[s])&&null!=e[s]?n[s]=t(e[s]):n[s]=e[s];return n}},function(t,e,n){var r=n(256);r.translate=function(t,e,n){var i=new Array(9);return r.fromTranslation(i,n),r.multiply(t,i,e)},r.rotate=function(t,e,n){var i=new Array(9);return r.fromRotation(i,n),r.multiply(t,i,e)},r.scale=function(t,e,n){var i=new Array(9);return r.fromScaling(i,n),r.multiply(t,i,e)},t.exports=r},function(t,e){t.exports=function(t,e,n){return t<e?e:t>n?n:t}},function(t,e){var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};t.exports=function(t){return"object"===(void 0===t?"undefined":n(t))&&null!==t}},function(t,e,n){var r=n(46),i=n(118);t.exports=function(t,e){if(!i(t))return t;var n=[];return r(t,(function(t,r){e(t,r)&&n.push(t)})),n}},function(t,e){var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};t.exports=function(t){var e=void 0===t?"undefined":n(t);return null!==t&&"object"===e||"function"===e}},function(t,e){var n=function(){function t(){}return t.prototype.execute=function(){throw new Error("please override this method")},t}();t.exports=n},function(t,e,n){t.exports={CompactBoxTree:n(688),Dendrogram:n(687),IndentedTree:n(686),Mindmap:n(685),Base:n(622)}},function(t,e,n){var r=n(26),i=function(t){function e(e){var n={type:"node",isNode:!0,zIndex:3,edges:[],linkable:!0};return r.mix(n,e),t.call(this,n)||this}!function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t);var n=e.prototype;return n.updatePosition=function(){var t=this.group,e=this.model;t.setMatrix([1,0,0,0,1,0,e.x?e.x:0,e.y?e.y:0,1]),this.bbox=this._calculateBBox()},n._shouldDraw=function(){var e=this._getDiff(),n=t.prototype._shouldDraw.call(this);return e&&!(2===e.length&&-1!==e.indexOf("x")&&-1!==e.indexOf("y"))&&!(1===e.length&&("x"===e[0]||"y"===e[0]))&&n},n._afterDraw=function(){this.updatePosition(),t.prototype._afterDraw.call(this)},n.layoutUpdate=function(){this._beforeDraw(),this._afterDraw()},n.getEdges=function(){var t=this;return this.graph.getEdges().filter((function(e){var n=e.getModel();return n.source===t.id||n.target===t.id}))},n.getInEdges=function(){var t=this;return this.getEdges().filter((function(e){return e.target===t}))},n.getOutEdges=function(){var t=this;return this.getEdges().filter((function(e){return e.source===t}))},n.getLinkPoints=function(t){var e=this.getAnchorPoints();if(r.isNumber(t)&&e[t])return[e[t]];var n=t.x,i=t.y,o=this.getBBox(),a=o.centerX,s=o.centerY,c=n-a,u=i-s,h=this.shapeObj,l=h.anchor||{},d=this.defaultIntersectBox,f=[];if(r.isEmpty(e)){switch(h.intersectBox||l.intersectBox||l.type||d){case"rect":f=[r.getIntersectPointRect(o,t)];break;case"path":if(this.keyShape&&"path"===this.keyShape.get("type")){var g=r.parsePathArray(["M",n,i,"L",a,s]);f=[r.intersection(g,this.keyShape.get("path"))]}break;default:f=[r.getIntersectPointCircle(n,i,o.centerX,o.centerY,Math.max(o.width,o.height)/2)]}r.isEmpty(f[0])&&(f=[{x:a,y:s}])}else f=e.map((function(t){var e=t.x-a,n=t.y-s,i=r.getArcOfVectors({x:c,y:u},{x:e,y:n});return r.mix({},t,{arc:i})})).sort((function(t,e){return t.arc-e.arc}));return f},n.getAnchorPoints=function(t){var e,n=this.shapeObj,i=this.getBBox(),o=[],a=n.anchor||{};return e=r.isArray(a)?a:r.isFunction(a)?a(this):r.isFunction(a.points)?a.points(this):a.points,r.each(e,(function(t,e){var n=r.mix({x:i.minX+t[0]*i.width,y:i.minY+t[1]*i.height},t[2],{index:e});o.push(n)})),this._anchorPoints=o,r.isNumber(t)?this._anchorPoints[t]:this._anchorPoints},e}(n(608));t.exports=i},function(t,e,n){function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}n(715),n(714),n(713);var i=n(712),o=n(710),a=n(683),s=n(26),c=n(706),u=n(248),h=n(704),l=n(702),d=n(700),f=n(699),g=n(697),p=n(696),m=n(695),v=n(692),x=n(691),y=[p,l,d,h,m,v,n(690),x,f,g],b=function(t){!function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(n,t);var e=n.prototype;function n(e){var n,r={};return y.forEach((function(t){s.mix(r,s.clone(t.CFG),e)})),(n=t.call(this,r)||this)._pluginInit(),n.emit("beforeinit"),n._init(),n.emit("afterinit"),n}return e.getDefaultCfg=function(){return{container:void 0,width:void 0,height:void 0,plugins:[],fontFamily:'"Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", SimSun, "sans-serif"',nodeDefaultShape:void 0,edgeDefaultShape:void 0,groupDefaultShape:void 0,defaultIntersectBox:"circle",renderer:"canvas",_type:"graph",_controllers:{},_timers:{},_dataMap:{},_itemMap:{},_freezMap:{},_data:{},_delayRunObj:{}}},e._init=function(){var t=this;this._initData(),this._initContainer(),this._initCanvas(),y.forEach((function(e){e.INIT&&t[e.INIT]()})),this.initEvent()},e.initEvent=function(){},e._executeLayout=function(t,e,n,r){s.isFunction(t)?t(e,n,this):s.isObject(t)&&(t.nodes=e,t.edges=n,t.groups=r,t.graph=this,t.execute())},e._pluginInit=function(){var t=this;this.get("plugins").forEach((function(e){t._initPlugin(e)}))},e._initPlugin=function(t){t.graph=this,t.init&&t.init()},e._getTimer=function(t){return this.get("_timers")[t]},e._setTimer=function(t,e){this.get("_timers")[t]=e},e._getController=function(t){return this.get("_controllers")[t]},e._initContainer=function(){var t=this.get("container");t||(t=this.get("id")),t=s.initDOMContainer(t,"graph");var e=s.createDOM('<div class="graph-container"></div>',{position:"relative"});t.appendChild(e),this.set("_containerDOM",t),this.set("_graphContainer",e)},e._initCanvas=function(){var t=this.get("_graphContainer"),e=this.get("width"),n=this.get("height"),r=this.get("fontFamily"),i=this.get("renderer"),o={width:e,height:n,fontFamily:r,renderer:i,eventEnable:!1,containerDOM:t};"svg"===i&&(o.pixelRatio=1);var a=new(0,u.Canvas)(o),s=a.get("el");s.style.top=0,s.style.left=0,s.style.overflow="hidden",this.set("_canvas",a);var c=this.getMouseEventWrapper();c.style.outline="none",c.style["user-select"]="none",c.setAttribute("tabindex",20);var h=a.addGroup(),l=h.addGroup();this.set("_itemGroup",l),this.set("_rootGroup",h)},e._initData=function(){this.set("_dataMap",{}),this.set("_itemMap",{_nodes:[],_edges:[],_groups:[],_guides:[]}),this.set("_data",{})},e._refresh=function(){},e.getKeyboardEventWrapper=function(){return this.get("keyboardEventWrapper")||this.getMouseEventWrapper()},e.getMouseEventWrapper=function(){return this.get("_canvas").get("el")},e.addPlugin=function(t){var e=this.get("plugins");this._initPlugin(t),e.push(t)},e.getGraphContainer=function(){return this.get("_graphContainer")},e._sortGroup=function(t){var e=this.get("_dataMap"),n={};t.forEach((function(t){var r=t.id,i=t.parent;for(n[r]=1;i&&e[i];)n[r]++,i=e[i].parent})),t.sort((function(t,e){return n[e.id]-n[t.id]}))},e._addItems=function(t,e){var n=this;this._addDatas(t,e),"group"===t&&this._sortGroup(e);var r=s.upperFirst(t),i=o[r],a=this.get("_itemMap"),c=this.get("_itemGroup"),u=this.get("_dataMap"),h=this.get("animate"),l=this.get("defaultIntersectBox");if(!i)throw new Error("please set valid item type!");e.forEach((function(e){var r=new i({id:e.id,type:t,model:e,group:c.addGroup(),graph:n,mapper:n._getController(t+"Mapper"),itemMap:a,animate:h,dataMap:u,defaultIntersectBox:l});a[e.id]=r,a["_"+t+"s"].push(r)}))},e._removeItems=function(t){var e=this.get("_dataMap"),n=this.get("_itemMap");t.forEach((function(t){delete e[t.id],delete n[t.id],s.Array.remove(n["_"+t.type+"s"],t),t.destroy()}))},e._updateItems=function(t,e){t.forEach((function(t,n){var r=e[n];r&&s.mix(t.getModel(),r),t.update()}))},e._getShowEdge=function(t){var e=t.getSource(),n=t.getTarget();return(e.linkable&&e.isVisible()||!e.linkable)&&(n.linkable&&n.isVisible()||!n.linkable)&&t},e._addDatas=function(t,e){var n=this.get("_dataMap");e.forEach((function(t){if(s.isNil(t.id)&&(t.id=s.guid()),n[t.id])throw new Error("id:"+t.id+" has already been set, please set new one");n[t.id]=t}))},e._drawInner=function(){var t=this.get("_data"),e=this.get("_itemGroup"),n=this.get("_dataMap"),r=this.get("_itemMap");t.nodes&&this._addItems("node",t.nodes),t.groups&&this._addItems("group",t.groups),t.edges&&this._addItems("edge",t.edges),t.guides&&this._addItems("guide",t.guides),e.sortBy((function(t){var e=t.id,i=r[e],o=n[e];return o&&!s.isNil(o.index)?o.index:!i||i.destroyed||s.isNil(i.zIndex)?void 0:i.zIndex}))},e._clearInner=function(){this.getItems().forEach((function(t){t&&t.destroy()}))},e.preventAnimate=function(t){return this.set("_forcePreventAnimate",!0),t(),this.set("_forcePreventAnimate",!1),this},e.getShapeObj=function(t,e){if(!s.isObject(t)){var n=s.upperFirst(t),r=a[n],i=this.get(t+"DefaultShape");return r.getShape(e.shape,i)}return t.getShapeObj()},e.getSource=function(){return this.get("_sourceData")},e.parseSource=function(t){return t},e.getCanvas=function(){return this.get("_canvas")},e.getRootGroup=function(){return this.get("_rootGroup")},e.getItemGroup=function(){return this.get("_itemGroup")},e.source=function(t){return this.emit("beforesource"),this.set("_data",t),this.set("_sourceData",t),this.emit("aftersource"),this},e.render=function(){return this.emit("beforerender"),this.emit("beforedrawinner"),this._drawInner(),this.emit("afterdrawinner"),this.emit("afterrender"),this},e.reRender=function(){var t=this.get("_sourceData");return this.read(t),this},e.setCapture=function(t){this.get("_rootGroup").set("capture",t)},e.destroy=function(){this.emit("beforedestroy");var e=this.get("_canvas"),n=this.get("_graphContainer"),r=this.get("_controllers"),i=this.get("_timers"),o=this.get("_windowForceResizeEvent"),a=this.get("plugins");return s.each(i,(function(t){clearTimeout(t)})),s.each(r,(function(t){t.destroy()})),a.forEach((function(t){t.destroy&&t.destroy()})),e&&e.destroy(),n.destroy(),window.removeEventListener("resize",o),this.emit("afterdestroy"),t.prototype.destroy.call(this),this},e.save=function(){var t={nodes:[],edges:[],groups:[],guides:[]};return this.get("_itemGroup").get("children").forEach((function(e,n){var r=e.model;if(r){var i=e.itemType,o=s.clone(r);o.index=n,t[i+"s"].push(o)}})),0===t.nodes.length&&delete t.nodes,0===t.edges.length&&delete t.edges,0===t.groups.length&&delete t.groups,0===t.guides.length&&delete t.guides,t},e.add=function(t,e){var n=[],r={action:"add",model:e,affectedItemIds:n};this.emit("beforechange",r);var i=this.get("_itemMap");this._addItems(t,[e]);var o=i[e.id];return o.getAllParents().forEach((function(t){t.update()})),r.item=o,n.push(e.id),this.emit("afterchange",r),o},e.remove=function(t){if((t=this.getItem(t))&&!t.destroyed){var e=[],n=[],r={action:"remove",item:t,affectedItemIds:n};if(t.isNode){var i=t.getEdges();e=e.concat(i)}if(t.isGroup){var o=t.getEdges(),a=t.getAllChildren(),c=t.getCrossEdges(),u=t.getInnerEdges();e=e.concat(o,a,c,u),e=s.uniq(e)}e.push(t);var h=t.getAllParents();return h.forEach((function(t){n.push(t.id)})),e.forEach((function(t){n.push(t.id)})),this.emit("beforechange",r),this._removeItems(e),h.forEach((function(t){t.update()})),this.emit("afterchange",r),this}},e.simpleUpdate=function(t,e){return this._updateItems([t],[e]),this.draw(),this},e.update=function(t,e){var n=this.get("_itemMap");if((t=this.getItem(t))&&!t.destroyed&&e){var r=this.get("animate"),i=[],o=[],a=[],c=t.getModel(),u=s.mix({},c),h={action:"update",item:t,originModel:u,updateModel:e,affectedItemIds:a},l=n[u.parent];if(i.push(t),o.push(e),a.push(t.id),l&&l!==parent&&s.isGroup(l)&&t.getAllParents().forEach((function(t){i.push(t),o.push(null),a.push(t.id)})),e.parent){var d=n[e.parent];if(!d)throw new Error("there is no "+e.parent+" exist, please add a new one!");i.push(d),o.push(null),a.push(d.id),d.getAllParents().forEach((function(t){i.push(t),o.push(null),a.push(t.id)}))}return(t.isNode||t.isGroup)&&t.getEdges().forEach((function(t){i.push(t),o.push(null),a.push(t.id)})),t.isGroup&&!s.isNil(e.collapsed)&&(r&&t.deepEach((function(t){a.push(t.id)})),t.getCrossEdges().forEach((function(t){i.push(t),o.push(null),a.push(t.id)}))),this.emit("beforechange",h),this._updateItems(i,o),this.emit("afterchange",h),this}},e.read=function(t){var e=this;if(!t)throw new Error("please read valid data!");var n={action:"changeData",data:t};return this.emit("beforechange",n),this.preventAnimate((function(){e.clear(),e.source(t),e.render()})),this.emit("afterchange",n),this},e.clear=function(){return this.emit("beforeclear"),this._clearInner(),this._initData(),this.emit("afterclear"),this},e.hide=function(t){var e=[],n=[],r={item:t=this.getItem(t),affectedItemIds:n};return e.push(t),t.isNode&&t.getEdges().forEach((function(t){e.push(t)})),t.isGroup&&(t.getEdges().forEach((function(t){e.push(t)})),t.deepEach((function(t){e.push(t)}))),(e=s.uniq(e)).forEach((function(t){n.push(t.id)})),this.emit("beforehide",r),e.forEach((function(t){t.hide()})),this.emit("afterhide",r),this},e.show=function(t){var e=this,n=[],r=[],i={item:t=this.getItem(t),affectedItemIds:r};if(t.visible=!0,t.isEdge){var o=this._getShowEdge(t);o&&n.push(o)}else n.push(t);return t.isNode&&t.getEdges().forEach((function(t){(t=e._getShowEdge(t))&&n.push(t)})),t.isGroup&&(t.getEdges().forEach((function(t){(t=e._getShowEdge(t))&&n.push(t)})),t.deepEach((function(t){n.push(t)}))),(n=s.uniq(n)).forEach((function(t){r.push(t.id)})),this.emit("beforeshow",i),n.forEach((function(t){t.show()})),this.emit("aftershow",i),this},e.getWidth=function(){return this.get("width")},e.getHeight=function(){return this.get("height")},e.changeSize=function(t,e){if(!(Math.abs(t)>=1/0||Math.abs(e)>=1/0)){var n=this.get("_canvas");return t===this.get("width")&&e===this.get("height")||(this.emit("beforechangesize"),n.changeSize(t,e),this.set("width",t),this.set("height",e),this.emit("afterchangesize"),this.draw()),this}console.warn("size parameter more than the maximum")},e.toFront=function(t){t=this.getItem(t);var e=this.get("_itemGroup"),n=t.getGraphicGroup();s.toFront(n,e),this.draw()},e.toBack=function(t){t=this.getItem(t);var e=this.get("_itemGroup"),n=t.getGraphicGroup();s.toBack(n,e),this.draw()},e.css=function(t){var e=this.getGraphContainer();s.modifyCSS(e,t)},e.saveImage=function(t){var e=this.getBBox(),n=this.getFitViewPadding();return new c(function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},i=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(i=i.concat(Object.getOwnPropertySymbols(n).filter((function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable})))),i.forEach((function(e){r(t,e,n[e])}))}return t}({graph:this,width:e.width+n[1]+n[3],height:e.height+n[0]+n[2]},t)).toCanvas()},n}(i);y.forEach((function(t){s.mix(b.prototype,t.AUGMENT)})),t.exports=b},function(t,e){var n={registerBehaviour:function(t,e,r){e.dependences=r,n[t]=e},resetMode:function(t,e){var r,i=[];e._off();for(var o=0;o<t.length;o++)(r=n[t[o]])&&(r.dependences&&r.dependences.forEach((function(t){t&&-1===i.indexOf(t)&&(n[t](e),i.push(t))})),r&&-1===i.indexOf(r)&&r(e))}};t.exports=n},function(t,e,n){var r=n(19),i=n(58),o=function t(e){t.superclass.constructor.call(this,e)};o.ATTRS={x:0,y:0,text:null,fontSize:12,fontFamily:"sans-serif",fontStyle:"normal",fontWeight:"normal",fontVariant:"normal",textAlign:"start",textBaseline:"bottom",lineHeight:null,textArr:null},r.extend(o,i),r.augment(o,{canFill:!0,canStroke:!0,type:"text",getDefaultAttrs:function(){return{lineWidth:1,lineCount:1,fontSize:12,fontFamily:"sans-serif",fontStyle:"normal",fontWeight:"normal",fontVariant:"normal",textAlign:"start",textBaseline:"bottom"}},initTransform:function(){var t=this._attrs.fontSize;t&&+t<12&&this.transform([["t",-1*this._attrs.x,-1*this._attrs.y],["s",+t/12,+t/12],["t",this._attrs.x,this._attrs.y]])},_assembleFont:function(){var t=this._attrs,e=t.fontSize,n=t.fontFamily,r=t.fontWeight,i=t.fontStyle,o=t.fontVariant;t.font=[i,o,r,e+"px",n].join(" ")},_setAttrText:function(){var t=this._attrs,e=t.text,n=null;if(r.isString(e)&&-1!==e.indexOf("\n")){var i=(n=e.split("\n")).length;t.lineCount=i}t.textArr=n},_getTextHeight:function(){var t=this._attrs,e=t.lineCount,n=1*t.fontSize;return e>1?n*e+this._getSpaceingY()*(e-1):n},isHitBox:function(){return!1},calculateBox:function(){var t=this._attrs,e=this._cfg;e.attrs&&!e.hasUpdate||(this._assembleFont(),this._setAttrText()),t.textArr||this._setAttrText();var n=t.x,r=t.y,i=this.measureText();if(!i)return{minX:n,minY:r,maxX:n,maxY:r};var o=this._getTextHeight(),a=t.textAlign,s=t.textBaseline,c=this.getHitLineWidth(),u={x:n,y:r-o};a&&("end"===a||"right"===a?u.x-=i:"center"===a&&(u.x-=i/2)),s&&("top"===s?u.y+=o:"middle"===s&&(u.y+=o/2)),this.set("startPoint",u);var h=c/2;return{minX:u.x-h,minY:u.y-h,maxX:u.x+i+h,maxY:u.y+o+h}},_getSpaceingY:function(){var t=this._attrs,e=t.lineHeight,n=1*t.fontSize;return e?e-n:.14*n},drawInner:function(t){var e=this._attrs,n=this._cfg;n.attrs&&!n.hasUpdate||(this._assembleFont(),this._setAttrText()),t.font=e.font;var i=e.text;if(i){var o=e.textArr,a=e.x,s=e.y;if(t.beginPath(),this.hasStroke()){var c=e.strokeOpacity;r.isNil(c)||1===c||(t.globalAlpha=c),o?this._drawTextArr(t,!1):t.strokeText(i,a,s),t.globalAlpha=1}if(this.hasFill()){var u=e.fillOpacity;r.isNil(u)||1===u||(t.globalAlpha=u),o?this._drawTextArr(t,!0):t.fillText(i,a,s)}n.hasUpdate=!1}},_drawTextArr:function(t,e){var n,i=this._attrs.textArr,o=this._attrs.textBaseline,a=1*this._attrs.fontSize,s=this._getSpaceingY(),c=this._attrs.x,u=this._attrs.y,h=this.getBBox(),l=h.maxY-h.minY;r.each(i,(function(r,i){n=u+i*(s+a)-l+a,"middle"===o&&(n+=l-a-(l-a)/2),"top"===o&&(n+=l-a),e?t.fillText(r,c,n):t.strokeText(r,c,n)}))},measureText:function(){var t,e=this._attrs,n=e.text,i=e.font,o=e.textArr,a=0;if(!r.isNil(n)){var s=document.createElement("canvas").getContext("2d");return s.save(),s.font=i,o?r.each(o,(function(e){t=s.measureText(e).width,a<t&&(a=t),s.restore()})):(a=s.measureText(n).width,s.restore()),a}}}),t.exports=o},function(t,e,n){var r=n(19),i=n(593).parseRadius,o=n(58),a=function t(e){t.superclass.constructor.call(this,e)};a.ATTRS={x:0,y:0,width:0,height:0,radius:0,lineWidth:1},r.extend(a,o),r.augment(a,{canFill:!0,canStroke:!0,type:"rect",getDefaultAttrs:function(){return{lineWidth:1,radius:0}},calculateBox:function(){var t=this._attrs,e=t.x,n=t.y,r=t.width,i=t.height,o=this.getHitLineWidth()/2;return{minX:e-o,minY:n-o,maxX:e+r+o,maxY:n+i+o}},createPath:function(t){var e=this._attrs,n=e.x,r=e.y,o=e.width,a=e.height,s=e.radius;if((t=t||this.get("context")).beginPath(),0===s)t.rect(n,r,o,a);else{var c=i(s);t.moveTo(n+c.r1,r),t.lineTo(n+o-c.r2,r),0!==c.r2&&t.arc(n+o-c.r2,r+c.r2,c.r2,-Math.PI/2,0),t.lineTo(n+o,r+a-c.r3),0!==c.r3&&t.arc(n+o-c.r3,r+a-c.r3,c.r3,0,Math.PI/2),t.lineTo(n+c.r4,r+a),0!==c.r4&&t.arc(n+c.r4,r+a-c.r4,c.r4,Math.PI/2,Math.PI),t.lineTo(n,r+c.r1),0!==c.r1&&t.arc(n+c.r1,r+c.r1,c.r1,Math.PI,1.5*Math.PI),t.closePath()}}}),t.exports=a},function(t,e,n){var r=n(19),i=n(58),o=n(601),a=n(603),s=function t(e){t.superclass.constructor.call(this,e)};s.ATTRS={points:null,lineWidth:1,startArrow:!1,endArrow:!1,tCache:null},r.extend(s,i),r.augment(s,{canStroke:!0,type:"polyline",tCache:null,getDefaultAttrs:function(){return{lineWidth:1,startArrow:!1,endArrow:!1}},calculateBox:function(){var t=this._attrs,e=this.getHitLineWidth(),n=t.points;if(!n||0===n.length)return null;var i=1/0,o=1/0,a=-1/0,s=-1/0;r.each(n,(function(t){var e=t[0],n=t[1];e<i&&(i=e),e>a&&(a=e),n<o&&(o=n),n>s&&(s=n)}));var c=e/2;return{minX:i-c,minY:o-c,maxX:a+c,maxY:s+c}},_setTcache:function(){var t,e,n=this._attrs.points,i=0,o=0,s=[];n&&0!==n.length&&(r.each(n,(function(t,e){n[e+1]&&(i+=a.len(t[0],t[1],n[e+1][0],n[e+1][1]))})),i<=0||(r.each(n,(function(r,c){n[c+1]&&((t=[])[0]=o/i,e=a.len(r[0],r[1],n[c+1][0],n[c+1][1]),o+=e,t[1]=o/i,s.push(t))})),this.tCache=s))},createPath:function(t){var e,n,r=this._attrs.points;if(!(r.length<2)){for((t=t||this.get("context")).beginPath(),t.moveTo(r[0][0],r[0][1]),n=1,e=r.length-1;n<e;n++)t.lineTo(r[n][0],r[n][1]);t.lineTo(r[e][0],r[e][1])}},getStartTangent:function(){var t=this.__attrs.points,e=[];return e.push([t[1][0],t[1][1]]),e.push([t[0][0],t[0][1]]),e},getEndTangent:function(){var t=this.__attrs.points,e=t.length-1,n=[];return n.push([t[e-1][0],t[e-1][1]]),n.push([t[e][0],t[e][1]]),n},afterPath:function(t){var e=this._attrs,n=e.points,r=n.length-1;t=t||this.get("context"),e.startArrow&&o.addStartArrow(t,e,n[1][0],n[1][1],n[0][0],n[0][1]),e.endArrow&&o.addEndArrow(t,e,n[r-1][0],n[r-1][1],n[r][0],n[r][1])},getPoint:function(t){var e,n,i=this._attrs.points,o=this.tCache;return o||(this._setTcache(),o=this.tCache),r.each(o,(function(r,i){t>=r[0]&&t<=r[1]&&(e=(t-r[0])/(r[1]-r[0]),n=i)})),{x:a.at(i[n][0],i[n+1][0],e),y:a.at(i[n][1],i[n+1][1],e)}}}),t.exports=s},function(t,e,n){var r=n(19),i=n(58),o=function t(e){t.superclass.constructor.call(this,e)};o.ATTRS={points:null,lineWidth:1},r.extend(o,i),r.augment(o,{canFill:!0,canStroke:!0,type:"polygon",getDefaultAttrs:function(){return{lineWidth:1}},calculateBox:function(){var t=this._attrs.points,e=this.getHitLineWidth();if(!t||0===t.length)return null;var n=1/0,i=1/0,o=-1/0,a=-1/0;r.each(t,(function(t){var e=t[0],r=t[1];e<n&&(n=e),e>o&&(o=e),r<i&&(i=r),r>a&&(a=r)}));var s=e/2;return{minX:n-s,minY:i-s,maxX:o+s,maxY:a+s}},createPath:function(t){var e=this._attrs.points;e.length<2||((t=t||this.get("context")).beginPath(),r.each(e,(function(e,n){0===n?t.moveTo(e[0],e[1]):t.lineTo(e[0],e[1])})),t.closePath())}}),t.exports=o},function(t,e,n){var r=n(19),i=n(58),o=n(600),a=n(593),s=n(601),c=n(610),u=n(612),h=function t(e){t.superclass.constructor.call(this,e)};h.ATTRS={path:null,lineWidth:1,startArrow:!1,endArrow:!1},r.extend(h,i),r.augment(h,{canFill:!0,canStroke:!0,type:"path",getDefaultAttrs:function(){return{lineWidth:1,startArrow:!1,endArrow:!1}},_afterSetAttrPath:function(t){if(r.isNil(t))return this.setSilent("segments",null),void this.setSilent("box",void 0);var e,n=a.parsePath(t),i=[];if(r.isArray(n)&&0!==n.length&&("M"===n[0][0]||"m"===n[0][0])){for(var s=n.length,c=0;c<n.length;c++){var u=n[c];e=new o(u,e,c===s-1),i.push(e)}this.setSilent("segments",i),this.setSilent("tCache",null),this.setSilent("box",null)}},calculateBox:function(){var t=this.get("segments");if(!t)return null;var e=this.getHitLineWidth(),n=1/0,i=-1/0,o=1/0,a=-1/0;return r.each(t,(function(t){t.getBBox(e);var r=t.box;r&&(r.minX<n&&(n=r.minX),r.maxX>i&&(i=r.maxX),r.minY<o&&(o=r.minY),r.maxY>a&&(a=r.maxY))})),n===1/0||o===1/0?{minX:0,minY:0,maxX:0,maxY:0}:{minX:n,minY:o,maxX:i,maxY:a}},_setTcache:function(){var t,e,n,i,o=0,a=0,s=[],c=this._cfg.curve;c&&(r.each(c,(function(t,e){n=c[e+1],i=t.length,n&&(o+=u.len(t[i-2],t[i-1],n[1],n[2],n[3],n[4],n[5],n[6]))})),r.each(c,(function(r,h){n=c[h+1],i=r.length,n&&((t=[])[0]=a/o,e=u.len(r[i-2],r[i-1],n[1],n[2],n[3],n[4],n[5],n[6]),a+=e,t[1]=a/o,s.push(t))})),this._cfg.tCache=s)},_calculateCurve:function(){var t=this._attrs.path;this._cfg.curve=c.pathTocurve(t)},getStartTangent:function(){var t,e,n,i,o=this.get("segments");if(o.length>1)if(t=o[0].endPoint,e=o[1].endPoint,n=o[1].startTangent,i=[],r.isFunction(n)){var a=n();i.push([t.x-a[0],t.y-a[1]]),i.push([t.x,t.y])}else i.push([e.x,e.y]),i.push([t.x,t.y]);return i},getEndTangent:function(){var t,e,n,i,o=this.get("segments"),a=o.length;if(a>1)if(t=o[a-2].endPoint,e=o[a-1].endPoint,n=o[a-1].endTangent,i=[],r.isFunction(n)){var s=n();i.push([e.x-s[0],e.y-s[1]]),i.push([e.x,e.y])}else i.push([t.x,t.y]),i.push([e.x,e.y]);return i},getPoint:function(t){var e,n,i=this._cfg.tCache;i||(this._calculateCurve(),this._setTcache(),i=this._cfg.tCache);var o=this._cfg.curve;if(!i)return o?{x:o[0][1],y:o[0][2]}:null;r.each(i,(function(r,i){t>=r[0]&&t<=r[1]&&(e=(t-r[0])/(r[1]-r[0]),n=i)}));var a=o[n];if(r.isNil(a)||r.isNil(n))return null;var s=a.length,c=o[n+1];return{x:u.at(a[s-2],c[1],c[3],c[5],1-e),y:u.at(a[s-1],c[2],c[4],c[6],1-e)}},createPath:function(t){var e=this.get("segments");if(r.isArray(e)){(t=t||this.get("context")).beginPath();for(var n=e.length,i=0;i<n;i++)e[i].draw(t)}},afterPath:function(t){var e=this._attrs,n=this.get("segments"),i=e.path;if(t=t||this.get("context"),r.isArray(n)&&1!==n.length&&(e.startArrow||e.endArrow)&&"z"!==i[i.length-1]&&"Z"!==i[i.length-1]&&!e.fill){var o=this.getStartTangent();s.addStartArrow(t,e,o[0][0],o[0][1],o[1][0],o[1][1]);var a=this.getEndTangent();s.addEndArrow(t,e,a[0][0],a[0][1],a[1][0],a[1][1])}}}),t.exports=h},function(t,e,n){var r=n(19),i=n(58),o=n(601),a=n(603),s=function t(e){t.superclass.constructor.call(this,e)};s.ATTRS={x1:0,y1:0,x2:0,y2:0,lineWidth:1,startArrow:!1,endArrow:!1},r.extend(s,i),r.augment(s,{canStroke:!0,type:"line",getDefaultAttrs:function(){return{lineWidth:1,startArrow:!1,endArrow:!1}},calculateBox:function(){var t=this._attrs,e=t.x1,n=t.y1,r=t.x2,i=t.y2,o=this.getHitLineWidth();return a.box(e,n,r,i,o)},createPath:function(t){var e=this._attrs,n=e.x1,r=e.y1,i=e.x2,o=e.y2;(t=t||self.get("context")).beginPath(),t.moveTo(n,r),t.lineTo(i,o)},afterPath:function(t){var e=this._attrs,n=e.x1,r=e.y1,i=e.x2,a=e.y2;t=t||this.get("context"),e.startArrow&&o.addStartArrow(t,e,i,a,n,r),e.endArrow&&o.addEndArrow(t,e,n,r,i,a)},getPoint:function(t){var e=this._attrs;return{x:a.at(e.x1,e.x2,t),y:a.at(e.y1,e.y2,t)}}}),t.exports=s},function(t,e,n){var r=n(19),i=n(58),o=function t(e){t.superclass.constructor.call(this,e)};o.ATTRS={x:0,y:0,img:void 0,width:0,height:0,sx:null,sy:null,swidth:null,sheight:null},r.extend(o,i),r.augment(o,{type:"image",isHitBox:function(){return!1},calculateBox:function(){var t=this._attrs;this._cfg.attrs&&this._cfg.attrs.img===t.img||this._setAttrImg();var e=t.x,n=t.y;return{minX:e,minY:n,maxX:e+t.width,maxY:n+t.height}},_beforeSetLoading:function(t){var e=this.get("canvas");return!1===t&&!0===this.get("toDraw")&&(this._cfg.loading=!1,e.draw()),t},_setAttrImg:function(){var t=this,e=t._attrs,n=e.img;if(!r.isString(n))return n instanceof Image?(e.width||t.attr("width",n.width),e.height||t.attr("height",n.height),n):n instanceof HTMLElement&&r.isString(n.nodeName)&&"CANVAS"===n.nodeName.toUpperCase()?(e.width||t.attr("width",Number(n.getAttribute("width"))),e.height||t.attr("height",Number(n.getAttribute("height"))),n):n instanceof ImageData?(e.width||t.attr("width",n.width),e.height||t.attr("height",n.height),n):null;var i=new Image;i.onload=function(){if(t.get("destroyed"))return!1;t.attr("imgSrc",n),t.attr("img",i);var e=t.get("callback");e&&e.call(t),t.set("loading",!1)},i.src=n,i.crossOrigin="Anonymous",t.set("loading",!0)},drawInner:function(t){this._cfg.hasUpdate&&this._setAttrImg(),this.get("loading")?this.set("toDraw",!0):(this._drawImage(t),this._cfg.hasUpdate=!1)},_drawImage:function(t){var e=this._attrs,n=e.x,i=e.y,o=e.img,a=e.width,s=e.height,c=e.sx,u=e.sy,h=e.swidth,l=e.sheight;this.set("toDraw",!1);var d=o;if(d instanceof ImageData&&((d=new Image).src=o),d instanceof Image||d instanceof HTMLElement&&r.isString(d.nodeName)&&"CANVAS"===d.nodeName.toUpperCase()){if(r.isNil(c)||r.isNil(u)||r.isNil(h)||r.isNil(l))return void t.drawImage(d,n,i,a,s);if(!(r.isNil(c)||r.isNil(u)||r.isNil(h)||r.isNil(l)))return void t.drawImage(d,c,u,h,l,n,i,a,s)}}}),t.exports=o},function(t,e,n){var r=n(19),i=n(58),o=n(602),a=function t(e){t.superclass.constructor.call(this,e)};a.ATTRS={x:0,y:0,rs:0,re:0,startAngle:0,endAngle:0,clockwise:!1,lineWidth:1},r.extend(a,i),r.augment(a,{canFill:!0,canStroke:!0,type:"fan",getDefaultAttrs:function(){return{clockwise:!1,lineWidth:1,rs:0,re:0}},calculateBox:function(){var t=this._attrs,e=t.x,n=t.y,r=t.rs,i=t.re,a=t.startAngle,s=t.endAngle,c=t.clockwise,u=this.getHitLineWidth(),h=o.box(e,n,r,a,s,c),l=o.box(e,n,i,a,s,c),d=u/2;return{minX:Math.min(h.minX,l.minX)-d,minY:Math.min(h.minY,l.minY)-d,maxX:Math.max(h.maxX,l.maxX)+d,maxY:Math.max(h.maxY,l.maxY)+d}},createPath:function(t){var e=this._attrs,n=e.x,r=e.y,i=e.rs,o=e.re,a=e.startAngle,s=e.endAngle,c=e.clockwise,u={x:Math.cos(a)*i+n,y:Math.sin(a)*i+r},h={x:Math.cos(a)*o+n,y:Math.sin(a)*o+r},l={x:Math.cos(s)*i+n,y:Math.sin(s)*i+r};(t=t||self.get("context")).beginPath(),t.moveTo(u.x,u.y),t.lineTo(h.x,h.y),t.arc(n,r,o,a,s,c),t.lineTo(l.x,l.y),t.arc(n,r,i,s,a,!c),t.closePath()}}),t.exports=a},function(t,e,n){var r=n(19),i=n(58),o=function t(e){t.superclass.constructor.call(this,e)};o.ATTRS={x:0,y:0,rx:1,ry:1,lineWidth:1},r.extend(o,i),r.augment(o,{canFill:!0,canStroke:!0,type:"ellipse",getDefaultAttrs:function(){return{lineWidth:1}},calculateBox:function(){var t=this._attrs,e=t.x,n=t.y,r=t.rx,i=t.ry,o=this.getHitLineWidth(),a=r+o/2,s=i+o/2;return{minX:e-a,minY:n-s,maxX:e+a,maxY:n+s}},createPath:function(t){var e=this._attrs,n=e.x,i=e.y,o=e.rx,a=e.ry;t=t||self.get("context");var s=o>a?o:a,c=o>a?1:o/a,u=o>a?a/o:1,h=[1,0,0,0,1,0,0,0,1];r.mat3.scale(h,h,[c,u]),r.mat3.translate(h,h,[n,i]),t.beginPath(),t.save(),t.transform(h[0],h[1],h[3],h[4],h[6],h[7]),t.arc(0,0,s,0,2*Math.PI),t.restore(),t.closePath()}}),t.exports=o},function(t,e,n){var r=n(19),i=n(58),o=function t(e){t.superclass.constructor.call(this,e)};r.extend(o,i),r.augment(o,{canFill:!0,canStroke:!0,type:"dom",calculateBox:function(){var t=this._attrs,e=t.x,n=t.y,r=t.width,i=t.height,o=this.getHitLineWidth()/2;return{minX:e-o,minY:n-o,maxX:e+r+o,maxY:n+i+o}}}),t.exports=o},function(t,e,n){var r=n(19),i=n(58),o=function t(e){t.superclass.constructor.call(this,e)};o.ATTRS={x:0,y:0,r:0,lineWidth:1},r.extend(o,i),r.augment(o,{canFill:!0,canStroke:!0,type:"circle",getDefaultAttrs:function(){return{lineWidth:1}},calculateBox:function(){var t=this._attrs,e=t.x,n=t.y,r=t.r,i=this.getHitLineWidth()/2+r;return{minX:e-i,minY:n-i,maxX:e+i,maxY:n+i}},createPath:function(t){var e=this._attrs,n=e.x,r=e.y,i=e.r;t.beginPath(),t.arc(n,r,i,0,2*Math.PI,!1),t.closePath()}}),t.exports=o},function(t,e,n){var r=n(19),i=n(58),o=n(602),a=n(601);function s(t,e,n){return t+e*Math.cos(n)}function c(t,e,n){return t+e*Math.sin(n)}var u=function t(e){t.superclass.constructor.call(this,e)};u.ATTRS={x:0,y:0,r:0,startAngle:0,endAngle:0,clockwise:!1,lineWidth:1,startArrow:!1,endArrow:!1},r.extend(u,i),r.augment(u,{canStroke:!0,type:"arc",getDefaultAttrs:function(){return{x:0,y:0,r:0,startAngle:0,endAngle:0,clockwise:!1,lineWidth:1,startArrow:!1,endArrow:!1}},calculateBox:function(){var t=this._attrs,e=t.x,n=t.y,r=t.r,i=t.startAngle,a=t.endAngle,s=t.clockwise,c=this.getHitLineWidth()/2,u=o.box(e,n,r,i,a,s);return u.minX-=c,u.minY-=c,u.maxX+=c,u.maxY+=c,u},getStartTangent:function(){var t=this._attrs,e=t.x,n=t.y,r=t.startAngle,i=t.r,o=t.clockwise,a=Math.PI/180;o&&(a*=-1);var u=[],h=s(e,i,r+a),l=c(n,i,r+a),d=s(e,i,r),f=c(n,i,r);return u.push([h,l]),u.push([d,f]),u},getEndTangent:function(){var t=this._attrs,e=t.x,n=t.y,r=t.endAngle,i=t.r,o=t.clockwise,a=Math.PI/180,u=[];o&&(a*=-1);var h=s(e,i,r+a),l=c(n,i,r+a),d=s(e,i,r),f=c(n,i,r);return u.push([d,f]),u.push([h,l]),u},createPath:function(t){var e=this._attrs,n=e.x,r=e.y,i=e.r,o=e.startAngle,a=e.endAngle,s=e.clockwise;(t=t||self.get("context")).beginPath(),t.arc(n,r,i,o,a,s)},afterPath:function(t){var e=this._attrs;if(t=t||this.get("context"),e.startArrow){var n=this.getStartTangent();a.addStartArrow(t,e,n[0][0],n[0][1],n[1][0],n[1][1])}if(e.endArrow){var r=this.getEndTangent();a.addEndArrow(t,e,r[0][0],r[0][1],r[1][0],r[1][1])}}}),t.exports=u},function(t,e){t.exports={xAt:function(t,e,n,r,i){return e*Math.cos(t)*Math.cos(i)-n*Math.sin(t)*Math.sin(i)+r},yAt:function(t,e,n,r,i){return e*Math.sin(t)*Math.cos(i)+n*Math.cos(t)*Math.sin(i)+r},xExtrema:function(t,e,n){return Math.atan(-n/e*Math.tan(t))},yExtrema:function(t,e,n){return Math.atan(n/(e*Math.tan(t)))}}},function(t,e,n){var r=n(19),i=r.vec2;function o(t,e,n,r){var i=1-r;return i*(i*t+2*r*e)+r*r*n}function a(t,e,n,r,a,s,c,u,h){var l,d,f,g,p,m,v,x=.005,y=1/0,b=[c,u];for(p=0;p<1;p+=.05)f=[o(t,n,a,p),o(e,r,s,p)],(d=i.squaredDistance(b,f))<y&&(l=p,y=d);for(y=1/0,v=0;v<32&&!(x<1e-4);v++){var w=l-x,M=l+x;f=[o(t,n,a,w),o(e,r,s,w)],d=i.squaredDistance(b,f),w>=0&&d<y?(l=w,y=d):(g=[o(t,n,a,M),o(e,r,s,M)],m=i.squaredDistance(b,g),M<=1&&m<y?(l=M,y=m):x*=.5)}return h&&(h.x=o(t,n,a,l),h.y=o(e,r,s,l)),Math.sqrt(y)}t.exports={at:o,projectPoint:function(t,e,n,r,i,o,s,c){var u={};return a(t,e,n,r,i,o,s,c,u),u},pointDistance:a,extrema:function(t,e,n){var i=t+n-2*e;if(r.isNumberEqual(i,0))return[.5];var o=(t-e)/i;return o<=1&&o>=0?[o]:[]}}},function(t,e,n){var r=n(19),i=n(746),o=n(745),a=n(744),s=n(116),c=function(t){this._cfg={zIndex:0,capture:!0,visible:!0,destroyed:!1},r.assign(this._cfg,this.getDefaultCfg(),t),this.initAttrs(this._cfg.attrs),this._cfg.attrs={},this.initTransform(),this.init()};c.CFG={id:null,zIndex:0,canvas:null,parent:null,capture:!0,context:null,visible:!0,destroyed:!1},r.augment(c,i,o,s,a,{init:function(){this.setSilent("animable",!0),this.setSilent("animating",!1)},getParent:function(){return this._cfg.parent},getDefaultCfg:function(){return{}},set:function(t,e){return"zIndex"===t&&this._beforeSetZIndex&&this._beforeSetZIndex(e),"loading"===t&&this._beforeSetLoading&&this._beforeSetLoading(e),this._cfg[t]=e,this},setSilent:function(t,e){this._cfg[t]=e},get:function(t){return this._cfg[t]},show:function(){return this._cfg.visible=!0,this},hide:function(){return this._cfg.visible=!1,this},remove:function(t,e){var n=this._cfg,i=n.parent,o=n.el;return i&&r.remove(i.get("children"),this),o&&(e?i&&i._cfg.tobeRemoved.push(o):o.parentNode.removeChild(o)),(t||void 0===t)&&this.destroy(),this},destroy:function(){this.get("destroyed")||(this._attrs=null,this.removeEvent(),this._cfg={destroyed:!0})},toFront:function(){var t=this._cfg,e=t.parent;if(e){var n=e._cfg.children,r=t.el,i=n.indexOf(this);n.splice(i,1),n.push(this),r&&(r.parentNode.removeChild(r),t.el=null)}},toBack:function(){var t=this._cfg,e=t.parent;if(e){var n=e._cfg.children,r=t.el,i=n.indexOf(this);if(n.splice(i,1),n.unshift(this),r){var o=r.parentNode;o.removeChild(r),o.insertBefore(r,o.firstChild)}}},_beforeSetZIndex:function(t){var e=this._cfg.parent;this._cfg.zIndex=t,r.isNil(e)||e.sort();var n=this._cfg.el;if(n){var i=e._cfg.children,o=i.indexOf(this),a=n.parentNode;a.removeChild(n),o===i.length-1?a.appendChild(n):a.insertBefore(n,a.childNodes[o])}return t},_setAttrs:function(t){return this.attr(t),t},setZIndex:function(t){return this._cfg.zIndex=t,this._beforeSetZIndex(t)},clone:function(){return r.clone(this)},getBBox:function(){}}),t.exports=c},function(t,e,n){var r=n(19),i=n(641),o=n(743),a={},s="_INDEX";function c(t,e,n){for(var r,i=t.length-1;i>=0;i--){var o=t[i];if(o._cfg.visible&&o._cfg.capture&&(o.isGroup?r=o.getShape(e,n):o.isHit(e,n)&&(r=o)),r)break}return r}var u=function t(e){t.superclass.constructor.call(this,e),this.set("children",[]),this.set("tobeRemoved",[]),this._beforeRenderUI(),this._renderUI(),this._bindUI()};r.extend(u,i),r.augment(u,{isGroup:!0,type:"group",canFill:!0,canStroke:!0,getDefaultCfg:function(){return function t(e){if(!e._cfg&&e!==u){var n=e.superclass.constructor;n&&!n._cfg&&t(n),e._cfg={},r.merge(e._cfg,n._cfg),r.merge(e._cfg,e.CFG)}}(this.constructor),r.merge({},this.constructor._cfg)},_beforeRenderUI:function(){},_renderUI:function(){},_bindUI:function(){},addShape:function(t,e){var n=this.get("canvas");e=e||{};var i=a[t];if(i||(i=r.upperFirst(t),a[t]=i),e.attrs&&n){var s=e.attrs;if("text"===t){var c=n.get("fontFamily");c&&(s.fontFamily=s.fontFamily?s.fontFamily:c)}}e.canvas=n,e.type=t;var u=new o[i](e);return this.add(u),u},addGroup:function(t,e){var n,i=this.get("canvas");if(e=r.merge({},e),r.isFunction(t))e?(e.canvas=i,e.parent=this,n=new t(e)):n=new t({canvas:i,parent:this}),this.add(n);else if(r.isObject(t))t.canvas=i,n=new u(t),this.add(n);else{if(void 0!==t)return!1;n=new u,this.add(n)}return n},renderBack:function(t,e){var n=this.get("backShape"),i=this.getBBox();return r.merge(e,{x:i.minX-t[3],y:i.minY-t[0],width:i.width+t[1]+t[3],height:i.height+t[0]+t[2]}),n?n.attr(e):n=this.addShape("rect",{zIndex:-1,attrs:e}),this.set("backShape",n),this.sort(),n},removeChild:function(t,e){if(arguments.length>=2)this.contain(t)&&t.remove(e);else{if(1===arguments.length){if(!r.isBoolean(t))return this.contain(t)&&t.remove(!0),this;e=t}0===arguments.length&&(e=!0),u.superclass.remove.call(this,e)}return this},add:function(t){var e=this,n=e.get("children");if(r.isArray(t))r.each(t,(function(t){var n=t.get("parent");n&&n.removeChild(t,!1),e._setCfgProperty(t)})),e._cfg.children=n.concat(t);else{var i=t,o=i.get("parent");o&&o.removeChild(i,!1),e._setCfgProperty(i),n.push(i)}return e},_setCfgProperty:function(t){var e=this._cfg;t.set("parent",this),t.set("canvas",e.canvas),e.timeline&&t.set("timeline",e.timeline)},contain:function(t){return this.get("children").indexOf(t)>-1},getChildByIndex:function(t){return this.get("children")[t]},getFirst:function(){return this.getChildByIndex(0)},getLast:function(){var t=this.get("children").length-1;return this.getChildByIndex(t)},getBBox:function(){var t=1/0,e=-1/0,n=1/0,i=-1/0,o=this.get("children");o.length>0?r.each(o,(function(r){if(r.get("visible")){if(r.isGroup&&0===r.get("children").length)return;var o=r.getBBox();if(!o)return!0;var a=[o.minX,o.minY,1],s=[o.minX,o.maxY,1],c=[o.maxX,o.minY,1],u=[o.maxX,o.maxY,1];r.apply(a),r.apply(s),r.apply(c),r.apply(u);var h=Math.min(a[0],s[0],c[0],u[0]),l=Math.max(a[0],s[0],c[0],u[0]),d=Math.min(a[1],s[1],c[1],u[1]),f=Math.max(a[1],s[1],c[1],u[1]);h<t&&(t=h),l>e&&(e=l),d<n&&(n=d),f>i&&(i=f)}})):(t=0,e=0,n=0,i=0);var a={minX:t,minY:n,maxX:e,maxY:i};return a.x=a.minX,a.y=a.minY,a.width=a.maxX-a.minX,a.height=a.maxY-a.minY,a},getCount:function(){return this.get("children").length},sort:function(){var t=this.get("children");return r.each(t,(function(t,e){return t[s]=e,t})),t.sort((function(t,e){var n=function(t,e){return t.get("zIndex")-e.get("zIndex")}(t,e);return 0===n?t[s]-e[s]:n})),this},findById:function(t){return this.find((function(e){return e.get("id")===t}))},find:function(t){if(r.isString(t))return this.findById(t);var e=this.get("children"),n=null;return r.each(e,(function(e){if(t(e)?n=e:e.find&&(n=e.find(t)),n)return!1})),n},findAll:function(t){var e=this.get("children"),n=[],i=[];return r.each(e,(function(e){t(e)&&n.push(e),e.findAllBy&&(i=e.findAllBy(t),n=n.concat(i))})),n},findBy:function(t){var e=this.get("children"),n=null;return r.each(e,(function(e){if(t(e)?n=e:e.findBy&&(n=e.findBy(t)),n)return!1})),n},findAllBy:function(t){var e=this.get("children"),n=[],i=[];return r.each(e,(function(e){t(e)&&n.push(e),e.findAllBy&&(i=e.findAllBy(t),n=n.concat(i))})),n},getShape:function(t,e){var n,r=this._attrs.clip,i=this._cfg.children;if(r){var o=[t,e,1];r.invert(o,this.get("canvas")),r.isPointInPath(o[0],o[1])&&(n=c(i,t,e))}else n=c(i,t,e);return n},clearTotalMatrix:function(){if(this.get("totalMatrix")){this.setSilent("totalMatrix",null);for(var t=this._cfg.children,e=0;e<t.length;e++)t[e].clearTotalMatrix()}},clear:function(t){for(var e=this._cfg.children,n=e.length-1;n>=0;n--)e[n].remove(!0,t);return this._cfg.children=[],this},destroy:function(){this.get("destroyed")||(this.clear(),u.superclass.destroy.call(this))},clone:function(){var t=this._cfg.children,e=new u;return r.each(t,(function(t){e.add(t.clone())})),e}}),t.exports=u},function(t,e,n){var r=n(19),i=function(t,e,n,r){this.type=t,this.target=null,this.currentTarget=null,this.bubbles=n,this.cancelable=r,this.timeStamp=(new Date).getTime(),this.defaultPrevented=!1,this.propagationStopped=!1,this.removed=!1,this.event=e};r.augment(i,{preventDefault:function(){this.defaultPrevented=this.cancelable&&!0},stopPropagation:function(){this.propagationStopped=!0},remove:function(){this.remove=!0},clone:function(){return r.clone(this)},toString:function(){return"[Event (type="+this.type+")]"}}),t.exports=i},function(t,e,n){t.exports={isFunction:n(84),isObject:n(621),isBoolean:n(653),isNil:n(237),isString:n(595),isArray:n(45),isNumber:n(236),isEmpty:n(647),uniqueId:n(646),clone:n(616),deepMix:n(615),assign:n(606),merge:n(615),upperFirst:n(655),each:n(46),isEqual:n(614),toArray:n(604),extend:n(650),augment:n(651),remove:n(676),isNumberEqual:n(673),toRadian:n(669),toDegree:n(671),mod:n(672),clamp:n(618),createDom:n(681),modifyCSS:n(680),requestAnimationFrame:n(679),getRatio:function(){return window.devicePixelRatio?window.devicePixelRatio:2},mat3:n(617),vec2:n(668),vec3:n(667),transform:n(666)}},function(t,e,n){var r=n(16),i=n(253),o=n(251),a=Math.max,s=Math.min;t.exports=function(t,e,n){var c,u,h,l,d,f,g=0,p=!1,m=!1,v=!0;if("function"!=typeof t)throw new TypeError("Expected a function");function x(e){var n=c,r=u;return c=u=void 0,g=e,l=t.apply(r,n)}function y(t){var n=t-f;return void 0===f||n>=e||n<0||m&&t-g>=h}function b(){var t=i();if(y(t))return w(t);d=setTimeout(b,function(t){var n=e-(t-f);return m?s(n,h-(t-g)):n}(t))}function w(t){return d=void 0,v&&c?x(t):(c=u=void 0,l)}function M(){var t=i(),n=y(t);if(c=arguments,u=this,f=t,n){if(void 0===d)return function(t){return g=t,d=setTimeout(b,e),p?x(t):l}(f);if(m)return d=setTimeout(b,e),x(f)}return void 0===d&&(d=setTimeout(b,e)),l}return e=o(e)||0,r(n)&&(p=!!n.leading,h=(m="maxWait"in n)?a(o(n.maxWait)||0,e):h,v="trailing"in n?!!n.trailing:v),M.cancel=function(){void 0!==d&&clearTimeout(d),g=0,c=f=u=d=void 0},M.flush=function(){return void 0===d?l:w(i())},M}},function(t,e){var n=function(){var t={};return function(e){return t[e=e||"g"]?t[e]+=1:t[e]=1,e+t[e]}}();t.exports=n},function(t,e,n){var r=n(237),i=n(118),o=n(654),a=n(652),s=Object.prototype.hasOwnProperty;t.exports=function(t){if(r(t))return!0;if(i(t))return!t.length;var e=o(t);if("Map"===e||"Set"===e)return!t.size;if(a(t))return!Object.keys(t).length;for(var n in t)if(s.call(t,n))return!1;return!0}},function(t,e,n){var r=n(46),i=n(45),o=Object.prototype.hasOwnProperty;t.exports=function(t,e){if(!e||!i(t))return t;var n={},a=null;return r(t,(function(t){a=e(t),o.call(n,a)?n[a].push(t):n[a]=[t]})),n}},function(t,e,n){var r=n(84),i=n(45),o=n(648);t.exports=function(t,e){if(!e)return{0:t};if(!r(e)){var n=i(e)?e:e.replace(/\s+/g,"").split("*");e=function(t){for(var e="_",r=0,i=n.length;r<i;r++)e+=t[n[r]]&&t[n[r]].toString();return e}}return o(t,e)}},function(t,e,n){var r=n(84),i=n(606);t.exports=function(t,e,n,o){r(e)||(n=e,e=t,t=function(){});var a=Object.create?function(t,e){return Object.create(t,{constructor:{value:e}})}:function(t,e){function n(){}n.prototype=t;var r=new n;return r.constructor=e,r},s=a(e.prototype,t);return t.prototype=i(s,t.prototype),t.superclass=a(e.prototype,e),i(s,n),i(t,o),t}},function(t,e,n){var r=n(84),i=n(604),o=n(606);t.exports=function(t){for(var e=i(arguments),n=1;n<e.length;n++){var a=e[n];r(a)&&(a=a.prototype),o(t.prototype,a)}}},function(t,e){var n=Object.prototype;t.exports=function(t){var e=t&&t.constructor;return t===("function"==typeof e&&e.prototype||n)}},function(t,e,n){var r=n(115);t.exports=function(t){return r(t,"Boolean")}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).replace(/^\[object /,"").replace(/\]$/,"")}},function(t,e,n){var r=n(594);t.exports=function(t){var e=r(t);return e.charAt(0).toUpperCase()+e.substring(1)}},function(t,e,n){var r=n(594);t.exports=function(t){return r(t).toUpperCase()}},function(t,e,n){var r=n(594);t.exports=function(t){return r(t).toLowerCase()}},function(t,e){t.exports=function(t,e){for(var n=[],r=0,i=t.length;i-2*!e>r;r+=2){var o=[{x:+t[r-2],y:+t[r-1]},{x:+t[r],y:+t[r+1]},{x:+t[r+2],y:+t[r+3]},{x:+t[r+4],y:+t[r+5]}];e?r?i-4===r?o[3]={x:+t[0],y:+t[1]}:i-2===r&&(o[2]={x:+t[0],y:+t[1]},o[3]={x:+t[2],y:+t[3]}):o[0]={x:+t[i-2],y:+t[i-1]}:i-4===r?o[3]=o[2]:r||(o[0]={x:+t[r],y:+t[r+1]}),n.push(["C",(-o[0].x+6*o[1].x+o[2].x)/6,(-o[0].y+6*o[1].y+o[2].y)/6,(o[1].x+6*o[2].x-o[3].x)/6,(o[1].y+6*o[2].y-o[3].y)/6,o[2].x,o[2].y])}return n}},function(t,e){var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},r="\t\n\v\f\r \u2028\u2029",i=new RegExp("([a-z])["+r+",]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?["+r+"]*,?["+r+"]*)+)","ig"),o=new RegExp("(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)["+r+"]*,?["+r+"]*","ig");t.exports=function(t){if(!t)return null;if((void 0===t?"undefined":n(t))===n([]))return t;var e={a:7,c:6,o:2,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,u:3,z:0},r=[];return String(t).replace(i,(function(t,n,i){var a=[],s=n.toLowerCase();if(i.replace(o,(function(t,e){e&&a.push(+e)})),"m"===s&&a.length>2&&(r.push([n].concat(a.splice(0,2))),s="l",n="m"===n?"l":"L"),"o"===s&&1===a.length&&r.push([n,a[0]]),"r"===s)r.push([n].concat(a));else for(;a.length>=e[s]&&(r.push([n].concat(a.splice(0,e[s]))),e[s]););})),r}},function(t,e,n){var r=n(659),i=n(658);function o(t,e,n,r,i){var o=[];if(null===i&&null===r&&(r=n),t=+t,e=+e,n=+n,r=+r,null!==i){var a=Math.PI/180,s=t+n*Math.cos(-r*a),c=t+n*Math.cos(-i*a);o=[["M",s,e+n*Math.sin(-r*a)],["A",n,n,0,+(i-r>180),0,c,e+n*Math.sin(-i*a)]]}else o=[["M",t,e],["m",0,-r],["a",n,r,0,1,1,0,2*r],["a",n,r,0,1,1,0,-2*r],["z"]];return o}t.exports=function(t){if(!(t=r(t))||!t.length)return[["M",0,0]];var e=[],n=0,a=0,s=0,c=0,u=0,h=void 0,l=void 0;"M"===t[0][0]&&(s=n=+t[0][1],c=a=+t[0][2],u++,e[0]=["M",n,a]);for(var d,f,g=3===t.length&&"M"===t[0][0]&&"R"===t[1][0].toUpperCase()&&"Z"===t[2][0].toUpperCase(),p=u,m=t.length;p<m;p++){if(e.push(d=[]),(h=(f=t[p])[0])!==h.toUpperCase())switch(d[0]=h.toUpperCase(),d[0]){case"A":d[1]=f[1],d[2]=f[2],d[3]=f[3],d[4]=f[4],d[5]=f[5],d[6]=+f[6]+n,d[7]=+f[7]+a;break;case"V":d[1]=+f[1]+a;break;case"H":d[1]=+f[1]+n;break;case"R":for(var v=2,x=(l=[n,a].concat(f.slice(1))).length;v<x;v++)l[v]=+l[v]+n,l[++v]=+l[v]+a;e.pop(),e=e.concat(i(l,g));break;case"O":e.pop(),(l=o(n,a,f[1],f[2])).push(l[0]),e=e.concat(l);break;case"U":e.pop(),e=e.concat(o(n,a,f[1],f[2],f[3])),d=["U"].concat(e[e.length-1].slice(-2));break;case"M":s=+f[1]+n,c=+f[2]+a;break;default:for(var y=1,b=f.length;y<b;y++)d[y]=+f[y]+(y%2?n:a)}else if("R"===h)l=[n,a].concat(f.slice(1)),e.pop(),e=e.concat(i(l,g)),d=["R"].concat(f.slice(-2));else if("O"===h)e.pop(),(l=o(n,a,f[1],f[2])).push(l[0]),e=e.concat(l);else if("U"===h)e.pop(),e=e.concat(o(n,a,f[1],f[2],f[3])),d=["U"].concat(e[e.length-1].slice(-2));else for(var w=0,M=f.length;w<M;w++)d[w]=f[w];if("O"!==(h=h.toUpperCase()))switch(d[0]){case"Z":n=+s,a=+c;break;case"H":n=d[1];break;case"V":a=d[1];break;case"M":s=d[d.length-2],c=d[d.length-1];break;default:n=d[d.length-2],a=d[d.length-1]}}return e}},function(t,e,n){var r=n(660),i=function(t,e,n,r){return[t,e,n,r,n,r]},o=function(t,e,n,r,i,o){return[1/3*t+2/3*n,1/3*e+2/3*r,1/3*i+2/3*n,1/3*o+2/3*r,i,o]};t.exports=function(t,e){var n=r(t),a=e&&r(e),s={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},c={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},u=[],h=[],l="",d="",f=void 0,g=function(t,e,n){var r=void 0,a=void 0;if(!t)return["C",e.x,e.y,e.x,e.y,e.x,e.y];switch(!(t[0]in{T:1,Q:1})&&(e.qx=e.qy=null),t[0]){case"M":e.X=t[1],e.Y=t[2];break;case"A":t=["C"].concat(function t(e,n,r,i,o,a,s,c,u,h){r===i&&(r+=1);var l=120*Math.PI/180,d=Math.PI/180*(+o||0),f=[],g=void 0,p=void 0,m=void 0,v=void 0,x=void 0,y=function(t,e,n){return{x:t*Math.cos(n)-e*Math.sin(n),y:t*Math.sin(n)+e*Math.cos(n)}};if(h)p=h[0],m=h[1],v=h[2],x=h[3];else{e=(g=y(e,n,-d)).x,n=g.y,c=(g=y(c,u,-d)).x,u=g.y,e===c&&n===u&&(c+=1,u+=1);var b=(e-c)/2,w=(n-u)/2,M=b*b/(r*r)+w*w/(i*i);M>1&&(r*=M=Math.sqrt(M),i*=M);var _=r*r,S=i*i,A=(a===s?-1:1)*Math.sqrt(Math.abs((_*S-_*w*w-S*b*b)/(_*w*w+S*b*b)));v=A*r*w/i+(e+c)/2,x=A*-i*b/r+(n+u)/2,p=Math.asin(((n-x)/i).toFixed(9)),m=Math.asin(((u-x)/i).toFixed(9)),p=e<v?Math.PI-p:p,m=c<v?Math.PI-m:m,p<0&&(p=2*Math.PI+p),m<0&&(m=2*Math.PI+m),s&&p>m&&(p-=2*Math.PI),!s&&m>p&&(m-=2*Math.PI)}var E=m-p;if(Math.abs(E)>l){var P=m,C=c,O=u;m=p+l*(s&&m>p?1:-1),f=t(c=v+r*Math.cos(m),u=x+i*Math.sin(m),r,i,o,0,s,C,O,[m,P,v,x])}E=m-p;var I=Math.cos(p),k=Math.sin(p),B=Math.cos(m),T=Math.sin(m),N=Math.tan(E/4),L=4/3*r*N,Y=4/3*i*N,X=[e,n],G=[e+L*k,n-Y*I],D=[c+L*T,u-Y*B],F=[c,u];if(G[0]=2*X[0]-G[0],G[1]=2*X[1]-G[1],h)return[G,D,F].concat(f);for(var j=[],R=0,H=(f=[G,D,F].concat(f).join().split(",")).length;R<H;R++)j[R]=R%2?y(f[R-1],f[R],d).y:y(f[R],f[R+1],d).x;return j}.apply(0,[e.x,e.y].concat(t.slice(1))));break;case"S":"C"===n||"S"===n?(r=2*e.x-e.bx,a=2*e.y-e.by):(r=e.x,a=e.y),t=["C",r,a].concat(t.slice(1));break;case"T":"Q"===n||"T"===n?(e.qx=2*e.x-e.qx,e.qy=2*e.y-e.qy):(e.qx=e.x,e.qy=e.y),t=["C"].concat(o(e.x,e.y,e.qx,e.qy,t[1],t[2]));break;case"Q":e.qx=t[1],e.qy=t[2],t=["C"].concat(o(e.x,e.y,t[1],t[2],t[3],t[4]));break;case"L":t=["C"].concat(i(e.x,e.y,t[1],t[2]));break;case"H":t=["C"].concat(i(e.x,e.y,t[1],e.y));break;case"V":t=["C"].concat(i(e.x,e.y,e.x,t[1]));break;case"Z":t=["C"].concat(i(e.x,e.y,e.X,e.Y))}return t},p=function(t,e){if(t[e].length>7){t[e].shift();for(var r=t[e];r.length;)u[e]="A",a&&(h[e]="A"),t.splice(e++,0,["C"].concat(r.splice(0,6)));t.splice(e,1),f=Math.max(n.length,a&&a.length||0)}},m=function(t,e,r,i,o){t&&e&&"M"===t[o][0]&&"M"!==e[o][0]&&(e.splice(o,0,["M",i.x,i.y]),r.bx=0,r.by=0,r.x=t[o][1],r.y=t[o][2],f=Math.max(n.length,a&&a.length||0))};f=Math.max(n.length,a&&a.length||0);for(var v=0;v<f;v++){n[v]&&(l=n[v][0]),"C"!==l&&(u[v]=l,v&&(d=u[v-1])),n[v]=g(n[v],s,d),"A"!==u[v]&&"C"===l&&(u[v]="C"),p(n,v),a&&(a[v]&&(l=a[v][0]),"C"!==l&&(h[v]=l,v&&(d=h[v-1])),a[v]=g(a[v],c,d),"A"!==h[v]&&"C"===l&&(h[v]="C"),p(a,v)),m(n,a,s,c,v),m(a,n,c,s,v);var x=n[v],y=a&&a[v],b=x.length,w=a&&y.length;s.x=x[b-2],s.y=x[b-1],s.bx=parseFloat(x[b-4])||s.x,s.by=parseFloat(x[b-3])||s.y,c.bx=a&&(parseFloat(y[w-4])||c.x),c.by=a&&(parseFloat(y[w-3])||c.y),c.x=a&&y[w-2],c.y=a&&y[w-1]}return a?[n,a]:n}},function(t,e){var n=/,?([a-z]),?/gi;t.exports=function(t){return t.join(",").replace(n,"$1")}},function(t,e,n){var r=n(662);t.exports=function(t,e,n,i,o){if(o)return[["M",+t+ +o,e],["l",n-2*o,0],["a",o,o,0,0,1,o,o],["l",0,i-2*o],["a",o,o,0,0,1,-o,o],["l",2*o-n,0],["a",o,o,0,0,1,-o,-o],["l",0,2*o-i],["a",o,o,0,0,1,o,-o],["z"]];var a=[["M",t,e],["l",n,0],["l",0,i],["l",-n,0],["z"]];return a.parsePathArray=r,a}},function(t,e,n){var r=n(46),i=n(84),o=Object.values?function(t){return Object.values(t)}:function(t){var e=[];return r(t,(function(n,r){i(t)&&"prototype"===r||e.push(n)})),e};t.exports=o},function(t,e){t.exports=function(t,e){return t.hasOwnProperty(e)}},function(t,e,n){var r=n(616),i=n(46),o=n(617);t.exports=function(t,e){return t=r(t),i(e,(function(e){switch(e[0]){case"t":o.translate(t,t,[e[1],e[2]]);break;case"s":o.scale(t,t,[e[1],e[2]]);break;case"r":o.rotate(t,t,e[1]);break;case"m":o.multiply(t,t,e[1]);break;default:return!1}})),t}},function(t,e,n){var r=n(254);t.exports=r},function(t,e,n){var r=n(255),i=n(618);r.angle=function(t,e){var n=r.dot(t,e)/(r.length(t)*r.length(e));return Math.acos(i(n,-1,1))},r.direction=function(t,e){return t[0]*e[1]-e[0]*t[1]},r.angleTo=function(t,e,n){var i=r.angle(t,e),o=r.direction(t,e)>=0;return n?o?2*Math.PI-i:i:o?i:2*Math.PI-i},r.vertical=function(t,e,n){return n?(t[0]=e[1],t[1]=-1*e[0]):(t[0]=-1*e[1],t[1]=e[0]),t},t.exports=r},function(t,e){var n=Math.PI/180;t.exports=function(t){return n*t}},function(t,e){t.exports=parseInt},function(t,e){var n=180/Math.PI;t.exports=function(t){return n*t}},function(t,e){t.exports=function(t,e){return(t%e+e)%e}},function(t,e){t.exports=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1e-5;return Math.abs(t-e)<n}},function(t,e,n){var r=n(46),i=n(605);t.exports=function(t){var e=[];return r(t,(function(t){i(e,t)||e.push(t)})),e}},function(t,e,n){var r=n(118),i=Array.prototype.splice;t.exports=function(t,e){if(!r(t))return[];for(var n=t?e.length:0,o=n-1;n--;){var a=void 0,s=e[n];n!==o&&s===a||(a=s,i.call(t,s,1))}return t}},function(t,e){var n=Array.prototype,r=n.splice,i=n.indexOf,o=n.slice;t.exports=function(t){for(var e=o.call(arguments,1),n=0;n<e.length;n++)for(var a=e[n],s=-1;(s=i.call(t,a))>-1;)r.call(t,s,1);return t}},function(t,e,n){var r=n(46),i=n(84),o=Object.keys?function(t){return Object.keys(t)}:function(t){var e=[];return r(t,(function(n,r){i(t)&&"prototype"===r||e.push(r)})),e};t.exports=o},function(t,e,n){var r=n(677),i=n(237);t.exports=function(t,e){var n=r(e),o=n.length;if(i(t))return!o;for(var a=0;a<o;a+=1){var s=n[a];if(e[s]!==t[s]||!(s in t))return!1}return!0}},function(t,e){t.exports=function(t){return(window.requestAnimationFrame||window.webkitRequestAnimationFrame||function(t){return setTimeout(t,16)})(t)}},function(t,e){t.exports=function(t,e){if(t)for(var n in e)e.hasOwnProperty(n)&&(t.style[n]=e[n]);return t}},function(t,e){var n=document.createElement("table"),r=document.createElement("tr"),i=/^\s*<(\w+|!)[^>]*>/,o={tr:document.createElement("tbody"),tbody:n,thead:n,tfoot:n,td:r,th:r,"*":document.createElement("div")};t.exports=function(t){var e=i.test(t)&&RegExp.$1;e in o||(e="*");var n=o[e];t=t.replace(/(^\s*)|(\s*$)/g,""),n.innerHTML=""+t;var r=n.childNodes[0];return n.removeChild(r),r}},function(t,e,n){var r=n(257),i={isBetween:function(t,e,n){return t>=e&&t<=n},getLineIntersect:function(t,e,n,r){var o=n.x-t.x,a=n.y-t.y,s=e.x-t.x,c=e.y-t.y,u=r.x-n.x,h=r.y-n.y,l=s*h-c*u,d=null;if(l*l>.001*(s*s+c*c)*(u*u+h*h)){var f=(o*h-a*u)/l,g=(o*c-a*s)/l;i.isBetween(f,0,1)&&i.isBetween(g,0,1)&&(d={x:t.x+f*s,y:t.y+f*c})}return d},getIntersectPointRect:function(t,e){var n=t.minX,r=t.minY,o=t.maxX-t.minX,a=t.maxY-t.minY,s=[],c={x:n+o/2,y:r+a/2};s.push({x:n,y:r}),s.push({x:n+o,y:r}),s.push({x:n+o,y:r+a}),s.push({x:n,y:r+a}),s.push({x:n,y:r});for(var u=null,h=1;h<s.length&&!(u=i.getLineIntersect(s[h-1],s[h],c,e));h++);return u},getIntersectPointCircle:function(t,e,n,r,i){if(Math.sqrt(Math.pow(t-n,2)+Math.pow(e-r,2))<i)return null;var o=t-n,a=e-r,s=Math.sign(o),c=Math.sign(a),u=Math.atan(a/o);return{x:n+Math.abs(i*Math.cos(u))*s,y:r+Math.abs(i*Math.sin(u))*c}},applyMatrix:function(t,e,n){void 0===n&&(n=1);var i=[t.x,t.y,n];return r.vec3.transformMat3(i,i,e),{x:i[0],y:i[1]}},invertMatrix:function(t,e,n){void 0===n&&(n=1);var i=r.mat3.invert([],e),o=[t.x,t.y,n];return r.vec3.transformMat3(o,o,i),{x:o[0],y:o[1]}},radixSort:function(t,e){var n,r,i,o,a,s,c,u=10,h=1,l=[],d=1;for(i=0;i<t.length;i++)n=e(t[i]),r=(n=parseInt(n,10)).toString().length,n.toString().length>d&&(d=r);for(i=0;i<d;i++,h*=10,u*=10){for(o=0;o<t.length;o++)a=e(t[o]),void 0===l[a=parseInt(a%u/h,10)]&&(l[a]=[]),l[a].push(t[o]);for(s=0,o=0;o<l.length;o++)if(c=void 0,void 0!==l[o])for(c=l[o].shift();void 0!==c;)t[s++]=c,c=l[o].shift()}return t},getArcOfVectors:function(t,e){var n=t.x,r=t.y,i=e.x,o=e.y,a=Math.sqrt(n*n+r*r),s=Math.sqrt(i*i+o*o);return Math.acos((n*i+r*o)/(a*s))}};t.exports=r.mix({},r,i)},function(t,e,n){var r=n(258);r.registerShapeManager("node",{defaultShapeType:"common"}),r.registerShapeManager("edge",{defaultShapeType:"common"}),r.registerShapeManager("group",{defaultShapeType:"common"}),r.registerShapeManager("guide",{defaultShapeType:"common"}),n(724),n(721),n(719),n(717),t.exports=r},function(t,e,n){var r=n(247),i=n(609),o=n(26);setTimeout((function(){var t=r.track;if(r.track){var e=new Image,n={pg:document.URL,r:(new Date).getTime(),g6:!0,version:i,page_type:"syslog"};o.isObject(t)&&o.mix(n,t);var a=encodeURIComponent(JSON.stringify([n]));e.src="https://kcart.alipay.com/web/bi.do?BIProfile=merge&d="+a}}),2e3)},function(t,e,n){var r=n(598),i=function(t){function e(e){var n;return(n=t.call(this,e)||this).layout=r.mindmap,n}return function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t),e}(n(597));t.exports=i},function(t,e,n){var r=n(598),i=function(t){function e(e){var n;return(n=t.call(this,e)||this).layout=r.indented,n}return function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t),e}(n(597));t.exports=i},function(t,e,n){var r=n(598),i=function(t){function e(e){var n;return(n=t.call(this,e)||this).layout=r.dendrogram,n}return function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t),e}(n(597));t.exports=i},function(t,e,n){var r=n(598),i=function(t){function e(e){var n;return(n=t.call(this,e)||this).layout=r.compactBox,n}return function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t),e}(n(597));t.exports=i},function(t,e,n){var r=n(26),i=n(625),o=n(623),a=function(t){function e(e){var n=r.mix({layout:new o.CompactBoxTree({getHGap:function(){return 10},getVGap:function(){return 10}}),_type:"tree"},e);return t.call(this,n)||this}!function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t);var n=e.prototype;return n.initEvent=function(){var t=this;this.on("afterdrawinner",(function(){t.get("_sourceData").roots.forEach((function(e){var n=t.find(e.id);t._setVisibleByCollapsed(n)}))}))},n._executeLayout=function(t){var e=this.get("_sourceData");r.isFunction(t)?t(e.roots,this):r.isObject(t)&&(t.roots=e.roots,t.graph=this,t.execute())},n.getHierarchy=function(t){t=this.getItem(t);for(var e=this.get("_dataMap"),n=t.getModel().parent,r=1;n;)n=e[n].parent,r++;return r},n.parseSource=function(t){var e=t.roots,n=this.get("_dataMap"),i=[],o=[];if(!e)throw new Error("please set data.roots!");return e.forEach((function(t){r.traverseTree(t,(function(t,e){t.id||(t.id=r.guid()),e||(e=n[t.parent]),e&&(t.parent=e.id,e.id||(e.id=r.guid()),o.push({source:e.id,target:t.id,id:e.id+"-"+t.id})),i.push(t)}),(function(t){return t.children}),!0)})),{nodes:i,edges:o}},n._setVisibleByCollapsed=function(t){var e=t.getModel();t.collapsedParent?(t.hide(),t.getEdges().forEach((function(t){t.hide()})),t.deepEach((function(t){t.hide(),t.getEdges().forEach((function(t){t.hide()}))}))):e.collapsed?t.deepEach((function(t){t.hide(),t.getEdges().forEach((function(t){t.hide()}))})):t.deepEach((function(t){t.collapsedParent&&(t.hide(),t.getEdges().forEach((function(t){t.hide()})))}))},n.source=function(t){var e=this.parseSource(t);this.emit("beforesource"),this.set("_sourceData",t),this.set("_data",e),this.emit("aftersource")},n._setNodeNth=function(t,e){var n=(t=this.getItem(t)).getModel(),i=t.getParent().getModel().children;r.Array.remove(i,n),i.splice(e,0,n)},n.getNth=function(t){var e=(t=this.getItem(t)).getModel();return t.getParent().getModel().children.indexOf(e)},n.add=function(t,e){var n,i=this.get("_dataMap")[e.parent],o={action:"add",model:e};if("node"===t||"guide"===t){if(this.emit("beforechange",o),"node"===t){if(!i)throw new Error("please set available parent Id !");r.isArray(i.children)?i.children.push(e):i.children=[e];var a=this.parseSource({roots:[e]});this._addItems("node",a.nodes),this._addItems("edge",a.edges),n=this.find(e.id),this._setVisibleByCollapsed(n),r.isNil(e.nth)||this._setNodeNth(n,e.nth),this.find(i.id).forceUpdate()}else this._addItems(t,[e]),n=this.find(e.id);return o.item=n,this.emit("afterchange",o),n}console.warn("Tree do not support add type "+t+"!")},n.update=function(t,e){var n=this;if(e){var i=(t=this.getItem(t)).getModel(),o=r.mix({},i),a={action:"update",item:t,originModel:o,updateModel:e};if(this.emit("beforechange",a),this._updateItems([t],[e]),t.isNode){if("collapsed"in e&&(e.collapsed?t.deepEach((function(t){t.hide(),t.getEdges().forEach((function(t){t.hide()}))})):t.deepEach((function(t){t.show(),t.getInEdges().forEach((function(t){t.show()}))}),(function(t){return t.model.collapsed?null:t.getChildren()}))),e.parent&&e.parent!==o.parent){var s=this.find(o.parent).getModel(),c=this.find(e.parent).getModel(),u=this.find(s.id+"-"+o.id),h={id:c.id+"-"+o.id,source:c.id,target:o.id};r.Array.remove(s.children,i),c.children?c.children.push(i):c.children=[i],this._removeItems([u]),this._addItems("edge",[h]),this.find(c.id).forceUpdate()}r.isArray(e.children)&&(o.children&&r.each(o.children,(function(t){var e=n.find(t.id),r=[e];e.getEdges().forEach((function(t){r.push(t)})),n._removeItems(r)})),r.each(e.children,(function(t){var e=n.parseSource({roots:[t]}),i=r.isNil(t.id)?r.guid():t.id;n._addItems("node",e.nodes),n._addItems("edge",e.edges),!t.parent&&n._addItems("edge",[{id:o.id+"-"+i,source:o.id,target:i}])}))),r.isNil(e.nth)||this._setNodeNth(t,e.nth);var l=this.find(i.parent);l&&l.forceUpdate()}return this.emit("afterchange",a),this}},n.remove=function(t){var e=this.get("_dataMap"),n=[];if((t=this.getItem(t))&&!t.destroyed){var i={action:"remove",item:t};if(this.emit("beforechange",i),n.push(t),"node"===t.type){t.getEdges().forEach((function(t){n.push(t)}));var o=t.getModel(),a=e[o.parent];t.deepEach((function(t){n.push(t),t.getEdges().forEach((function(t){n.push(t)}))})),r.Array.remove(a.children,o),this.find(a.id).forceUpdate()}return this._removeItems(r.uniq(n)),this.emit("afterchange",i),this}},n.getRoots=function(){var t=this;return this.getSource().roots.map((function(e){return t.find(e.id)}))},n.save=function(){var t={roots:r.clone(this.getSource().roots),guides:this.getGuides().map((function(t){return t.getModel()}))};return 0===t.roots.length&&delete t.roots,0===t.guides.length&&delete t.guides,t},e}(i);t.exports=a},function(t,e,n){var r=n(26),i={INIT:"_initForceFit"};i.AUGMENT={_initForceFit:function(){var t=this.get("width"),e=this.get("height");return t||e?t?e?void 0:(this.forceFit("height"),void this._bindForceEvent("height")):(this.forceFit("width"),void this._bindForceEvent("width")):(this.forceFit(),void this._bindForceEvent())},_bindForceEvent:function(t){var e=this,n=this._getTimer("forceFit"),r=function(){var r=setTimeout((function(){e.forceFit(t)}),200);n&&clearTimeout(n),e._setTimer("forceFit",r)};window.addEventListener("resize",r),this.set("_windowForceResizeEvent",r)},forceFit:function(t){var e=this.get("_containerDOM"),n=this.get("width"),i=this.get("height"),o=r.getHeight(e),a=r.getWidth(e);return"width"===t?(this.changeSize(a,i),this):"height"===t?(this.changeSize(n,o),this):(this.changeSize(a,o),this)}},t.exports=i},function(t,e,n){var r=n(26),i={CFG:{fitView:void 0,fitViewPadding:10,minZoom:.2,maxZoom:10}};i.AUGMENT={getBBox:function(){var t=this.get("_itemGroup"),e=this.get("_itemMap"),n=t.get("children");return n.length>0?(n=n.filter((function(t){var n=e[t.id];return!!n&&!1!==n.getShapeObj().bboxCalculation})),r.getChildrenBBox(n)):{minX:0,minY:0,maxX:this.get("width"),maxY:this.get("height")}},getFitViewPadding:function(){return r.toAllPadding(this.get("fitViewPadding"))},setFitView:function(t){if(!t)return this;if("autoZoom"===t)return this.autoZoom(),this;var e=this.getFitViewPadding(),n=this.get("width"),i=this.get("height"),o=this.getBBox(),a=o.maxX-o.minX,s=o.maxY-o.minY,c={x:0,y:0,width:n,height:i},u=r.getNineBoxPosition(t,c,a,s,e),h=[1,0,0,0,1,0,0,0,1];r.mat3.translate(h,h,[-o.minX+u.x,-o.minY+u.y]),this.updateMatrix(h)},_getZoomRatio:function(t){var e=this.get("maxZoom"),n=this.get("minZoom");return t<n&&(t=n),t>e&&(t=e),t},autoZoom:function(t){var e=this;t||(t=this.getFitViewPadding());var n=this.get("width"),i=this.get("height"),o=this.getBBox(),a=r.getAutoZoomMatrix({minX:0,minY:0,maxX:n,maxY:i},o,t,(function(t){return e._getZoomRatio(t)}));this.updateMatrix(a)},getZoom:function(){return this.getMatrix()[0]},updateMatrix:function(t){var e=this.getMatrix(),n={updateMatrix:t,originMatrix:e},r=e[0]!==t[0];return this.emit("beforeviewportchange",n),r&&this.emit("beforezoom",n),this.setMatrix(t),r&&this.emit("afterzoom",n),this.emit("afterviewportchange",n),this.draw(),this},zoom:function(t,e){if(!r.isNumber(t)){e=this._getZoomRatio(e);var n=this.get("_rootGroup"),i=r.clone(n.getMatrix()),o=i[6]+i[0]*t.x-e*t.x,a=i[7]+i[0]*t.y-e*t.y;return i[6]=0,i[7]=0,i[0]=e,i[4]=e,r.mat3.translate(i,i,[o,a]),this.updateMatrix(i),this}var s=this.get("width"),c=this.get("height");this.zoomByDom({x:s/2,y:c/2},t)},zoomByDom:function(t,e){var n=this.getPoint(t);return this.zoom(n,e),this},translate:function(t,e){var n=this.get("_rootGroup").getMatrix();return r.mat3.translate(n,n,[t,e]),this.updateMatrix(n),this},translateByDom:function(t,e){var n=this.get("_rootGroup").getMatrix()[0];return this.translate(t/n,e/n),this},getMatrix:function(){return this.get("_rootGroup").getMatrix()},setMatrix:function(t){this.get("_rootGroup").setMatrix(t)},getPoint:function(t){return this.getPointByDom(t)},getPointByDom:function(t){var e=this.get("_rootGroup").getMatrix();return r.invertMatrix(t,e)},getPointByCanvas:function(t){var e=this.get("_canvas").get("pixelRatio");return this.getPoint({x:t.x/e,y:t.y/e})},getPointByClient:function(t){var e=this.get("_canvas").getPointByClient(t.x,t.y);return this.getPointByCanvas(e)},getDomPoint:function(t){var e=this.get("_rootGroup").getMatrix();return r.applyMatrix(t,e)},getCanvasPoint:function(t){var e=this.get("_canvas").get("pixelRatio"),n=this.getDomPoint(t);return{x:n.x*e,y:n.y*e}},getClientPoint:function(t){var e=this.getCanvasPoint(t),n=this.get("_canvas").getClientByPoint(e.x,e.y);return{x:n.clientX,y:n.clientY}},focus:function(t){if(r.isString(t)&&(t=this.find(t)),t){var e=t.getCenter();this.focusPoint(e)}return this},focusPoint:function(t){var e=this.get("_rootGroup").getMatrix(),n=this.get("width"),r=this.get("height"),i=-e[6]+n/2-e[0]*t.x,o=-e[7]+r/2-e[0]*t.y;return this.translate(i,o),this},focusPointByDom:function(t){var e=this.getPoint(t);return this.focusPoint(e),this}},t.exports=i},function(t,e){t.exports={INIT:"_initDraw",AUGMENT:{_initDraw:function(){var t=this,e=this.get("_controllers").animate;["clear","show","hide","change","updatenodeposition"].forEach((function(n){e&&t.on("before"+n,(function(n){var r=t.get("_forcePreventAnimate"),i=n?n.affectedItemIds:void 0;!0!==r&&e&&e.cacheGraph("startCache",i)})),t.on("after"+n,(function(n){var r=n?n.affectedItemIds:void 0,i=t.get("_forcePreventAnimate");if(n&&"changeData"===n.action){var o=t.get("fitView");o&&t.setFitView(o)}!0!==i&&e?(e.cacheGraph("endCache",r),e.run()):t.draw()}))}))},draw:function(){this.get("_canvas").draw()},animateDraw:function(){this.get("_controllers").animate.run()}}}},function(t,e,n){var r=n(247);function i(t,e){var n=t.getGraphicGroup(),i=t.getBBox(),o=(i.minX+i.maxX)/2,a=(i.minY+i.maxY)/2,s=n.getMatrix()[0];n.transform([["t",-o,-a],["s",.01/s,.01/s],["t",o,a]]),n.animate({transform:[["t",-o,-a],["s",100*s,100*s],["t",o,a]]},r.enterDuration,r.enterEasing,e)}function o(t,e){var n=t.getGraphicGroup(),i=t.getBBox(),o=(i.minX+i.maxX)/2,a=(i.minY+i.maxY)/2,s=n.getMatrix()[0];n.animate({transform:[["t",-o,-a],["s",.01/s,.01/s],["t",o,a]]},r.leaveDuration,r.leaveEasing,e)}function a(t,e){t.deepEach((function(t){if(t.isShape){var n=t.attr("fillOpacity"),i=t.attr("strokeOpacity");t.attr({fillOpacity:0,strokeOpacity:0}),t.animate({fillOpacity:n,strokeOpacity:i},r.enterDuration,r.enterEasing,e)}}))}function s(t,e){t.deepEach((function(t){var n=t.attr("fillOpacity"),i=t.attr("strokeOpacity");t.isShape&&t.animate({fillOpacity:0,strokeOpacity:0},r.leaveDuration,r.leaveEasing,(function(){t.attr({fillOpacity:n,strokeOpacity:i}),e()}))}))}t.exports={enterScaleIn:function(t){var e=t.item;t.element.isItemContainer&&e.getKeyShape()&&i(e)},showScaleIn:function(t){var e=t.item;t.element.isItemContainer&&e.getKeyShape()&&i(e)},leaveScaleOut:function(t){var e=t.item,n=t.element,r=t.done;n.isItemContainer&&o(e,(function(){r()}))},hideScaleOut:function(t){var e=t.item,n=t.element,r=t.done;n.isItemContainer&&o(e,(function(){r()}))},enterFadeIn:function(t){var e=t.element,n=t.item;e.isItemContainer&&n.getKeyShape()&&a(e)},showFadeIn:function(t){var e=t.element,n=t.item;e.isItemContainer&&n.getKeyShape()&&a(e)},leaveFadeOut:function(t){var e=t.element,n=t.item,r=t.done;e.isItemContainer&&n.getKeyShape()&&s(e,r)},hideFadeOut:function(t){var e=t.element,n=t.item,r=t.done;e.isItemContainer&&n.getKeyShape()&&s(e,r)}}},function(t,e,n){function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var i=n(599),o=n(693),a=n(26),s=n(247),c=["matrix","fillStyle","strokeStyle","endArrow","startArrow"],u=function(t){function e(){return t.apply(this,arguments)||this}!function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t);var n=e.prototype;return n.getDefaultCfg=function(){return{show:"scaleIn",hide:"scaleOut",enter:"scaleIn",leave:"scaleOut",update:function(t){var e=t.element,n=t.endKeyFrame.props;e.animate(function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},i=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(i=i.concat(Object.getOwnPropertySymbols(n).filter((function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable})))),i.forEach((function(e){r(t,e,n[e])}))}return t}({matrix:n.matrix},n.attrs),s.updateDuration,s.updateEasing)},graph:null,startCache:{},endCache:{},keykeyCache:{}}},n._init=function(){var t=this,e=this.graph,n=this.keykeyCache;e.on("afteritemdraw",(function(e){e.item.getGraphicGroup().deepEach((function(e){n[e.gid]=t._getCache(e)}),!0)}))},n.cacheGraph=function(t,e){var n,r=this,i=this.graph;n=e?e.map((function(t){return i.find(t)})):i.getItems(),this[t]={},n.forEach((function(e){e&&r.cache(e,r[t],t)}))},n._getCache=function(t){var e=this.keykeyCache;if(!a.isObject(t))return e[t];var n={props:{matrix:a.clone(t.getMatrix()),attrs:{}}};if(t.isShape){var r=t.attr();r=a.omit(r,c),n.props.attrs=a.clone(r)}return n},n._getAnimation=function(t,e){var n=this.graph,r=t.shapeObj,i=this[e],s=r[e+"Animation"]||r[e+"Animate"],c=n.get("_"+e+"Animation"),u=s||c||i;return a.isString(u)?o[e+a.upperFirst(u)]:u},n.cache=function(t,e,n){var r=this;t.getGraphicGroup().deepEach((function(i){var o=i.gid,a="startCache"===n?r._getCache(i):r._getCache(i.gid);a.enterAnimate=r._getAnimation(t,"enter"),a.leaveAnimate=r._getAnimation(t,"leave"),a.showAnimate=r._getAnimation(t,"show"),a.hideAnimate=r._getAnimation(t,"hide"),a.updateAnimate=r._getAnimation(t,"update"),a.item=t,a.element=i,a.visible=i.get("visible"),e[o]=a}),!0)},n._compare=function(){var t=this.startCache,e=this.endCache,n=[],r=[],i=[],o=[],s=[];a.each(e,(function(e,r){var a=t[r];a?a.element.get("type")===e.element.get("type")&&(a.visible&&e.visible?i.push(r):a.visible&&!e.visible?o.push(r):!a.visible&&e.visible&&s.push(r)):n.push(r)})),a.each(t,(function(t,n){e[n]||r.push(n)})),this.enterElements=n,this.leaveElements=r,this.updateElements=i,this.hideElements=o,this.showElements=s},n._addTween=function(){var t=this.enterElements,e=this.leaveElements,n=this.updateElements,r=this.hideElements,i=this.showElements,o=this.startCache,s=this.endCache;t.forEach((function(t){var e=s[t],n=e.enterAnimate;n&&n({element:e.element,item:e.item,endKeyFrame:e,startKeyFrame:null,startCache:o,endCache:s,done:function(){}})})),e.forEach((function(t){var e=o[t],n=e.leaveAnimate;if(n){var r=o[t].element;r.isItemContainer&&r.getParent().add(r),n({element:r,item:e.item,endKeyFrame:null,startKeyFrame:e,startCache:o,endCache:s,done:function(){r.isItemContainer&&r.remove()}})}})),n.forEach((function(t){var e=s[t],n=o[t],r=e.element,i=n.element,c=n.props,u=e.props,h=e.updateAnimate;c.attrs&&r.attr(c.attrs),a.isEqual(c.matrix,u.matrix)||r.setMatrix(c.matrix),h({element:r,item:e,endKeyFrame:e,startKeyFrame:n,startCache:o,endCache:s,done:function(){}}),i!==r&&i.remove()})),r.forEach((function(t){var e=s[t],n=o[t],r=e.hideAnimate;r&&(e.element.show(),r({element:e.element,item:e.item,endKeyFrame:e,startKeyFrame:n,startCache:o,endCache:s,done:function(){var t=e.item,n=t.getGraphicGroup();!t.visible&&n.hide()}}))})),i.forEach((function(t){var e=s[t],n=o[t],r=e.showAnimate;r&&r({element:e.element,item:e.item,endKeyFrame:e,startKeyFrame:n,startCache:o,endCache:s,done:function(){}})}))},n.run=function(){this.graph.destroyed||(this._compare(),this._addTween())},e}(i);t.exports=u},function(t,e,n){function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var i=n(26),o=n(694),a={INIT:"_initAnimate",CFG:{animate:!1}};a.AUGMENT={_initAnimate:function(){var t=this.get("animate");if(t){var e=this.get("_controllers"),n={graph:this};i.isPlainObject(t)&&(n=function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},i=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(i=i.concat(Object.getOwnPropertySymbols(n).filter((function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable})))),i.forEach((function(e){r(t,e,n[e])}))}return t}({},n,t)),e.animate=new o(n)}}},t.exports=a},function(t,e,n){var r=n(26),i={INIT:"_initFilter",CFG:{filters:[]}};i.AUGMENT={_initFilter:function(){var t=this,e=this.get("filters");r.isFunction(e)&&this.set("filters",[e]),this.on("afterchange",(function(n){var r=n.action;e.length>0&&"changeData"===r&&!t.destroyed&&t.filter()}))},addFilter:function(t){return this.get("filters").push(t),t},removeFilter:function(t){var e=this.get("filters");this.set("filters",r.filter(e,t))},filter:function(){this.emit("beforefilter");var t=this.get("filters"),e=this.getItems(),n=this._getFilterItems();t.forEach((function(t){n=n.filter(t)})),e.forEach((function(t){-1===n.indexOf(t)?t.hide():t.show()})),this.draw(),this.emit("afterfilter")},_getFilterItems:function(){return this.getItems().filter((function(t){return!1!==t.getShapeObj().filter}))}},t.exports=i},function(t,e,n){var r=n(26),i=n(626),o={CFG:{modes:{default:[]},mode:"default",_eventCache:{}},INIT:"_initModes"};o.AUGMENT={_initModes:function(){var t=this.get("mode");this.changeMode(t)},changeMode:function(t){var e=this.get("modes");r.isEmpty(e)||r.isEmpty(e[t])||(i.resetMode(e[t],this),this.set("mode",t))},addBehaviour:function(t,e){var n=this.get("modes");e=e||this.get("mode"),r.isEmpty(n[e])&&(n[e]=[]);var o=n[e],a=[].concat(t);return r.each(a,(function(t){-1===o.indexOf(t)&&o.push(t)})),i.resetMode(n[e],this),this},removeBehaviour:function(t){var e=this.get("modes"),n=this.get("mode"),o=e[n];if(!r.isEmpty(o)){var a=[].concat(t);return o=o.filter((function(t){return-1===a.indexOf(t)})),e[n]=o,i.resetMode(o,this),this}},behaviourOn:function(t,e){var n=this._eventCache;n[t]||(n[t]=[]),n[t].push(e),this.on(t,e)},_off:function(){var t=this,e=this._eventCache;r.each(e,(function(e,n){r.each(e,(function(e){t.off(n,e)}))})),this._eventCache={}}},t.exports=o},function(t,e,n){var r=n(599),i=n(26),o={MOUSEMOVE:"mousemove",MOUSEDOWN:"mousedown",MOUSEUP:"mouseup",MOUSEENTER:"mouseenter",MOUSELEAVE:"mouseleave",CLICK:"click",DBLCLICK:"dblclick",DRAGSTART:"dragstart",DRAG:"drag",DRAGENTER:"dragenter",DRAGLEAVE:"dragleave",DRAGEND:"dragend",DROP:"drop",CONTEXTMENU:"contextmenu",WHEEL:"wheel",KEYDOWN:"keydown",KEYUP:"keyup",KEYPRESS:"keypress",MOUSEWHEEL:"mousewheel"},a=[o.DBLCLICK,o.MOUSEDOWN,o.MOUSEUP,o.MOUSEENTER,o.MOUSELEAVE,o.MOUSEMOVE,o.CONTEXTMENU,o.WHEEL,o.MOUSEWHEEL],s=[o.KEYDOWN,o.KEYUP,o.KEYPRESS],c=function(t){function e(e){var n;return(n=t.call(this,e)||this)._domEvents=[],n._initEventStates(),n._registerEvents(),n}!function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t);var n=e.prototype;return n._initEventStates=function(){this._pressing=!1,this._dragging=!1,this._currentEventObj={},this._dragEventObj={}},n._registerEvents=function(){this._registerMouseEvents(),this._registerKeyboardEvents()},n._registerKeyboardEvents=function(){var t=this.graph,e=t.getKeyboardEventWrapper(),n=this._domEvents,r=t.get("keyboardEnable");i.each(s,(function(o){n.push(i.addEventListener(e,o,(function(e){var n=!0;i.isFunction(r)&&(n=r()),n&&t.emit(o,{domEvent:e})})))}))},n._registerMouseEvents=function(){var t=this,e=this,n=this.graph.getMouseEventWrapper(),r=this._domEvents;i.each(a,(function(a){r.push(i.addEventListener(n,a,(function(n){if(n.type!==o.MOUSEENTER||!n.fromElement||n.fromElement.parentNode&&!function(t,e){for(var n=t.parentNode;n;){if("foreignObject"===n.tagName)return!0;n=n.parentNode}return!1}(n.fromElement)){var r=t._currentEventObj;t._oldEventObj=r,t._processEventObj(n);var a=t._currentEventObj;e._simulateEvents(n,r,a),-1!==[o.MOUSELEAVE,o.MOUSEENTER].indexOf(n.type)&&e._triggerEvent("canvas:"+n.type),e._triggerEvent(n.type),n.type===o.MOUSELEAVE&&(t._dragging&&e._triggerEvent(o.DRAGLEAVE,i.mix({},a,{item:null,shape:null,currentItem:t._dragEventObj.item,currentShape:t._dragEventObj.shape})),e._initEventStates())}})))}))},n.destroy=function(){var t=this._domEvents;i.each(t,(function(t){t&&t.remove()})),this._domEvents=null},n._triggerEvent=function(t,e){if(e||(e="mouseleave"===t?this._oldEventObj:this._currentEventObj),"mousedown"===t&&(e.button=this._button),e._type=t,this.emitGraphEvent(t,e),-1===["canvas:"+o.MOUSELEAVE,"canvas:"+o.MOUSEENTER].indexOf(t)){var n=e.shape&&e.shape.eventPreFix;if(-1!==[o.DRAGSTART,o.DRAG,o.DRAGEND].indexOf(t)&&(n=e.currentShape&&e.currentShape.eventPreFix),n){var r=n+":"+t;e._type=r,i.isBoolean(e._isItemChange)?e._isItemChange&&this.emitGraphEvent(r,e):this.emitGraphEvent(r,e)}}},n.emitGraphEvent=function(t,e){this.graph.emit(t,e)},n._getDistanceToPress=function(t){return Math.pow(t.clientX-this._pressX,2)+Math.pow(t.clientY-this._pressY,2)},n._simulateEvents=function(t,e,n){void 0===e&&(e={}),void 0===n&&(n={});var r=this._dragEventObj.item,a=this._dragEventObj.shape;switch(t.type){case o.MOUSEDOWN:this._pressing=!0,this._button=t.button,this._pressX=t.clientX,this._pressY=t.clientY;break;case o.MOUSEMOVE:if(this._dragging){if(this._triggerEvent(o.DRAG,i.mix({},n,{button:this._button,currentItem:r,currentShape:a})),e.shape!==n.shape){var s=this._isItemChange(e,n);e.shape&&this._triggerEvent(o.DRAGLEAVE,i.mix({},n,{button:this._button,item:e.item,shape:e.shape,toItem:n.item,toShape:n.shape,currentItem:r,currentShape:a,_isItemChange:s})),n.shape&&this._triggerEvent(o.DRAGENTER,i.mix({},n,{button:this._button,currentItem:r,currentShape:a,fromItem:e.item,fromShape:e.shape,_isItemChange:s}))}}else this._pressing&&this._getDistanceToPress(t)>9&&(this._dragging=!0,this._dragEventObj=e,r=this._dragEventObj.item,a=this._dragEventObj.shape,this._triggerEvent(o.DRAGSTART,i.mix({},e,{button:this._button,currentItem:r,currentShape:a})));if(e.shape!==n.shape){var c=this._isItemChange(e,n);e.shape&&this._triggerEvent(o.MOUSELEAVE,i.mix({},n,{item:e.item,shape:e.shape,toItem:n.item,toShape:n.shape,_isItemChange:c})),n.shape&&this._triggerEvent(o.MOUSEENTER,i.mix({},n,{fromtItem:e.item,fromShape:e.shape,_isItemChange:c}))}break;case o.MOUSEUP:!this._dragging&&this._pressing?this._triggerEvent(o.CLICK,i.mix({},n,{button:this._button})):(this._triggerEvent(o.DROP,i.mix({},n,{button:this._button,currentItem:r,currentShape:a})),this._triggerEvent(o.DRAGEND,i.mix({},n,{button:this._button,currentItem:r,currentShape:a}))),this._pressing=!1,this._dragging=!1,this._dragEventObj={};break;default:return}},n._isItemChange=function(t,e){var n=t.shape,r=e.shape,o=n&&r&&(n.get("isItemChange")||r.get("isItemChange"));return o?o(r,n):i.isObject(t.item)&&i.isObject(e.item)?t.item.id!==e.item.id:t.item!==e.item},n._processEventObj=function(t){var e=this.graph.get("_canvas"),n=this._getEventObj(t,e);this._currentEventObj=n},n._parsePoint=function(t,e){return this.graph.getPointByCanvas({x:t,y:e})},n._getEventObj=function(t,e){var n=this.graph,r=t.clientX,i=t.clientY,o=e.getPointByClient(r,i),a=this._parsePoint(o.x,o.y),s=e.getShape(o.x,o.y,t),c=n.getItemByShape(s),u=e.get("pixelRatio");return{item:c,shape:s,x:a.x,y:a.y,domX:o.x/u,domY:o.y/u,domEvent:t}},e}(r);t.exports=c},function(t,e,n){var r={},i=n(698);r.INIT="_initEvents",r.CFG={keyboardEnable:!0},r.AUGMENT={_initEvents:function(){this.get("_controllers").events=new i({graph:this})}},t.exports=r},function(t,e,n){var r=n(26),i={};i.AUGMENT={find:function(t){return this.get("_itemMap")[t]},getNodes:function(){return this.get("_itemMap")._nodes},getEdges:function(){return this.get("_itemMap")._edges},getGroups:function(){return this.get("_itemMap")._groups},getGuides:function(){return this.get("_itemMap")._guides},getItems:function(){var t=this.get("_itemMap"),e=[];return r.each(t,(function(t){t.type&&e.push(t)})),e},getItemByShape:function(t){return t?this.getItem(t.id):null},getItem:function(t){var e=this.get("_itemMap");return r.isObject(t)?t.destroyed&&(t=e[t.id]):t=e[t],t}},t.exports=i},function(t,e,n){var r=n(599),i=n(26),o=["color","shape","size","label","style"],a=function(t){function e(){return t.apply(this,arguments)||this}!function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t);var n=e.prototype;return n._init=function(){var t=this,e={};i.each(o,(function(n){e[n]={},t[n]=function(r){return e[n].input=r,t}})),this.channels=e},n.addChannels=function(t){var e=this.channels;i.each(t,(function(t,n){e[n]={input:t}}))},n.mapping=function(t){var e=this.channels;i.each(e,(function(e,n){i.isFunction(e.input)?t[n]=e.input(t):e.input&&(t[n]=e.input)}))},e}(r);t.exports=a},function(t,e,n){var r=n(701),i={INIT:"_initMapper"};i.AUGMENT={_initMapper:function(){var t=this.get("_controllers");t.nodeMapper=new r({graph:this}),t.edgeMapper=new r({graph:this}),t.groupMapper=new r({graph:this}),t.guideMapper=new r({graph:this})},node:function(t){var e=this._getController("nodeMapper");return t&&e.addChannels(t),e},edge:function(t){var e=this._getController("edgeMapper");return t&&e.addChannels(t),e},group:function(t){var e=this._getController("groupMapper");return t&&e.addChannels(t),this._getController("groupMapper")},guide:function(t){var e=this._getController("guideMapper");return t&&e.addChannels(t),this._getController("guideMapper")}},t.exports=i},function(t,e,n){var r=function(t){function e(){return t.apply(this,arguments)||this}!function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t);var n=e.prototype;return n.getDefaultCfg=function(){return{graph:null,auto:!0,processor:null}},n._init=function(){var t=this,e=this.graph;e.on("afteritemdraw",(function(t){var e=t.item,n=e.getKeyShape(),r=e.getModel();if(e.isEdge)r.lineWidth=n.attr("lineWidth");else if(e.isNode||e.isGroup){var i=e.getBBox();r.width=i.width,r.height=i.height}})),e.on("afterchange",(function(n){var r=n.action;"once"===t.auto?"changeData"===r&&(e.destroyed||e.preventAnimate((function(){t.layout()}))):t.auto&&!e.destroyed&&e.preventAnimate((function(){t.layout()}))}))},n.changeLayout=function(t){this.processor=t,this.layout()},n.layout=function(){var t=this.graph,e=this.getLayoutProcessor();t.emit("beforelayout");var n=t.getNodes().filter((function(t){return t.isVisible()})).map((function(t){return t.getModel()})),r=t.getEdges().filter((function(t){return t.isVisible()})).map((function(t){return t.getModel()})),i=t.getGroups().filter((function(t){return t.isVisible()})).map((function(t){return t.getModel()}));t._executeLayout(e,n,r,i),t.updateNodePosition(),t.emit("afterlayout")},n.getLayoutProcessor=function(){return this.processor?this.processor:this.processer},e}(n(599));t.exports=r},function(t,e,n){var r=n(26),i=n(703),o={CFG:{layout:void 0},INIT:"_initLayout"};o.AUGMENT={_initLayout:function(){var t=this.get("_controllers"),e=this._getLayoutCfg();e&&(t.layout=new i(r.mix({graph:this},e)))},_getLayoutCfg:function(){var t=this.get("layout");return r.isPlainObject(t)?t:r.isFunction(t)||r.isObject(t)?{processor:t}:null},layout:function(){return this._getController("layout").layout(),this},updateNodePosition:function(t){var e=this.getGuides(),n=[],i=[];return this.emit("beforeupdatenodeposition"),t?(t.forEach((function(t){t.getEdges().forEach((function(t){i.push(t)}));var e=t.getParent();e&&n.push(e)})),i=r.uniq(i),n=r.uniq(n)):(t=this.getNodes(),n=this.getGroups(),i=this.getEdges()),t.forEach((function(t){t.layoutUpdate()})),n.forEach((function(t){t.layoutUpdate()})),i.forEach((function(t){t.layoutUpdate()})),e.forEach((function(t){t.layoutUpdate()})),this.emit("afterupdatenodeposition"),this},changeLayout:function(t){return this._getController("layout").changeLayout(t),this},getLayout:function(){return this._getController("layout").getLayoutProcessor()}},t.exports=o},function(t,e,n){!function(e){"use strict";var n=function(){return{escape:function(t){return t.replace(/([.*+?^${}()|\[\]\/\\])/g,"\\$1")},parseExtension:t,mimeType:function(e){var n=t(e).toLowerCase();return function(){var t="application/font-woff";return{woff:t,woff2:t,ttf:"application/font-truetype",eot:"application/vnd.ms-fontobject",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",tiff:"image/tiff",svg:"image/svg+xml"}}()[n]||""},dataAsUrl:function(t,e){return"data:"+e+";base64,"+t},isDataUrl:function(t){return-1!==t.search(/^(data:)/)},canvasToBlob:function(t){return t.toBlob?new Promise((function(e){t.toBlob(e)})):function(t){return new Promise((function(e){for(var n=window.atob(t.toDataURL().split(",")[1]),r=n.length,i=new Uint8Array(r),o=0;o<r;o++)i[o]=n.charCodeAt(o);e(new Blob([i],{type:"image/png"}))}))}(t)},resolveUrl:function(t,e){var n=document.implementation.createHTMLDocument(),r=n.createElement("base");n.head.appendChild(r);var i=n.createElement("a");return n.body.appendChild(i),r.href=e,i.href=t,i.href},getAndEncode:function(t){return c.impl.options.cacheBust&&(t+=(/\?/.test(t)?"&":"?")+(new Date).getTime()),new Promise((function(e){var n,r=new XMLHttpRequest;if(r.onreadystatechange=function(){if(4===r.readyState)if(200===r.status){var i=new FileReader;i.onloadend=function(){var t=i.result.split(/,/)[1];e(t)},i.readAsDataURL(r.response)}else n?e(n):o("cannot fetch resource: "+t+", status: "+r.status)},r.ontimeout=function(){n?e(n):o("timeout of 30000ms occured while fetching resource: "+t)},r.responseType="blob",r.timeout=3e4,r.open("GET",t,!0),r.send(),c.impl.options.imagePlaceholder){var i=c.impl.options.imagePlaceholder.split(/,/);i&&i[1]&&(n=i[1])}function o(t){console.error(t),e("")}}))},uid:function(){var t=0;return function(){return"u"+("0000"+(Math.random()*Math.pow(36,4)<<0).toString(36)).slice(-4)+t++}}(),delay:function(t){return function(e){return new Promise((function(n){setTimeout((function(){n(e)}),t)}))}},asArray:function(t){for(var e=[],n=t.length,r=0;r<n;r++)e.push(t[r]);return e},escapeXhtml:function(t){return t.replace(/#/g,"%23").replace(/\n/g,"%0A")},makeImage:function(t){return new Promise((function(e,n){var r=new Image;r.onload=function(){e(r)},r.onerror=n,r.src=t}))},width:function(t){var n=e(t,"border-left-width"),r=e(t,"border-right-width");return t.scrollWidth+n+r},height:function(t){var n=e(t,"border-top-width"),r=e(t,"border-bottom-width");return t.scrollHeight+n+r}};function t(t){var e=/\.([^\.\/]*?)$/g.exec(t);return e?e[1]:""}function e(t,e){var n=window.getComputedStyle(t).getPropertyValue(e);return parseFloat(n.replace("px",""))}}(),r=function(){var t=/url\(['"]?([^'"]+?)['"]?\)/g;return{inlineAll:function(t,n,o){return e(t)?Promise.resolve(t).then(r).then((function(e){var r=Promise.resolve(t);return e.forEach((function(t){r=r.then((function(e){return i(e,t,n,o)}))})),r})):Promise.resolve(t)},shouldProcess:e,impl:{readUrls:r,inline:i}};function e(e){return-1!==e.search(t)}function r(e){for(var r,i=[];null!==(r=t.exec(e));)i.push(r[1]);return i.filter((function(t){return!n.isDataUrl(t)}))}function i(t,e,r,i){return Promise.resolve(e).then((function(t){return r?n.resolveUrl(t,r):t})).then(i||n.getAndEncode).then((function(t){return n.dataAsUrl(t,n.mimeType(e))})).then((function(r){return t.replace(function(t){return new RegExp("(url\\(['\"]?)("+n.escape(t)+")(['\"]?\\))","g")}(e),"$1"+r+"$3")}))}}(),i=function(){return{resolveAll:function(){return t(document).then((function(t){return Promise.all(t.map((function(t){return t.resolve()})))})).then((function(t){return t.join("\n")}))},impl:{readAll:t}};function t(){return Promise.resolve(n.asArray(document.styleSheets)).then((function(t){var e=[];return t.forEach((function(t){try{n.asArray(t.cssRules||[]).forEach(e.push.bind(e))}catch(e){console.log("Error while reading CSS rules from "+t.href,e.toString())}})),e})).then((function(t){return t.filter((function(t){return t.type===CSSRule.FONT_FACE_RULE})).filter((function(t){return r.shouldProcess(t.style.getPropertyValue("src"))}))})).then((function(e){return e.map(t)}));function t(t){return{resolve:function(){var e=(t.parentStyleSheet||{}).href;return r.inlineAll(t.cssText,e)},src:function(){return t.style.getPropertyValue("src")}}}}}(),o=function(){return{inlineAll:function e(i){return i instanceof Element?function(t){var e=t.style.getPropertyValue("background");return e?r.inlineAll(e).then((function(e){t.style.setProperty("background",e,t.style.getPropertyPriority("background"))})).then((function(){return t})):Promise.resolve(t)}(i).then((function(){return i instanceof HTMLImageElement?t(i).inline():Promise.all(n.asArray(i.childNodes).map((function(t){return e(t)})))})):Promise.resolve(i)},impl:{newImage:t}};function t(t){return{inline:function(e){return n.isDataUrl(t.src)?Promise.resolve():Promise.resolve(t.src).then(e||n.getAndEncode).then((function(e){return n.dataAsUrl(e,n.mimeType(t.src))})).then((function(e){return new Promise((function(n,r){t.onload=n,t.onerror=r,t.src=e}))}))}}}}(),a=void 0,s=!1,c={toSvg:u,toPng:function(t,e){return h(t,e||{}).then((function(t){return t.toDataURL()}))},toJpeg:function(t,e){return h(t,e=e||{}).then((function(t){return t.toDataURL("image/jpeg",e.quality||1)}))},toBlob:function(t,e){return h(t,e||{}).then(n.canvasToBlob)},toPixelData:function(t,e){return h(t,e||{}).then((function(e){return e.getContext("2d").getImageData(0,0,n.width(t),n.height(t)).data}))},impl:{fontFaces:i,images:o,util:n,inliner:r,options:{}}};function u(t,e){return function(t){void 0===t.imagePlaceholder?c.impl.options.imagePlaceholder=a:c.impl.options.imagePlaceholder=t.imagePlaceholder,void 0===t.cacheBust?c.impl.options.cacheBust=s:c.impl.options.cacheBust=t.cacheBust}(e=e||{}),Promise.resolve(t).then((function(t){return function(t,e,r){return Promise.resolve(t).then((function(t){return t instanceof HTMLCanvasElement?n.makeImage(t.toDataURL()):t.cloneNode(!1)})).then((function(r){return function(t,e,r){var i=t.childNodes;return 0===i.length?Promise.resolve(e):function(t,e,n){var r=Promise.resolve();return e.forEach((function(e){r=r.then((function(){return l(e,n)})).then((function(e){e&&t.appendChild(e)}))})),r}(e,n.asArray(i),r).then((function(){return e}))}(t,r,e)})).then((function(e){return function(t,e){return e instanceof Element?Promise.resolve().then((function(){!function(t,e){t.cssText?e.cssText=t.cssText:function(t,e){n.asArray(t).forEach((function(n){e.setProperty(n,t.getPropertyValue(n),t.getPropertyPriority(n))}))}(t,e)}(window.getComputedStyle(t),e.style)})).then((function(){[":before",":after"].forEach((function(r){!function(r){var i=window.getComputedStyle(t,r),o=i.getPropertyValue("content");if(""!==o&&"none"!==o){var a=n.uid();e.className=e.className+" "+a;var s=document.createElement("style");s.appendChild(function(t,e,r){var i="."+t+":"+e,o=r.cssText?function(t){var e=t.getPropertyValue("content");return t.cssText+" content: "+e+";"}(r):function(t){return n.asArray(t).map((function(e){return e+": "+t.getPropertyValue(e)+(t.getPropertyPriority(e)?" !important":"")})).join("; ")+";"}(r);return document.createTextNode(i+"{"+o+"}")}(a,r,i)),e.appendChild(s)}}(r)}))})).then((function(){t instanceof HTMLTextAreaElement&&(e.innerHTML=t.value),t instanceof HTMLInputElement&&e.setAttribute("value",t.value)})).then((function(){e instanceof SVGElement&&(e.setAttribute("xmlns","http://www.w3.org/2000/svg"),e instanceof SVGRectElement&&["width","height"].forEach((function(t){var n=e.getAttribute(t);n&&e.style.setProperty(t,n)})))})).then((function(){return e})):e}(t,e)}))}(t,e.filter)})).then(d).then(f).then((function(t){return e.bgcolor&&(t.style.backgroundColor=e.bgcolor),e.width&&(t.style.width=e.width+"px"),e.height&&(t.style.height=e.height+"px"),e.style&&Object.keys(e.style).forEach((function(n){t.style[n]=e.style[n]})),t})).then((function(r){return function(t,e,r){return Promise.resolve(t).then((function(t){return t.setAttribute("xmlns","http://www.w3.org/1999/xhtml"),(new XMLSerializer).serializeToString(t)})).then(n.escapeXhtml).then((function(t){return'<foreignObject x="0" y="0" width="100%" height="100%">'+t+"</foreignObject>"})).then((function(t){return'<svg xmlns="http://www.w3.org/2000/svg" width="'+e+'" height="'+r+'">'+t+"</svg>"})).then((function(t){return"data:image/svg+xml;charset=utf-8,"+t}))}(r,e.width||n.width(t),e.height||n.height(t))}))}function h(t,e){return u(t,e).then(n.makeImage).then(n.delay(100)).then((function(r){var i=function(t){var r=document.createElement("canvas");if(r.width=e.width||n.width(t),r.height=e.height||n.height(t),e.bgcolor){var i=r.getContext("2d");i.fillStyle=e.bgcolor,i.fillRect(0,0,r.width,r.height)}return r}(t);return i.getContext("2d").drawImage(r,0,0),i}))}function l(t,e,r){return r||!e||e(t)?Promise.resolve(t).then((function(t){return t instanceof HTMLCanvasElement?n.makeImage(t.toDataURL()):t.cloneNode(!1)})).then((function(n){return i(t,n,e)})).then((function(e){return function(t,e){return e instanceof Element?Promise.resolve().then((function(){!function(t,e){t.cssText?e.cssText=t.cssText:function(t,e){n.asArray(t).forEach((function(n){e.setProperty(n,t.getPropertyValue(n),t.getPropertyPriority(n))}))}(t,e)}(window.getComputedStyle(t),e.style)})).then((function(){[":before",":after"].forEach((function(r){!function(r){var i=window.getComputedStyle(t,r),o=i.getPropertyValue("content");if(""!==o&&"none"!==o){var a=n.uid();e.className=e.className+" "+a;var s=document.createElement("style");s.appendChild(function(t,e,r){var i="."+t+":"+e,o=r.cssText?function(t){var e=t.getPropertyValue("content");return t.cssText+" content: "+e+";"}(r):function(t){return n.asArray(t).map((function(e){return e+": "+t.getPropertyValue(e)+(t.getPropertyPriority(e)?" !important":"")})).join("; ")+";"}(r);return document.createTextNode(i+"{"+o+"}")}(a,r,i)),e.appendChild(s)}}(r)}))})).then((function(){t instanceof HTMLTextAreaElement&&(e.innerHTML=t.value),t instanceof HTMLInputElement&&e.setAttribute("value",t.value)})).then((function(){e instanceof SVGElement&&(e.setAttribute("xmlns","http://www.w3.org/2000/svg"),e instanceof SVGRectElement&&["width","height"].forEach((function(t){var n=e.getAttribute(t);n&&e.style.setProperty(t,n)})))})).then((function(){return e})):e}(t,e)})):Promise.resolve();function i(t,e,r){var i=t.childNodes;return 0===i.length?Promise.resolve(e):function(t,e,n){var r=Promise.resolve();return e.forEach((function(e){r=r.then((function(){return l(e,n)})).then((function(e){e&&t.appendChild(e)}))})),r}(e,n.asArray(i),r).then((function(){return e}))}}function d(t){return i.resolveAll().then((function(e){var n=document.createElement("style");return t.appendChild(n),n.appendChild(document.createTextNode(e)),t}))}function f(t){return o.inlineAll(t).then((function(){return t}))}t.exports=c}()},function(t,e,n){function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var i=n(26),o=n(248),a=n(705),s=function(){function t(t){this.options=function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},i=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(i=i.concat(Object.getOwnPropertySymbols(n).filter((function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable})))),i.forEach((function(e){r(t,e,n[e])}))}return t}({graph:null,width:null,height:null,canvas:null,beforeTransform:function(){},afterTransform:function(){},drawCount:0},t)}var e=t.prototype;return e.getCanvas=function(){var t=this.options,e=t.width,n=t.height,r=t.canvas;if(!r){var a=i.createDOM("<canvas></canvas>");r=new o.Canvas({containerDOM:a,width:e,height:n})}return r.drawCount||(r.drawCount=0),r},e.drawInner=function(t,e){var n=this.options.graph,r=n.getCanvas(),i=n.get("renderer"),o=t.drawCount;if("svg"===i){var s=[];r.deepEach((function(t){"dom"===t.get("type")&&s.push(t)})),s.length>0?s.forEach((function(n){var r=n.get("el");if(r){n.domImageOnload=!1;var i=n.attr("width"),c=n.attr("height");a.toPng(r,{width:i,height:c}).then((function(r){var i=new Image;i.src=r,i.onload=function(){if(o===t.drawCount-1){n.domImage=i,n.domImageOnload=!0;for(var r=0;r<s.length;r++){var a=s[r];if(!a.domImageOnload||a.get("destroyed"))break;a.domImageOnload&&r===s.length-1&&e()}}}}))}})):e()}else e();t.drawCount+=1},e.toCanvas=function(){var t=this.options,e=t.graph,n=t.width,r=t.height,o=t.beforeTransform,a=t.limitRatio,s=t.afterTransform,c=this.getCanvas(),u=e.getBBox(),h=i.clone(e.getMatrix()),l=e.getFitViewPadding(),d=e.getCanvas(),f=i.getAutoZoomMatrix({minX:0,minY:0,maxX:n,maxY:r},u,l,a);return this.drawInner(c,(function(){var t=d.get("children");c.set("children",t),o(f,h),e.setMatrix(f),c.draw(),e.setMatrix(h),s(f,h)})),c.matrix=f,c.get("el")},t}();t.exports=s},function(t,e,n){var r=n(26),i=function(t){function e(e){var n={type:"guide",isGuide:!0,zIndex:4};return r.mix(n,e),t.call(this,n)||this}return function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t),e}(n(608));t.exports=i},function(t,e,n){var r=n(26),i=function(t){function e(e){var n={type:"group",isNode:!1,isGroup:!0,zIndex:1};return r.mix(n,e),t.call(this,n)||this}!function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t);var n=e.prototype;return n._beforeDraw=function(){this.deepEach((function(t,e){e&&(t.zIndex=e.zIndex+1),t.updateCollapsedParent(),t.collapsedParent?t.hide():t.show()})),this.getInnerEdges().forEach((function(t){t.linkedItemVisible()?t.show():t.hide()})),t.prototype._beforeDraw.call(this)},n.updatePosition=function(){},n._shouldDraw=function(){return!0},n.getCrossEdges=function(){var t=[],e=this.getInnerEdges();this.deepEach((function(e){t.push(e.id)}));var n=e.filter((function(e){var n=e.getModel();return-1===t.indexOf(n.source)||-1===t.indexOf(n.target)}));return r.uniq(n)},n.getInnerEdges=function(){var t=[];return this.deepEach((function(e){e.getEdges().forEach((function(e){t.push(e)}))})),r.uniq(t)},n.getChildrenBBox=function(){var t=this.getChildren().map((function(t){return t.getGraphicGroup()}));return r.getChildrenBBox(t)},e}(n(624));t.exports=i},function(t,e,n){function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var i=n(26),o=function(t){function e(e){var n={type:"edge",isEdge:!0,zIndex:2};return i.mix(n,e),t.call(this,n)||this}!function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(e,t);var n=e.prototype;return n._init=function(){t.prototype._init.call(this)},n._beforeDraw=function(){var e=this.model,n=this.itemMap;i.isObject(e.source)?this.source=e.source:this.source=n[e.source],i.isObject(e.target)?this.target=e.target:this.target=n[e.target],t.prototype._beforeDraw.call(this)},n._afterDraw=function(){this.linkedItemVisible()||this.hide(),this._addArrow(),t.prototype._afterDraw.call(this)},n._addArrow=function(){var t=this.model,e=this.keyShape;if("path"===e.get("type")){var n=this.shapeObj,r=e.attr("endArrow"),i=e.attr("startArrow"),o=t.endArrow||r,a=t.startArrow||i;i&&e.attr("startArrow",!1),r&&e.attr("endArrow",!1),o&&this._drawArrow(n.endArrow,"end"),a&&this._drawArrow(n.startArrow,"start")}},n._drawArrow=function(t,e){var n=t.path,o=t.shorten,a=t.tangent,s=t.ratio,c=t.style;a=a(this),o=o(this),n=n(this),c=c(this),s=s();var u=this.group,h=this.keyShape,l=i.parsePathString(h.attr("path")),d=l[l.length-1],f=l[0],g=h.getPoint(s);if(g&&!isNaN(g.x)){var p=u.addShape("path",{attrs:function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},i=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(i=i.concat(Object.getOwnPropertySymbols(n).filter((function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable})))),i.forEach((function(e){r(t,e,n[e])}))}return t}({path:n},c)}),m=a[1][0]-a[0][0],v=a[1][1]-a[0][1],x=o/Math.sqrt(m*m+v*v),y=[-m*x,-v*x],b=0,w=Math.atan(m/v);0===v&&m<0?b=Math.PI:m>0&&v>0?b=Math.PI/2-w:m<0&&v<0?b=-Math.PI/2-w:m>=0&&v<0?b=-w-Math.PI/2:m<=0&&v>0&&(b=Math.PI/2-w),p.rotate(b),p.translate(g.x,g.y),"end"===e?(d[d.length-1]=y[1]+g.y,d[d.length-2]=y[0]+g.x):(f[f.length-1]=y[1]+g.y,f[f.length-2]=y[0]+g.x),h.attr("path",l),this[e+"Arrow"]=p}},n._getControlPoints=function(){var t=this.model.controlPoints;return i.isArray(t)?t:[]},n._shouldDraw=function(){return t.prototype._shouldDraw.call(this)&&this.linkedItemVisible()},n._getPoint=function(t){if(t.isItem){var e=t.getBBox();return{x:e.centerX,y:e.centerY}}return{x:t.x,y:t.y}},n.linkedItemVisible=function(){var t=this.source,e=this.target;return i.isPlainObject(t)||i.isPlainObject(e)||t.isVisible()||e.isVisible()||t.collapsedParent!==e.collapsedParent},n.getSource=function(){var t=this.source,e=t.collapsedParent,n=this.itemMap;return e?n[e.id]:t},n.getTarget=function(){var t=this.target,e=t.collapsedParent,n=this.itemMap;return e?n[e.id]:t},n.getPoints=function(){var t=this.getSource(),e=this.getTarget(),n=this.model,r=this._getControlPoints(),o=this._getPoint(t),a=this._getPoint(e),s=[o].concat(r).concat([a]),c=s.length;if(t.isItem){var u=i.isNumber(this.model.sourceAnchor)&&t.id===n.source?this.model.sourceAnchor:s[1],h=t.getLinkPoints(u);s[0]=h[0]}if(e.isItem){var l=i.isNumber(this.model.targetAnchor)&&e.id===n.target?this.model.targetAnchor:s[c-2],d=e.getLinkPoints(l);s[c-1]=d[0]}return s},n.destroy=function(){var e=this.itemMap,n=this.model,r=e[n.source],o=e[n.target];r&&r.isItem&&i.Array.remove(r.edges,this),o&&o.isItem&&i.Array.remove(o.edges,this),t.prototype.destroy.call(this)},e}(n(608));t.exports=o},function(t,e,n){t.exports={Node:n(624),Edge:n(709),Group:n(708),Guide:n(707)}},function(t,e,n){var r; +/*! + * EventEmitter v5.2.5 - git.io/ee + * Unlicense - http://unlicense.org/ + * Oliver Caldwell - http://oli.me.uk/ + * @preserve + */!function(e){"use strict";function i(){}var o=i.prototype,a=e.EventEmitter;function s(t,e){for(var n=t.length;n--;)if(t[n].listener===e)return n;return-1}function c(t){return function(){return this[t].apply(this,arguments)}}o.getListeners=function(t){var e,n,r=this._getEvents();if(t instanceof RegExp)for(n in e={},r)r.hasOwnProperty(n)&&t.test(n)&&(e[n]=r[n]);else e=r[t]||(r[t]=[]);return e},o.flattenListeners=function(t){var e,n=[];for(e=0;e<t.length;e+=1)n.push(t[e].listener);return n},o.getListenersAsObject=function(t){var e,n=this.getListeners(t);return n instanceof Array&&((e={})[t]=n),e||n},o.addListener=function(t,e){if(!function t(e){return"function"==typeof e||e instanceof RegExp||!(!e||"object"!=typeof e)&&t(e.listener)}(e))throw new TypeError("listener must be a function");var n,r=this.getListenersAsObject(t),i="object"==typeof e;for(n in r)r.hasOwnProperty(n)&&-1===s(r[n],e)&&r[n].push(i?e:{listener:e,once:!1});return this},o.on=c("addListener"),o.addOnceListener=function(t,e){return this.addListener(t,{listener:e,once:!0})},o.once=c("addOnceListener"),o.defineEvent=function(t){return this.getListeners(t),this},o.defineEvents=function(t){for(var e=0;e<t.length;e+=1)this.defineEvent(t[e]);return this},o.removeListener=function(t,e){var n,r,i=this.getListenersAsObject(t);for(r in i)i.hasOwnProperty(r)&&-1!==(n=s(i[r],e))&&i[r].splice(n,1);return this},o.off=c("removeListener"),o.addListeners=function(t,e){return this.manipulateListeners(!1,t,e)},o.removeListeners=function(t,e){return this.manipulateListeners(!0,t,e)},o.manipulateListeners=function(t,e,n){var r,i,o=t?this.removeListener:this.addListener,a=t?this.removeListeners:this.addListeners;if("object"!=typeof e||e instanceof RegExp)for(r=n.length;r--;)o.call(this,e,n[r]);else for(r in e)e.hasOwnProperty(r)&&(i=e[r])&&("function"==typeof i?o.call(this,r,i):a.call(this,r,i));return this},o.removeEvent=function(t){var e,n=typeof t,r=this._getEvents();if("string"===n)delete r[t];else if(t instanceof RegExp)for(e in r)r.hasOwnProperty(e)&&t.test(e)&&delete r[e];else delete this._events;return this},o.removeAllListeners=c("removeEvent"),o.emitEvent=function(t,e){var n,r,i,o,a=this.getListenersAsObject(t);for(o in a)if(a.hasOwnProperty(o))for(n=a[o].slice(0),i=0;i<n.length;i++)!0===(r=n[i]).once&&this.removeListener(t,r.listener),r.listener.apply(this,e||[])===this._getOnceReturnValue()&&this.removeListener(t,r.listener);return this},o.trigger=c("emitEvent"),o.emit=function(t){var e=Array.prototype.slice.call(arguments,1);return this.emitEvent(t,e)},o.setOnceReturnValue=function(t){return this._onceReturnValue=t,this},o._getOnceReturnValue=function(){return!this.hasOwnProperty("_onceReturnValue")||this._onceReturnValue},o._getEvents=function(){return this._events||(this._events={})},i.noConflict=function(){return e.EventEmitter=a,i},void 0===(r=function(){return i}.call(e,n,e,t))||(t.exports=r)}("undefined"!=typeof window?window:this||{})},function(t,e,n){var r=n(26),i=function(t){!function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}(n,t);var e=n.prototype;function n(e){var n,i=(n=t.call(this)||this).getDefaultCfg();return n._cfg=r.mix({},i,e),n}return e.getDefaultCfg=function(){return{}},e.get=function(t){return this._cfg[t]},e.set=function(t,e){this._cfg[t]=e},e.destroy=function(){this._cfg={},this.removeAllListeners(),this.destroyed=!0},n}(n(711));t.exports=i},function(t,e,n){var r=n(26),i=n(248),o=function(){};r.augment(o,{drawInner:function(t){var e=r.clone(this.getTotalMatrix()),n=this._attrs,i=n.x,o=n.y,a=n.width,s=n.height;t.setTransform(e[0],e[1],e[3],e[4],e[6],e[7]),t.drawImage(this.domImage,i,o,a,s)}}),r.mixin(i.Dom,[o]),t.exports=o},function(t,e,n){var r=n(26),i=n(248),o=function(){};r.augment(o,{hasClass:function(t){var e=this.get("class");return!(!e||-1===e.indexOf(t))}}),r.mixin(i.Shape,[o]),t.exports=o},function(t,e,n){var r=n(248),i=n(26),o=function(){};i.augment(o,{findByClass:function(t){var e=[];return this.deepEach((function(n){n.hasClass(t)&&e.push(n)})),e},hasClass:function(t){var e=this.get("class");return!(!e||-1===e.indexOf(t))},deepEach:function(t,e){i.traverseTree(this,t,(function(t){return t.get("children")}),e)},sort:function(){var t=this.get("children");this.set("children",i.radixSort(t,(function(t){return t.get("zIndex")})))},sortBy:function(t){var e=this.get("children");this.set("children",i.radixSort(e,t))},clear:function(t){for(var e=this._cfg.children,n=e.length-1;n>=0;n--)e[n].remove(t);return this._cfg.children=[],this}}),i.mixin(r.Group,[o]),t.exports=o},function(t,e,n){n(258).registerGuide("common",{draw:function(){console.warn("do not have this guide, please register one")}})},function(t,e,n){t.exports={common:n(716)}},function(t,e,n){function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var i=n(258),o=n(26),a=n(247);i.registerGroup("common",{draw:function(t){return t.getModel().collapsed?this.drawCollapsed(t):this.drawExpanded(t)},defaultWidth:184,defaultHeight:40,getLabel:function(t){return t.getModel().label},drawLabel:function(t,e,n){var r=this.getLabel(t);if(r){var i=t.getGraphicGroup(),s=[8,8];e+=s[0],n+=s[1];var c=t.getModel(),u=c.labelOffsetX,h=c.labelOffsetY,l=c.labelRotate;e=u?u+e:e,n=h?h+n:n;var d=o.mix(!0,{},a.labelStyle,{x:e,y:n,textAlign:"left",textBaseline:"top"});o.isObject(r)?o.mix(d,r):d.text=r;var f=i.addShape("text",{class:"label",attrs:d});if(l){var g=f.getBBox(),p=(g.maxX+g.minX)/2,m=(g.maxY+g.minY)/2;f.transform([["t",-p,-m],["r",l,l],["t",p,m]])}}},drawKeyShape:function(t,e){var n=e.x,r=e.y,i=e.width,s=e.height,c=t.getModel(),u=t.getGraphicGroup(),h=o.mix({},a.groupStyle,c.style),l=o.getRectPath(n,r,i,s,h.radius);return t.lastChildrenBox=e,u.addShape("path",{attrs:o.mix({},h,{path:l})})},getChildrenBBox:function(t){var e=function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},i=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(i=i.concat(Object.getOwnPropertySymbols(n).filter((function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable})))),i.forEach((function(e){r(t,e,n[e])}))}return t}({},t.lastChildrenBox),n=t.getModel();if(t.getChildren().length>0){var i=t.getChildrenBBox();e.x=i.minX-a.groupBackgroundPadding[3],e.y=i.minY-a.groupBackgroundPadding[0],e.width=i.maxX-i.minX+a.groupBackgroundPadding[3]+a.groupBackgroundPadding[1],e.height=i.maxY-i.minY+a.groupBackgroundPadding[0]+a.groupBackgroundPadding[2]}else e.width=this.defaultWidth,e.height=this.defaultHeight;return o.isNil(e.x)&&!o.isNil(n.x)&&(e.x=n.x),o.isNil(e.y)&&!o.isNil(n.y)&&(e.y=n.y),e},drawExpanded:function(t){var e=this.getChildrenBBox(t),n=this.drawKeyShape(t,e);return this.drawLabel(t,e.x,e.y),n},drawCollapsed:function(t){var e=this.getChildrenBBox(t);e.width=this.defaultWidth,e.height=this.defaultHeight;var n=this.drawKeyShape(t,e);return this.drawLabel(t,e.x,e.y),n},anchor:{intersectBox:"rect"}})},function(t,e,n){t.exports={common:n(718)}},function(t,e,n){function r(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter((function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable})))),r.forEach((function(e){i(t,e,n[e])}))}return t}function i(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var o=n(258),a=n(26),s=n(247),c={path:function(t){var e=t.getKeyShape().attr("lineWidth"),n=10*(e=e>3?e:3)/3,r=4*e/3,i=4*e;return[["M",-n,r],["L",0,0],["L",-n,-r],["A",i,i,0,0,1,-n,r],["Z"]]},shorten:function(t){var e=t.getKeyShape().attr("lineWidth");return 3.1*(e>3?e:3)},style:function(t){var e=t.getKeyShape().attr();return{fillOpacity:e.strokeOpacity,fill:e.stroke}}};o.registerEdge("common",{draw:function(t){var e=this.drawKeyShape(t);return this.drawLabel(t,e),e},drawKeyShape:function(t){var e=t.getGraphicGroup(),n=this.getStyle(t),r=this.getPath(t);return e.addShape("path",{attrs:a.mix({},n,{path:r})})},getStyle:function(t){var e=t.getModel();return a.mix(!0,{},{stroke:e.color||"#A3B1BF",strokeOpacity:.92,lineAppendWidth:4,lineWidth:e.size||1},e.style)},getPath:function(t){var e=t.getPoints();return a.pointsToPolygon(e)},getLabel:function(t){return t.getModel().label},getDefaultLabelRectStyle:function(){return{fill:"white"}},getDefaultLabelRectPadding:function(){return a.toAllPadding([4,8])},drawLabel:function(t,e){var n=this.getLabel(t),r=t.getGraphicGroup(),i=t.getModel(),o=i.labelOffsetX,c=i.labelOffsetY,u=i.labelRotate;if(n){var h=e.getPoint(.5);if(!h)return;h.x=o?h.x+o:h.x,h.y=c?h.y+c:h.y;var l=a.mix(!0,{},s.labelStyle,h);a.isObject(n)?a.mix(l,n):l.text=n,n=r.addShape("text",{class:"label",attrs:l});var d=this.getDefaultLabelRectPadding(t),f=this.getDefaultLabelRectStyle(t),g=n.getBBox(),p=i.labelRectStyle?a.mix({},f,i.labelRectStyle):f,m=r.addShape("rect",{attrs:a.mix({},p,{x:g.minX-d[3],y:g.minY-d[0],width:g.maxX-g.minX+d[1]+d[3],height:g.maxY-g.minY+d[0]+d[2]})});if(u){var v=(g.maxX+g.minX)/2,x=(g.maxY+g.minY)/2;n.transform([["t",-v,-x],["r",u,u],["t",v,x]]),m.transform([["t",-v,-x],["r",u,u],["t",v,x]])}a.toFront(n)}},startArrow:r({},c,{tangent:function(t){return t.getKeyShape().getStartTangent()},ratio:function(){return 0}}),endArrow:r({},c,{tangent:function(t){return t.getKeyShape().getEndTangent()},ratio:function(){return 1}})})},function(t,e,n){t.exports={common:n(720)}},function(t,e,n){var r=n(258),i=n(26);r.registerNode("html",{getHtml:function(t){return t.getModel().html},cssSize:!0,draw:function(t){var e=i.createDOM('<div class="g6-html-node-container"></div>'),n=t.getGraphicGroup(),r=t.getGraph();if("svg"!==r.get("renderer"))throw new Error("please use svg renderer draw html element !");var o=r.getGraphContainer(),a=this.getSize(t),s=this.getStyle(t),c=this.cssSize,u=this.getHtml(t);u=i.createDOM(u),e.css({position:"absolute",padding:"0px",margin:"0px"}),e.appendChild(u),o.appendChild(e),c&&(a[0]=e.width(),a[1]=e.height());var h=-a[0]/2,l=-a[1]/2,d=a[0],f=a[1],g=n.addShape("rect",{attrs:i.mix({},s,{x:h,y:l,width:d,height:f})});return n.addShape("dom",{attrs:i.mix({x:h,y:l,width:d,height:f,html:e})}),g}})},function(t,e,n){var r=n(258),i=n(26),o=n(247);r.registerNode("common",{draw:function(t){var e=t.getGraphicGroup(),n=this.drawLabel(t),r=this.drawKeyShape(t);return n&&i.toFront(n,e),r},getSize:function(t){var e=t.getModel().size;return i.isArray(e)?e:i.isNumber(e)?[e,e]:[o.defaultNodeSize,o.defaultNodeSize]},getStyle:function(t){var e=t.getModel();return i.mix(!0,{lineWidth:1,fill:e.color||"#40a9ff",stroke:e.color||"#096dd9",fillOpacity:.92},e.style)},getLabel:function(t){return t.getModel().label},drawKeyShape:function(t){var e=t.getGraphicGroup(),n=this.getStyle(t),r=this.getPath(t);return e.addShape("path",{attrs:i.mix({},n,{path:r})})},drawLabel:function(t){var e=t.getGraphicGroup(),n=this.getLabel(t),r=t.getModel(),a=r.labelOffsetX,s=r.labelOffsetY,c=r.labelRotate;if(!i.isNil(n)){var u=i.mix(!0,{},o.labelStyle,{x:a||0,y:s||0});i.isObject(n)?i.mix(u,n):u.text=n;var h=e.addShape("text",{class:"label",attrs:u});return c&&h.rotate(c),h}},getPath:function(t){var e=this.getSize(t);return i.getEllipsePath(0,0,e[0]/2,e[1]/2)}})},function(t,e,n){t.exports={common:n(723),html:n(722)}},function(t,e,n){var r=n(682),i=n(257),o={getAutoZoomMatrix:function(t,e,n,i){var o=[1,0,0,0,1,0,0,0,1],a=t.maxX-t.minX,s=t.maxY-t.minY,c=(e.maxX+e.minX)/2,u=(e.maxY+e.minY)/2,h=a-n[1]-n[3],l=s-n[0]-n[2],d=e.maxX-e.minX,f=e.maxY-e.minY,g=Math.min(l/f,h/d);return i&&(g=i(g)),r.mat3.translate(o,o,[-c,-u]),r.mat3.scale(o,o,[g,g]),r.mat3.translate(o,o,[a/2,s/2]),o},getNineBoxPosition:function(t,e,n,r,i){var o={};switch(t){case"tl":o.y=e.x+i[0],o.x=e.y+i[3];break;case"lc":o.y=(e.height-r)/2,o.x=i[3];break;case"bl":o.y=e.height-r-i[2],o.x=i[3];break;case"cc":o.y=(e.height-r)/2,o.x=(e.width-n)/2;break;case"tc":o.y=i[0],o.x=(e.width-n)/2;break;case"tr":o.y=i[0],o.x=e.width-n-i[1];break;case"rc":o.y=(e.height-r)/2,o.x=e.width-n-i[1];break;case"br":o.y=e.height-r-i[2],o.x=e.width-n-i[1];break;case"bc":o.y=e.height-r-i[2],o.x=(e.width-n)/2;break;default:o.y=e.x+i[0],o.x=e.y+i[3]}return o.x+=e.x,o.y+=e.y,o},getTotalBBox:function(t){var e=1/0,n=-1/0,r=1/0,i=-1/0;return t.forEach((function(t){t.minX<e&&(e=t.minX),t.maxX>n&&(n=t.maxX),t.minY<r&&(r=t.minY),t.maxY>i&&(i=t.maxY)})),{minX:e,minY:r,maxX:n,maxY:i,width:n-e,height:i-r}},getChildrenBBox:function(t){var e=1/0,n=-1/0,r=1/0,a=-1/0;i.each(t,(function(t){var i=t.isGroup?o.getChildrenBBox(t.get("children")):t.getBBox();if(!i)return!0;var s=[i.minX,i.minY,1],c=[i.minX,i.maxY,1],u=[i.maxX,i.minY,1],h=[i.maxX,i.maxY,1];t.apply(s),t.apply(c),t.apply(u),t.apply(h);var l=Math.min(s[0],c[0],u[0],h[0]),d=Math.max(s[0],c[0],u[0],h[0]),f=Math.min(s[1],c[1],u[1],h[1]),g=Math.max(s[1],c[1],u[1],h[1]);l<e&&(e=l),d>n&&(n=d),f<r&&(r=f),g>a&&(a=g)}));var s={minX:e,minY:r,maxX:n,maxY:a};return s.x=s.minX,s.y=s.minY,s.width=s.maxX-s.minX,s.height=s.maxY-s.minY,s.centerX=(s.minX+s.maxX)/2,s.centerY=(s.minY+s.maxY)/2,s},getBBox:function(t,e){var n,i=t.getBBox(),o={x:i.minX,y:i.minY},a={x:i.maxX,y:i.maxY};if(e.isGroup){for(n=t;n!==e;){var s=n.getMatrix();o=r.applyMatrix(o,s),a=r.applyMatrix(a,s),n=n.getParent()}var c=n.getMatrix();o=r.applyMatrix(o,c),a=r.applyMatrix(a,c)}else o=r.applyMatrix(o,e),a=r.applyMatrix(a,e);return{minX:o.x,minY:o.y,maxX:a.x,maxY:a.y}},toBack:function(t){t.toBack()},toFront:function(t){t.toFront()}};t.exports=o},function(t,e,n){var r=n(257);t.exports={isNode:function(t){return t&&r.isObject(t)&&"node"===t.type},isEdge:function(t){return t&&r.isObject(t)&&"edge"===t.type},isGroup:function(t){return t&&r.isObject(t)&&"group"===t.type}}},function(t,e,n){var r=n(257),i={};r.mix(i,{addEventListener:function(t,e,n){return t.attachEvent?(t.attachEvent("on"+e,n),{remove:function(){t.detachEvent("on"+e,n)}}):t.addEventListener?(t.addEventListener(e,n,!1),{remove:function(){t.removeEventListener(e,n,!1)}}):void 0},createDOM:function(t,e){var n;return(n=r.isString(t)?r.createDom(t):t).bbox=n.getBoundingClientRect(),n.hide=function(){return n.style.visibility="hidden",n},n.show=function(){return n.style.visibility="visible",n},n.css=function(t){return r.modifyCSS(n,t),n},n.width=function(){return r.getWidth(n)},n.height=function(){return r.getHeight(n)},n.destroy=function(){n.parentNode&&n.parentNode.removeChild(n)},n.on=function(t,e){n.addEventListener(t,e)},n.off=function(t,e){n.removeEventListener(t,e)},n.css(e),n},initDOMContainer:function(t,e){if(!t)throw new Error("please set the container for the "+e+" !");return r.isString(t)&&(t=document.getElementById(t)),t}}),t.exports=i},function(t,e){var n={svg:"svg",circle:"circle",rect:"rect",text:"text",path:"path",foreignObject:"foreignObject",polygon:"polygon",ellipse:"ellipse",image:"image"};t.exports=function(t,e,r){var i=r.target||r.srcElement;if(!n[i.tagName]){for(var o=i.parentNode;o&&!n[o.tagName];)o=o.parentNode;i=o}return this._cfg.el===i?this:this.find((function(t){return t._cfg&&t._cfg.el===i}))}},function(t,e,n){var r=n(19),i=/^p\s*\(\s*([axyn])\s*\)\s*(.*)/i,o=function(){function t(t){var e=document.createElementNS("http://www.w3.org/2000/svg","pattern");e.setAttribute("patternUnits","userSpaceOnUse");var n=document.createElementNS("http://www.w3.org/2000/svg","image");e.appendChild(n);var o=r.uniqueId("pattern_");e.id=o,this.el=e,this.id=o,this.cfg=t;var a=i.exec(t)[2];n.setAttribute("href",a);var s=new Image;function c(){console.log(s.width,s.height),e.setAttribute("width",s.width),e.setAttribute("height",s.height)}return a.match(/^data:/i)||(s.crossOrigin="Anonymous"),s.src=a,s.complete?c():(s.onload=c,s.src=s.src),this}return t.prototype.match=function(t,e){return this.cfg===e},t}();t.exports=o},function(t,e,n){var r=n(19),i=function(){function t(t){this.type="clip";var e=document.createElementNS("http://www.w3.org/2000/svg","clipPath");this.el=e,this.id=r.uniqueId("clip_"),e.id=this.id;var n=t._cfg.el;return e.appendChild(n.cloneNode(!0)),this.cfg=t,this}var e=t.prototype;return e.match=function(){return!1},e.remove=function(){var t=this.el;t.parentNode.removeChild(t)},t}();t.exports=i},function(t,e,n){var r=n(19),i=function(){function t(t,e){var n=document.createElementNS("http://www.w3.org/2000/svg","marker"),i=r.uniqueId("marker_");n.setAttribute("id",i);var o=document.createElementNS("http://www.w3.org/2000/svg","path");return o.setAttribute("stroke","none"),o.setAttribute("fill",t.stroke||"#000"),n.appendChild(o),n.setAttribute("overflow","visible"),n.setAttribute("orient","auto-start-reverse"),this.el=n,this.child=o,this.id=i,this.cfg=t["marker-start"===e?"startArrow":"endArrow"],this.stroke=t.stroke||"#000",!0===this.cfg?this._setDefaultPath(e,o):this._setMarker(t.lineWidth,o),this}var e=t.prototype;return e.match=function(){return!1},e._setDefaultPath=function(t,e){var n=this.el;e.setAttribute("d","M0,0 L6,3 L0,6 L3,3Z"),n.setAttribute("refX",3),n.setAttribute("refY",3)},e._setMarker=function(t,e){var n=this.el,i=this.cfg.path,o=this.cfg.d;r.isArray(i)&&(i=i.map((function(t){return t.join(" ")})).join("")),e.setAttribute("d",i),n.appendChild(e),o&&n.setAttribute("refX",o/t)},e.update=function(t){var e=this.child;e.attr?e.attr("fill",t):e.setAttribute("fill",t)},t}();t.exports=i},function(t,e,n){var r=n(19),i={shadowColor:"color",shadowOpacity:"opacity",shadowBlur:"blur",shadowOffsetX:"dx",shadowOffsetY:"dy"},o={x:"-40%",y:"-40%",width:"200%",height:"200%"},a=function(){function t(t){this.type="filter";var e=document.createElementNS("http://www.w3.org/2000/svg","filter");return r.each(o,(function(t,n){e.setAttribute(n,t)})),this.el=e,this.id=r.uniqueId("filter_"),this.el.id=this.id,this.cfg=t,this._parseShadow(t,e),this}var e=t.prototype;return e.match=function(t,e){if(this.type!==t)return!1;var n=!0,i=this.cfg;return r.each(Object.keys(i),(function(t){if(i[t]!==e[t])return n=!1,!1})),n},e.update=function(t,e){var n=this.cfg;return n[i[t]]=e,this._parseShadow(n,this.el),this},e._parseShadow=function(t,e){var n='<feDropShadow \n dx="'+(t.dx||0)+'" \n dy="'+(t.dy||0)+'" \n stdDeviation="'+(t.blur?t.blur/10:0)+'"\n flood-color="'+(t.color?t.color:"#000")+'"\n flood-opacity="'+(t.opacity?t.opacity:1)+'"\n />';e.innerHTML=n},t}();t.exports=a},function(t,e,n){var r=n(19),i=/^l\s*\(\s*([\d.]+)\s*\)\s*(.*)/i,o=/^r\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)\s*(.*)/i,a=/[\d.]+:(#[^\s]+|[^\)]+\))/gi;function s(t){var e=t.match(a);if(!e)return"";var n="";return e.sort((function(t,e){return t=t.split(":"),e=e.split(":"),Number(t[0])-Number(e[0])})),r.each(e,(function(t){t=t.split(":"),n+='<stop offset="'+t[0]+'" stop-color="'+t[1]+'"></stop>'})),n}var c=function(){function t(t){var e=null,n=r.uniqueId("gradient_");return"l"===t.toLowerCase()[0]?function(t,e){var n,o,a=i.exec(t),c=r.mod(r.toRadian(parseFloat(a[1])),2*Math.PI),u=a[2];c>=0&&c<.5*Math.PI?(n={x:0,y:0},o={x:1,y:1}):.5*Math.PI<=c&&c<Math.PI?(n={x:1,y:0},o={x:0,y:1}):Math.PI<=c&&c<1.5*Math.PI?(n={x:1,y:1},o={x:0,y:0}):(n={x:0,y:1},o={x:1,y:0});var h=Math.tan(c),l=h*h,d=(o.x-n.x+h*(o.y-n.y))/(l+1)+n.x,f=h*(o.x-n.x+h*(o.y-n.y))/(l+1)+n.y;e.setAttribute("x1",n.x),e.setAttribute("y1",n.y),e.setAttribute("x2",d),e.setAttribute("y2",f),e.innerHTML=s(u)}(t,e=document.createElementNS("http://www.w3.org/2000/svg","linearGradient")):function(t,e){var n=o.exec(t),r=parseFloat(n[1]),i=parseFloat(n[2]),a=parseFloat(n[3]),c=n[4];e.setAttribute("cx",r),e.setAttribute("cy",i),e.setAttribute("r",a),e.innerHTML=s(c)}(t,e=document.createElementNS("http://www.w3.org/2000/svg","radialGradient")),e.setAttribute("id",n),this.el=e,this.id=n,this.cfg=t,this}return t.prototype.match=function(t,e){return this.cfg===e},t}();t.exports=c},function(t,e,n){var r=n(19),i=n(733),o=n(732),a=n(731),s=n(730),c=n(729),u=function(){function t(t){var e=document.createElementNS("http://www.w3.org/2000/svg","defs"),n=r.uniqueId("defs_");e.id=n,t.appendChild(e),this.children=[],this.defaultArrow={},this.el=e,this.canvas=t}var e=t.prototype;return e.find=function(t,e){for(var n=this.children,r=null,i=0;i<n.length;i++)if(n[i].match(t,e)){r=n[i].id;break}return r},e.findById=function(t){for(var e=this.children,n=null,r=0;r<e.length;r++)if(e[r].id===t){n=e[r];break}return n},e.add=function(t){this.children.push(t),t.canvas=this.canvas,t.parent=this},e.getDefaultArrow=function(t,e){var n=t.stroke||t.strokeStyle;if(this.defaultArrow[n])return this.defaultArrow[n].id;var r=new a(t,e);return this.defaultArrow[n]=r,this.el.appendChild(r.el),r.id},e.addGradient=function(t){var e=new i(t);return this.el.appendChild(e.el),this.add(e),e.id},e.addArrow=function(t,e){var n=new a(t,e);return this.el.appendChild(n.el),n.id},e.addShadow=function(t){var e=new o(t);return this.el.appendChild(e.el),this.add(e),e.id},e.addPattern=function(t){var e=new c(t);return this.el.appendChild(e.el),this.add(e),e.id},e.addClip=function(t){var e=new s(t);return this.el.appendChild(e.el),this.add(e),e.id},t}();t.exports=u},function(t,e,n){var r=n(19),i=n(593).parseRadius,o=n(611),a=n(734),s={rect:"path",circle:"circle",line:"line",path:"path",marker:"path",text:"text",polygon:"polygon",image:"image",ellipse:"ellipse",dom:"foreignObject",fan:"path",group:"g"},c={opacity:"opacity",fillStyle:"fill",strokeOpacity:"stroke-opacity",fillOpacity:"fill-opacity",strokeStyle:"stroke",x:"x",y:"y",r:"r",width:"width",height:"height",x1:"x1",x2:"x2",y1:"y1",y2:"y2",lineCap:"stroke-linecap",lineJoin:"stroke-linejoin",lineWidth:"stroke-width",lineDash:"stroke-dasharray",lineDashOffset:"stroke-dashoffset",miterLimit:"stroke-miterlimit",font:"font",fontSize:"font-size",fontStyle:"font-style",fontVariant:"font-variant",fontWeight:"font-weight",fontFamily:"font-family",startArrow:"marker-start",endArrow:"marker-end",path:"d",class:"class",id:"id",style:"style",preserveAspectRatio:"preserveAspectRatio"},u={top:"before-edge",middle:"central",bottom:"after-edge",alphabetic:"baseline",hanging:"hanging"},h={left:"left",start:"left",center:"middle",right:"end",end:"end"},l=function(){function t(t){if(!t)return null;var e=r.uniqueId("canvas_"),n=r.createDom('<svg id="'+e+'"></svg>');return t.appendChild(n),this.type="svg",this.canvas=n,this.context=new a(n),this.toDraw=!1,this}var e=t.prototype;return e.draw=function(t){var e=this;e.animateHandler?e.toDraw=!0:function n(){e.animateHandler=r.requestAnimationFrame((function(){e.animateHandler=void 0,e.toDraw&&n()}));try{e._drawChildren(t)}catch(t){console.warn("error in draw canvas, detail as:"),console.warn(t),e.toDraw=!1}e.toDraw=!1}()},e.drawSync=function(t){this._drawChildren(t)},e._drawGroup=function(t,e){var n=t._cfg;n.removed||n.destroyed||(n.tobeRemoved&&(r.each(n.tobeRemoved,(function(t){t.parentNode&&t.parentNode.removeChild(t)})),n.tobeRemoved=[]),this._drawShape(t,e),n.children&&n.children.length>0&&this._drawChildren(t))},e._drawChildren=function(t){var e,n=t._cfg.children;if(n)for(var r=0;r<n.length;r++)(e=n[r]).isGroup?this._drawGroup(e,r):this._drawShape(e,r)},e._drawShape=function(t,e){var n=t._attrs,r=t._cfg,i=r.el;r.removed||r.destroyed?i&&i.parentNode.removeChild(r.el):(!i&&r.parent&&(this._createDom(t,e),this._updateShape(t)),i=r.el,!1!==r.visible?(r.visible&&i.hasAttribute("visibility")&&i.removeAttribute("visibility"),r.hasUpdate&&this._updateShape(t),n.clip&&n.clip._cfg.hasUpdate&&this._updateShape(n.clip)):i.setAttribute("visibility","hidden"))},e._updateShape=function(t){var e=t._attrs,n=t._cfg.attrs;if(n)if(t._cfg.el||this._createDom(t),"clip"in e&&this._setClip(t,e.clip),("shadowOffsetX"in e||"shadowOffsetY"in e||"shadowBlur"in e||"shadowColor"in e)&&this._setShadow(t),"text"!==t.type){for(var i in"fan"===t.type&&this._updateFan(t),"marker"===t.type&&t._cfg.el.setAttribute("d",this._assembleMarker(e)),"rect"===t.type&&t._cfg.el.setAttribute("d",this._assembleRect(e)),e)e[i]!==n[i]&&this._setAttribute(t,i,e[i]);t._cfg.attrs=r.deepMix({},t._attrs),t._cfg.hasUpdate=!1}else this._updateText(t)},e._setAttribute=function(t,e,n){var i=t.type,o=t._attrs,a=t._cfg.el,s=this.context;if("marker"!==i&&"rect"!==i||!~["x","y","radius","r"].indexOf(e))if(~["circle","ellipse"].indexOf(i)&&~["x","y"].indexOf(e))a.setAttribute("c"+e,parseInt(n,10));else{if("polygon"===i&&"points"===e)return n&&0!==n.length||(n=""),r.isArray(n)&&(n=(n=n.map((function(t){return t[0]+","+t[1]}))).join(" ")),void a.setAttribute("points",n);if("path"===e&&r.isArray(n))a.setAttribute("d",this._formatPath(n));else if("img"!==e){if("transform"===e)return n?void this._setTransform(t):void a.removeAttribute("transform");if("rotate"===e)return n?void this._setTransform(t):void a.removeAttribute("transform");if("matrix"!==e)if("fillStyle"!==e&&"strokeStyle"!==e){if("clip"!==e)if(~e.indexOf("Arrow"))if(e=c[e],n){var u;u="boolean"==typeof n?s.getDefaultArrow(o,e):s.addArrow(o,e),a.setAttribute(e,"url(#"+u+")"),t._cfg[e]=u}else t._cfg[e]=null,a.removeAttribute(e);else"html"===e&&("string"==typeof n?a.innerHTML=n:(a.innerHTML="",a.appendChild(n))),c[e]&&a.setAttribute(c[e],n)}else this._setColor(t,e,n);else this._setTransform(t)}else this._setImage(t,n)}},e._createDom=function(t,e){var n=s[t.type],r=t._attrs,i=t._cfg.parent,o=i._cfg.el;if(!n)throw new Error("the type"+t.type+"is not supported by svg");var a=document.createElementNS("http://www.w3.org/2000/svg",n);if(t._cfg.el=a,i)if(void 0===e)o.appendChild(a);else{var c=i._cfg.el.childNodes;"svg"===o.tagName&&(e+=1),c.length<=e?o.appendChild(a):o.insertBefore(a,c[e])}return t._cfg.attrs={},"text"===t.type?(a.setAttribute("paint-order","stroke"),a.setAttribute("style","stroke-linecap:butt; stroke-linejoin:miter;")):(r.stroke||r.strokeStyle||a.setAttribute("stroke","none"),r.fill||r.fillStyle||a.setAttribute("fill","none")),a},e._assembleMarker=function(t){var e=t.r;if(void 0===t.r&&(e=t.radius),isNaN(Number(t.x))||isNaN(Number(t.y))||isNaN(Number(e)))return"";var n="";return n="function"==typeof t.symbol?t.symbol(t.x,t.y,e):o.Symbols[t.symbol||"circle"](t.x,t.y,e),r.isArray(n)&&(n=n.map((function(t){return t.join(" ")})).join("")),n},e._assembleRect=function(t){var e=t.x,n=t.y,o=t.width,a=t.height,s=t.radius;if(!s)return"M "+e+","+n+" l "+o+",0 l 0,"+a+" l"+-o+" 0 z";var c=i(s);return r.isArray(s)?1===s.length?c.r1=c.r2=c.r3=c.r4=s[0]:2===s.length?(c.r1=c.r3=s[0],c.r2=c.r4=s[1]):3===s.length?(c.r1=s[0],c.r2=c.r4=s[1],c.r3=s[2]):(c.r1=s[0],c.r2=s[1],c.r3=s[2],c.r4=s[3]):c.r1=c.r2=c.r3=c.r4=s,[["M "+(e+c.r1)+","+n],["l "+(o-c.r1-c.r2)+",0"],["a "+c.r2+","+c.r2+",0,0,1,"+c.r2+","+c.r2],["l 0,"+(a-c.r2-c.r3)],["a "+c.r3+","+c.r3+",0,0,1,"+-c.r3+","+c.r3],["l "+(c.r3+c.r4-o)+",0"],["a "+c.r4+","+c.r4+",0,0,1,"+-c.r4+","+-c.r4],["l 0,"+(c.r4+c.r1-a)],["a "+c.r1+","+c.r1+",0,0,1,"+c.r1+","+-c.r1],["z"]].join(" ")},e._formatPath=function(t){return~(t=t.map((function(t){return t.join(" ")})).join("")).indexOf("NaN")?"":t},e._setTransform=function(t){for(var e=t._attrs.matrix,n=t._cfg.el,r=[],i=0;i<9;i+=3)r.push(e[i]+","+e[i+1]);-1===(r=r.join(",")).indexOf("NaN")?n.setAttribute("transform","matrix("+r+")"):console.warn("invalid matrix:",e)},e._setImage=function(t,e){var n=t._attrs,i=t._cfg.el;if(r.isString(e))i.setAttribute("href",e);else if(e instanceof Image)n.width||(i.setAttribute("width",e.width),t._attrs.width=e.width),n.height||(i.setAttribute("height",e.height),t._attrs.height=e.height),i.setAttribute("href",e.src);else if(e instanceof HTMLElement&&r.isString(e.nodeName)&&"CANVAS"===e.nodeName.toUpperCase())i.setAttribute("href",e.toDataURL());else if(e instanceof ImageData){var o=document.createElement("canvas");o.setAttribute("width",e.width),o.setAttribute("height",e.height),o.getContext("2d").putImageData(e,0,0),n.width||(i.setAttribute("width",e.width),t._attrs.width=e.width),n.height||(i.setAttribute("height",e.height),t._attrs.height=e.height),i.setAttribute("href",o.toDataURL())}},e._updateFan=function(t){function e(t,e,n){return{x:e*Math.cos(t)+n.x,y:e*Math.sin(t)+n.y}}var n=t._attrs,i=t._cfg,o={x:n.x,y:n.y},a=[],s=n.startAngle,c=n.endAngle;r.isNumberEqual(c-s,2*Math.PI)&&(c-=1e-5);var u=e(s,n.re,o),h=e(c,n.re,o),l=c>s?1:0,d=Math.abs(c-s)>Math.PI?1:0,f=n.rs,g=n.re,p=e(s,n.rs,o),m=e(c,n.rs,o);n.rs>0?(a.push("M "+h.x+","+h.y),a.push("L "+m.x+","+m.y),a.push("A "+f+","+f+",0,"+d+","+(1===l?0:1)+","+p.x+","+p.y),a.push("L "+u.x+" "+u.y)):(a.push("M "+o.x+","+o.y),a.push("L "+u.x+","+u.y)),a.push("A "+g+","+g+",0,"+d+","+l+","+h.x+","+h.y),n.rs>0?a.push("L "+m.x+","+m.y):a.push("Z"),i.el.setAttribute("d",a.join(" "))},e._updateText=function(t){var e=t._attrs,n=t._cfg.attrs,r=t._cfg.el;for(var i in this._setFont(t),e)if(e[i]!==n[i]){if("text"===i){this._setText(t,""+e[i]);continue}if("fillStyle"===i||"strokeStyle"===i){this._setColor(t,i,e[i]);continue}if("matrix"===i){this._setTransform(t);continue}c[i]&&r.setAttribute(c[i],e[i])}t._cfg.attrs=Object.assign({},t._attrs),t._cfg.hasUpdate=!1},e._setFont=function(t){var e=t.get("el"),n=t._attrs,r=n.fontSize;e.setAttribute("alignment-baseline",u[n.textBaseline]||"baseline"),e.setAttribute("text-anchor",h[n.textAlign]||"left"),r&&+r<12&&(n.matrix=[1,0,0,0,1,0,0,0,1],t.transform([["t",-n.x,-n.y],["s",+r/12,+r/12],["t",n.x,n.y]]))},e._setText=function(t,e){var n=t._cfg.el,i=t._attrs.textBaseline||"bottom";if(e)if(~e.indexOf("\n")){var o=t._attrs.x,a=e.split("\n"),s=a.length-1,c="";r.each(a,(function(t,e){0===e?"alphabetic"===i?c+='<tspan x="'+o+'" dy="'+-s+'em">'+t+"</tspan>":"top"===i?c+='<tspan x="'+o+'" dy="0.9em">'+t+"</tspan>":"middle"===i?c+='<tspan x="'+o+'" dy="'+-(s-1)/2+'em">'+t+"</tspan>":"bottom"===i?c+='<tspan x="'+o+'" dy="-'+(s+.3)+'em">'+t+"</tspan>":"hanging"===i&&(c+='<tspan x="'+o+'" dy="'+(-(s-1)-.3)+'em">'+t+"</tspan>"):c+='<tspan x="'+o+'" dy="1em">'+t+"</tspan>"})),n.innerHTML=c}else n.innerHTML=e;else n.innerHTML=""},e._setClip=function(t,e){var n=t._cfg.el;if(e)if(n.hasAttribute("clip-path"))e._cfg.hasUpdate&&this._updateShape(e);else{this._createDom(e),this._updateShape(e);var r=this.context.addClip(e);n.setAttribute("clip-path","url(#"+r+")")}else n.removeAttribute("clip-path")},e._setColor=function(t,e,n){var r=t._cfg.el,i=this.context;if(n)if(n=n.trim(),/^[r,R,L,l]{1}[\s]*\(/.test(n)){var o=i.find("gradient",n);o||(o=i.addGradient(n)),r.setAttribute(c[e],"url(#"+o+")")}else if(/^[p,P]{1}[\s]*\(/.test(n)){var a=i.find("pattern",n);a||(a=i.addPattern(n)),r.setAttribute(c[e],"url(#"+a+")")}else r.setAttribute(c[e],n);else r.setAttribute(c[e],"none")},e._setShadow=function(t){var e=t._cfg.el,n=t._attrs,r={dx:n.shadowOffsetX,dy:n.shadowOffsetY,blur:n.shadowBlur,color:n.shadowColor};if(r.dx||r.dy||r.blur||r.color){var i=this.context.find("filter",r);i||(i=this.context.addShadow(r,this)),e.setAttribute("filter","url(#"+i+")")}else e.removeAttribute("filter")},t}();t.exports=l},function(t,e,n){t.exports={painter:n(735),getShape:n(728)}},function(t,e,n){var r=n(19),i=/[MLHVQTCSAZ]([^MLHVQTCSAZ]*)/gi,o=/[^\s\,]+/gi,a=/^l\s*\(\s*([\d.]+)\s*\)\s*(.*)/i,s=/^r\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)\s*(.*)/i,c=/^p\s*\(\s*([axyn])\s*\)\s*(.*)/i,u=/[\d.]+:(#[^\s]+|[^\)]+\))/gi;function h(t,e){var n=t.match(u);r.each(n,(function(t){t=t.split(":"),e.addColorStop(t[0],t[1])}))}t.exports={parsePath:function(t){return t=t||[],r.isArray(t)?t:r.isString(t)?(t=t.match(i),r.each(t,(function(e,n){if((e=e.match(o))[0].length>1){var i=e[0].charAt(0);e.splice(1,0,e[0].substr(1)),e[0]=i}r.each(e,(function(t,n){isNaN(t)||(e[n]=+t)})),t[n]=e})),t):void 0},parseStyle:function(t,e,n){if(r.isString(t)){if("("===t[1]||"("===t[2]){if("l"===t[0])return function(t,e,n){var i,o,s=a.exec(t),c=r.mod(r.toRadian(parseFloat(s[1])),2*Math.PI),u=s[2],l=e.getBBox();c>=0&&c<.5*Math.PI?(i={x:l.minX,y:l.minY},o={x:l.maxX,y:l.maxY}):.5*Math.PI<=c&&c<Math.PI?(i={x:l.maxX,y:l.minY},o={x:l.minX,y:l.maxY}):Math.PI<=c&&c<1.5*Math.PI?(i={x:l.maxX,y:l.maxY},o={x:l.minX,y:l.minY}):(i={x:l.minX,y:l.maxY},o={x:l.maxX,y:l.minY});var d=Math.tan(c),f=d*d,g=(o.x-i.x+d*(o.y-i.y))/(f+1)+i.x,p=d*(o.x-i.x+d*(o.y-i.y))/(f+1)+i.y,m=n.createLinearGradient(i.x,i.y,g,p);return h(u,m),m}(t,e,n);if("r"===t[0])return function(t,e,n){var r=s.exec(t),i=parseFloat(r[1]),o=parseFloat(r[2]),a=parseFloat(r[3]),c=r[4];if(0===a){var l=c.match(u);return l[l.length-1].split(":")[1]}var d=e.getBBox(),f=d.maxX-d.minX,g=d.maxY-d.minY,p=Math.sqrt(f*f+g*g)/2,m=n.createRadialGradient(d.minX+f*i,d.minY+g*o,a*p,d.minX+f/2,d.minY+g/2,p);return h(c,m),m}(t,e,n);if("p"===t[0])return function(t,e,n){if(e.get("patternSource")&&e.get("patternSource")===t)return e.get("pattern");var r,i,o=c.exec(t),a=o[1],s=o[2];function u(){r=n.createPattern(i,a),e.setSilent("pattern",r),e.setSilent("patternSource",t)}switch(a){case"a":a="repeat";break;case"x":a="repeat-x";break;case"y":a="repeat-y";break;case"n":a="no-repeat";break;default:a="no-repeat"}return i=new Image,s.match(/^data:/i)||(i.crossOrigin="Anonymous"),i.src=s,i.complete?u():(i.onload=u,i.src=i.src),r}(t,e,n)}return t}}}},function(t,e,n){var r=n(19),i=n(737),o=["fillStyle","font","globalAlpha","lineCap","lineWidth","lineJoin","miterLimit","shadowBlur","shadowColor","shadowOffsetX","shadowOffsetY","strokeStyle","textAlign","textBaseline","lineDash","lineDashOffset"],a=function(){function t(t){if(!t)return null;var e=r.uniqueId("canvas_"),n=r.createDom('<canvas id="'+e+'"></canvas>');return t.appendChild(n),this.type="canvas",this.canvas=n,this.context=n.getContext("2d"),this.toDraw=!1,this}var e=t.prototype;return e.beforeDraw=function(){var t=this.canvas;this.context&&this.context.clearRect(0,0,t.width,t.height)},e.draw=function(t){var e=this;e.animateHandler?e.toDraw=!0:function n(){e.animateHandler=r.requestAnimationFrame((function(){e.animateHandler=void 0,e.toDraw&&n()})),e.beforeDraw();try{e._drawGroup(t)}catch(t){console.warn("error in draw canvas, detail as:"),console.warn(t),e.toDraw=!1}e.toDraw=!1}()},e.drawSync=function(t){this.beforeDraw(),this._drawGroup(t)},e._drawGroup=function(t){if(!t._cfg.removed&&!t._cfg.destroyed&&t._cfg.visible){var e=t._cfg.children,n=null;this.setContext(t);for(var r=0;r<e.length;r++)n=e[r],e[r].isGroup?this._drawGroup(n):this._drawShape(n);this.restoreContext(t)}},e._drawShape=function(t){t._cfg.removed||t._cfg.destroyed||!t._cfg.visible||(this.setContext(t),t.drawInner(this.context),this.restoreContext(t),t._cfg.attrs=t._attrs,t._cfg.hasUpdate=!1)},e.setContext=function(t){var e=this.context,n=t._attrs.clip;e.save(),n&&(n.resetTransform(e),n.createPath(e),e.clip()),this.resetContext(t),t.resetTransform(e)},e.restoreContext=function(){this.context.restore()},e.resetContext=function(t){var e=this.context,n=t._attrs;if(!t.isGroup)for(var a in n)if(o.indexOf(a)>-1){var s=n[a];"fillStyle"===a&&(s=i.parseStyle(s,t,e)),"strokeStyle"===a&&(s=i.parseStyle(s,t,e)),"lineDash"===a&&e.setLineDash?r.isArray(s)?e.setLineDash(s):r.isString(s)&&e.setLineDash(s.split(" ")):e[a]=s}},t}();t.exports=a},function(t,e,n){t.exports={painter:n(738)}},function(t,e,n){t.exports={canvas:n(739),svg:n(736)}},function(t,e,n){var r=n(19),i=n(610),o=n(17),a=n(44),s=n(238),c=s.interpolate,u=s.interpolateArray,h=function(t){this._animators=[],this._current=0,this._timer=null,this.canvas=t};function l(t,e,n){var o,s=e.startTime;if(n<s+e.delay||e.isPaused)return!1;var h=e.duration,l=e.easing;if(n=n-s-e.delay,e.toAttrs.repeat)o=n%h/h,o=a[l](o);else{if(!((o=n/h)<1))return t.attr(e.toAttrs),e.toMatrix&&t.setMatrix(e.toMatrix),!0;o=a[l](o)}return function(t,e,n){var o={},a=e.toAttrs,s=e.fromAttrs,h=e.toMatrix;if(!t.get("destroyed")){var l;for(var d in a)if(!r.isEqual(s[d],a[d]))if("path"===d){var f=a[d],g=s[d];f.length>g.length?(f=i.parsePathString(a[d]),g=i.parsePathString(s[d]),g=i.fillPathByDiff(g,f),g=i.formatPath(g,f),e.fromAttrs.path=g,e.toAttrs.path=f):e.pathFormatted||(f=i.parsePathString(a[d]),g=i.parsePathString(s[d]),g=i.formatPath(g,f),e.fromAttrs.path=g,e.toAttrs.path=f,e.pathFormatted=!0),o[d]=[];for(var p=0;p<f.length;p++){for(var m=f[p],v=g[p],x=[],y=0;y<m.length;y++)r.isNumber(m[y])&&v&&r.isNumber(v[y])?(l=c(v[y],m[y]),x.push(l(n))):x.push(m[y]);o[d].push(x)}}else l=c(s[d],a[d]),o[d]=l(n);if(h){var b=u(e.fromMatrix,h)(n);t.setMatrix(b)}t.attr(o)}}(t,e,o),!1}r.augment(h,{initTimer:function(){var t,e,n,r=this,i=this;i._timer=o.timer((function(o){if(i._current=o,r._animators.length>0){for(var a=r._animators.length-1;a>=0;a--)if((t=r._animators[a]).get("destroyed"))i.removeAnimator(a);else{if(!t.get("pause").isPaused)for(var s=(e=t.get("animators")).length-1;s>=0;s--)n=e[s],l(t,n,o)&&(e.splice(s,1),n.callback&&n.callback());0===e.length&&i.removeAnimator(a)}r.canvas.draw()}}))},addAnimator:function(t){this._animators.push(t)},removeAnimator:function(t){this._animators.splice(t,1)},isAnimating:function(){return!!this._animators.length},stop:function(){this._timer&&this._timer.stop()},stopAllAnimations:function(){this._animators.forEach((function(t){t.stopAnimate()})),this._animators=[],this.canvas.draw()},getTime:function(){return this._current}}),t.exports=h},function(t,e,n){var r=n(19),i=n(613),o={arc:n(602),ellipse:n(639),line:n(603)},a=r.createDom('<canvas width="500" height="500"></canvas>').getContext("2d");function s(t,e,n){return n.createPath(a),a.isPointInPath(t,e)}var c={arc:function(t,e){var n=this._attrs,r=n.x,o=n.y,a=n.r,s=n.startAngle,c=n.endAngle,u=n.clockwise,h=this.getHitLineWidth();return!!this.hasStroke()&&i.arcline(r,o,a,s,c,u,h,t,e)},circle:function(t,e){var n=this._attrs,r=n.x,o=n.y,a=n.r,s=this.getHitLineWidth(),c=this.hasFill(),u=this.hasStroke();return c&&u?i.circle(r,o,a,t,e)||i.arcline(r,o,a,0,2*Math.PI,!1,s,t,e):c?i.circle(r,o,a,t,e):!!u&&i.arcline(r,o,a,0,2*Math.PI,!1,s,t,e)},dom:function(t,e){if(!this._cfg.el)return!1;var n=this._cfg.el.getBBox();return i.box(n.x,n.x+n.width,n.y,n.y+n.height,t,e)},ellipse:function(t,e){var n=this._attrs,o=this.hasFill(),a=this.hasStroke(),s=n.x,c=n.y,u=n.rx,h=n.ry,l=this.getHitLineWidth(),d=u>h?u:h,f=u>h?1:u/h,g=u>h?h/u:1,p=[t,e,1],m=[1,0,0,0,1,0,0,0,1];r.mat3.scale(m,m,[f,g]),r.mat3.translate(m,m,[s,c]);var v=r.mat3.invert([],m);return r.vec3.transformMat3(p,p,v),o&&a?i.circle(0,0,d,p[0],p[1])||i.arcline(0,0,d,0,2*Math.PI,!1,l,p[0],p[1]):o?i.circle(0,0,d,p[0],p[1]):!!a&&i.arcline(0,0,d,0,2*Math.PI,!1,l,p[0],p[1])},fan:function(t,e){var n=this,a=n.hasFill(),s=n.hasStroke(),c=n._attrs,u=c.x,h=c.y,l=c.rs,d=c.re,f=c.startAngle,g=c.endAngle,p=c.clockwise,m=[t-u,e-h],v=r.vec2.angleTo([1,0],m);function x(){var t=o.arc.nearAngle(v,f,g,p);if(r.isNumberEqual(v,t)){var e=r.vec2.squaredLength(m);if(l*l<=e&&e<=d*d)return!0}return!1}function y(){var r=n.getHitLineWidth(),o={x:Math.cos(f)*l+u,y:Math.sin(f)*l+h},a={x:Math.cos(f)*d+u,y:Math.sin(f)*d+h},s={x:Math.cos(g)*l+u,y:Math.sin(g)*l+h},c={x:Math.cos(g)*d+u,y:Math.sin(g)*d+h};return!!(i.line(o.x,o.y,a.x,a.y,r,t,e)||i.line(s.x,s.y,c.x,c.y,r,t,e)||i.arcline(u,h,l,f,g,p,r,t,e)||i.arcline(u,h,d,f,g,p,r,t,e))}return a&&s?x()||y():a?x():!!s&&y()},image:function(t,e){var n=this._attrs;if(this.get("toDraw")||!n.img)return!1;this._cfg.attrs&&this._cfg.attrs.img===n.img||this._setAttrImg();var r=n.x,o=n.y,a=n.width,s=n.height;return i.rect(r,o,a,s,t,e)},line:function(t,e){var n=this._attrs,r=n.x1,o=n.y1,a=n.x2,s=n.y2,c=this.getHitLineWidth();return!!this.hasStroke()&&i.line(r,o,a,s,c,t,e)},path:function(t,e){var n=this,i=n.get("segments"),o=n.hasFill(),a=n.hasStroke();function c(){if(!r.isEmpty(i)){for(var o=n.getHitLineWidth(),a=0,s=i.length;a<s;a++)if(i[a].isInside(t,e,o))return!0;return!1}}return o&&a?s(t,e,n)||c():o?s(t,e,n):!!a&&c()},marker:function(t,e){var n=this._attrs,r=n.x,o=n.y,a=n.radius||n.r,s=this.getHitLineWidth();return i.circle(r,o,a+s/2,t,e)},polygon:function(t,e){var n=this,r=n.hasFill(),o=n.hasStroke();function a(){var r=n._attrs.points;if(r.length<2)return!1;var o=n.getHitLineWidth(),a=r.slice(0);return r.length>=3&&a.push(r[0]),i.polyline(a,o,t,e)}return r&&o?s(t,e,n)||a():r?s(t,e,n):!!o&&a()},polyline:function(t,e){var n=this._attrs;if(this.hasStroke()){var r=n.points;if(r.length<2)return!1;var o=n.lineWidth;return i.polyline(r,o,t,e)}return!1},rect:function(t,e){var n=this,r=n.hasFill(),o=n.hasStroke();function a(){var r=n._attrs,o=r.x,a=r.y,s=r.width,c=r.height,u=r.radius,h=n.getHitLineWidth();if(0===u){var l=h/2;return i.line(o-l,a,o+s+l,a,h,t,e)||i.line(o+s,a-l,o+s,a+c+l,h,t,e)||i.line(o+s+l,a+c,o-l,a+c,h,t,e)||i.line(o,a+c+l,o,a-l,h,t,e)}return i.line(o+u,a,o+s-u,a,h,t,e)||i.line(o+s,a+u,o+s,a+c-u,h,t,e)||i.line(o+s-u,a+c,o+u,a+c,h,t,e)||i.line(o,a+c-u,o,a+u,h,t,e)||i.arcline(o+s-u,a+u,u,1.5*Math.PI,2*Math.PI,!1,h,t,e)||i.arcline(o+s-u,a+c-u,u,0,.5*Math.PI,!1,h,t,e)||i.arcline(o+u,a+c-u,u,.5*Math.PI,Math.PI,!1,h,t,e)||i.arcline(o+u,a+u,u,Math.PI,1.5*Math.PI,!1,h,t,e)}return r&&o?s(t,e,n)||a():r?s(t,e,n):!!o&&a()},text:function(t,e){var n=this.getBBox();if(this.hasFill()||this.hasStroke())return i.box(n.minX,n.maxX,n.minY,n.maxY,t,e)}};t.exports={isPointInPath:function(t,e){var n=c[this.type];return!!n&&n.call(this,t,e)}}},function(t,e,n){var r=n(58);r.Arc=n(638),r.Circle=n(637),r.Dom=n(636),r.Ellipse=n(635),r.Fan=n(634),r.Image=n(633),r.Line=n(632),r.Marker=n(611),r.Path=n(631),r.Polygon=n(630),r.Polyline=n(629),r.Rect=n(628),r.Text=n(627),t.exports=r},function(t,e,n){var r=n(19),i={delay:"delay",rotate:"rotate"},o={fill:"fill",stroke:"stroke",fillStyle:"fillStyle",strokeStyle:"strokeStyle"};t.exports={animate:function(t,e,n,a,s){void 0===s&&(s=0),this.set("animating",!0);var c=this.get("timeline");c||(c=this.get("canvas").get("timeline"),this.setSilent("timeline",c));var u=this.get("animators")||[];c._timer||c.initTimer(),r.isNumber(a)&&(s=a,a=null),r.isFunction(n)?(a=n,n="easeLinear"):n=n||"easeLinear";var h=function(t,e){var n={matrix:null,attrs:{}},a=e._attrs;for(var s in t)if("transform"===s)n.matrix=r.transform(e.getMatrix(),t[s]);else if("rotate"===s)n.matrix=r.transform(e.getMatrix(),[["r",t[s]]]);else if("matrix"===s)n.matrix=t[s];else{if(o[s]&&/^[r,R,L,l]{1}[\s]*\(/.test(t[s]))continue;i[s]||a[s]===t[s]||(n.attrs[s]=t[s])}return n}(t,this),l={fromAttrs:function(t,e){var n={},r=e._attrs;for(var i in t.attrs)n[i]=r[i];return n}(h,this),toAttrs:h.attrs,fromMatrix:r.clone(this.getMatrix()),toMatrix:h.matrix,duration:e,easing:n,callback:a,delay:s,startTime:c.getTime(),id:r.uniqueId()};u.length>0?u=function(t,e){var n=e.delay,i=Object.prototype.hasOwnProperty;return r.each(e.toAttrs,(function(e,o){r.each(t,(function(t){n<t.startTime+t.duration&&i.call(t.toAttrs,o)&&(delete t.toAttrs[o],delete t.fromAttrs[o])}))})),e.toMatrix&&r.each(t,(function(t){n<t.startTime+t.duration&&t.toMatrix&&delete t.toMatrix})),t}(u,l):c.addAnimator(this),u.push(l),this.setSilent("animators",u),this.setSilent("pause",{isPaused:!1})},stopAnimate:function(){var t=this,e=this.get("animators");r.each(e,(function(e){t.attr(e.toAttrs),e.toMatrix&&t.attr("matrix",e.toMatrix),e.callback&&e.callback()})),this.setSilent("animating",!1),this.setSilent("animators",[])},pauseAnimate:function(){var t=this.get("timeline");return this.setSilent("pause",{isPaused:!0,pauseTime:t.getTime()}),this},resumeAnimate:function(){var t=this.get("timeline").getTime(),e=this.get("animators"),n=this.get("pause").pauseTime;return r.each(e,(function(e){e.startTime=e.startTime+(t-n),e._paused=!1,e._pauseTime=null})),this.setSilent("pause",{isPaused:!1}),this.setSilent("animators",e),this}}},function(t,e,n){var r=n(19);function i(t){return 1===t[0]&&0===t[1]&&0===t[3]&&1===t[4]&&0===t[6]&&0===t[7]}function o(t){return 0===t[1]&&0===t[3]&&0===t[6]&&0===t[7]}function a(t,e){i(e)||(o(e)?(t[0]*=e[0],t[4]*=e[4]):r.mat3.multiply(t,t,e))}t.exports={initTransform:function(){},resetMatrix:function(){this.attr("matrix",[1,0,0,0,1,0,0,0,1])},translate:function(t,e){var n=this._attrs.matrix;return r.mat3.translate(n,n,[t,e]),this.clearTotalMatrix(),this.attr("matrix",n),this},rotate:function(t){var e=this._attrs.matrix;return r.mat3.rotate(e,e,t),this.clearTotalMatrix(),this.attr("matrix",e),this},scale:function(t,e){var n=this._attrs.matrix;return r.mat3.scale(n,n,[t,e]),this.clearTotalMatrix(),this.attr("matrix",n),this},rotateAtStart:function(t){var e=this._attrs.x||this._cfg.attrs.x,n=this._attrs.y||this._cfg.attrs.y;return Math.abs(t)>2*Math.PI&&(t=t/180*Math.PI),this.transform([["t",-e,-n],["r",t],["t",e,n]])},move:function(t,e){var n=this.get("x")||0,r=this.get("y")||0;return this.translate(t-n,e-r),this.set("x",t),this.set("y",e),this},transform:function(t){var e=this,n=this._attrs.matrix;return r.each(t,(function(t){switch(t[0]){case"t":e.translate(t[1],t[2]);break;case"s":e.scale(t[1],t[2]);break;case"r":e.rotate(t[1]);break;case"m":e.attr("matrix",r.mat3.multiply([],n,t[1])),e.clearTotalMatrix()}})),e},setTransform:function(t){return this.attr("matrix",[1,0,0,0,1,0,0,0,1]),this.transform(t)},getMatrix:function(){return this.attr("matrix")},setMatrix:function(t){return this.attr("matrix",t),this.clearTotalMatrix(),this},apply:function(t,e){var n;return n=e?this._getMatrixByRoot(e):this.attr("matrix"),r.vec3.transformMat3(t,t,n),this},_getMatrixByRoot:function(t){t=t||this;for(var e=this,n=[];e!==t;)n.unshift(e),e=e.get("parent");n.unshift(e);var i=[1,0,0,0,1,0,0,0,1];return r.each(n,(function(t){r.mat3.multiply(i,t.attr("matrix"),i)})),i},getTotalMatrix:function(){var t=this._cfg.totalMatrix;if(!t){t=[1,0,0,0,1,0,0,0,1];var e=this._cfg.parent;e&&a(t,e.getTotalMatrix()),a(t,this.attr("matrix")),this._cfg.totalMatrix=t}return t},clearTotalMatrix:function(){},invert:function(t){var e=this.getTotalMatrix();if(o(e))t[0]/=e[0],t[1]/=e[4];else{var n=r.mat3.invert([],e);n&&r.vec3.transformMat3(t,t,n)}return this},resetTransform:function(t){var e=this.attr("matrix");i(e)||t.transform(e[0],e[1],e[3],e[4],e[6],e[7])}}},function(t,e,n){var r=n(19);t.exports={canFill:!1,canStroke:!1,initAttrs:function(t){return this._attrs={opacity:1,fillOpacity:1,strokeOpacity:1,matrix:[1,0,0,0,1,0,0,0,1]},this.attr(r.assign(this.getDefaultAttrs(),t)),this},getDefaultAttrs:function(){return{}},attr:function(t,e){if(0===arguments.length)return this._attrs;if(r.isObject(t)){for(var n in t)this._setAttr(n,t[n]);return this.clearBBox(),this._cfg.hasUpdate=!0,this}return 2===arguments.length?(this._setAttr(t,e),this.clearBBox(),this._cfg.hasUpdate=!0,this):this._attrs[t]},_setAttr:function(t,e){var n=this._attrs;n[t]=e,"fill"!==t&&"stroke"!==t?"opacity"!==t?"clip"===t&&e?this._setClip(e):"path"===t&&this._afterSetAttrPath?this._afterSetAttrPath(e):"transform"!==t?"rotate"===t&&this.rotateAtStart(e):this.transform(e):n.globalAlpha=e:n[t+"Style"]=e},clearBBox:function(){this.setSilent("box",null)},hasFill:function(){return this.canFill&&this._attrs.fillStyle},hasStroke:function(){return this.canStroke&&this._attrs.strokeStyle},_setClip:function(t){t._cfg.renderer=this._cfg.renderer,t._cfg.canvas=this._cfg.canvas,t._cfg.parent=this._cfg.parent,t.hasFill=function(){return!0}}}},function(t,e,n){var r=n(19),i=n(643),o=n(642),a=n(741),s=n(740),c=function t(e){t.superclass.constructor.call(this,e)};c.CFG={eventEnable:!0,width:null,height:null,widthCanvas:null,heightCanvas:null,widthStyle:null,heightStyle:null,containerDOM:null,canvasDOM:null,pixelRatio:null,renderer:"canvas"},r.extend(c,o),r.augment(c,{init:function(){c.superclass.init.call(this),this._setGlobalParam(),this._setContainer(),this._initPainter(),this._scale(),this.get("eventEnable")&&this._registEvents()},getEmitter:function(t,e){if(t){if(!r.isEmpty(t._getEvents()))return t;var n=t.get("parent");if(n&&!e.propagationStopped)return this.getEmitter(n,e)}},_getEventObj:function(t,e,n,r){var o=new i(t,e,!0,!0);return o.x=n.x,o.y=n.y,o.clientX=e.clientX,o.clientY=e.clientY,o.currentTarget=r,o.target=r,o},_triggerEvent:function(t,e){var n,r=this.getPointByClient(e.clientX,e.clientY),i=this.getShape(r.x,r.y,e),o=this.get("el");if("mousemove"===t){var a=this.get("preShape");if(a&&a!==i){var s=this._getEventObj("mouseleave",e,r,a);(n=this.getEmitter(a,e))&&n.emit("mouseleave",s),o.style.cursor="default"}if(i){var c=this._getEventObj("mousemove",e,r,i);if((n=this.getEmitter(i,e))&&n.emit("mousemove",c),a!==i){var u=this._getEventObj("mouseenter",e,r,i);n&&n.emit("mouseenter",u,e)}}else{var h=this._getEventObj("mousemove",e,r,this);this.emit("mousemove",h)}this.set("preShape",i)}else{var l=this._getEventObj(t,e,r,i||this);(n=this.getEmitter(i,e))&&n!==this&&n.emit(t,l),this.emit(t,l)}i&&!i.get("destroyed")&&(o.style.cursor=i.attr("cursor")||"default")},_registEvents:function(){var t=this,e=t.get("el");r.each(["mouseout","mouseover","mousemove","mousedown","mouseleave","mouseup","click","dblclick"],(function(n){e.addEventListener(n,(function(e){t._triggerEvent(n,e)}),!1)})),e.addEventListener("touchstart",(function(e){r.isEmpty(e.touches)||t._triggerEvent("touchstart",e.touches[0])}),!1),e.addEventListener("touchmove",(function(e){r.isEmpty(e.touches)||t._triggerEvent("touchmove",e.touches[0])}),!1),e.addEventListener("touchend",(function(e){r.isEmpty(e.changedTouches)||t._triggerEvent("touchend",e.changedTouches[0])}),!1)},_scale:function(){if("svg"!==this._cfg.renderType){var t=this.get("pixelRatio");this.scale(t,t)}},_setGlobalParam:function(){var t=this.get("renderer")||"canvas";"svg"===t?this.set("pixelRatio",1):this.get("pixelRatio")||this.set("pixelRatio",r.getRatio()),this._cfg.renderType=t;var e=s[t];this._cfg.renderer=e,this._cfg.canvas=this;var n=new a(this);this._cfg.timeline=n},_setContainer:function(){var t=this.get("containerId"),e=this.get("containerDOM");e||(e=document.getElementById(t),this.set("containerDOM",e)),r.modifyCSS(e,{position:"relative"})},_initPainter:function(){var t=this.get("containerDOM"),e=new this._cfg.renderer.painter(t);this._cfg.painter=e,this._cfg.canvasDOM=this._cfg.el=e.canvas,this.changeSize(this.get("width"),this.get("height"))},_resize:function(){var t=this.get("canvasDOM"),e=this.get("widthCanvas"),n=this.get("heightCanvas"),r=this.get("widthStyle"),i=this.get("heightStyle");t.style.width=r,t.style.height=i,t.setAttribute("width",e),t.setAttribute("height",n)},getWidth:function(){var t=this.get("pixelRatio");return this.get("width")*t},getHeight:function(){var t=this.get("pixelRatio");return this.get("height")*t},changeSize:function(t,e){var n=this.get("pixelRatio"),r=t*n,i=e*n;this.set("widthCanvas",r),this.set("heightCanvas",i),this.set("widthStyle",t+"px"),this.set("heightStyle",e+"px"),this.set("width",t),this.set("height",e),this._resize()},getPointByClient:function(t,e){var n=this.get("el"),r=this.get("pixelRatio")||1,i=n.getBoundingClientRect();return{x:(t-i.left)*r,y:(e-i.top)*r}},getClientByPoint:function(t,e){var n=this.get("el").getBoundingClientRect(),r=this.get("pixelRatio")||1;return{clientX:t/r+n.left,clientY:e/r+n.top}},draw:function(){this._cfg.painter.draw(this)},getShape:function(t,e,n){return 3===arguments.length&&this._cfg.renderer.getShape?this._cfg.renderer.getShape.call(this,t,e,n):c.superclass.getShape.call(this,t,e)},getRenderer:function(){return this._cfg.renderType},_drawSync:function(){this._cfg.painter.drawSync(this)},destroy:function(){var t=this._cfg,e=t.containerDOM,n=t.canvasDOM;n&&e&&e.removeChild(n),t.timeline.stop(),c.superclass.destroy.call(this)}}),t.exports=c},function(t,e,n){var r=n(248),i={};n(257).mix(i,r.PathUtil,{getRectPath:r.PathUtil.rectPath,pointsToPolygon:function(t){for(var e=[["M",t[0].x,t[0].y]],n=1;n<t.length;n++){var r=t[n];e.push(["L",r.x,r.y])}return e},getEllipsePath:function(t,e,n,r){return[["M",t,e-r],["a",n,r,0,1,1,0,2*r],["a",n,r,0,1,1,0,-2*r],["z"]]}}),t.exports=i},function(t,e,n){var r=n(645),i=n(16);t.exports=function(t,e,n){var o=!0,a=!0;if("function"!=typeof t)throw new TypeError("Expected a function");return i(n)&&(o="leading"in n?!!n.leading:o,a="trailing"in n?!!n.trailing:a),r(t,e,{leading:o,maxWait:e,trailing:a})}},function(t,e){t.exports=function(t,e,n){var r=void 0,i=void 0,o=void 0,a=void 0,s=0;n||(n={});var c=function(){s=!1===n.leading?0:Date.now(),r=null,a=t.apply(i,o),r||(i=o=null)},u=function(){var u=Date.now();s||!1!==n.leading||(s=u);var h=e-(u-s);return i=this,o=arguments,h<=0||h>e?(r&&(clearTimeout(r),r=null),s=u,a=t.apply(i,o),r||(i=o=null)):r||!1===n.trailing||(r=setTimeout(c,h)),a};return u.cancel=function(){clearTimeout(r),s=0,r=i=o=null},u}},function(t,e,n){var r=n(46),i=n(596),o=Object.prototype.hasOwnProperty;t.exports=function(t,e){if(null===t||!i(t))return{};var n={};return r(e,(function(e){o.call(t,e)&&(n[e]=t[e])})),n}},function(t,e,n){var r=n(46),i=n(118);t.exports=function(t,e){if(!i(t))return t;var n=[];return r(t,(function(t,r){n.push(e(t,r))})),n}},function(t,e,n){var r=n(84),i=n(614);t.exports=function(t,e,n){return r(n)?!!n(t,e):i(t,e)}},function(t,e,n){var r=n(118);t.exports=function(t,e){if(!r(t))return-1;var n=Array.prototype.indexOf;if(n)return n.call(t,e);for(var i=-1,o=0;o<t.length;o++)if(t[o]===e){i=o;break}return i}},function(t,e,n){var r=n(649);t.exports=function(t,e){if(!e)return[t];var n=r(t,e),i=[];for(var o in n)i.push(n[o]);return i}},function(t,e){t.exports=function(t,e,n){var r=void 0;return function(){var i=this,o=arguments,a=n&&!r;clearTimeout(r),r=setTimeout((function(){r=null,n||t.apply(i,o)}),e),a&&t.apply(i,o)}}},function(t,e,n){var r=n(115);t.exports=function(t){return r(t,"Error")}},function(t,e,n){var r=n(115);t.exports=function(t){return r(t,"Arguments")}},function(t,e,n){var r=n(115);t.exports=function(t){return r(t,"Date")}},function(t,e,n){var r=n(115);t.exports=function(t){return r(t,"RegExp")}},function(t,e){t.exports=function(t){return void 0===t}},function(t,e){t.exports=function(t){return null===t}},function(t,e,n){var r=n(115),i={getType:n(654),isArray:n(45),isArrayLike:n(118),isBoolean:n(653),isFunction:n(84),isNil:n(237),isNull:n(762),isNumber:n(236),isObject:n(621),isObjectLike:n(619),isPlainObject:n(596),isPrototype:n(652),isType:r,isUndefined:n(761),isString:n(595),isRegExp:n(760),isDate:n(759),isArguments:n(758),isError:n(757)};t.exports=i},function(t,e,n){t.exports=n(656)},function(t,e){t.exports=function(t,e){return t&&e?t.replace(/\\?\{([^{}]+)\}/g,(function(t,n){return"\\"===t.charAt(0)?t.slice(1):void 0===e[n]?"":e[n]})):t}},function(t,e,n){var r=n(594);t.exports=function(t){var e=r(t);return e.charAt(0).toLowerCase()+e.substring(1)}},function(t,e,n){t.exports=n(657)},function(t,e,n){var r={lc:n(767),lowerCase:n(657),lowerFirst:n(766),substitute:n(765),uc:n(764),upperCase:n(656),upperFirst:n(655)};t.exports=r},function(t,e){function n(t){var e=[];switch(t[0]){case"M":case"L":e.push([t[1],t[2]]);break;case"A":e.push([t[6],t[7]]);break;case"Q":e.push([t[3],t[4]]),e.push([t[1],t[2]]);break;case"T":e.push([t[1],t[2]]);break;case"C":e.push([t[5],t[6]]),e.push([t[1],t[2]]),e.push([t[3],t[4]]);break;case"S":e.push([t[3],t[4]]),e.push([t[1],t[2]]);break;case"H":case"V":e.push([t[1],t[1]])}return e}function r(t,e,r){for(var i=[].concat(t),o=void 0,a=1/(r+1),s=n(e)[0],c=1;c<=r;c++)a*=c,0===(o=Math.floor(t.length*a))?i.unshift([s[0]*a+t[o][0]*(1-a),s[1]*a+t[o][1]*(1-a)]):i.splice(o,0,[s[0]*a+t[o][0]*(1-a),s[1]*a+t[o][1]*(1-a)]);return i}t.exports=function(t,e){if(t.length<=1)return t;for(var i=void 0,o=0;o<e.length;o++)if(t[o][0]!==e[o][0])switch(i=n(t[o]),e[o][0]){case"M":t[o]=["M"].concat(i[0]);break;case"L":t[o]=["L"].concat(i[0]);break;case"A":t[o]=[].concat(e[o]),t[o][6]=i[0][0],t[o][7]=i[0][1];break;case"Q":if(i.length<2){if(!(o>0)){t[o]=e[o];break}i=r(i,t[o-1],1)}t[o]=["Q"].concat(i.reduce((function(t,e){return t.concat(e)}),[]));break;case"T":t[o]=["T"].concat(i[0]);break;case"C":if(i.length<3){if(!(o>0)){t[o]=e[o];break}i=r(i,t[o-1],2)}t[o]=["C"].concat(i.reduce((function(t,e){return t.concat(e)}),[]));break;case"S":if(i.length<2){if(!(o>0)){t[o]=e[o];break}i=r(i,t[o-1],1)}t[o]=["S"].concat(i.reduce((function(t,e){return t.concat(e)}),[]));break;default:t[o]=e[o]}return t}},function(t,e,n){var r=n(46);t.exports=function(t,e){if(t.length!==e.length)return!1;var n=!0;return r(t,(function(t,r){if(t!==e[r])return n=!1,!1})),n}},function(t,e,n){var r=n(770);function i(t,e,n){var r=null,i=n;return e<i&&(i=e,r="add"),t<i&&(i=t,r="del"),{type:r,min:i}}t.exports=function(t,e){var n=function(t,e){var n=t.length,o=e.length,a=void 0,s=void 0,c=0;if(0===n||0===o)return null;for(var u=[],h=0;h<=n;h++)u[h]=[],u[h][0]={min:h};for(var l=0;l<=o;l++)u[0][l]={min:l};for(var d=1;d<=n;d++){a=t[d-1];for(var f=1;f<=o;f++){s=e[f-1],c=r(a,s)?0:1;var g=u[d-1][f].min+1,p=u[d][f-1].min+1,m=u[d-1][f-1].min+c;u[d][f]=i(g,p,m)}}return u}(t,e),o=t.length,a=e.length,s=[],c=1,u=1;if(n[o][a]!==o){for(var h=1;h<=o;h++){var l=n[h][h].min;u=h;for(var d=c;d<=a;d++)n[h][d].min<l&&(l=n[h][d].min,u=d);c=u,n[h][c].type&&s.push({index:h-1,type:n[h][c].type})}for(var f=s.length-1;f>=0;f--)c=s[f].index,"add"===s[f].type?t.splice(c,0,[].concat(t[c])):t.splice(c,1)}if((o=t.length)<a)for(var g=0;g<a-o;g++)"z"===t[o-1][0]||"Z"===t[o-1][0]?t.splice(o-2,0,t[o-2]):t.push(t[o-1]);return t}},function(t,e){function n(t,e){var n=[],r=[];return t.length&&function t(e,i){if(1===e.length)n.push(e[0]),r.push(e[0]);else{for(var o=[],a=0;a<e.length-1;a++)0===a&&n.push(e[0]),a===e.length-2&&r.push(e[a+1]),o[a]=[(1-i)*e[a][0]+i*e[a+1][0],(1-i)*e[a][1]+i*e[a+1][1]];t(o,i)}}(t,e),{left:n,right:r.reverse()}}function r(t,e,r){if(1===r)return[[].concat(t)];var i=[];if("L"===e[0]||"C"===e[0]||"Q"===e[0])i=i.concat(function(t,e,r){var i=[[t[1],t[2]]];r=r||2;var o=[];"A"===e[0]?(i.push(e[6]),i.push(e[7])):"C"===e[0]?(i.push([e[1],e[2]]),i.push([e[3],e[4]]),i.push([e[5],e[6]])):"S"===e[0]||"Q"===e[0]?(i.push([e[1],e[2]]),i.push([e[3],e[4]])):i.push([e[1],e[2]]);for(var a=i,s=1/r,c=0;c<r-1;c++){var u=n(a,s/(1-s*c));o.push(u.left),a=u.right}return o.push(a),o.map((function(t){var e=[];return 4===t.length&&(e.push("C"),e=e.concat(t[2])),t.length>=3&&(3===t.length&&e.push("Q"),e=e.concat(t[1])),2===t.length&&e.push("L"),e.concat(t[t.length-1])}))}(t,e,r));else{var o=[].concat(t);"M"===o[0]&&(o[0]="L");for(var a=0;a<=r-1;a++)i.push(o)}return i}t.exports=function(t,e){if(1===t.length)return t;var n=t.length-1,i=e.length-1,o=n/i,a=[];if(1===t.length&&"M"===t[0][0]){for(var s=0;s<i-n;s++)t.push(t[0]);return t}for(var c=0;c<i;c++){var u=Math.floor(o*c);a[u]=(a[u]||0)+1}var h=a.reduce((function(e,i,o){return o===n?e.concat(t[n]):e.concat(r(t[o],t[o+1],i))}),[]);return h.unshift(t[0]),"Z"!==e[i]&&"z"!==e[i]||h.push("Z"),h}},function(t,e,n){var r=n(45),i=n(663),o=n(661),a=function(t,e,n,r,i){return t*(t*(-3*e+9*n-9*r+3*i)+6*e-12*n+6*r)-3*e+3*n},s=function(t,e,n,r,i,o,s,c,u){null===u&&(u=1);for(var h=(u=u>1?1:u<0?0:u)/2,l=[-.1252,.1252,-.3678,.3678,-.5873,.5873,-.7699,.7699,-.9041,.9041,-.9816,.9816],d=[.2491,.2491,.2335,.2335,.2032,.2032,.1601,.1601,.1069,.1069,.0472,.0472],f=0,g=0;g<12;g++){var p=h*l[g]+h,m=a(p,t,n,i,s),v=a(p,e,r,o,c),x=m*m+v*v;f+=d[g]*Math.sqrt(x)}return h*f},c=function(t,e,n,r,i,o,a,s){if(!(Math.max(t,n)<Math.min(i,a)||Math.min(t,n)>Math.max(i,a)||Math.max(e,r)<Math.min(o,s)||Math.min(e,r)>Math.max(o,s))){var c=(t-n)*(o-s)-(e-r)*(i-a);if(c){var u=((t*r-e*n)*(i-a)-(t-n)*(i*s-o*a))/c,h=((t*r-e*n)*(o-s)-(e-r)*(i*s-o*a))/c,l=+u.toFixed(2),d=+h.toFixed(2);if(!(l<+Math.min(t,n).toFixed(2)||l>+Math.max(t,n).toFixed(2)||l<+Math.min(i,a).toFixed(2)||l>+Math.max(i,a).toFixed(2)||d<+Math.min(e,r).toFixed(2)||d>+Math.max(e,r).toFixed(2)||d<+Math.min(o,s).toFixed(2)||d>+Math.max(o,s).toFixed(2)))return{x:u,y:h}}}},u=function(t,e,n){return e>=t.x&&e<=t.x+t.width&&n>=t.y&&n<=t.y+t.height},h=function(t,e,n,r){return null===t&&(t=e=n=r=0),null===e&&(e=t.y,n=t.width,r=t.height,t=t.x),{x:t,y:e,width:n,w:n,height:r,h:r,x2:t+n,y2:e+r,cx:t+n/2,cy:e+r/2,r1:Math.min(n,r)/2,r2:Math.max(n,r)/2,r0:Math.sqrt(n*n+r*r)/2,path:i(t,e,n,r),vb:[t,e,n,r].join(" ")}},l=function(t,e,n,i,o,a,s,c){r(t)||(t=[t,e,n,i,o,a,s,c]);var u=function(t,e,n,r,i,o,a,s){for(var c=[],u=[[],[]],h=void 0,l=void 0,d=void 0,f=void 0,g=0;g<2;++g)if(0===g?(l=6*t-12*n+6*i,h=-3*t+9*n-9*i+3*a,d=3*n-3*t):(l=6*e-12*r+6*o,h=-3*e+9*r-9*o+3*s,d=3*r-3*e),Math.abs(h)<1e-12){if(Math.abs(l)<1e-12)continue;(f=-d/l)>0&&f<1&&c.push(f)}else{var p=l*l-4*d*h,m=Math.sqrt(p);if(!(p<0)){var v=(-l+m)/(2*h);v>0&&v<1&&c.push(v);var x=(-l-m)/(2*h);x>0&&x<1&&c.push(x)}}for(var y=c.length,b=y,w=void 0;y--;)w=1-(f=c[y]),u[0][y]=w*w*w*t+3*w*w*f*n+3*w*f*f*i+f*f*f*a,u[1][y]=w*w*w*e+3*w*w*f*r+3*w*f*f*o+f*f*f*s;return u[0][b]=t,u[1][b]=e,u[0][b+1]=a,u[1][b+1]=s,u[0].length=u[1].length=b+2,{min:{x:Math.min.apply(0,u[0]),y:Math.min.apply(0,u[1])},max:{x:Math.max.apply(0,u[0]),y:Math.max.apply(0,u[1])}}}.apply(null,t);return h(u.min.x,u.min.y,u.max.x-u.min.x,u.max.y-u.min.y)},d=function(t,e,n,r,i,o,a,s,c){var u=1-c,h=Math.pow(u,3),l=Math.pow(u,2),d=c*c,f=d*c,g=t+2*c*(n-t)+d*(i-2*n+t),p=e+2*c*(r-e)+d*(o-2*r+e),m=n+2*c*(i-n)+d*(a-2*i+n),v=r+2*c*(o-r)+d*(s-2*o+r);return{x:h*t+3*l*c*n+3*u*c*c*i+f*a,y:h*e+3*l*c*r+3*u*c*c*o+f*s,m:{x:g,y:p},n:{x:m,y:v},start:{x:u*t+c*n,y:u*e+c*r},end:{x:u*i+c*a,y:u*o+c*s},alpha:90-180*Math.atan2(g-m,p-v)/Math.PI}},f=function(t,e,n){if(!function(t,e){return t=h(t),e=h(e),u(e,t.x,t.y)||u(e,t.x2,t.y)||u(e,t.x,t.y2)||u(e,t.x2,t.y2)||u(t,e.x,e.y)||u(t,e.x2,e.y)||u(t,e.x,e.y2)||u(t,e.x2,e.y2)||(t.x<e.x2&&t.x>e.x||e.x<t.x2&&e.x>t.x)&&(t.y<e.y2&&t.y>e.y||e.y<t.y2&&e.y>t.y)}(l(t),l(e)))return n?0:[];for(var r=~~(s.apply(0,t)/8),i=~~(s.apply(0,e)/8),o=[],a=[],f={},g=n?0:[],p=0;p<r+1;p++){var m=d.apply(0,t.concat(p/r));o.push({x:m.x,y:m.y,t:p/r})}for(var v=0;v<i+1;v++){var x=d.apply(0,e.concat(v/i));a.push({x:x.x,y:x.y,t:v/i})}for(var y=0;y<r;y++)for(var b=0;b<i;b++){var w=o[y],M=o[y+1],_=a[b],S=a[b+1],A=Math.abs(M.x-w.x)<.001?"y":"x",E=Math.abs(S.x-_.x)<.001?"y":"x",P=c(w.x,w.y,M.x,M.y,_.x,_.y,S.x,S.y);if(P){if(f[P.x.toFixed(4)]===P.y.toFixed(4))continue;f[P.x.toFixed(4)]=P.y.toFixed(4);var C=w.t+Math.abs((P[A]-w[A])/(M[A]-w[A]))*(M.t-w.t),O=_.t+Math.abs((P[E]-_[E])/(S[E]-_[E]))*(S.t-_.t);C>=0&&C<=1&&O>=0&&O<=1&&(n?g++:g.push({x:P.x,y:P.y,t1:C,t2:O}))}}return g};t.exports=function(t,e){return function(t,e,n){t=o(t),e=o(e);for(var r=void 0,i=void 0,a=void 0,s=void 0,c=void 0,u=void 0,h=void 0,l=void 0,d=void 0,g=void 0,p=[],m=0,v=t.length;m<v;m++){var x=t[m];if("M"===x[0])r=c=x[1],i=u=x[2];else{"C"===x[0]?(r=(d=[r,i].concat(x.slice(1)))[6],i=d[7]):(d=[r,i,r,i,c,u,c,u],r=c,i=u);for(var y=0,b=e.length;y<b;y++){var w=e[y];if("M"===w[0])a=h=w[1],s=l=w[2];else{"C"===w[0]?(a=(g=[a,s].concat(w.slice(1)))[6],s=g[7]):(g=[a,s,a,s,h,l,h,l],a=h,s=l);for(var M=f(d,g,n),_=0,S=M.length;_<S;_++)M[_].segment1=m,M[_].segment2=y,M[_].bez1=d,M[_].bez2=g;p=p.concat(M)}}}}return p}(t,e)}},function(t,e,n){var r=n(773),i=n(660),o=n(661),a=n(658);t.exports={catmullRom2Bezier:a,catmullRomToBezier:a,fillPath:n(772),fillPathByDiff:n(771),formatPath:n(769),intersection:r,pathIntersection:r,parsePathArray:n(662),parsePathString:n(659),pathToAbsolute:i,path2absolute:i,pathTocurve:o,path2curve:o,rectPath:n(663)}},function(t,e,n){var r=n(605),i=n(664);t.exports=function(t,e){return r(i(t),e)}},function(t,e,n){t.exports=n(665)},function(t,e,n){t.exports=n(46)},function(t,e,n){t.exports={forIn:n(777),has:n(665),hasKey:n(776),hasValue:n(775),keys:n(677),isMatch:n(678),values:n(664)}},function(t,e,n){t.exports={mat3:n(617),vec2:n(668),vec3:n(667),transform:n(666)}},function(t,e,n){var r=n(45),i=n(84),o=n(46);t.exports=function(t,e){if(r(t)){var n=t[0],a=void 0;a=i(e)?e(t[0]):t[0][e];var s=void 0;return o(t,(function(t){(s=i(e)?e(t):t[e])<a&&(n=t,a=s)})),n}}},function(t,e,n){var r=n(45),i=n(84),o=n(46);t.exports=function(t,e){if(r(t)){var n=t[0],a=void 0;a=i(e)?e(t[0]):t[0][e];var s=void 0;return o(t,(function(t){(s=i(e)?e(t):t[e])>a&&(n=t,a=s)})),n}}},function(t,e,n){var r=n(236);t.exports=function(t){return r(t)&&t>0}},function(t,e,n){var r=n(236);t.exports=function(t){return r(t)&&t%2!=0}},function(t,e,n){var r=n(236);t.exports=function(t){return r(t)&&t<0}},function(t,e,n){var r=n(236),i=Number.isInteger?Number.isInteger:function(t){return r(t)&&t%1==0};t.exports=i},function(t,e,n){var r=n(236);t.exports=function(t){return r(t)&&t%2==0}},function(t,e,n){var r=n(236);t.exports=function(t){return r(t)&&t%1!=0}},function(t,e){t.exports=function(t,e){var n=e.toString(),r=n.indexOf(".");if(-1===r)return Math.round(t);var i=n.substr(r+1).length;return i>20&&(i=20),parseFloat(t.toFixed(i))}},function(t,e,n){var r=n(673);t.exports={clamp:n(618),fixedBase:n(788),isDecimal:n(787),isEven:n(786),isInteger:n(785),isNegative:n(784),isNumberEqual:r,isOdd:n(783),isPositive:n(782),maxBy:n(781),minBy:n(780),mod:n(672),snapEqual:r,toDegree:n(671),toInt:n(670),toInteger:n(670),toRadian:n(669)}},function(t,e,n){var r=n(45);t.exports=function(t){var e=0,n=0,i=0,o=0;return r(t)?1===t.length?e=n=i=o=t[0]:2===t.length?(e=i=t[0],n=o=t[1]):3===t.length?(e=t[0],n=o=t[1],i=t[2]):(e=t[0],n=t[1],i=t[2],o=t[3]):e=n=i=o=t,{r1:e,r2:n,r3:i,r4:o}}},function(t,e,n){var r=n(45),i=n(595),o=n(46),a=/[MLHVQTCSAZ]([^MLHVQTCSAZ]*)/gi,s=/[^\s\,]+/gi;t.exports=function(t){return r(t=t||[])?t:i(t)?(t=t.match(a),o(t,(function(e,n){if((e=e.match(s))[0].length>1){var r=e[0].charAt(0);e.splice(1,0,e[0].substr(1)),e[0]=r}o(e,(function(t,n){isNaN(t)||(e[n]=+t)})),t[n]=e})),t):void 0}},function(t,e){var n={};t.exports=function(t){var e=n[t];if(!e){for(var r=t.toString(16),i=r.length;i<6;i++)r="0"+r;e="#"+r,n[t]=e}return e}},function(t,e,n){var r=n(792);t.exports={number2color:r,numberToColor:r,parsePath:n(791),parseRadius:n(790)}},function(t,e){t.exports=function(t,e){if(t["_wrap_"+e])return t["_wrap_"+e];var n=function(n){t[e](n)};return t["_wrap_"+e]=n,n}},function(t,e){t.exports=function(t,e){return t["_wrap_"+e]}},function(t,e,n){t.exports={getWrapBehavior:n(795),wrapBehavior:n(794)}},function(t,e,n){var r=n(237),i=n(45),o=n(46);t.exports=function(t,e){for(var n=[],a={},s=0;s<t.length;s++){var c=t[s][e];r(c)||(i(c)||(c=[c]),o(c,(function(t){a[t]||(n.push(t),a[t]=!0)})))}return n}},function(t,e,n){var r=n(46),i=n(604),o=n(674);t.exports=function(){var t=[],e=i(arguments);return r(e,(function(e){t=t.concat(e)})),o(t)}},function(t,e,n){var r=n(595),i=n(84),o=n(45);t.exports=function(t,e){var n=void 0;if(i(e))n=function(t,n){return e(t)-e(n)};else{var a=[];r(e)?a.push(e):o(e)&&(a=e),n=function(t,e){for(var n=0;n<a.length;n+=1){var r=a[n];if(t[r]>e[r])return 1;if(t[r]<e[r])return-1}return 0}}return t.sort(n),t}},function(t,e,n){var r=n(118),i=n(675);t.exports=function(t,e){var n=[];if(!r(t))return n;for(var o=-1,a=[],s=t.length;++o<s;){var c=t[o];e(c,o,t)&&(n.push(c),a.push(o))}return i(t,a),n}},function(t,e,n){var r=n(45),i=n(596),o=n(46);t.exports=function(t,e,n){if(!r(t)&&!i(t))return t;var a=n;return o(t,(function(t,n){a=e(a,t,n)})),a}},function(t,e){t.exports=function(t){for(var e=[],n=0;n<t.length;n++)e=e.concat(t[n]);return e}},function(t,e,n){var r=n(620),i=n(45);t.exports=function(t){if(!(t=r(t,(function(t){return!isNaN(t)}))).length)return{min:0,max:0};if(i(t[0])){for(var e=[],n=0;n<t.length;n++)e=e.concat(t[n]);t=e}var o=Math.max.apply(null,t);return{min:Math.min.apply(null,t),max:o}}},function(t,e,n){var r=n(45);t.exports=function t(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];if(r(e))for(var i=0;i<e.length;i+=1)t(e[i],n);else n.push(e);return n}},function(t,e,n){var r=n(45),i=n(46);t.exports=function(t){if(!r(t))return t;var e=[];return i(t,(function(t){r(t)?i(t,(function(t){e.push(t)})):e.push(t)})),e}},function(t,e,n){var r=n(237),i=n(45);t.exports=function(t,e){for(var n=null,o=0;o<t.length;o++){var a=t[o][e];if(!r(a)){n=i(a)?a[0]:a;break}}return n}},function(t,e,n){var r=n(84),i=n(596),o=n(678);t.exports=function(t,e){var n=void 0;if(r(e)&&(n=e),i(e)&&(n=function(t){return o(t,e)}),n)for(var a=0;a<t.length;a+=1)if(n(t[a]))return t[a];return null}},function(t,e,n){var r=n(620),i=n(605);t.exports=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];return r(t,(function(t){return!i(e,t)}))}},function(t,e,n){t.exports={contains:n(605),difference:n(808),find:n(807),firstValue:n(806),flatten:n(805),flattenDeep:n(804),getRange:n(803),merge:n(802),pull:n(676),pullAt:n(675),reduce:n(801),remove:n(800),sortBy:n(799),union:n(798),uniq:n(674),valuesOfKey:n(797)}},function(t,e){t.exports=function(t,e){var n=this.getStyle(t,"width",e);return"auto"===n&&(n=t.offsetWidth),parseFloat(n)}},function(t,e,n){var r=n(237);t.exports=function(t,e,n){try{return window.getComputedStyle?window.getComputedStyle(t,null)[e]:t.currentStyle[e]}catch(t){return r(n)?null:n}}},function(t,e){t.exports=function(){return window.devicePixelRatio?window.devicePixelRatio:2}},function(t,e){t.exports=function(t,e){var n=this.getWidth(t,e),r=parseFloat(this.getStyle(t,"borderLeftWidth"))||0,i=parseFloat(this.getStyle(t,"paddingLeft"))||0,o=parseFloat(this.getStyle(t,"paddingRight"))||0;return n+r+(parseFloat(this.getStyle(t,"borderRightWidth"))||0)+i+o}},function(t,e){t.exports=function(t,e){var n=this.getHeight(t,e),r=parseFloat(this.getStyle(t,"borderTopWidth"))||0,i=parseFloat(this.getStyle(t,"paddingTop"))||0,o=parseFloat(this.getStyle(t,"paddingBottom"))||0;return n+r+(parseFloat(this.getStyle(t,"borderBottomWidth"))||0)+i+o}},function(t,e){t.exports=function(t,e){var n=this.getStyle(t,"height",e);return"auto"===n&&(n=t.offsetHeight),parseFloat(n)}},function(t,e){t.exports=function(t,e){if(t&&t.getBoundingClientRect){var n=t.getBoundingClientRect(),r=document.documentElement.clientTop,i=document.documentElement.clientLeft;return{top:n.top-r,bottom:n.bottom-r,left:n.left-i,right:n.right-i}}return e||null}},function(t,e){t.exports=function(t,e,n){if(t){if(t.addEventListener)return t.addEventListener(e,n,!1),{remove:function(){t.removeEventListener(e,n,!1)}};if(t.attachEvent)return t.attachEvent("on"+e,n),{remove:function(){t.detachEvent("on"+e,n)}}}}},function(t,e,n){t.exports={addEventListener:n(817),createDom:n(681),getBoundingClientRect:n(816),getHeight:n(815),getOuterHeight:n(814),getOuterWidth:n(813),getRatio:n(812),getStyle:n(811),getWidth:n(810),modifyCSS:n(680),requestAnimationFrame:n(679)}},function(t,e,n){var r=n(46),i=n(606),o=n(818),a=n(809),s=n(796),c=n(793),u=n(789),h=n(779),l=n(778),d=n(774),f=n(768),g=n(763),p={DOMUtil:o,DomUtil:o,MatrixUtil:h,PathUtil:d,arrayUtil:a,domUtil:o,eventUtil:s,formatUtil:c,mathUtil:u,matrixUtil:h,objectUtil:l,stringUtil:f,pathUtil:d,typeUtil:g,augment:n(651),clone:n(616),debounce:n(756),deepMix:n(615),each:r,extend:n(650),filter:n(620),group:n(755),groupBy:n(648),groupToMap:n(649),indexOf:n(754),isEmpty:n(647),isEqual:n(614),isEqualWith:n(753),map:n(752),mix:i,pick:n(751),throttle:n(750),toArray:n(604),toString:n(594),uniqueId:n(646)};r([o,a,s,c,u,h,l,d,f,g],(function(t){i(p,t)})),t.exports=p},function(t,e,n){var r=n(683),i=n(626),o=n(247),a=n(609),s=n(248),c={Graph:n(625),Tree:n(689),Util:n(26),Layouts:n(623),G:s,Plugins:{},Components:{},Global:o,Shape:r,registerNode:r.registerNode,registerEdge:r.registerEdge,registerGroup:r.registerGroup,registerGuide:r.registerGuide,registerBehaviour:i.registerBehaviour,version:a,track:function(t){o.track=t}};n(684),t.exports=c}])},function(t,e,n){const r=n(7),i=n(1),o=n(10),a=[];class s extends i{constructor(t){const e={showHotArea:!1,defaultData:{roots:[{label:"思维导图",children:[{label:"新建节点"},{label:"新建节点"},{label:"新建节点"}]}]},shortcut:{append:!0,appendChild:!0,collapseExpand:!0,selectAll:!0},labelEditable:!0,graph:{modes:{default:["clickNodeSelected","keydownMoveSelection","clickCanvasSelected","keydownEditLabel","panBlank","wheelChangeViewport","panMindNode","clickCollapsedButton","clickExpandedButton","hoverButton","hoverNodeActived","dblclickItemEditLabel"],readOnly:["clickNodeSelected","wheelChangeViewport","keydownMoveSelection","hoverNodeActived","panCanvas","clickExpandedButton","hoverButton","clickCanvasSelected"]},layout:new r.Layouts.Mindmap({direction:"H",getSubTreeSep:t=>t.children&&t.children.length>0?t.hierarchy<=2?8:2:0,getHGap:t=>1===t.hierarchy?8:2===t.hierarchy?24:18,getVGap:t=>1===t.hierarchy||2===t.hierarchy?24:2,getSide:t=>t.data.side?t.data.side:"right"}),mode:"default",defaultIntersectBox:"rect",nodeDefaultShape:"mind-base",edgeDefaultShape:"mind-edge",minZoom:.2,maxZoom:2},align:{item:!1},rootShape:"mind-root",firstSubShape:"mind-first-sub",secondSubShape:"mind-second-sub",subShape:"mind-base",nodeDefaultShape:"mind-base",graphConstructor:r.Tree,defaultSide:"right"},n={};o.each(a,t=>{o.mix(n,t.CFG)}),o.mix(!0,e,n,t),super(e),this.isMind=!0}_init(){super._init(),o.each(a,t=>{t.INIT&&this[t.INIT]()});const t=this.getGraph(),e=this.get("defaultData"),n=t.get("mode"),r=t.getRootGroup().addGroup();if(this.set("hotAreaGroup",r),t.edge().shape(e=>{if(t.find(e.target).getModel().isPlaceholder)return"mind-placeholder-edge"}),e&&this.read(e),"default"===n){if(e){const e=this.getRoot(),n=t.find(e.id);this.setSelected(n,!0)}}else if("readOnly"===n){const t=this.get("shortcut");t.append=!1,t.appendChild=!1,t.selectAll=!1,t.delete=!1}if(e){const t=this.getRoot();this.focus(t.id)}}bindEvent(){super.bindEvent();const t=this.get("_graph");t.on("keydown",t=>{t.domEvent.preventDefault()}),t.on("beforechange",t=>{"add"===t.action?this._beforeAdd(t):"changeData"===t.action&&this._beforeChangeData(t)}),t.on("aftersource",()=>{this._setHierarchy()}),t.on("afterchange",()=>{this._setHotArea()}),t.on("afteritemdraw",t=>{const e=t.item,n=e.getModel();if(e.isEdge){const t=e.getGraphicGroup();o.toBack(t,t.getParent()),t.setSilent("capture",!1)}n.parent||(e.isRoot=!0,e.deleteable=!1,e.collapseExpand=!1,e.appendable=!1,e.dragable=!1)}),this.on("beforedelete",t=>{const e=t.items[0],n=this._getBrothers(e),r=this._getNth(e);n[r-1]?this.setSelected(n[r-1].id,!0):n[r+1]?this.setSelected(n[r+1].id,!0):this.setSelected(e.getParent(),!0)}),this.on("afteritemselected",t=>{this._tryAdjustViewport(t.item)})}getRoot(){return this.getGraph().getSource().roots[0]}_setHierarchy(t){const e=this.getGraph(),n=this.get("firstSubShape"),r=this.get("secondSubShape"),i=this.get("defaultSide");if(t){const o=e.find(t.parent);if(o){const e=o.getModel();t.hierarchy=e.hierarchy+1,"mind-placeholder"!==t.shape&&(2===t.hierarchy&&(t.shape=n,t.side||(t.side=i)),3===t.hierarchy&&(t.shape=r))}}else(t=this.getRoot()).hierarchy=1;o.traverseTree(t,(t,e)=>{t.hierarchy=e.hierarchy+1,t.side||(t.side=i),e.side&&(t.side=e.side),2===t.hierarchy?t.shape=n:3===t.hierarchy&&(t.shape=r)},t=>t.children)}getFirstChildrenBySide(t){const e=this.getRoot(),n=[];return e.children.forEach(e=>{e.side===t&&n.push(e)}),n}_getNth(t){return this.getGraph().getNth(t)}_getBrothers(t){return t.getParent().getModel().children}_getMoveChildModel(t){if(t&&t.length>0){const e=t.length;return t[parseInt(e/2)]}}_getVerticalMoveItem(t,e,n){const r=this.getGraph().getNodes(),i=t.getBBox(),o=[i.minX,i.maxX],a=[];let s;for(let t=0;t<o.length;t++){const s=o[t];for(let t=0;t<r.length;t++){const o=r[t],c=o.getBBox();e(c,i,s)&&a.push({long:n(c,i),node:o})}}return a.length>0&&(a.sort((t,e)=>t.long-e.long),s=a[0].node),s}_arrowTopItem(t){const e=this._getBrothers(t),n=this._getNth(t);return e[n-1]?e[n-1]:this._getVerticalMoveItem(t,(t,e,n)=>t.centerY<e.centerY&&n<=t.maxX&&n>=t.minX,(t,e)=>e.centerY-t.centerY)}_arrowBottomItem(t){const e=this._getBrothers(t),n=this._getNth(t);return e[n+1]?e[n+1]:this._getVerticalMoveItem(t,(t,e,n)=>t.centerY>e.centerY&&n<=t.maxX&&n>=t.minX,(t,e)=>t.centerY-e.centerY)}_arrowLeftItem(t){const e=o.getMindNodeSide(t);if(t.isRoot){const t=this.getFirstChildrenBySide("left");return this._getMoveChildModel(t)}if("left"===e){const e=t.getModel().children;return this._getMoveChildModel(e)}return t.getParent()}_arrowRightItem(t){const e=o.getMindNodeSide(t);if(t.isRoot){const t=this.getFirstChildrenBySide("right");return this._getMoveChildModel(t)}if("right"===e){const e=t.getModel().children;return this._getMoveChildModel(e)}return t.getParent()}_moveItemSelection(t){const e=this.getGraph(),n=this.getSelected()[0];if(!n)return;const{domEvent:r}=t,i=o.getKeyboradKey(r);let a;"ArrowUp"!==i||n.isRoot?"ArrowDown"!==i||n.isRoot?"ArrowLeft"===i?a=this._arrowLeftItem(n):"ArrowRight"===i&&(a=this._arrowRightItem(n)):a=this._arrowBottomItem(n):a=this._arrowTopItem(n),a&&(a=e.find(a.id),a.isVisible()&&(this.clearSelected(),this.setSelected(a,!0)))}showLabelEditor(t){const{domEvent:e}=t,n=this.getSelected()[0],r=o.getKeyboradKey(e);if(n&&1===r.length&&!e.metaKey&&!e.ctrlKey){const t=this.get("labelTextArea");n&&(this.beginEditLabel(n),t.innerHTML=r,o.setEndOfContenteditable(t))}}_tryAdjustViewport(t){const e=this.get("_graph"),n=t.getBBox(),r={x:n.minX,y:n.minY},i={x:n.maxX,y:n.maxY},o=e.getDomPoint(r),a=e.getDomPoint(i),s=e.getWidth(),c=e.getHeight();o.x<0&&e.translate(16-o.x,0),o.y<0&&e.translate(0,16-o.y),a.x>s&&e.translate(s-a.x-16,0),a.y>c&&e.translate(0,c-a.y-16)}_beforeChangeData(t){const e=t.data.roots[0],n=this.get("rootShape");e.shape=n,this._setHierarchy(e)}_beforeAdd(t){const e=this.get("_graph"),{model:n}=t,r=e.find(n.parent);r.getModel().collapsed&&e.update(r,{collapsed:!1}),this._setHierarchy(n)}_drawHotAreaShape(){const t=this.get("_graph"),e=this.get("hotAreaGroup"),n=this.get("hotAreas");e.clear(),n.forEach(t=>{e.addShape("rect",{attrs:{x:t.minX,y:t.minY,width:t.maxX-t.minX,height:t.maxY-t.minY,fill:t.color,fillOpacity:.4},capture:!1})}),t.draw()}_setHotArea(){const t=[],e=this.get("_graph"),n=this.getRoot(),r="placeholder",i=this.get("showHotArea"),a=e.find(n.id).getBBox();t.push({minX:a.minX-90,minY:a.minY-60,maxX:(a.minX+a.maxX)/2,maxY:a.maxY+60,parent:n,current:n,id:n.id+"left"+r,nth:n.children.length,side:"left",color:"orange"}),t.push({minX:(a.minX+a.maxX)/2,minY:a.minY-60,maxX:a.maxX+90,maxY:a.maxY+60,parent:n,current:n,id:n.id+"right"+r,nth:n.children.length,side:"right",color:"pink"}),o.traverseTree(n,(n,i,o)=>{const a=e.find(n.id);if(n.isPlaceholder||!a||!a.isVisible())return;const s=function(t,e,n){const r=n.children;let i=t;if(!n.parent)for(;r[i]&&r[i].side!==e.side;)i++;for(;r[i]&&r[i].isPlaceholder;)i++;if(r[i]&&r[i].side===e.side)return r[i]}(o+1,n,i),c=function(t,e,n){const r=n.children;let i=t;if(!n.parent)for(;r[i]&&r[i].side!==e.side;)i--;for(;r[i]&&r[i].isPlaceholder;)i--;if(r[i]&&r[i].side===e.side)return r[i]}(o-1,n,i),u=e.find(n.id).getBBox(),h=i.children,l=2===n.hierarchy&&"right"===n.side,d=2===n.hierarchy&&"left"===n.side;if(c||t.push({minX:l?u.minX-90:u.minX,minY:(()=>{let t=c?u.minY:u.minY-16;if(h[o-1]&&h[o-1].isPlaceholder&&h[o-1].side===n.side){t=e.find(h[o-1].id).getBBox().minY}return t})(),maxX:d?u.maxX+90:u.maxX,maxY:(u.minY+u.maxY)/2,parent:i,id:(c?c.id:void 0)+n.id+i.id+r,side:n.side,color:"yellow",nth:o}),s){const a=e.find(s.id).getBBox();t.push({minX:"left"===n.side?Math.max(u.minX,a.minX):l?u.minX-90:u.minX,minY:(u.minY+u.maxY)/2,maxX:"right"===n.side?Math.min(u.maxX,a.maxX):d?u.maxX+90:u.maxX,maxY:(a.minY+a.maxY)/2,parent:i,id:n.id+(s?s.id:void 0)+i.id+r,side:n.side,color:"blue",nth:o+1})}else t.push({minX:l?u.minX-90:u.minX,minY:(u.minY+u.maxY)/2,maxX:d?u.maxX+90:u.maxX,maxY:(()=>{let t=u.maxY+16;if(h[o+1]&&h[o+1].isPlaceholder&&h[o+1].side===n.side){t=e.find(h[o+1].id).getBBox().maxY}return t})(),parent:i,id:n.id+void 0+i.id+r,color:"red",nth:o+1,addOrder:"push",side:n.side});if(!n.children||0===n.children.length||1===n.children.length&&n.children[0].isPlaceholder){const e=100,o=0;let a;a=n.x>i.x?{minX:u.maxX,minY:u.minY-o,maxX:u.maxX+e,maxY:u.maxY+o}:{minX:u.minX-e,minY:u.minY-o,maxX:u.minX,maxY:u.maxY+o},t.push({...a,parent:n,id:NaN+n.id+r,nth:0,color:"green",side:n.side,addOrder:"push"})}},t=>t.children),this.set("hotAreas",t),i&&this._drawHotAreaShape()}hideHotArea(){const t=this.get("_graph");this.get("hotAreaGroup").clear(),t.draw(),this.set("showHotArea",!1)}showHotArea(){this._drawHotAreaShape(),this.set("showHotArea",!0)}getHotArea(t){let e;return this.get("hotAreas").forEach(n=>{if(t.x>n.minX&&t.x<n.maxX&&t.y>n.minY&&t.y<n.maxY)return e=n,!1}),e}saveExpandImage(t){const e=this.getGraph(),n=e.getBBox(),r=e.getFitViewPadding();let i,o,a;return e.saveImage({width:n.width+r[1]+r[3],height:n.height+r[0]+r[2],beforeTransform:()=>{const t=e.getNodes();i=t.filter(t=>t.getModel().collapsed).map(t=>t.getModel().id),i.forEach(t=>{e.update(t,{collapsed:!1})}),e.layout(),o=this.getSelected().map(t=>t.id),a=this.getSelected().map(t=>t.id),this.clearSelected(),this.clearActived()},afterTransform:()=>{i.forEach(t=>{e.update(t,{collapsed:!0})}),this.setSelected(o,!0),this.setActived(a,!0)},...t})}save(){const t=this.get("_graph").save();return t.roots.forEach(t=>{o.traverseTree(t,t=>{delete t.x,delete t.y,delete t.width,delete t.height,delete t.parent,delete t.nth,delete t.hierarchy,delete t.index,delete t.shape},t=>t.children,!0)}),t}}o.each(a,t=>{o.mix(s.prototype,t.AUGMENT)}),i.setRegister(s,"mind","page"),t.exports=s},function(t,e,n){const r=n(7).Util;t.exports=class{getDefaultCfg(){return{}}constructor(t){const e=this.getDefaultCfg();r.mix(!0,this,e,t),this.init()}init(){}destroy(){}}},function(t,e,n){const r={...n(4),getMindNodeSide(t){const e=t.getModel();if(e.side)return e.side;const n=t.getParent();return n?n.getModel().side?n.getModel().side:r.getMindNodeSide(n):void 0}};t.exports=r},function(t,e,n){const r=n(1),i=n(16),o=n(19);class a extends i{constructor(t){const e={graph:{modes:{default:["panBlank","hoverGroupActived","keydownCmdWheelZoom","clickEdgeSelected","clickNodeSelected","clickCanvasSelected","clickGroupSelected","hoverNodeActived","hoverEdgeActived","hoverButton","clickCollapsedButton","clickExpandedButton","wheelChangeViewport","keydownShiftMultiSelected","dragNodeAddToGroup","dragOutFromGroup","panItem","hoverEdgeControlPoint","dragEdgeControlPoint"],add:["dragPanelItemAddNode"],readOnly:["panCanvas"],move:["panCanvas"],multiSelect:["dragMultiSelect"]},mode:"default",defaultIntersectBox:"rect",nodeDefaultShape:"flow-base",edgeDefaultShape:"flow-smooth",groupDefaultShape:"flow-base"},linkNode:!1};o.mix(!0,e,{},t),super(e),this.isFlow=!0}}r.setRegister(a,"flow","diagram"),t.exports=a},function(t,e,n){const r=n(16),i=n(1),o=n(6);class a extends r{constructor(t){const e={graph:{modes:{default:["panBlank","keydownCmdWheelZoom","clickEdgeSelected","clickNodeSelected","clickCanvasSelected","hoverNodeActived","hoverEdgeActived","hoverButton","wheelChangeViewport","keydownShiftMultiSelected","panItem","hoverNodeShowArrowController","hoverEdgeControlPoint","dragEdgeControlPoint","bpmnMoveEdgeController"],add:["dragPanelItemAddNode","processAddEdge"],readOnly:["panCanvas"],move:["panCanvas"],multiSelect:["dragMultiSelect"]},mode:"default",defaultIntersectBox:"rect",nodeDefaultShape:"bpmn-base",edgeDefaultShape:"bpmn-base"},arrowController:{thickness:32,long:32,controllers:[]}};o.mix(!0,e,{},t),super(e),this.isBPMN=!0}_init(){super._init(),this._initArrowController()}_createArrowController(t,e){const n=this.get("arrowController").controllers,r=o.createDOM('<div class="g6-bpmn-arrow"><svg t="1543840367375" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1061" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M906.77248 512c0 4.77184-2.21184 9.2672-5.9904 12.17536l-376.5248 289.4848c-2.7648 2.11968-6.06208 3.18464-9.3696 3.18464-3.25632 0-6.5024-1.03424-9.24672-3.09248-5.50912-4.15744-7.5776-11.48928-5.03808-17.90976l75.71456-191.67232L132.58752 604.17024c-8.48896 0-15.36-6.88128-15.36-15.36l0-153.6c0-8.48896 6.87104-15.36 15.36-15.36l443.72992 0-75.71456-191.68256c-2.53952-6.42048-0.47104-13.75232 5.04832-17.90976 5.50912-4.15744 13.12768-4.13696 18.60608 0.09216l376.5248 289.4848C904.56064 502.7328 906.77248 507.22816 906.77248 512z" p-id="1062" fill="#34B7EF"></path></svg></div>',{visibility:"hidden",width:t+"px",height:e+"px",position:"absolute"});return r.setAttribute("draggable","true"),o.addEventListener(r,"dragstart",()=>{const t=r.hoverNode,e={shape:"bpmn-base",source:t.id,anchorIndex:r.getAttribute("anchorIndex")},n=t.getBBox(),i=this.getDelegation([{isEdge:!0}]);this.setSignal("dragEdge",!0),this.beginAdd("edge",e),this.set("addEdgeConfig",{addModel:e,delegation:i,startPoint:{x:n.centerX,y:n.centerY},sourceItem:t}),this.hideArrowController()}),n.push(r),r}showArrowController(t){this.get("arrowController").controllers.forEach(e=>{e.show(),e.hoverNode=t})}hideArrowController(){this.get("arrowController").controllers.forEach(t=>{t.hide()})}_initArrowController(){const t=this.getGraph().getGraphContainer(),e=this.get("arrowController"),{thickness:n,long:r}=e,i=this._createArrowController(n,r),o=this._createArrowController(n,r),a=this._createArrowController(r,n),s=this._createArrowController(r,n);t.appendChild(i),t.appendChild(o),t.appendChild(a),t.appendChild(s),e.topArrow=i,e.bottomArrow=o,e.leftArrow=a,e.rightArrow=s}bindEvent(){super.bindEvent();const t=this.getGraph();t.on("beforepanitem",()=>{this.hideArrowController()}),t.on("afterviewportchange",()=>{this.hideArrowController()})}}i.setRegister(a,"bpmn","diagram"),t.exports=a},function(t,e,n){const r=n(7),i=n(1),o=n(2),a=n(65),s=n(66),c=n(68),u=n(72),h=[a,n(73),u,s,c,n(74)];class l extends i{constructor(t){const e={shortcut:{copy:!0,paste:!0,selectAll:!0,addGroup:!0,unGroup:!0},graph:{minZoom:.2,maxZoom:2},graphConstructor:r.Graph,noEndEdge:!0},n={};o.each(h,t=>{o.mix(n,t.CFG)}),o.mix(!0,e,n,t),super(e),this.isFlow=!0}_init(){super._init(),o.each(h,t=>{t.INIT&&this[t.INIT]()})}bindEvent(){super.bindEvent(),this.on("beforeitemactived",t=>{const e=t.item,n=this.get("_graph").getShapeObj(e).getActivedOutterStyle(e);e.isNode&&this.addOutterShape(e,n)}),this.on("beforeitemunactived",t=>{const e=t.item;(e.isNode||e.isGroup)&&this.clearOutterShape(e)}),this.on("beforeitemselected",t=>{const e=t.item,n=this.get("_graph").getShapeObj(e).getSelectedOutterStyle(e);(e.isNode||e.isGroup)&&this.addOutterShape(e,n)}),this.on("beforeitemunselected",t=>{const e=t.item;(e.isNode||e.isGroup)&&this.clearOutterShape(e)})}}o.each(h,t=>{o.mix(l.prototype,t.AUGMENT)}),i.setRegister(l,"diagram","page"),t.exports=l},function(t,e){t.exports={gridStyle:{stroke:"#A3B1BF",lineWidth:.5},cursor:{panningCanvas:"-webkit-grabbing",beforePanCanvas:"-webkit-grab"},wheelPanRatio:.3,alignLineStyle:{stroke:"#FA8C16",lineWidth:1},nodeDelegationStyle:{stroke:"#1890FF",fill:"#1890FF",fillOpacity:.08,lineDash:[4,4],radius:4,lineWidth:1},edgeDelegationStyle:{stroke:"#1890FF",lineDash:[4,4],lineWidth:1}}},function(t,e,n){const r=n(18);n(32),n(33),t.exports=r},function(t,e,n){const r=n(13);n(75),n(80),t.exports=r},function(t,e,n){const r=n(1),i=n(16),o=n(24);class a extends i{constructor(t){const e={graph:{modes:{default:["panBlank","hoverGroupActived","keydownCmdWheelZoom","clickEdgeSelected","clickNodeSelected","clickCanvasSelected","clickGroupSelected","hoverNodeActived","hoverEdgeActived","hoverButton","clickCollapsedButton","clickExpandedButton","wheelChangeViewport","keydownShiftMultiSelected","dragNodeAddToGroup","dragOutFromGroup","panItem","hoverEdgeControlPoint","dragEdgeControlPoint"],add:["dragPanelItemAddNode","processAddEdge"],readOnly:["panCanvas"],move:["panCanvas"],multiSelect:["dragMultiSelect"]},mode:"default",defaultIntersectBox:"circle",nodeDefaultShape:"koni-base",edgeDefaultShape:"koni-base",groupDefaultShape:"koni-base",minZoom:.5,maxZoom:2},orbit:{satellite:["forkAndLink"]},anchorLink:!1,noEndEdge:!1};o.mix(!0,e,{},t),super(e),this.isKoni=!0}bindEvent(){super.bindEvent();const t=this.getGraph();t.on("afterchange",({item:e,action:n,originModel:r,updateModel:i})=>{if(e&&e.isEdge)if("add"===n||"remove"===n){const t=e.getSource(),n=e.getTarget();o.getParallelEdges(t,n,!0).forEach(t=>{t.update()})}else if("update"===n){const e=t.find(r.source),n=t.find(r.target);let a=[];if(o.getParallelEdges(e,n,!0).forEach(t=>{t.update()}),o.isNil(i.target)&&!o.isNil(i.source)){const e=t.find(i.source);a=o.getParallelEdges(e,n,!0)}else if(!o.isNil(i.target)&&o.isNil(i.source)){const n=t.find(i.target);a=o.getParallelEdges(e,n,!0)}else if(!o.isNil(i.target)&&!o.isNil(i.source)){const e=t.find(i.source),n=t.find(i.target);a=o.getParallelEdges(e,n,!0)}a.forEach(t=>{t.update()})}"changeData"===n&&t.getEdges().forEach(t=>{t.update()}),t.draw()})}}r.setRegister(a,"koni","diagram"),t.exports=a},function(t,e,n){const r=n(6),i={};function o(t){return t.getCurrentPage().getSelected().length>0}function a(t){const e=t.getCurrentPage();this.snapShot=e.save(),this.selectedItems=e.getSelected().map(t=>t.id),this.method&&(r.isString(this.method)?e[this.method]():this.method(t))}function s(t){const e=t.getCurrentPage();e.read(this.snapShot),e.setSelected(this.selectedItems,!0)}function c(t){return t.getCurrentPage().getMode()!==this.toMode}function u(t){const e=t.getCurrentPage();this.fromMode=e.getMode(),e.changeMode(this.toMode)}function h(t){t.getCurrentPage().changeMode(this.fromMode)}function l(t){const e={},n=[];return t.forEach(t=>{const i=t.model,o=r.mix(!0,{},{...i,id:r.guid()});e[i.id]=o.id,n.push({...t,model:o})}),n.forEach(t=>{const n=t.model;if(n.parent){const t=e[n.parent];t?n.parent=t:delete n.parent}}),n.sort((t,e)=>t.index-e.index),n}i.list=[],i.registerCommand=(t,e,n)=>{if(i[t])r.mix(i[t],e);else{let o={enable:()=>!0,init(){},execute:a,back:s,shortcutCodes:void 0,executeTimes:1,name:t,queue:!0,...e};n&&i[n]&&(o=r.mix({},i[n],e)),i[t]=o,i.list.push(o)}},i.execute=(t,e,n)=>{const o=r.mix(!0,{},i[t],n),a=e.get("_command");return o.enable(e)&&(o.init(),o.queue&&(a.queue.splice(a.current,a.queue.length-a.current,o),a.current+=1),e.emit("beforecommandexecute",{command:o}),o.execute(e),e.emit("aftercommandexecute",{command:o}),e.setCommandDOMenable()),o},i.enable=(t,e)=>i[t].enable(e),i.registerCommand("common",{back:s}),i.registerCommand("copyAdjacent",{enable(){return this.copyNode&&this.copyNode.isNode&&this.x&&this.y},execute(t){const{copyNode:e}=this,n=t.getCurrentPage(),i=n.getGraph(),o=e.getModel(),a=r.clone(o);a.id=r.guid(),a.x=this.x,a.y=this.y;const s=i.add("node",a),c=i.add("edge",{source:o.id,target:a.id});1===this.executeTimes&&(this.addIds=[s.id,c.id],this.page=n)},back(){const t=this.page.getGraph();this.addIds.forEach(e=>{t.remove(e)})}}),i.registerCommand("add",{enable(){return this.type&&this.addModel},execute(t){const e=t.getCurrentPage(),n=e.getGraph().add(this.type,this.addModel);1===this.executeTimes&&(this.addId=n.id,this.page=e)},back(){this.page.getGraph().remove(this.addId)}}),i.registerCommand("update",{enable(){return this.itemId&&this.updateModel},execute(t){const e=t.getCurrentPage(),n=e.getGraph(),i=n.find(this.itemId);1===this.executeTimes&&(this.originModel=r.getContrast(i.getModel(),this.updateModel),this.page=e),n.update(i,this.updateModel)},back(){const t=this.page.getGraph(),e=t.find(this.itemId);t.update(e,this.originModel)}}),i.registerCommand("redo",{queue:!1,enable(t){const e=t.get("_command"),n=e.queue;return e.current<n.length},execute(t){const e=t.get("_command");e.queue[e.current].execute(t),e.current+=1},shortcutCodes:[["metaKey","shiftKey","z"],["ctrlKey","shiftKey","z"]]}),i.registerCommand("undo",{queue:!1,enable:t=>t.get("_command").current>0,execute(t){const e=t.get("_command"),n=e.queue[e.current-1];n.executeTimes++,n.back(t),e.current-=1},shortcutCodes:[["metaKey","z"],["ctrlKey","z"]]}),i.registerCommand("copy",{queue:!1,enable:o,method(t){const e=t.getCurrentPage().getSelected(),n=t.get("_command"),i=e.map(t=>t.getGraphicGroup()),o=r.getChildrenBBox(i);n.clipboard=[],e.forEach(t=>{r.traverseTree(t,t=>{const e=t.getModel(),i=t.getGraphicGroup();n.clipboard.push({type:t.type,index:r.getIndex(i),model:e})},t=>t.getChildren&&t.getChildren(),!0)}),t.set("copyCenterBox",{...o})}}),i.registerCommand("pasteHere",{enable:t=>t.get("_command").clipboard.length>0,method(t){const e=t.getCurrentPage(),n=t.get("_command"),i=this.pasteData?this.pasteData:l(n.clipboard),o=this.copyCenterBox?this.copyCenterBox:t.get("copyCenterBox"),a=this.contextmenuPoint?this.contextmenuPoint:t.get("contextmenuPoint");e.clearSelected(),this.copyCenterBox=r.clone(o),this.pasteData=r.clone(i),this.contextmenuPoint=r.clone(a),i.forEach(t=>{const n=t.model;n.x&&(n.x+=a.x-o.minX),n.y&&(n.y+=a.y-o.minY),e.add(t.type,n)})},back:s}),i.registerCommand("paste",{enable:t=>t.get("_command").clipboard.length>0,method(t){const e=t.getCurrentPage(),n=t.get("_command"),i=this.pasteData?this.pasteData:l(n.clipboard);e.clearSelected(),this.pasteData=r.clone(i),i.forEach(t=>{const n=t.model;n.x&&(n.x+=10),n.y&&(n.y+=10),e.add(t.type,n)})},back:s}),i.registerCommand("addGroup",{init(){this.addGroupId=r.guid()},enable:t=>t.getCurrentPage().getSelected().length>1,method(t){t.getCurrentPage().addGroup({id:this.addGroupId})},back:s}),i.registerCommand("unGroup",{enable(t){const e=t.getCurrentPage().getSelected();return 1===e.length&&e[0].isGroup},method:"unGroup",back:s}),i.registerCommand("delete",{getDeleteItems(t){const e=t.getCurrentPage(),n=e.getGraph();let r=this.itemIds?this.itemIds.map(t=>n.find(t)):e.getSelected();return r=r.filter(t=>!1!==t.deleteable),r},enable(t){return this.getDeleteItems(t).length>0},method(t){const e=t.getCurrentPage(),n=this.getDeleteItems(t),i=e.getGraph();e.emit("beforedelete",{items:n}),r.each(n,t=>{i.remove(t)}),e.emit("afterdelete",{items:n}),this.itemIds=n.map(t=>t.getModel().id)},back:s,shortcutCodes:["Delete","Backspace"]}),i.registerCommand("selectAll",{method(t){const e=t.getCurrentPage();e.getGraph().getItems().forEach(t=>{e.setSelected(t,!0)})},back:s,shortcutCodes:[["metaKey","a"]]}),i.registerCommand("toBack",{enable:o,method:"toBack",back:s}),i.registerCommand("toFront",{enable:o,method:"toFront",back:s}),i.registerCommand("clear",{enable:t=>t.getCurrentPage().getItems().length>0,method:"clear",back:s}),i.registerCommand("multiSelect",{enable:c,toMode:"multiSelect",execute:u,back:h}),i.registerCommand("move",{enable:c,toMode:"move",execute:u,back:h}),t.exports=i},function(t,e,n){t.exports=n(2)},function(t,e,n){"use strict";n.r(e),n.d(e,"mouseEnterEdge",(function(){return i})),n.d(e,"mouseLeaveEdge",(function(){return o})),n.d(e,"startMove",(function(){return a})),n.d(e,"endMove",(function(){return s})),n.d(e,"mouseMoveEdge",(function(){return c})),n.d(e,"mergeLine",(function(){return u}));var r=n(0);function i({graph:t,bpmn:e,ev:n,backUpCursor:i}){const o=n.item,a=o.model.controlPoints,{index:s,vertical:c}=Object(r.e)({x:n.x,y:n.y},a);null!=s&&(i&&(o._cursor=e.getGraph().getMouseEventWrapper().style.cursor),t.update(o,{hold:{index:s,vertical:c}}),c?e.css({cursor:"col-resize"}):e.css({cursor:"row-resize"}))}function o({graph:t,bpmn:e,item:n}){n._cursor&&e.css({cursor:n._cursor}),delete n._cursor,t.update(n,{hold:void 0})}function a(t,e){const n=e.item;t.update(n,{lastMouse:{x:e.x,y:e.y}})}function s({graph:t,item:e}){t.update(e,{lastMouse:void 0,moveDelta:void 0})}function c(t,e,n){let r;r=e.model&&e.model.hold&&e.model.hold.vertical?{x:n.x-e.model.lastMouse.x,y:0}:{x:0,y:n.y-e.model.lastMouse.y},t.update(e,{edgeMoved:r,modifiedByMouse:!0})}function u(t,e,n){const r=t.model,i=e||r.hold.index,o=r.controlPoints;let a;null===n&&(n=r.hold.vertical);const s=[];return i>=2&&(n?Math.abs(o[i-2].x-o[i].x)<=3&&(a=[{x:o[i-2].x,y:o[i-2].y},{x:o[i-2].x,y:o[i+1].y}],s.push(i-1,i),r.hold.index=i-2,r.controlPoints[i+1].x=o[i-2].x):Math.abs(o[i-2].y-o[i].y)<=3&&(a=[{x:o[i-2].x,y:o[i-2].y},{x:o[i+1].x,y:o[i-2].y}],s.push(i-1,i),r.hold.index=i-2,r.controlPoints[i+1].y=o[i-2].y)),i<=o.length-4&&(n?Math.abs(o[i].x-o[i+2].x)<=3&&(a?(a[1]={x:o[i-2].x,y:o[i+3].y},r.controlPoints[i+3].x=o[i-2].x):(a=[{x:o[i+3].x,y:o[i].y},{x:o[i+3].x,y:o[i+3].y}],r.controlPoints[i].x=o[i+3].x),s.push(i+1,i+2)):Math.abs(o[i].y-o[i+2].y)<=3&&(a?(a[1]={x:o[i+3].x,y:o[i-2].y},r.controlPoints[i+3].y=o[i-2].y):(a=[{x:o[i].x,y:o[i+3].y},{x:o[i+3].x,y:o[i+3].y}],r.controlPoints[i].y=o[i+3].y),s.push(i+1,i+2))),s&&s.length&&o.splice(s[0],s.length),a}},function(t,e,n){const r=n(27),i=n(6);t.exports=class extends r{getDefaultCfg(){return{}}constructor(t){super();const e=this.getDefaultCfg();this._cfg=i.mix(!0,{},this._cfg,e,t)}get(t){return this._cfg[t]}set(t,e){this._cfg[t]=e}destroy(){this._cfg={},this.destroyed=!0}}},function(t,e,n){const r=n(4);t.exports={...r,getParallelEdges:(t,e,n=!1)=>t.getEdges().filter(t=>{const r=t.getModel();return r.target===e.id||n&&r.source===e.id}),object2array(t){const e=[];return r.each(t,t=>{e.push(t)}),e}}},function(t,e,n){const r=n(9),i=n(2);t.exports=class extends r{getDefaultCfg(){return{name:"",render:()=>"<button>satellite</button>",bindEvent:()=>[]}}_renderDOM(){const t=i.createDOM(this.render(this.diagram));return this.dom=t,t.isSatellite=!0,t}getDOM(){return this.dom||this._renderDOM()}init(){const t=this.getDOM(),e=this.diagram.getGraph().getGraphContainer();t&&(t.css({position:"absolute",visibility:"hidden"}),e.appendChild(t),t&&this.bindEvent(t,this.diagram))}enable(){return!0}show(){this.getDOM().show()}hide(){this.getDOM().hide()}isVisible(){return"hidden"!==this.getDOM().style.visibility}destroy(){const{events:t}=this;t&&t.forEach(t=>{t.remove()})}}},function(t,e,n){t.exports=n(2)},function(t,e,n){const r=n(26),i=n(6),o=n(15);n(7);r.Editor=r,r.Util=i,r.Diagram=n(16),r.Page=n(1),r.Flow=n(95),r.Koni=n(102),r.Mind=n(107),r.Toolbar=n(121),r.Contextmenu=n(122),r.Command=n(15),r.BPMN=n(123),r.registerBehaviour=r.Page.registerBehaviour,r.registerNode=r.Page.registerNode,r.registerEdge=r.Page.registerEdge,r.registerGroup=r.Page.registerGroup,r.registerGuide=r.Page.registerGuide,r.registerCommand=o.registerCommand,t.exports=r},function(t,e,n){const r=n(21),i=n(6),o=n(15);t.exports=class extends r{getDefaultCfg(){return{_components:[],_command:{zoomDelta:.1,queue:[],current:0,clipboard:[]}}}_getComponentsBy(t){return this.get("_components").filter(t)}_bindCommands(t){i.each(t,t=>{const e=t.dataset,n=e.command;o[n]?i.addEventListener(t,"click",()=>{this.getCurrentPage().focusGraphWrapper(),this.executeCommand(n,e)}):console.warn("请设置有效的命令!")})}getCommands(){return this.get("_command").queue}getCurrentCommand(){const t=this.get("_command"),{queue:e,current:n}=t;return e[n-1]}executeCommand(t,e){i.isString(t)?o.execute(t,this,e):o.execute("common",this,{method:t},e)}commandEnable(t){return o.enable(t,this)}setCommandDOMenable(){const t=this.getComponentsByType("toolbar"),e=this.getComponentsByType("contextmenu"),n=[];t.forEach(t=>{i.each(t.getCommandDoms(),t=>{n.push(t)})}),e.forEach(t=>{i.each(t.getCommandDoms(),t=>{n.push(t)})}),i.each(n,t=>{const e=t.dataset.command;o.enable(e,this)?t.classList.remove("disable"):t.classList.add("disable")})}_onPageStatusChange(){this.setCommandDOMenable()}_afterAddContextmenu(){this.getCurrentPage()&&this.setCommandDOMenable()}_afterAddPage(t){this.setCommandDOMenable(),t.on("statuschange",t=>{this._onPageStatusChange(t)}),t.on("mousedown",()=>{this.getComponentsByType("contextmenu").forEach(t=>{t.hide()})}),t.on("contextmenu",e=>{const n=this.getComponentsByType("contextmenu"),r=t.getGraph().getCanvas().get("el"),o=i.getBoundingClientRect(r),a={x:e.x,y:e.y},{item:s}=e;s&&!s.isSelected&&(t.clearSelected(),t.setSelected(e.item,!0)),this.set("contextmenuPoint",a),e.domEvent.preventDefault(),n.forEach(t=>{t.show(),t.contextmenuPoint=a,t.move(o.left+e.domX,o.top+e.domY)})}),t.on("statuschange",t=>{this.getComponentsByType("contextmenu").forEach(e=>{e.switch(t.status)})}),this._bindShortcut(t)}_beforeAddToolbar(t){const e=t.getCommandDoms();this._bindCommands(e)}_beforeAddContextmenu(t){const e=t.getCommandDoms();t.bindEvent(),this._bindCommands(e)}getComponentsByType(t){return this._getComponentsBy(e=>e.type===t)}getCurrentPage(){const t=this.getComponentsByType("page");let e;return t.every(t=>!t.isActived||(e=t,!1)),e||(e=t[0]),e}getComponents(){return this.get("_components")}_shortcutEnable(t,e){const n=t.shortcutCodes,r=i.getKeyboradKey(e);let o=!1;for(let t=0;t<n.length;t++){const a=n[t];if(i.isArray(a)){const t=a.length;let n=!0;for(let r=0;r<t-1;r++)if(!e[a[r]]){n=!1;break}a[t-1]!==r&&a[t-1]!==i.lowerFirst(r)||!n||(o=!0)}else a===r&&(o=!0);if(o)break}return o}_bindShortcut(t){const e=t.get("shortcut");t.getGraph().on("keydown",t=>{const n=this.getComponentsByType("contextmenu"),{domEvent:r}=t;n.forEach(t=>{t.hide()}),r.preventDefault();const i=o.list.filter(t=>t.shortcutCodes&&e[t.name]);for(let t=0;t<i.length;t++){const e=i[t];if(this._shortcutEnable(e,r))return this.executeCommand(e.name),!1}})}add(t){const e=this.get("_components"),n=i.upperFirst(t.type);t.editor=this,this["_beforeAdd"+n]&&this["_beforeAdd"+n](t),e.push(t),this["_afterAdd"+n]&&this["_afterAdd"+n](t)}destroy(){this.get("_components").forEach(t=>{t.destroy()})}}},function(t,e,n){var r; +/*! + * EventEmitter v5.2.9 - git.io/ee + * Unlicense - http://unlicense.org/ + * Oliver Caldwell - https://oli.me.uk/ + * @preserve + */!function(e){"use strict";function i(){}var o=i.prototype,a=e.EventEmitter;function s(t,e){for(var n=t.length;n--;)if(t[n].listener===e)return n;return-1}function c(t){return function(){return this[t].apply(this,arguments)}}o.getListeners=function(t){var e,n,r=this._getEvents();if(t instanceof RegExp)for(n in e={},r)r.hasOwnProperty(n)&&t.test(n)&&(e[n]=r[n]);else e=r[t]||(r[t]=[]);return e},o.flattenListeners=function(t){var e,n=[];for(e=0;e<t.length;e+=1)n.push(t[e].listener);return n},o.getListenersAsObject=function(t){var e,n=this.getListeners(t);return n instanceof Array&&((e={})[t]=n),e||n},o.addListener=function(t,e){if(!function t(e){return"function"==typeof e||e instanceof RegExp||!(!e||"object"!=typeof e)&&t(e.listener)}(e))throw new TypeError("listener must be a function");var n,r=this.getListenersAsObject(t),i="object"==typeof e;for(n in r)r.hasOwnProperty(n)&&-1===s(r[n],e)&&r[n].push(i?e:{listener:e,once:!1});return this},o.on=c("addListener"),o.addOnceListener=function(t,e){return this.addListener(t,{listener:e,once:!0})},o.once=c("addOnceListener"),o.defineEvent=function(t){return this.getListeners(t),this},o.defineEvents=function(t){for(var e=0;e<t.length;e+=1)this.defineEvent(t[e]);return this},o.removeListener=function(t,e){var n,r,i=this.getListenersAsObject(t);for(r in i)i.hasOwnProperty(r)&&-1!==(n=s(i[r],e))&&i[r].splice(n,1);return this},o.off=c("removeListener"),o.addListeners=function(t,e){return this.manipulateListeners(!1,t,e)},o.removeListeners=function(t,e){return this.manipulateListeners(!0,t,e)},o.manipulateListeners=function(t,e,n){var r,i,o=t?this.removeListener:this.addListener,a=t?this.removeListeners:this.addListeners;if("object"!=typeof e||e instanceof RegExp)for(r=n.length;r--;)o.call(this,e,n[r]);else for(r in e)e.hasOwnProperty(r)&&(i=e[r])&&("function"==typeof i?o.call(this,r,i):a.call(this,r,i));return this},o.removeEvent=function(t){var e,n=typeof t,r=this._getEvents();if("string"===n)delete r[t];else if(t instanceof RegExp)for(e in r)r.hasOwnProperty(e)&&t.test(e)&&delete r[e];else delete this._events;return this},o.removeAllListeners=c("removeEvent"),o.emitEvent=function(t,e){var n,r,i,o,a=this.getListenersAsObject(t);for(o in a)if(a.hasOwnProperty(o))for(n=a[o].slice(0),i=0;i<n.length;i++)!0===(r=n[i]).once&&this.removeListener(t,r.listener),r.listener.apply(this,e||[])===this._getOnceReturnValue()&&this.removeListener(t,r.listener);return this},o.trigger=c("emitEvent"),o.emit=function(t){var e=Array.prototype.slice.call(arguments,1);return this.emitEvent(t,e)},o.setOnceReturnValue=function(t){return this._onceReturnValue=t,this},o._getOnceReturnValue=function(){return!this.hasOwnProperty("_onceReturnValue")||this._onceReturnValue},o._getEvents=function(){return this._events||(this._events={})},i.noConflict=function(){return e.EventEmitter=a,i},void 0===(r=function(){return i}.call(e,n,e,t))||(t.exports=r)}("undefined"!=typeof window?window:this||{})},function(t,e,n){const r=n(7).Util;t.exports={getGroupIconPath:()=>"M9.75,9.60000014 L3.75,9.60000014 C3.33578644,9.60000014 3,9.2865995 3,8.90000022 C3,8.51340093 3.33578644,8.20000029 3.75,8.20000029 L9.75,8.20000029 C10.1642136,8.20000029 10.5,8.51340093 10.5,8.90000022 C10.5,9.2865995 10.1642136,9.60000014 9.75,9.60000014 M3,11.6999999 C3,11.3134006 3.33578644,11 3.75,11 L6.75,11 C7.16421356,11 7.5,11.3134006 7.5,11.6999999 C7.5,12.0865992 7.16421356,12.3999999 6.75,12.3999999 L3.75,12.3999999 C3.33578644,12.3999999 3,12.0865992 3,11.6999999 M3.75,13.7999997 L6.75,13.7999997 C7.16421356,13.7999997 7.5,14.1134004 7.5,14.4999996 C7.5,14.8865989 7.16421356,15.1999996 6.75,15.1999996 L3.75,15.1999996 C3.33578644,15.1999996 3,14.8865989 3,14.4999996 C3,14.1134004 3.33578644,13.7999997 3.75,13.7999997 M16.4985,4.00000072 L1.5015,4.00000072 C0.674533504,3.99922416 0.00289396564,4.6232696 0,5.39510058 L0,16.6048994 C0.00289396564,17.3767304 0.674533504,18.0007758 1.5015,17.9999993 L16.4985,17.9999993 C17.3254665,18.0007758 17.997106,17.3767304 18,16.6048994 L18,5.39510058 C17.997106,4.6232696 17.3254665,3.99922416 16.4985,4.00000072M19,13.9999993 L19,3 L5,3 L5,1.39510058 C5.00289397,0.623269599 5.6745335,-0.00077583787 6.5015,7.23978642e-07 L21.4985,7.23978642e-07 C22.3254665,-0.00077583787 22.997106,0.623269599 23,1.39510058 L23,12.6048994 C22.997106,13.3767304 22.3254665,14.0007758 21.4985,13.9999993 L19,13.9999993 Z",getCollapsedButtonPath:()=>r.getRectPath(0,0,14,14,2)+"M3,7L11,7",getExpandedButtonPath:()=>r.getRectPath(0,0,14,14,2)+"M3,7L11,7M7,3L7,11"}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.presetPrimaryColors=e.presetPalettes=e.generate=void 0;var r,i=n(30),o=(r=i)&&r.__esModule?r:{default:r};var a={red:"#F5222D",volcano:"#FA541C",orange:"#FA8C16",gold:"#FAAD14",yellow:"#FADB14",lime:"#A0D911",green:"#52C41A",cyan:"#13C2C2",blue:"#1890FF",geekblue:"#2F54EB",purple:"#722ED1",magenta:"#EB2F96",grey:"#666666"},s={};Object.keys(a).forEach((function(t){s[t]=(0,o.default)(a[t])})),e.generate=o.default,e.presetPalettes=s,e.presetPrimaryColors=a},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(t){for(var e=[],n=(0,o.default)(t),r=5;r>0;r-=1){var i=n.toHsv(),u=(0,o.default)({h:a(i,r,!0),s:s(i,r,!0),v:c(i,r,!0)}).toHexString();e.push(u)}e.push(n.toHexString());for(var h=1;h<=4;h+=1){var l=n.toHsv(),d=(0,o.default)({h:a(l,h),s:s(l,h),v:c(l,h)}).toHexString();e.push(d)}return e};var r,i=n(31),o=(r=i)&&r.__esModule?r:{default:r};function a(t,e,n){var r=void 0;return(r=Math.round(t.h)>=60&&Math.round(t.h)<=240?n?Math.round(t.h)-2*e:Math.round(t.h)+2*e:n?Math.round(t.h)+2*e:Math.round(t.h)-2*e)<0?r+=360:r>=360&&(r-=360),r}function s(t,e,n){if(0===t.h&&0===t.s)return t.s;var r=void 0;return(r=n?Math.round(100*t.s)-16*e:4===e?Math.round(100*t.s)+16:Math.round(100*t.s)+5*e)>100&&(r=100),n&&5===e&&r>10&&(r=10),r<6&&(r=6),r}function c(t,e,n){return n?Math.round(100*t.v)+5*e:Math.round(100*t.v)-15*e}},function(t,e,n){var r;!function(i){var o=/^\s+/,a=/\s+$/,s=0,c=i.round,u=i.min,h=i.max,l=i.random;function d(t,e){if(e=e||{},(t=t||"")instanceof d)return t;if(!(this instanceof d))return new d(t,e);var n=function(t){var e={r:0,g:0,b:0},n=1,r=null,s=null,c=null,l=!1,d=!1;"string"==typeof t&&(t=function(t){t=t.replace(o,"").replace(a,"").toLowerCase();var e,n=!1;if(I[t])t=I[t],n=!0;else if("transparent"==t)return{r:0,g:0,b:0,a:0,format:"name"};if(e=H.rgb.exec(t))return{r:e[1],g:e[2],b:e[3]};if(e=H.rgba.exec(t))return{r:e[1],g:e[2],b:e[3],a:e[4]};if(e=H.hsl.exec(t))return{h:e[1],s:e[2],l:e[3]};if(e=H.hsla.exec(t))return{h:e[1],s:e[2],l:e[3],a:e[4]};if(e=H.hsv.exec(t))return{h:e[1],s:e[2],v:e[3]};if(e=H.hsva.exec(t))return{h:e[1],s:e[2],v:e[3],a:e[4]};if(e=H.hex8.exec(t))return{r:L(e[1]),g:L(e[2]),b:L(e[3]),a:D(e[4]),format:n?"name":"hex8"};if(e=H.hex6.exec(t))return{r:L(e[1]),g:L(e[2]),b:L(e[3]),format:n?"name":"hex"};if(e=H.hex4.exec(t))return{r:L(e[1]+""+e[1]),g:L(e[2]+""+e[2]),b:L(e[3]+""+e[3]),a:D(e[4]+""+e[4]),format:n?"name":"hex8"};if(e=H.hex3.exec(t))return{r:L(e[1]+""+e[1]),g:L(e[2]+""+e[2]),b:L(e[3]+""+e[3]),format:n?"name":"hex"};return!1}(t));"object"==typeof t&&(q(t.r)&&q(t.g)&&q(t.b)?(f=t.r,g=t.g,p=t.b,e={r:255*T(f,255),g:255*T(g,255),b:255*T(p,255)},l=!0,d="%"===String(t.r).substr(-1)?"prgb":"rgb"):q(t.h)&&q(t.s)&&q(t.v)?(r=X(t.s),s=X(t.v),e=function(t,e,n){t=6*T(t,360),e=T(e,100),n=T(n,100);var r=i.floor(t),o=t-r,a=n*(1-e),s=n*(1-o*e),c=n*(1-(1-o)*e),u=r%6;return{r:255*[n,s,a,a,c,n][u],g:255*[c,n,n,s,a,a][u],b:255*[a,a,c,n,n,s][u]}}(t.h,r,s),l=!0,d="hsv"):q(t.h)&&q(t.s)&&q(t.l)&&(r=X(t.s),c=X(t.l),e=function(t,e,n){var r,i,o;function a(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+(e-t)*(2/3-n)*6:t}if(t=T(t,360),e=T(e,100),n=T(n,100),0===e)r=i=o=n;else{var s=n<.5?n*(1+e):n+e-n*e,c=2*n-s;r=a(c,s,t+1/3),i=a(c,s,t),o=a(c,s,t-1/3)}return{r:255*r,g:255*i,b:255*o}}(t.h,r,c),l=!0,d="hsl"),t.hasOwnProperty("a")&&(n=t.a));var f,g,p;return n=B(n),{ok:l,format:t.format||d,r:u(255,h(e.r,0)),g:u(255,h(e.g,0)),b:u(255,h(e.b,0)),a:n}}(t);this._originalInput=t,this._r=n.r,this._g=n.g,this._b=n.b,this._a=n.a,this._roundA=c(100*this._a)/100,this._format=e.format||n.format,this._gradientType=e.gradientType,this._r<1&&(this._r=c(this._r)),this._g<1&&(this._g=c(this._g)),this._b<1&&(this._b=c(this._b)),this._ok=n.ok,this._tc_id=s++}function f(t,e,n){t=T(t,255),e=T(e,255),n=T(n,255);var r,i,o=h(t,e,n),a=u(t,e,n),s=(o+a)/2;if(o==a)r=i=0;else{var c=o-a;switch(i=s>.5?c/(2-o-a):c/(o+a),o){case t:r=(e-n)/c+(e<n?6:0);break;case e:r=(n-t)/c+2;break;case n:r=(t-e)/c+4}r/=6}return{h:r,s:i,l:s}}function g(t,e,n){t=T(t,255),e=T(e,255),n=T(n,255);var r,i,o=h(t,e,n),a=u(t,e,n),s=o,c=o-a;if(i=0===o?0:c/o,o==a)r=0;else{switch(o){case t:r=(e-n)/c+(e<n?6:0);break;case e:r=(n-t)/c+2;break;case n:r=(t-e)/c+4}r/=6}return{h:r,s:i,v:s}}function p(t,e,n,r){var i=[Y(c(t).toString(16)),Y(c(e).toString(16)),Y(c(n).toString(16))];return r&&i[0].charAt(0)==i[0].charAt(1)&&i[1].charAt(0)==i[1].charAt(1)&&i[2].charAt(0)==i[2].charAt(1)?i[0].charAt(0)+i[1].charAt(0)+i[2].charAt(0):i.join("")}function m(t,e,n,r){return[Y(G(r)),Y(c(t).toString(16)),Y(c(e).toString(16)),Y(c(n).toString(16))].join("")}function v(t,e){e=0===e?0:e||10;var n=d(t).toHsl();return n.s-=e/100,n.s=N(n.s),d(n)}function x(t,e){e=0===e?0:e||10;var n=d(t).toHsl();return n.s+=e/100,n.s=N(n.s),d(n)}function y(t){return d(t).desaturate(100)}function b(t,e){e=0===e?0:e||10;var n=d(t).toHsl();return n.l+=e/100,n.l=N(n.l),d(n)}function w(t,e){e=0===e?0:e||10;var n=d(t).toRgb();return n.r=h(0,u(255,n.r-c(-e/100*255))),n.g=h(0,u(255,n.g-c(-e/100*255))),n.b=h(0,u(255,n.b-c(-e/100*255))),d(n)}function M(t,e){e=0===e?0:e||10;var n=d(t).toHsl();return n.l-=e/100,n.l=N(n.l),d(n)}function _(t,e){var n=d(t).toHsl(),r=(n.h+e)%360;return n.h=r<0?360+r:r,d(n)}function S(t){var e=d(t).toHsl();return e.h=(e.h+180)%360,d(e)}function A(t){var e=d(t).toHsl(),n=e.h;return[d(t),d({h:(n+120)%360,s:e.s,l:e.l}),d({h:(n+240)%360,s:e.s,l:e.l})]}function E(t){var e=d(t).toHsl(),n=e.h;return[d(t),d({h:(n+90)%360,s:e.s,l:e.l}),d({h:(n+180)%360,s:e.s,l:e.l}),d({h:(n+270)%360,s:e.s,l:e.l})]}function P(t){var e=d(t).toHsl(),n=e.h;return[d(t),d({h:(n+72)%360,s:e.s,l:e.l}),d({h:(n+216)%360,s:e.s,l:e.l})]}function C(t,e,n){e=e||6,n=n||30;var r=d(t).toHsl(),i=360/n,o=[d(t)];for(r.h=(r.h-(i*e>>1)+720)%360;--e;)r.h=(r.h+i)%360,o.push(d(r));return o}function O(t,e){e=e||6;for(var n=d(t).toHsv(),r=n.h,i=n.s,o=n.v,a=[],s=1/e;e--;)a.push(d({h:r,s:i,v:o})),o=(o+s)%1;return a}d.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var t=this.toRgb();return(299*t.r+587*t.g+114*t.b)/1e3},getLuminance:function(){var t,e,n,r=this.toRgb();return t=r.r/255,e=r.g/255,n=r.b/255,.2126*(t<=.03928?t/12.92:i.pow((t+.055)/1.055,2.4))+.7152*(e<=.03928?e/12.92:i.pow((e+.055)/1.055,2.4))+.0722*(n<=.03928?n/12.92:i.pow((n+.055)/1.055,2.4))},setAlpha:function(t){return this._a=B(t),this._roundA=c(100*this._a)/100,this},toHsv:function(){var t=g(this._r,this._g,this._b);return{h:360*t.h,s:t.s,v:t.v,a:this._a}},toHsvString:function(){var t=g(this._r,this._g,this._b),e=c(360*t.h),n=c(100*t.s),r=c(100*t.v);return 1==this._a?"hsv("+e+", "+n+"%, "+r+"%)":"hsva("+e+", "+n+"%, "+r+"%, "+this._roundA+")"},toHsl:function(){var t=f(this._r,this._g,this._b);return{h:360*t.h,s:t.s,l:t.l,a:this._a}},toHslString:function(){var t=f(this._r,this._g,this._b),e=c(360*t.h),n=c(100*t.s),r=c(100*t.l);return 1==this._a?"hsl("+e+", "+n+"%, "+r+"%)":"hsla("+e+", "+n+"%, "+r+"%, "+this._roundA+")"},toHex:function(t){return p(this._r,this._g,this._b,t)},toHexString:function(t){return"#"+this.toHex(t)},toHex8:function(t){return function(t,e,n,r,i){var o=[Y(c(t).toString(16)),Y(c(e).toString(16)),Y(c(n).toString(16)),Y(G(r))];if(i&&o[0].charAt(0)==o[0].charAt(1)&&o[1].charAt(0)==o[1].charAt(1)&&o[2].charAt(0)==o[2].charAt(1)&&o[3].charAt(0)==o[3].charAt(1))return o[0].charAt(0)+o[1].charAt(0)+o[2].charAt(0)+o[3].charAt(0);return o.join("")}(this._r,this._g,this._b,this._a,t)},toHex8String:function(t){return"#"+this.toHex8(t)},toRgb:function(){return{r:c(this._r),g:c(this._g),b:c(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+c(this._r)+", "+c(this._g)+", "+c(this._b)+")":"rgba("+c(this._r)+", "+c(this._g)+", "+c(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:c(100*T(this._r,255))+"%",g:c(100*T(this._g,255))+"%",b:c(100*T(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+c(100*T(this._r,255))+"%, "+c(100*T(this._g,255))+"%, "+c(100*T(this._b,255))+"%)":"rgba("+c(100*T(this._r,255))+"%, "+c(100*T(this._g,255))+"%, "+c(100*T(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(k[p(this._r,this._g,this._b,!0)]||!1)},toFilter:function(t){var e="#"+m(this._r,this._g,this._b,this._a),n=e,r=this._gradientType?"GradientType = 1, ":"";if(t){var i=d(t);n="#"+m(i._r,i._g,i._b,i._a)}return"progid:DXImageTransform.Microsoft.gradient("+r+"startColorstr="+e+",endColorstr="+n+")"},toString:function(t){var e=!!t;t=t||this._format;var n=!1,r=this._a<1&&this._a>=0;return e||!r||"hex"!==t&&"hex6"!==t&&"hex3"!==t&&"hex4"!==t&&"hex8"!==t&&"name"!==t?("rgb"===t&&(n=this.toRgbString()),"prgb"===t&&(n=this.toPercentageRgbString()),"hex"!==t&&"hex6"!==t||(n=this.toHexString()),"hex3"===t&&(n=this.toHexString(!0)),"hex4"===t&&(n=this.toHex8String(!0)),"hex8"===t&&(n=this.toHex8String()),"name"===t&&(n=this.toName()),"hsl"===t&&(n=this.toHslString()),"hsv"===t&&(n=this.toHsvString()),n||this.toHexString()):"name"===t&&0===this._a?this.toName():this.toRgbString()},clone:function(){return d(this.toString())},_applyModification:function(t,e){var n=t.apply(null,[this].concat([].slice.call(e)));return this._r=n._r,this._g=n._g,this._b=n._b,this.setAlpha(n._a),this},lighten:function(){return this._applyModification(b,arguments)},brighten:function(){return this._applyModification(w,arguments)},darken:function(){return this._applyModification(M,arguments)},desaturate:function(){return this._applyModification(v,arguments)},saturate:function(){return this._applyModification(x,arguments)},greyscale:function(){return this._applyModification(y,arguments)},spin:function(){return this._applyModification(_,arguments)},_applyCombination:function(t,e){return t.apply(null,[this].concat([].slice.call(e)))},analogous:function(){return this._applyCombination(C,arguments)},complement:function(){return this._applyCombination(S,arguments)},monochromatic:function(){return this._applyCombination(O,arguments)},splitcomplement:function(){return this._applyCombination(P,arguments)},triad:function(){return this._applyCombination(A,arguments)},tetrad:function(){return this._applyCombination(E,arguments)}},d.fromRatio=function(t,e){if("object"==typeof t){var n={};for(var r in t)t.hasOwnProperty(r)&&(n[r]="a"===r?t[r]:X(t[r]));t=n}return d(t,e)},d.equals=function(t,e){return!(!t||!e)&&d(t).toRgbString()==d(e).toRgbString()},d.random=function(){return d.fromRatio({r:l(),g:l(),b:l()})},d.mix=function(t,e,n){n=0===n?0:n||50;var r=d(t).toRgb(),i=d(e).toRgb(),o=n/100;return d({r:(i.r-r.r)*o+r.r,g:(i.g-r.g)*o+r.g,b:(i.b-r.b)*o+r.b,a:(i.a-r.a)*o+r.a})},d.readability=function(t,e){var n=d(t),r=d(e);return(i.max(n.getLuminance(),r.getLuminance())+.05)/(i.min(n.getLuminance(),r.getLuminance())+.05)},d.isReadable=function(t,e,n){var r,i,o=d.readability(t,e);switch(i=!1,(r=function(t){var e,n;e=((t=t||{level:"AA",size:"small"}).level||"AA").toUpperCase(),n=(t.size||"small").toLowerCase(),"AA"!==e&&"AAA"!==e&&(e="AA");"small"!==n&&"large"!==n&&(n="small");return{level:e,size:n}}(n)).level+r.size){case"AAsmall":case"AAAlarge":i=o>=4.5;break;case"AAlarge":i=o>=3;break;case"AAAsmall":i=o>=7}return i},d.mostReadable=function(t,e,n){var r,i,o,a,s=null,c=0;i=(n=n||{}).includeFallbackColors,o=n.level,a=n.size;for(var u=0;u<e.length;u++)(r=d.readability(t,e[u]))>c&&(c=r,s=d(e[u]));return d.isReadable(t,s,{level:o,size:a})||!i?s:(n.includeFallbackColors=!1,d.mostReadable(t,["#fff","#000"],n))};var I=d.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},k=d.hexNames=function(t){var e={};for(var n in t)t.hasOwnProperty(n)&&(e[t[n]]=n);return e}(I);function B(t){return t=parseFloat(t),(isNaN(t)||t<0||t>1)&&(t=1),t}function T(t,e){(function(t){return"string"==typeof t&&-1!=t.indexOf(".")&&1===parseFloat(t)})(t)&&(t="100%");var n=function(t){return"string"==typeof t&&-1!=t.indexOf("%")}(t);return t=u(e,h(0,parseFloat(t))),n&&(t=parseInt(t*e,10)/100),i.abs(t-e)<1e-6?1:t%e/parseFloat(e)}function N(t){return u(1,h(0,t))}function L(t){return parseInt(t,16)}function Y(t){return 1==t.length?"0"+t:""+t}function X(t){return t<=1&&(t=100*t+"%"),t}function G(t){return i.round(255*parseFloat(t)).toString(16)}function D(t){return L(t)/255}var F,j,R,H=(j="[\\s|\\(]+("+(F="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)")+")[,|\\s]+("+F+")[,|\\s]+("+F+")\\s*\\)?",R="[\\s|\\(]+("+F+")[,|\\s]+("+F+")[,|\\s]+("+F+")[,|\\s]+("+F+")\\s*\\)?",{CSS_UNIT:new RegExp(F),rgb:new RegExp("rgb"+j),rgba:new RegExp("rgba"+R),hsl:new RegExp("hsl"+j),hsla:new RegExp("hsla"+R),hsv:new RegExp("hsv"+j),hsva:new RegExp("hsva"+R),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/});function q(t){return!!H.CSS_UNIT.exec(t)}t.exports?t.exports=d:void 0===(r=function(){return d}.call(e,n,e,t))||(t.exports=r)}(Math)},function(t,e,n){const r=n(18);function i(t){const e=t.getCurrentPage();this.matrixCache=e.getMatrix().slice(0),this._zoom(t),e.updateStatus()}function o(t){t.getCurrentPage().updateMatrix(this.matrixCache)}r.registerCommand("zoomTo",{_zoom(t){t.getCurrentPage().zoom(Number(this.zoom))},queue:!1,execute:i,back:o}),r.registerCommand("zoomIn",{enable(t){const e=t.getCurrentPage(),n=e.getMaxZoom(),r=e.getMinZoom(),i=e.getZoom();return i<n||i===r},_zoom(t){const e=t.getCurrentPage(),n=t.get("_command"),r=e.getZoom(),i=e.getMaxZoom();let o=r+n.zoomDelta;o>=i&&(o=i),e.zoom(o)},queue:!1,execute:i,back:o,shortcutCodes:[["metaKey","="],["ctrlKey","="]]}),r.registerCommand("zoomOut",{enable(t){const e=t.getCurrentPage(),n=e.getMaxZoom(),r=e.getMinZoom(),i=e.getZoom();return i>r||i===n},_zoom(t){const e=t.getCurrentPage(),n=e.getZoom(),r=e.getMinZoom();let i=n-t.get("_command").zoomDelta;i<=r&&(i=r),e.zoom(i)},queue:!1,execute:i,back:o,shortcutCodes:[["metaKey","-"],["ctrlKey","-"]]}),r.registerCommand("autoZoom",{enable:()=>!0,_zoom(t){t.getCurrentPage().autoZoom()},queue:!1,execute:i,back:o}),r.registerCommand("resetZoom",{enable:()=>!0,_zoom(t){t.getCurrentPage().resetZoom()},queue:!1,execute:i,back:o,shortcutCodes:[["metaKey","0"],["ctrlKey","0"]]})},function(t,e,n){const r=n(18);r.registerCommand("collapseExpand",{getItem(t){const e=t.getCurrentPage(),n=e.getGraph();return this.itemId?n.find(this.itemId):e.getSelected()[0]},enable(t){const e=this.getItem(t);return e&&!1!==e.collapseExpand&&e.getChildren().length>0},execute(t){const e=t.getCurrentPage(),n=e.getGraph(),r=this.getItem(t);r.getModel().collapsed?(n.update(r,{collapsed:!1}),r.getInnerEdges&&r.getInnerEdges().forEach(t=>{t.update()}),this.toCollapsed=!1):(n.update(r,{collapsed:!0}),this.toCollapsed=!0),e.clearSelected(),e.setSelected(r,!0),1===this.executeTimes&&(this.itemId=r.id)},back(t){const e=t.getCurrentPage(),n=e.getGraph(),r=this.getItem(t);this.toCollapsed?n.update(r,{collapsed:!1}):n.update(r,{collapsed:!0}),e.clearSelected(),e.setSelected(r,!0)},shortcutCodes:[["metaKey","/"],["ctrlKey","/"]]}),r.registerCommand("collapse",{enable(t){const e=this.getItem(t);return e&&!1!==e.collapseExpand&&e.getChildren().length>0&&!e.getModel().collapsed}},"collapseExpand"),r.registerCommand("expand",{enable(t){const e=this.getItem(t);return e&&!1!==e.collapseExpand&&e.getChildren().length>0&&e.getModel().collapsed}},"collapseExpand")},function(t,e,n){const r=n(4),i={INIT:"_initGraph"};i.AUGMENT={_initGraph(){const t=this.get("graph"),e=new(this.get("graphConstructor"))({page:this,...t});e.draw(),this.set("_graph",e)},changeMode(t){this.get("_graph").changeMode(t)},updateMatrix(t){this.get("_graph").updateMatrix(t)},getMode(){return this.get("_graph").get("mode")},getMatrix(){return this.get("_graph").getMatrix()},getZoom(){return this.get("_graph").getMatrix()[0]},getMaxZoom(){return this.get("_graph").get("maxZoom")},getMinZoom(){return this.get("_graph").get("minZoom")},getGraph(){return this.get("_graph")},getItems(){return this.get("_graph").getItems()},getNodes(){return this.get("_graph").getNodes()},translate(t,e){return this.get("_graph").translate(t,e)},getEdges(){return this.get("_graph").getEdges()},getGroups(){return this.get("_graph").getGroups()},render(){return this.get("_graph").render(),this},add(t,e){return this.get("_graph").add(t,e),this},focusPointByDom(t){return this.get("_graph").focusPointByDom(t),this},focusPoint(t){return this.get("_graph").focusPoint(t),this},find(t){return this.get("_graph").find(t)},focus(t){const e=this.get("_graph"),n=e.find(t);if(n){const t=n.getCenter();e.focusPoint(t)}return this},save(){return this.get("_graph").save()},read(t){this.get("_graph").read(t)},clear(){this.get("_graph").clear()},remove(t){return this.get("_graph").remove(t),this},update(t,e){return this.get("_graph").update(t,e),this},zoom(t,e){return this.get("_graph").zoom(t,e),this},getDomPoint(t){return this.get("_graph").getDomPoint(t)},getPoint(t){return this.get("_graph").getPoint(t)},zoomByDom(t,e){const n=this.get("_graph"),r=n.getPoint(t);return n.zoom(r,e),this},autoZoom(){return this.get("_graph").autoZoom(),this},resetZoom(){const t=this.get("_graph"),e=t.getWidth(),n=t.getHeight();return t.zoomByDom({x:e/2,y:n/2},1),this},css(t){const e=this.get("_graph").getMouseEventWrapper();r.modifyCSS(e,t)},setCapture(t){this.get("_graph").getRootGroup().set("capture",t)},destroy(){this.get("_graph").destroy()},delete(){const t=this.getSelected(),e=this.get("_graph");r.each(t,t=>{e.remove(t)})}},t.exports=i},function(t,e,n){const r=n(36),i=n(4),o={CFG:{grid:void 0},INIT:"_initGrid"};o.AUGMENT={_initGrid(){const t=this.get("grid"),e=this.get("_graph");if(t){const n=new r({page:this,graph:e,...t});this.setController("grid",n)}},showGrid(t){const e=this.get("_graph");let n=this.getController("grid");n||(t?i.isObject(t)&&this.set("grid",t):this.set("grid",!0),this._initGrid()),n=this.getController("grid"),n.show(),e.draw()},hideGrid(){const t=this.get("_graph"),e=this.getController("grid");e&&e.hide(),t.draw()},getGridCell(){return this.getController("grid").getCell()}},t.exports=o},function(t,e,n){const r=n(9),i=n(14),o=n(4);t.exports=class extends r{getDefaultCfg(){return{cell:16,line:i.gridStyle,type:"point",visible:!0}}init(){this._draw(),this._onViewPortChange(),!this.visible&&this.hide()}_onViewPortChange(){const t=this.graph;t.on("afterviewportchange",()=>{this.update()}),t.on("beforechangesize",()=>{this.update()})}_draw(){const t=this.graph,e=this._getPath(),n=t.getRootGroup(),r=o.mix({},this.line),i=t.getMatrix(),a=this.type,s="line"===a?1/i[0]:2/i[0];"point"===a&&(r.lineDash=null),r.lineWidth=s,r.path=e;const c=n.addShape("path",{attrs:r,capture:!1,zIndex:0});o.toBack(c,n),this.gridEl=c}show(){this.gridEl.show(),this.visible=!0}hide(){this.gridEl.hide(),this.visible=!1}_getLinePath(){const t=this.graph,e=t.get("width"),n=t.get("height"),r=t.getPoint({x:0,y:0}),i=t.getPoint({x:e,y:n}),o=this.cell,a=Math.ceil(r.x/o)*o,s=Math.ceil(r.y/o)*o,c=[];for(let t=0;t<=i.x-r.x;t+=o){const e=a+t;c.push(["M",e,r.y]),c.push(["L",e,i.y])}for(let t=0;t<=i.y-r.y;t+=o){const e=s+t;c.push(["M",r.x,e]),c.push(["L",i.x,e])}return c}_getPointPath(){const t=this.graph,e=t.get("width"),n=t.get("height"),r=t.getPoint({x:0,y:0}),i=2/t.getMatrix()[0],o=t.getPoint({x:e,y:n}),a=this.getCell(),s=Math.ceil(r.x/a)*a,c=Math.ceil(r.y/a)*a,u=[];for(let t=0;t<=o.x-r.x;t+=a){const e=s+t;for(let t=0;t<=o.y-r.y;t+=a){const n=c+t;u.push(["M",e,n]),u.push(["L",e+i,n])}}return u}getCell(){const t=this.cell,e=this.graph.getMatrix()[0];return t*e<9.6?9.6/e:t}_getPath(){const t=this.type;return this["_get"+o.upperFirst(t)+"Path"]()}update(t){o.mix(this,t);const e=this._getPath(),n=this.gridEl,r=this.graph.getMatrix(),i="line"===this.type?1/r[0]:2/r[0];n.attr("lineWidth",i),n.attr("path",e)}destroy(){const t=this.gridEl;t&&t.remove()}}},function(t,e){const n={};function r(t,e,n){t.on(n,t=>{e.emit(n,t)}),t.on("node:"+n,t=>{e.emit("node:"+n,t)}),t.on("edge:"+n,t=>{e.emit("edge:"+n,t)}),t.on("group:"+n,t=>{e.emit("group:"+n,t)}),t.on("anchor:"+n,t=>{e.emit("anchor:"+n,t)})}n.INIT="_initEvent",n.AUGMENT={_initEvent(){const t=this.get("_graph");r(t,this,"click"),r(t,this,"dblclick"),r(t,this,"mouseenter"),r(t,this,"mouseleave"),r(t,this,"mousedown"),r(t,this,"mouseup"),r(t,this,"contextmenu"),t.on("keydown",t=>{this.emit("keydown",t)}),t.on("keyup",t=>{this.emit("keyup",t)}),t.on("beforechange",t=>{this.emit("beforechange",t)}),t.on("afterchange",t=>{this.emit("afterchange",t)}),t.on("afterviewportchange",t=>{this.emit("afterviewportchange",t),t.updateMatrix[0]!==t.originMatrix[0]&&this.emit("afterzoom",t)}),t.on("beforeviewportchange",t=>{this.emit("beforeviewportchange",t),t.updateMatrix[0]!==t.originMatrix[0]&&this.emit("beforezoom",t)})}},t.exports=n},function(t,e,n){const r=n(4),i={CFG:{selectable:!0,multiSelectable:!0,_selectedCache:{}},INIT:"_initSelected"};i.AUGMENT={_initSelected(){const t=this.get("_graph");t.on("afteritemdraw",({item:t})=>{t.isSelected&&this.setItemSelected(t)}),t.on("beforeitemdestroy",t=>{this.clearItemSelected(t.item)})},setItemSelected(t){const e=this.get("_graph").getShapeObj(t).getSelectedStyle(t),n=t.getKeyShape();this.get("_selectedCache")[t.id]=t,e&&n.attr(e),t.isEdge&&(t.startArrow&&t.startArrow.attr({fill:e.stroke}),t.endArrow&&t.endArrow.attr({fill:e.stroke}))},clearItemSelected(t){const e=this.get("_graph"),n=t.getKeyShape(),i=e.getShapeObj(t),o=i.getStyle(t),a=i.getSelectedStyle(t),s=this.get("_selectedCache"),c=r.getContrast(o,a);if(n.attr(c),t.isEdge)try{t.startArrow&&t.startArrow.attr({fill:c.stroke}),t.endArrow&&t.endArrow.attr({fill:c.stroke})}catch(t){}delete s[t.id]},setSelected(t,e){const n=this.get("selectable"),i=this.get("_graph");if(!n)return;let o;o=r.isArray(t)?t:[t],r.each(o,t=>{r.isString(t)&&(t=i.find(t)),t&&!t.destroyed&&(e?(this.emit("beforeitemselected",{item:t}),this.setItemSelected(t),this.emit("afteritemselected",{item:t})):(this.emit("beforeitemunselected",{item:t}),this.clearItemSelected(t),this.emit("afteritemunselected",{item:t})),t.isSelected=e,this.updateStatus(),i.draw())})},getSelected(){const t=this.get("_selectedCache");return r.objectToValues(t)},clearSelected(){const t=this.get("_graph"),e=this.get("_selectedCache");r.each(e,t=>{t.isSelected&&this.setSelected(t,!1)}),t.draw()}},t.exports=i},function(t,e,n){const r=n(4),i={CFG:{activeable:!0,_activedCache:{}},INIT:"_initActived"};i.AUGMENT={_initActived(){const t=this.get("_graph");t.on("afteritemdraw",({item:t})=>{t.isActived&&this.setItemActived(t)}),t.on("beforeitemdestroy",t=>{this.clearItemActived(t.item)})},setItemActived(t){const e=this.get("_graph").getShapeObj(t),n=this.get("_activedCache"),r=e.getActivedStyle(t),i=t.getKeyShape();n[t.id]=t,r&&i.attr(r),t.isEdge&&(t.startArrow&&t.startArrow.attr({fill:r.stroke}),t.endArrow&&t.endArrow.attr({fill:r.stroke}))},clearItemActived(t){const e=this.get("_graph"),n=t.getKeyShape(),i=e.getShapeObj(t),o=i.getStyle(t),a=this.get("_activedCache"),s=i.getActivedStyle(t),c=r.getContrast(o,s);n.attr(c);try{t.isEdge&&(t.startArrow&&t.startArrow.attr({fill:c.stroke}),t.endArrow&&t.endArrow.attr({fill:c.stroke}))}catch(t){}delete a[t.id]},setActived(t,e){const n=this.get("activeable"),i=this.get("_graph");if(!n)return;let o;o=r.isArray(t)?t:[t],r.each(o,t=>{r.isString(t)&&(t=i.find(t)),t&&!t.destroyed&&(e?(this.emit("beforeitemactived",{item:t}),this.setItemActived(t),this.emit("afteritemactived",{item:t})):(this.emit("beforeitemunactived",{item:t}),this.clearItemActived(t),this.emit("afteritemunactived",{item:t})),t.isActived=e)}),i.draw()},getActived(){const t=this.get("_activedCache");return r.objectToValues(t)},clearActived(){const t=this.get("_graph"),e=this.get("_activedCache");r.each(e,t=>{t.isActived&&this.setActived(t,!1)}),t.draw()}},t.exports=i},function(t,e,n){const r=n(41),i={CFG:{align:{}},INIT:"_initAlign"};i.AUGMENT={_initAlign(){const t=this.get("align"),e=this.get("_graph"),n=new r({flow:this,graph:e,...t});this.setController("align",n)},align(t,e,n){return this.getController("align").align(t,e,n)},clearAlignLine(){return this.getController("align").clearAlignLine()}},t.exports=i},function(t,e,n){const r=n(9),i=n(14),o=n(4);function a(t,e){return{line:t,point:e,dis:o.pointLineDistance(t[0],t[1],t[2],t[3],e.x,e.y)}}t.exports=class extends r{getDefaultCfg(){return{line:i.alignLineStyle,item:!0,grid:!1,tolerance:5,_horizontalLines:{},_verticalLines:{},_alignLines:[]}}init(){this.item&&this._cacheBoxLine()}_cacheBoxLine(){const t=this.graph,e=this._horizontalLines,n=this._verticalLines,r=this.item;t.on("afteritemdraw",t=>{const i=t.item;if(!o.isEdge(i)){const t=i.getBBox();!0===r||"horizontal"===r?(e[i.id+"tltr"]=[t.minX,t.minY,t.maxX,t.minY,i],e[i.id+"lcrc"]=[t.minX,t.centerY,t.maxX,t.centerY,i],e[i.id+"blbr"]=[t.minX,t.maxY,t.maxX,t.maxY,i]):"center"===r&&(e[i.id+"lcrc"]=[t.minX,t.centerY,t.maxX,t.centerY,i]),!0===r||"vertical"===r?(n[i.id+"tlbl"]=[t.minX,t.minY,t.minX,t.maxY,i],n[i.id+"tcbc"]=[t.centerX,t.minY,t.centerX,t.maxY,i],n[i.id+"trbr"]=[t.maxX,t.minY,t.maxX,t.maxY,i]):"center"===r&&(n[i.id+"tcbc"]=[t.centerX,t.minY,t.centerX,t.maxY,i])}}),t.on("beforeitemdestroy",t=>{const r=t.item;delete e[r.id+"tltr"],delete e[r.id+"lcrc"],delete e[r.id+"blbr"],delete n[r.id+"tlbl"],delete n[r.id+"tcbc"],delete n[r.id+"trbr"]})}align(t,e){const n=o.mix({},t),r=this.flow.getController("grid");return this.grid&&r&&r.visible&&this._gridAlign(t,e),this.item&&this._itemAlign(t,e,n),t}_gridAlign(t,e){const n=this.flow,r=this.grid,i=n.getGridCell();if("cc"===r){const n=Math.round((t.x+e.width/2)/i)*i,r=Math.round((t.y+e.height/2)/i)*i;t.x=n-e.width/2,t.y=r-e.height/2}else t.x=Math.round(t.x/i)*i,t.y=Math.round(t.y/i)*i}_itemAlign(t,e,n){const r=this._horizontalLines,i=this._verticalLines,s=this.tolerance,c={x:n.x+e.width/2,y:n.y},u={x:n.x+e.width/2,y:n.y+e.height/2},h={x:n.x+e.width/2,y:n.y+e.height},l={x:n.x,y:n.y+e.height/2},d={x:n.x+e.width,y:n.y+e.height/2},f=[],g=[];let p=null;if(this.clearAlignLine(),o.each(r,t=>{t[4].isVisible()&&(f.push(a(t,c)),f.push(a(t,u)),f.push(a(t,h)))}),o.each(i,t=>{t[4].isVisible()&&(g.push(a(t,l)),g.push(a(t,u)),g.push(a(t,d)))}),f.sort((t,e)=>t.dis-e.dis),g.sort((t,e)=>t.dis-e.dis),0!==f.length&&f[0].dis<s){t.y=f[0].line[1]-f[0].point.y+n.y,p={type:"item",horizontals:[f[0]]};for(let t=1;t<3;t++)f[0].dis===f[t].dis&&p.horizontals.push(f[t])}if(0!==g.length&&g[0].dis<s){t.x=g[0].line[0]-g[0].point.x+n.x,p?p.verticals=[g[0]]:p={type:"item",verticals:[g[0]]};for(let t=1;t<3;t++)g[0].dis===g[t].dis&&p.verticals.push(g[t])}p&&(p.bbox=e,this._addAlignLine(p))}clearAlignLine(){const t=this._alignLines;o.each(t,t=>{t.remove()}),this._alignLines=[]}_addAlignLine(t){const e=t.bbox,n=this.graph.getRootGroup(),r=this.line,i=this._alignLines;"item"===t.type&&(t.horizontals&&o.each(t.horizontals,t=>{const a=t.line,s=t.point,c=(a[0]+a[2])/2;let u,h;s.x<c?(u=s.x-e.width/2,h=Math.max(a[0],a[2])):(u=s.x+e.width/2,h=Math.min(a[0],a[2]));const l=n.addShape("line",{attrs:o.mix({x1:u,y1:a[1],x2:h,y2:a[1]},r),capture:!1});i.push(l)}),t.verticals&&o.each(t.verticals,t=>{const a=t.line,s=t.point,c=(a[1]+a[3])/2;let u,h;s.y<c?(u=s.y-e.height/2,h=Math.max(a[1],a[3])):(u=s.y+e.height/2,h=Math.min(a[1],a[3]));const l=n.addShape("line",{attrs:o.mix({x1:a[0],y1:u,x2:a[0],y2:h},r),capture:!1});i.push(l)}))}}},function(t,e,n){const r=n(4),i={CFG:{labelEditable:!1},INIT:"_initLabelEditor"};i.AUGMENT={_initLabelEditor(){if(this.get("labelEditable")){const t=this.getGraph(),e=r.createDOM('<div contenteditable="true" role="textbox" tabindex="1" class="g6-label-editor"></div>',{position:"absolute",visibility:"hidden","z-index":"2",padding:"0px 2px 0px 0px",resize:"none",width:"auto",height:"auto",outline:"none",border:"1px solid #1890FF","transform-origin":"left top","max-width":"320px",background:"white","box-sizing":"content-box"});t.getGraphContainer().appendChild(e),e.on("blur",e=>{e.stopPropagation(),!t.destroyed&&this.endEditLabel()}),e.on("keydown",t=>{t.stopPropagation();const e=r.getKeyboradKey(t);(t.metaKey&&"s"===e||t.ctrlKey&&"s"===e)&&t.preventDefault(),"Enter"!==e&&"Escape"!==e||this.endEditLabel()}),this.set("labelTextArea",e),t.on("beforeviewportchange",()=>{e.focusItem&&this.setLabelEditorBeginPosition(e.focusItem)})}},_getLabelTextAreaBox(t,e,n=[0,0]){e&&t.attr("text",e);const i=this.getGraph().getRootGroup(),o=r.getBBox(t,i);return{minX:o.minX-n[1],minY:o.minY-n[0],maxX:o.maxX+n[1],maxY:o.maxY+n[0]}},setLabelEditorBeginPosition(t){const e=this.get("labelTextArea"),n=t.getLabel();if(n){const t=this._getLabelTextAreaBox(n),r=n.attr("lineHeight"),i=n.attr("fontSize"),o={x:t.minX,y:t.minY-r/4+i/4-1,width:t.maxX-t.minX,height:t.maxY-t.minY};e.css({top:o.y+"px",left:o.x+"px"}),e.labelPoint=o}else{const n=this.getGraph().getRootGroup(),i=t.getKeyShape(),o=r.getBBox(i,n),a={x:o.minY+(o.maxY-o.minY-e.height())/2,y:(o.minX+o.maxX)/2};e.css({top:a.x+"px",left:a.y+"px"}),e.labelPoint=a}},beginEditLabel(t){const e=this.get("labelTextArea"),n=this.getGraph();if(r.isString(t)&&(t=n.find(t)),t&&!t.destroyed&&e){this.setSignal("preventWheelPan",!0);const r=t.getModel(),i=t.getLabel(),o=n.getZoom();if(e.focusItem=t,i){const t=i.attr("lineHeight"),n=this._getLabelTextAreaBox(i),a=(n.maxX-n.minX)/o,s=(n.maxY-n.minY+t/4)/o;e.innerHTML=r.label,e.innerHTML=r.label,e.css({"min-width":a+"px","min-height":s+"px",visibility:"visible","font-family":i.attr("fontFamily"),"line-height":t+"px","font-size":i.attr("fontSize")+"px",transform:"scale("+o+")"})}else e.innerHTML="",e.css({"min-width":"auto","min-height":"auto"});this.setLabelEditorBeginPosition(t),e.css({visibility:"visible"}),e.focus(),document.execCommand("selectAll",!1,null)}},endEditLabel(){const t=this.get("labelTextArea");if(this.setSignal("preventWheelPan",!1),t){const e=t.focusItem;if(e){const n=e.getModel(),r=this.editor;n.label!==t.textContent&&r.executeCommand("update",{action:"updateLabel",itemId:e.id,updateModel:{label:t.textContent}}),t.hide(),t.focusItem=void 0,this.focusGraphWrapper()}}}},t.exports=i},function(t,e){const n={};n.AUGMENT={updateStatus(){const t=this.getSelected();let e;0===t.length?e="canvas-selected":1===t.length?t[0].isNode?e="node-selected":t[0].isEdge?e="edge-selected":t[0].isGroup&&(e="group-selected"):e="multi-selected",this.emit("statuschange",{status:e})}},t.exports=n},function(t,e,n){n(45),n(46),n(47),n(48),n(49),n(50),n(51),n(52),n(53),n(54),n(55),n(56),n(57),n(58),n(59),n(60),n(61),n(62)},function(t,e,n){const r=n(3),i=n(4);r.registerBehaviour("panBlank",i.getPanCanvasBehaviour(!0))},function(t,e,n){n(3).registerBehaviour("hoverButton",t=>{t.getGraph().behaviourOn("mouseenter",e=>{t.getSignal("panningItem")||e.shape&&e.shape.isButton&&t.css({cursor:"pointer"})})})},function(t,e,n){const r=n(3),i=n(4);r.registerBehaviour("panCanvas",i.getPanCanvasBehaviour())},function(t,e,n){const r=n(3),i=n(14),o=n(4);r.registerBehaviour("wheelChangeViewport",t=>{const e=t.getGraph();let n;e.behaviourOn("wheel",t=>{const{domEvent:e}=t;e.preventDefault()}),e.behaviourOn("wheel",o.throttle((function(r){if(t.getSignal("preventWheelPan"))return;const{domEvent:a}=r,s=t.getSignal("wheelZoom");n||t.setCapture(!1);if(s){const t=a.wheelDelta,n=1.05;if(Math.abs(t)>10){const i=e.getMatrix()[0];t>0?e.zoom({x:r.x,y:r.y},i*n):e.zoom({x:r.x,y:r.y},i*(1/n))}}else{const n=[],r=e.getMatrix();o.mat3.translate(n,r,[a.wheelDeltaX*i.wheelPanRatio,a.wheelDeltaY*i.wheelPanRatio]),t.translateLimt(n)&&e.updateMatrix(n)}n&&clearTimeout(n),n=setTimeout(()=>{t.setCapture(!0),n=void 0},50)}),16))})},function(t,e,n){n(3).registerBehaviour("processPanItem",t=>{const e=t.getGraph();e.behaviourOn("mousemove",n=>{const r=t.get("panItemDelegation");if(r){const i=t.get("panItemStartPoint"),o=t.get("panItemStartBox"),a=n.x-i.x,s=n.y-i.y,c=t.align({x:o.minX+a,y:o.minY+s},{width:o.width,height:o.height});r.attr({x:c.x,y:c.y}),e.emit("itempanning",n),e.draw()}})})},function(t,e,n){n(3).registerBehaviour("startPanItem",t=>{const e=t.getGraph(),n=e.getRootGroup();e.behaviourOn("dragstart",r=>{if(2===r.button||!r.item||!r.item.isNode&&!r.item.isGroup)return;const i=r.item;let o;if(o=i.isSelected?t.getSelected():[i],o=o.filter(t=>t.isNode||t.isGroup),o[0]&&!1!==o[0].dragable){e.emit("beforepanitem",{items:o}),e.emit("beforeshowdelegation",{items:o});const i=t.getDelegation(o,n),a=i.getBBox();t.setSignal("panningItem",!0),t.set("panItems",o),t.set("panItemDelegation",i),t.set("panItemStartBox",a),t.set("panItemStartPoint",{x:r.x,y:r.y}),e.draw()}})})},function(t,e,n){n(3).registerBehaviour("endPanItem",t=>{const e=t.getGraph();e.behaviourOn("panitemend",()=>{const n=t.get("panItemDelegation");n&&(n.remove(),e.draw()),t.setSignal("panningItem",!1),t.set("panItemDelegation",void 0),t.set("panItemStartPoint",void 0),t.set("panItemStartBox",void 0),t.set("panItems",void 0)}),e.behaviourOn("canvas:mouseleave",()=>{t.get("panItems")&&(t.clearAlignLine(),e.emit("panitemend"))})})},function(t,e,n){n(3).registerBehaviour("dblclickItemEditLabel",t=>{t.getGraph().behaviourOn("node:dblclick",e=>{e.shape&&!e.shape.isButton&&t.beginEditLabel(e.item)})})},function(t,e,n){n(3).registerBehaviour("clickCanvasSelected",t=>{const e=t.getGraph();e.behaviourOn("click",e=>{e.shape||(t.clearSelected(),t.clearActived(),t.updateStatus())}),e.behaviourOn("contextmenu",e=>{e.shape||(t.clearSelected(),t.clearActived(),t.updateStatus())})})},function(t,e,n){n(3).registerBehaviour("clickCollapsedButton",t=>{const e=t.getGraph();e.behaviourOn("click",n=>{const r=n.item,i=n.shape;if(r&&i&&i.isCollapsedButton){const n=t.editor;n?n.executeCommand("collapseExpand",{itemId:r.id}):e.update(r,{collapsed:!0})}})})},function(t,e,n){n(3).registerBehaviour("clickEdgeSelected",t=>{t.getGraph().behaviourOn("edge:click",e=>{t.get("multiSelectable")&&!0===t.getSignal("shiftKeyDown")||(t.clearActived(),t.clearSelected()),t.setSelected(e.item.id,!0)})})},function(t,e,n){n(3).registerBehaviour("clickExpandedButton",t=>{const e=t.getGraph();e.behaviourOn("click",n=>{const r=n.item,i=n.shape;if(r&&i&&i.isExpandedButton){const n=t.editor;n?n.executeCommand("collapseExpand",{itemId:r.id}):e.update(r,{collapsed:!1})}})})},function(t,e,n){n(3).registerBehaviour("clickGroupSelected",t=>{t.getGraph().behaviourOn("group:click",e=>{t.get("multiSelectable")&&!0===t.getSignal("shiftKeyDown")||(t.clearActived(),t.clearSelected()),t.setSelected(e.item.id,!0)})})},function(t,e,n){n(3).registerBehaviour("clickNodeSelected",t=>{t.getGraph().behaviourOn("node:click",e=>{t.get("multiSelectable")&&!0===t.getSignal("shiftKeyDown")||(t.clearActived(),t.clearSelected()),t.setSelected(e.item.id,!0)})})},function(t,e,n){n(3).registerBehaviour("hoverNodeActived",t=>{const e=t.getGraph();let n;e.behaviourOn("node:mouseenter",e=>{const{item:r}=e;!1!==r.getShapeObj().panAble&&t.css({cursor:"move"}),t.getSignal("panningItem")||t.getSignal("dragEdge")||e.item&&e.item.isSelected||(n=e.item,t.setActived(n,!0))}),e.behaviourOn("node:mouseleave",e=>{const r=e.toShape;n&&(r&&r.isAnchor&&r.getItem()===n||t.getSignal("dragEdge")||(n.isSelected||t.setActived(n,!1),n=void 0))})})},function(t,e,n){n(3).registerBehaviour("hoverGroupActived",t=>{const e=t.getGraph();e.behaviourOn("mouseenter",e=>{t.getSignal("panningItem")||e.item&&e.item.isSelected||t.getSignal("dragEdge")||e.shape&&e.shape.isGroupKeyShape&&(t.css({cursor:"move"}),t.setActived(e.item,!0))}),e.behaviourOn("group:mouseleave",e=>{e.item.isActived&&!e.item.isSelected&&t.setActived(e.item,!1)})})},function(t,e,n){n(3).registerBehaviour("hoverEdgeActived",t=>{const e=t.getGraph();e.behaviourOn("edge:mouseenter",e=>{t.getSignal("panningItem")||e.item&&e.item.isSelected||t.getSignal("dragEdge")||t.setActived(e.item,!0)}),e.behaviourOn("edge:mouseleave",e=>{t.setActived(e.item,!1)})})},function(t,e,n){n(3).registerBehaviour("keydownCmdWheelZoom",t=>{const e=t.getGraph();e.behaviourOn("keydown",e=>{91===e.domEvent.keyCode&&t.setSignal("wheelZoom",!0)}),e.behaviourOn("keyup",e=>{91===e.domEvent.keyCode&&t.setSignal("wheelZoom",!1)})})},function(t,e,n){const r=n(22);t.exports={dragingEdgeEndPoint({endPointType:t,edgeModel:e,graph:n,delegation:r,startPoint:i,ev:o,source:a,target:s}){const{item:c}=o,u="source"===t?[o,i]:[i,o];c&&("source"===t?s=c:a=c);const h=n.getShapeObj("edge",e).getPathByPoints({points:u,source:a,target:s});r.attr("path",h),n.draw()},panGroup(t,e,n,i){const o=t.getModel();r.traverseTree(t,r=>{if("node"===r.type){const t=r.getModel();i.update(r,{x:t.x+e,y:t.y+n})}t.getCrossEdges&&t.getCrossEdges().forEach(t=>{t.update()})},t=>"group"===t.type?t.getChildren():[]),i.update(t,{x:o.x+e,y:o.y+n})},dropUpdateEdge({ev:t,endPointType:e,model:n,diagram:r}){const i=r.get("noEndEdge"),o=r.get("linkAnchor"),a=r.get("linkNode"),{item:s,shape:c,x:u,y:h}=t;if(r.getGraph().emit("beforedropedge"),c){if(o&&c.isAnchor&&c.hasHotspot){const t=c,r=t.getItem();return"target"===e?(n.target=r.id,n.targetAnchor=t.getIndex(),!0):(n.source=r.id,n.sourceAnchor=t.getIndex(),!0)}if(a&&s&&s.isNode)return"target"===e?(n.target=s.id,!0):(n.source=s.id,!0)}else if(i)return"target"===e?(n.target={x:u,y:h},!0):(n.source={x:u,y:h},!0);return!1}}},function(t,e){t.exports={rectRectCrossAlgorithm(t,e){const n=Math.max(t.minX,e.minX),r=Math.max(t.minY,e.minY),i=Math.min(t.maxX,e.maxX),o=Math.min(t.maxY,e.maxY);return n>i||r>o},euclideanDistance:{pointPoint(t,e){const n=Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2);return Math.sqrt(n)}}}},function(t,e,n){const r={},i=n(2);r.AUGMENT={changeAddEdgeModel(t){this.set("addEdgeModel",t)},cancelAdd(){this.set("addType",void 0),this.set("addModel",void 0),this.changeMode("default")},beginAdd(t,e){this.set("addType",t),this.set("addModel",e),this.changeMode("add")},endAdd(){this.set("addType",void 0),this.set("addModel",void 0),this.changeMode("default")},delete(){const t=this.getSelected(),e=this.get("_graph");i.each(t,t=>{e.remove(t)})},toBack(){const t=this.getSelected(),e=this.get("_graph");t.sort((t,e)=>{const n=t.getGraphicGroup(),r=e.getGraphicGroup();return i.getIndex(r)-i.getIndex(n)}),t.forEach(t=>{e.toBack(t)})},toFront(){const t=this.getSelected(),e=this.get("_graph");t.sort((t,e)=>{const n=t.getGraphicGroup(),r=e.getGraphicGroup();return i.getIndex(n)-i.getIndex(r)}),t.forEach(t=>{e.toFront(t)})},addGroup(t){const e=this.get("_graph"),n=this.getSelected();let r,o=!0;if(0===n.length)return;t||(t={label:"新建分组"}),i.setId(t),e.add("group",t),e.toFront(t.id);const a=e.find(t.id);if(n.forEach(t=>{const e=t.getParent();e&&(r?r!==e&&(o=!1):r=e)}),!o)return void console.warn("add group elements must have the same parent");r&&(t.parent=r.getModel().id),n.forEach(n=>{e.update(n,{parent:t.id})});const s=a.getInnerEdges();a.deepEach(t=>{e.toFront(t)}),s.forEach(t=>{e.toFront(t)})},unGroup(){const t=this.get("_graph"),e=this.getSelected(),n=e[0];1===e.length&&i.isGroup(n)&&(n.getChildren().forEach(e=>{t.update(e,{parent:void 0}),e.collapsedParent||e.show(),e.isGroup&&e.deepEach(t=>{t.collapsedParent||t.show()})}),t.remove(n))},newGroup(t){this.addGroup(t)}},t.exports=r},function(t,e,n){const r=n(67),i=n(2),o={CFG:{anchor:{}},INIT:"_initAnchor"};o.AUGMENT={_initAnchor(){const t=this.get("anchor"),e=this.get("_graph");if(t){const n=new r({diagram:this,graph:e,...t});this.setController("anchor",n)}},showAnchor(t,e,n){this.getController("anchor").showAnchor(t,e,n)},clearAnchor(t){this.getController("anchor").clearAnchor(t)},setHotspotActived(t,e){this.getController("anchor").setHotspotActived(t,e)},hoverShowAnchor(t){const e=t.getAnchorPoints(),n=[];e.forEach((e,r)=>{const i={anchor:e,item:t};this.emit("hovernode:beforeshowanchor",i),i.cancel||n.push(r)}),this.showAnchor(t,n)},anchorHasBeenLinked(t,e){const n=t.getEdges(),r=[];return n.forEach(e=>{const n=e.getModel();n.source!==t.id||i.isNil(n.sourceAnchor)||r.push(n.sourceAnchor),n.target!==t.id||i.isNil(n.targetAnchor)||r.push(n.targetAnchor)}),i.isObject(e)?-1!==r.indexOf(e.index):-1!==r.indexOf(e)},dragEdgeBeforeShowAnchor(t,e,n){this.getGraph().getNodes().forEach(r=>{const i=[],o=r.getAnchorPoints();let a;if(t.isNode){const s=t.getAnchorPoints();o.forEach((o,c)=>{a="target"===n?{source:t,sourceAnchor:s[e],target:r,targetAnchor:o,dragEndPointType:n}:{target:t,targetAnchor:s[e],source:r,sourceAnchor:o,dragEndPointType:n},this.emit("dragedge:beforeshowanchor",a),a.cancel||i.push(c)})}else o.forEach((t,e)=>{i.push(e)});r===t&&r.isAnchorShow?i.forEach(t=>{const n=r.getAnchor(t);e!==t&&n&&n.showHotspot()}):this.showAnchor(r,i,!0)})}},t.exports=o},function(t,e,n){const r=n(9),i=n(5),o=n(2);t.exports=class extends r{getDefaultCfg(){return{_anchorItemCache:{}}}init(){const t=this.graph;t.on("afteritemdraw",t=>{t.item.isAnchorShow&&this.showAnchor(t.item)}),t.on("beforeitemdestroy",t=>{this._clearAnchor(t.item)}),t.on("afteritemhide",t=>{t.item.isNode&&this._clearAnchor(t.item)})}_updateAnchor(t){const e=this.graph;t.anchorShapes.forEach(t=>{t.updatePosition()}),e.draw()}_drawAnchor(t,e,n,r){const a=t.getAnchorPoints();this._clearAnchor(t),o.each(a,(o,a)=>{if(n&&-1===n.indexOf(a))return;let s;const c=e.addShape("marker",{attrs:{symbol:"circle",...i.anchorPointStyle,x:o.x,y:o.y},freezePoint:o,item:t,index:a,eventPreFix:"anchor",isItemChange(){},zIndex:i.zIndex.anchorPoint});c.toFront(),c.eventPreFix="anchor",c.showHotspot=()=>{s=e.addShape("marker",{attrs:{symbol:"circle",...i.anchorHotsoptStyle,x:o.x,y:o.y},freezePoint:o,capture:!1,zIndex:i.zIndex.anchorHotsopt}),t.anchorShapes.push(s),c.hasHotspot=!0,s.toFront(),c.toFront()},c.getIndex=()=>a,c.getItem=()=>t,c.getPoint=()=>o,c.updatePosition=()=>{const e=t.getAnchorPoints()[a];c.attr(e)},c.setActived=()=>{c.attr(i.anchorPointHoverStyle)},c.clearActived=()=>{c.attr(i.anchorPointStyle)},c.isAnchor=!0,c.setHotspotActived=t=>{s&&(t?s.attr(i.anchorHotsoptActivedStyle):s.attr(i.anchorHotsoptStyle))},r&&c.showHotspot(),t.anchorShapes.push(c),t.getAllAnchors=()=>t.anchorShapes.filter(t=>t.isAnchor),t.getAnchor=e=>t.anchorShapes.find(t=>t.get("index")===e)})}_clearAnchor(t){t.anchorShapes&&t.anchorShapes.forEach(t=>{t.remove()}),t.anchorShapes=[]}setHotspotActived(t,e){const n=this.diagram.getGraph();t.setHotspotActived(e),n.draw()}showAnchor(t,e,n){if(!t.isVisible())return;const r=this.graph,i=this._anchorItemCache,o=r.getRootGroup();this._drawAnchor(t,o,e,n),t.isAnchorShow=!0,i[t.id]=t}clearAnchor(t){const e=this.graph,n=e.get("itemCache"),r=this._anchorItemCache;let i=t;i=o.isObject(t)?[t]:o.isString(t)?[n[t]]:r,o.each(i,t=>{this._clearAnchor(t),t.isAnchorShow=!1,delete r[t.id]}),e.draw()}}},function(t,e,n){const r=n(69),i={CFG:{orbit:null},INIT:"_initOrbit"};i.AUGMENT={_initOrbit(){const t=this.get("orbit");if(t){const e=new r({diagram:this,...t});this.setController("orbit",e)}},showOrbit(t){this.getController("orbit").show(t)},hideOrbit(){this.getController("orbit").hide()},layoutOrbit(t,e){this.getController("orbit").layout(t,e)}},t.exports=i},function(t,e,n){const r=n(9),i=n(5),o=n(70),{vec2:a,isString:s}=n(2);t.exports=class extends r{getDefaultCfg(){return{satellite:[],satelliteCache:[]}}init(){const t=this.satellite,e=this.diagram,n={diagram:e};e.getGraph().addBehaviour("orbit"),t.forEach(t=>{s(t)?this.satelliteCache.push(new o[t](n)):this.satelliteCache.push(new o({...n,...t}))})}layout(t,e){const n=this.diagram,r=n.getGraph(),{satelliteCache:o}=this,s=t.getBBox(),{centerX:c,centerY:u}=s,h=n.getZoom(),l=i.orbitGap/h,d=o.filter(t=>t.isVisible()),f=[e.x-c,e.y-u],g=a.length(f),p=s.width/2+l,m=a.scale([],f,p/g);d.forEach(t=>{const e=t.getDOM(),n=e.width()/2,i=r.getDomPoint({x:m[0]+c,y:m[1]+u});e.css({top:i.y-n+"px",left:i.x-n+"px"})})}show(t){const{satelliteCache:e}=this;e.forEach(e=>{e.enable()&&(e.item=t,e.show())})}hide(){const{satelliteCache:t}=this;t.forEach(t=>{t.hide()})}}},function(t,e,n){const r=n(23);r.forkAndLink=n(71),t.exports=r},function(t,e,n){const r=n(23),i=n(2);t.exports=class extends r{getDefaultCfg(){return{name:"forkAndLink",render:()=>'\n <div style="\n width: 11px;\n height: 11px;\n cursor: copy;\n background-image: url(https://gw.alipayobjects.com/zos/rmsportal/yWAiQOmucbYMCpwkvTBP.svg)\n "></div>\n ',bindEvent(t,e){const n=e.getGraph(),r=n.getRootGroup();t.setAttribute("draggable","true");return[i.addEventListener(t,"dragstart",()=>{const n=this.item,i={...e.get("addEdgeModel"),source:n.id},o=n.getBBox(),a=e.getDelegation([{isEdge:!0}],r);e.setSignal("dragEdge",!0),e.beginAdd("edge",i),e.set("addEdgeConfig",{addModel:i,delegation:a,startPoint:{x:o.centerX,y:o.centerY},sourceItem:n}),t.hide()}),i.addEventListener(t,"click",({clientX:t,clientY:r})=>{const o=e.editor,a=this.item,s=n.getPointByClient({x:t,y:r}),c=a.getBBox(),u=a.getModel(),h=[s.x-c.centerX,s.y-c.centerY],l=i.vec2.length(h);if(i.vec2.scale(h,h,160/l),o)o.executeCommand("copyAdjacent",{copyNode:a,x:s.x+h[0],y:s.y+h[1]});else{const t=i.clone(u);t.x=s.x+h[0],t.y=s.y+h[1],n.add(a.type,t)}})]}}}}},function(t,e,n){const r=n(2),i=n(5),o={};function a(t){t.controlPointShapes&&r.each(t.controlPointShapes,t=>{t.remove()}),t.controlPointShapes=[],t.isControlPointShow=!1}o.INIT="_initResize",o.CFG={nodeResizeable:!1,edgeResizeable:!0},o.AUGMENT={_initResize(){const t=this.get("_graph"),e=this.get("nodeResizeable"),n=this.get("edgeResizeable");e&&t.on("afteritemdraw",t=>{"node"===t.item.type&&t.item.isVisible()&&this.drawControlPoints(t.item)}),n&&t.on("afteritemdraw",t=>{"edge"===t.item.type&&t.item.isVisible()&&this.drawControlPoints(t.item)}),t.on("afteritemhide",t=>{var e;t.item.isControlPointShow&&((e=t.item).controlPointShapes&&r.each(e.controlPointShapes,t=>{t.hide()}),e.isControlPointShow=!1)}),t.on("afteritemshow",t=>{var e;!t.item.isControlPointShow&&((e=t.item).controlPointShapes&&r.each(e.controlPointShapes,t=>{t.show()}),e.isControlPointShow=!0)}),t.on("beforeitemdestroy",t=>{t.item.isControlPointShow&&a(t.item)})},drawControlPoints(t){const e=this.get("_graph").getRootGroup(),n=this.get("nodeResizeable"),o=this.get("edgeResizeable");"node"===t.type?n&&function(t,e){const n=t.getBBox(),o=[{x:n.minX,y:n.minY},{x:n.maxX,y:n.minY},{x:n.minX,y:n.maxY},{x:n.maxX,y:n.maxY}];a(t);const s=e.addShape("rect",{attrs:r.mix({},i.nodeSelectedBoxStyle,{symbol:"square",x:n.minX,y:n.minY,width:n.maxX-n.minX,height:n.maxY-n.minY})});t.controlPointShapes.push(s),r.each(o,n=>{const o=e.addShape("marker",{attrs:r.mix({},i.nodeControlPointStyle,{symbol:"square",x:n.x,y:n.y}),freezePoint:{x:n.x,y:n.y},item:t});t.controlPointShapes.push(o)})}(t,e):"edge"===t.type&&o&&function(t,e){const n=t.getKeyShape().attr("path"),o=n[0],s=o.length,c=n[n.length-1],u=c.length,h=[{x:o[s-2],y:o[s-1]},{x:c[u-2],y:c[u-1]}],l=t.getModel();a(t),r.each(h,(n,o)=>{const a=e.addShape("marker",{attrs:r.mix({},i.edgeControlPointStyle,{x:n.x,y:n.y}),freezePoint:{x:n.x,y:n.y},item:t});a.eventPreFix="edgeControlPoint",a.getSourcePoint=()=>h[0],a.getTargetPoint=()=>h[h.length-1],a.getItem=()=>t,a.isSourceEndPoint=()=>l.source&&0===o,a.isTargetEndPoint=()=>l.target&&o===h.length-1,t.controlPointShapes.push(a)})}(t,e),t.isControlPointShow=!0}},t.exports=o},function(t,e,n){const r=n(2),i={};i.AUGMENT={addOutterShape(t,e){this.clearOutterShape(t);const{lineWidth:n}=e,i=t.getKeyShape(),o=t.getGraphicGroup(),a=i.attr(),s=i.get("type"),c=i.attr("lineWidth"),u=r.clone(a);delete u.fillStyle,delete u.strokeStyle,delete u.matrix;const h=o.addShape(s,{attrs:{...u,fill:null,...e}});r.toBack(h,o);const l=h.getBBox(),d=l.maxX-l.minX,f=l.maxY-l.minY,g=(l.minX+l.maxX)/2,p=(l.minY+l.maxY)/2;h.transform([["t",-g,-p],["s",(n+d+c)/d,(n+f+c)/f],["t",g,p]]),h.isOutter=!0,t.outterShape=h},clearOutterShape(t){t.outterShape&&t.outterShape.remove()}},t.exports=i},function(t,e){const n={CFG:{linkNode:!0,linkAnchor:!0},INIT:"_initLink"};n.AUGMENT={_initLink(){const t=this.getGraph(),e=this.get("linkAnchor"),n=this.get("linkNode"),r=t.get("mode");e&&(this.on("beforeitemactived",t=>{const e=t.item;e.isNode&&this.hoverShowAnchor(e)}),this.on("beforeitemunactived",t=>{const e=t.item;(e.isNode||e.isGroup)&&this.clearAnchor(e)}),this.on("beforeitemselected",t=>{const e=t.item;(e.isNode||e.isGroup)&&this.hoverShowAnchor(e)}),this.on("beforeitemunselected",t=>{const e=t.item;(e.isNode||e.isGroup)&&this.clearAnchor(e)}),t.addBehaviour("dragAnchorAddEdge","add"),t.addBehaviour("hoverAnchorActived","default"),t.changeMode(r)),n&&(t.addBehaviour("hoverNodeAddOutter","add"),t.addBehaviour("hoverNodeAddOutter","default"),t.changeMode(r))}},t.exports=n},function(t,e,n){n(76),n(77),n(78),n(79)},function(t,e,n){const r=n(13),i=n(2),o=n(5);r.registerNode("diagram-base",{getSize(t){const e=t.getModel();return i.getNodeSize(e.size)},defaultFillPalette:0,defaultStrokePalette:3,activedFillPalette:0,activedStrokePalette:5,selectedFillPalette:2,selectedStrokePalette:5,getDefaulStyle:()=>o.nodeStyle,getDefaulActivedStyle:()=>o.nodeActivedStyle,getDefaulSelectedtyle:()=>o.nodeSelectedStyle,getStyle(t){const e=t.getModel(),n=e.color;let r,o;if(n){const t=i.Palettes.generate(n);r=t[this.defaultFillPalette],o=t[this.defaultStrokePalette]}return i.mix(!0,{},this.getDefaulStyle(),{fill:r,stroke:o},e.style)},getPath(t){const e=this.getSize(t),n=this.getStyle(t);return i.getRectPath(-e[0]/2,-e[1]/2,e[0],e[1],n.radius)},getActivedOutterStyle:()=>o.nodeActivedOutterStyle,getActivedStyle(t){const e=t.getModel(),n=this.getDefaulActivedStyle(t),{color:r}=e;if(r){const t=i.Palettes.generate(r);return{...n,fill:t[this.activedFillPalette],stroke:t[this.activedStrokePalette]}}return n},getSelectedStyle(t){const e=t.getModel(),n=this.getDefaulSelectedtyle(t),{color:r}=e;if(r){const t=i.Palettes.generate(r);return{...n,fill:t[this.selectedFillPalette],stroke:t[this.selectedStrokePalette]}}return n},getSelectedOutterStyle(t){const e=t.getModel(),{color:n}=e;if(n){const t=i.Palettes.generate(n);return{...o.nodeSelectedOutterStyle,stroke:t[1],fill:t[1]}}return o.nodeSelectedOutterStyle},anchor:[[.5,0],[1,.5],[.5,1],[0,.5]]}),r.registerNode("capsule",{getPath(t){const e=this.getSize(t);return i.getRectPath(-e[0]/2,-e[1]/2,e[0],e[1],e[1]/2)}}),r.registerNode("circle",{getPath(t){const e=this.getSize(t),n=e[0],r=e[1];return i.getEllipsePath(0,0,n/2,r/2)}}),r.registerNode("rhombus",{getPath(t){const e=this.getSize(t),n=e[0],r=e[1],o=[{x:0,y:0-r/2},{x:0+n/2,y:0},{x:0,y:0+r/2},{x:0-n/2,y:0},{x:0,y:0-r/2}];return i.pointsToPolygon(o)}})},function(t,e,n){const r=n(13),i=n(2),o=n(5);r.registerEdge("diagram-base",{getPath(t){const e=t.getPoints(),n=t.getSource(),r=t.getTarget();return this.getPathByPoints({points:e,source:n,target:r,item:t})},getPathByPoints:({points:t})=>i.pointsToPolygon(t),getStyle(t){const e=t.getModel();return i.mix(!0,{},o.edgeStyle,{stroke:e.color},e.style)},getActivedStyle:()=>o.edgeActivedStyle,getSelectedStyle:()=>o.edgeSelectedStyle,getActivedOutterStyle(){},getSelectedOutterStyle(){}})},function(t,e,n){const r=n(13),i=n(5),o=n(2),a=o.getGroupIconPath(),s=o.getCollapsedButtonPath(),c=o.getExpandedButtonPath(),u={fill:"#CED4D9"},h={stroke:"#697B8C",fill:"#fff",fillOpacity:0},l={stroke:"#697B8C",fill:"#fff",fillOpacity:0},d={fill:"#000000",textBaseline:"top",textAlign:"left"},f={stroke:"#CED4D9",fill:"#F2F4F5",radius:4},g=i.groupBackgroundPadding,p=184-g[1]-g[3],m=40-g[0]-g[2];r.registerGroup("diagram-base",{draw(t){const e=t.getModel(),n=t.getGraphicGroup(),r=t.getChildrenBBox(),i=this.getStyle(t),f=e.collapsed,v=e.padding?e.padding:g;if(r.minX===1/0&&(r.minX=e.x,r.maxX=e.x+p,r.minY=e.y,r.maxY=e.y+m),f&&(r.minX=r.maxX-p,r.maxY=r.minY+m),r.maxX-r.minX<p){const t=p-r.maxX+r.minX;r.minX-=t/2,r.maxX+=t/2}const x=function(t,e){return t.minX-e[3]}(r,v),y=function(t,e){return t.minY-e[0]}(r,v),b=function(t,e){return t.maxX-t.minX+e[3]+e[1]}(r,v),w=function(t,e){return t.maxY-t.minY+e[0]+e[2]}(r,v),M=function(t,e,n,r){const i=e.addShape("path",{attrs:{...r,path:n}});return i.isGroupKeyShape=!0,i}(0,n,o.getRectPath(x,y,b,w,i.radius),i);!function(t,e,n,r){const i=o.mix(!0,{},d,{x:n+40,y:r+13});o.isString(t)?i.text=t:o.mix(i,t),e.addShape("text",{attrs:i})}(o.isNil(e.label)?"新建分组":e.label,n,x,y),function(t,e,n,r){const i=e.addShape("path",{attrs:{path:t,...u}}),o=i.getBBox();i.translate(n-o.minX+8,r-o.minY+12)}(o.isNil(e.icon)?a:e.icon,n,x,y);return(function(t,e,n,r,i){let o;if(t){o=e.addShape("path",{attrs:{path:c,...l}});const t=o.getBBox(),a=t.maxX-t.minX;o.isExpandedButton=!0,o.translate(n+i-t.minX-a-12,r-t.minY+12)}else{o=e.addShape("path",{attrs:{path:s,...h}});const t=o.getBBox(),a=t.maxX-t.minX;o.isCollapsedButton=!0,o.translate(n+i-t.minX-a-12,r-t.minY+12)}return o.isButton=!0,o}(f,n,x,y,b)).item=t,e.x=r.minX,e.y=r.minY,M},getStyle(t){const e=t.getModel();return o.mix(!0,{},f,{fill:e.color,stroke:e.color},e.style)},getActivedStyle:()=>i.groupActivedStyle,getSelectedStyle:()=>i.groupSelectedStyle,getSelectedOutterStyle:()=>i.groupSelectedOutterStyle,getActivedOutterStyle(){},intersectBox:"rect"})},function(t,e,n){n(13).registerGuide("diagram-base")},function(t,e,n){n(81),n(82),n(83),n(84),n(85),n(86),n(87),n(88),n(89),n(90),n(91),n(92),n(93),n(94)},function(t,e,n){const r=n(1),i=n(2);r.registerBehaviour("panItem",t=>{const e=t.getGraph();e.behaviourOn("drop",()=>{const n=t.get("panItems");if(!n)return;const r=n[0],o=n.map(t=>t.id),a=t.get("panItemDelegation"),s=t.get("panItemStartBox"),c=r.id,u=a.attr("x")-s.minX,h=a.attr("y")-s.minY;function l(){o.forEach(t=>{const n=e.find(t),r=n.getModel();n.isGroup?i.panGroup(n,u,h,e):(e.update(n,{x:r.x+u,y:r.y+h}),e.toFront(n))}),1===o.length&&(t.clearSelected(),t.setSelected(c,!0))}e.emit("afterpanitemdrop",{panItems:n}),t.clearAlignLine();const d=t.editor;e.emit("panitemend"),!d||t.getSignal("dragaddnodetogroup")?l():d.executeCommand(l)})},["startPanItem","processPanItem","endPanItem"])},function(t,e,n){const r=n(1),i=n(5);r.registerBehaviour("hoverAnchorActived",t=>{const e=t.getGraph();e.behaviourOn("anchor:mouseenter",n=>{if(t.getSignal("panningItem")||t.getSignal("dragEdge"))return;const r=n.shape,o=r.getItem(),a=o.getModel(),s={...t.get("addEdgeModel"),source:a.id},c={anchor:r.getPoint(),item:o};t.emit("hoveranchor:beforeaddedge",c),c.cancel?t.css({cursor:i.cursor.hoverUnEffectiveAnchor}):(t.css({cursor:i.cursor.hoverEffectiveAnchor}),!r.get("destroyed")&&r.setActived(),t.beginAdd("edge",s),e.draw())}),e.behaviourOn("anchor:mouseleave",n=>{if(!t.getSignal("dragEdge")&&!t.getSignal("panningItem")){const r=n.shape,o=r.getItem();t.css({cursor:i.cursor.beforePanCanvas}),o.isSelected||(t.clearAnchor(o),t.setActived(o,!1)),!r.get("destroyed")&&r.clearActived(),t.cancelAdd(),e.draw()}})})},function(t,e,n){const r=n(1),i=n(5);r.registerBehaviour("hoverEdgeControlPoint",t=>{t.getGraph().behaviourOn("edgeControlPoint:mouseenter",e=>{if(t.getSignal("dragEdge")||t.getSignal("panningItem"))return;const n=e.shape;(n.isTargetEndPoint()||n.isSourceEndPoint())&&t.css({cursor:i.cursor.hoverEdgeControllPoint})})})},function(t,e,n){const r=n(1),i=n(5),o=n(2);r.registerBehaviour("dragEdgeControlPoint",t=>{const e=t.getGraph(),n=e.getRootGroup();let r,a,s,c,u,h,l,d,f,g;function p(n){if(!s)return;const p={};e.getNodes().forEach(e=>{t.clearAnchor(e)}),t.css({cursor:i.cursor.beforePanCanvas}),s.remove();const m=o.dropUpdateEdge({ev:n,endPointType:r?"target":"source",model:p,diagram:t});e.show(f);const v=f.id;if(m){const n=t.editor;n?n.executeCommand("update",{itemId:v,updateModel:p}):e.update(v,p)}t.setSignal("dragEdge",!1),r=void 0,a=void 0,s=void 0,c=void 0,u=void 0,h=void 0,l=void 0,d=void 0,f=void 0,g=void 0}e.behaviourOn("edgeControlPoint:mousedown",i=>{if(2===i.button)return;const o=i.shape;o.isTargetEndPoint()?(f=o.getItem(),g=f.getModel(),r=o,c=o.getSourcePoint(),u=f.getSource(),l=g.sourceAnchor):o.isSourceEndPoint()&&(f=o.getItem(),g=f.getModel(),a=o,c=o.getTargetPoint(),h=f.getTarget(),d=g.targetAnchor),f&&(s=t.getDelegation([f],n),u?t.dragEdgeBeforeShowAnchor(u,l,"target"):h&&t.dragEdgeBeforeShowAnchor(h,d,"source"),e.hide(f),t.setSignal("dragEdge",!0))}),e.behaviourOn("mousemove",t=>{s&&o.dragingEdgeEndPoint({endPointType:u?"target":"source",edgeModel:g,graph:e,delegation:s,startPoint:c,ev:t,originSource:u,originTarget:h})}),e.behaviourOn("edgeControlPoint:mouseleave",e=>{r||a||e.toShape||t.css({cursor:i.cursor.beforePanCanvas})}),e.behaviourOn("mouseup",p),e.behaviourOn("canvas:mouseleave",p)},["dragHoverAnchorHotspot"])},function(t,e,n){const r=n(1),i=n(2);r.registerBehaviour("dragPanelItemAddNode",t=>{const e=t.getGraph(),n=e.getRootGroup();let r,o,a,s,c;function u(){t.setSignal("panningItem",!1),t.set("panItemDelegation",void 0),t.set("panItemStartBox",void 0),t.set("panItemStartPoint",void 0),o=void 0,a=void 0,s=void 0,c=void 0}e.behaviourOn("canvas:mouseenter",e=>{if(!o&&(s=t.get("addType"),c=t.get("addModel"),c=i.clone(c),"node"===s)){a=i.getNodeSize(c.size);const s=a[0]/2,u=a[1]/2;r={minX:e.x-s,minY:e.y-u,maxX:e.x+s,maxY:e.y+u,width:a[0],height:a[1]},o=t.getDelegation([r],n),t.setSignal("panningItem",!0),t.set("panItemDelegation",o),t.set("panItemStartBox",r),t.set("panItemStartPoint",{x:e.x,y:e.y})}}),e.behaviourOn("mouseup",n=>{if(!o)return;c.x=n.x,c.y=n.y;const r=s;i.setId(c);const a=t.editor;o.remove(),t.endAdd(),t.clearAlignLine(),t.clearSelected(),t.focusGraphWrapper(),a?a.executeCommand("add",{type:"node",addModel:c}):e.add(r,c),t.setSelected(e.find(c.id),!0),u()}),e.behaviourOn("canvas:mouseleave",()=>{o&&(t.clearAlignLine(),o.remove(),e.draw(),t.cancelAdd(),u())})},["processPanItem"])},function(t,e,n){n(1).registerBehaviour("dragHoverAnchorHotspot",t=>{const e=t.getGraph();e.behaviourOn("anchor:dragenter",e=>{if(t.getSignal("dragEdge")){const n=e.shape;t.setHotspotActived(n,!0)}}),e.behaviourOn("anchor:dragleave",e=>{if(t.getSignal("dragEdge")){const n=e.shape;t.setHotspotActived(n,!1)}})})},function(t,e,n){const r=n(1),i=n(2);r.registerBehaviour("dragAnchorAddEdge",t=>{const e=t.getGraph(),n=e.getRootGroup();e.behaviourOn("anchor:dragstart",e=>{if(2===e.button)return;const r=e.shape,o=r.get("freezePoint"),a=r.getItem(),s=i.clone(t.get("addModel")),c=r.getIndex();s.source=a.id,s.sourceAnchor=c;const u={x:o.x,y:o.y},h=t.getDelegation([{isEdge:!0}],n);t.setSignal("dragEdge",!0),t.dragEdgeBeforeShowAnchor(a,c,"target"),t.set("addEdgeConfig",{addModel:s,delegation:h,startPoint:u,sourceItem:a})})},["processAddEdge","dragHoverAnchorHotspot","hoverAnchorActived"])},function(t,e,n){const r=n(1),i=n(5);r.registerBehaviour("dragMultiSelect",t=>{const e=t.getGraph(),n=e.getRootGroup();let r,o;function a(){t.css({cursor:i.cursor.beforePanCanvas}),r=void 0,o=void 0}t.css({cursor:i.cursor.multiSelect}),e.behaviourOn("dragstart",t=>{2!==t.button&&(r={x:t.x,y:t.y},o=n.addShape("rect",{attrs:i.multiSelectRectStyle}))}),e.behaviourOn("drag",t=>{o&&(o.attr({x:Math.min(r.x,t.x),y:Math.min(r.y,t.y),width:Math.abs(t.x-r.x),height:Math.abs(t.y-r.y)}),e.draw())}),e.behaviourOn("dragend",()=>{if(!o)return;const n=e.getNodes().map(t=>t.id),r=o.getBBox();function i(){t.clearSelected(),n.forEach(n=>{const i=e.find(n),o=i.getBBox();o.minX>r.minX&&o.minY>r.minY&&o.maxX<r.maxX&&o.maxY<r.maxY&&t.setSelected(i,!0)})}const s=t.editor;s?s.executeCommand(i):i(),o.remove(),t.changeMode("default"),t.updateStatus(),e.draw(),a()}),e.behaviourOn("canvas:mouseleave",()=>{o&&(o.remove(),e.draw(),a())})})},function(t,e,n){n(1).registerBehaviour("keydownShiftMultiSelected",t=>{const e=t.getGraph();e.behaviourOn("keydown",e=>{e.domEvent.shiftKey&&t.setSignal("shiftKeyDown",!0)}),e.behaviourOn("keyup",e=>{e.domEvent.shiftKey||t.setSignal("shiftKeyDown",!1)})})},function(t,e,n){const r=n(1),i=n(5);r.registerBehaviour("dragNodeAddToGroup",t=>{const e=t.getGraph();let n,r;function o(){t.setSignal("dragaddnodetogroup",!1),n=void 0,r=void 0}e.behaviourOn("dragenter",o=>{if(!t.getSignal("panningItem"))return;const a=t.get("panItems");a[0]&&a[0].isNode&&1===a.length&&o.item&&o.item.isGroup&&a[0].getParent()!==o.item&&(n=a[0],r=o.item,e.update(r,{padding:i.groupBackgroundPadding.map(t=>t+4),style:i.dragNodeHoverToGroupStyle}))}),e.behaviourOn("dragleave",()=>{r&&n&&e.update(r,{padding:void 0,style:void 0})}),e.behaviourOn("drop",i=>{if(!r||!n||r!==i.item)return;t.setSignal("dragaddnodetogroup",!0);const o=n.id,a=r.id;function s(){e.update(o,{parent:a})}e.update(a,{padding:void 0,style:void 0,collapsed:!1});const c=t.editor;c?c.executeCommand(s):s()}),e.behaviourOn("dragend",()=>{o()}),e.behaviourOn("canvas:mouseleave",()=>{r&&(e.update(r,{padding:void 0,style:void 0}),o())})})},function(t,e,n){const r=n(1),i=n(5),o=n(2);r.registerBehaviour("dragOutFromGroup",t=>{const e=t.getGraph();let n,r,a,s=!1;function c(){clearTimeout(a),r&&e.update(r,{padding:void 0,style:void 0}),s=!1,n=void 0,r=void 0}e.behaviourOn("drag",c=>{t.getSignal("panningItem")&&!s&&(clearTimeout(a),a=setTimeout(()=>{const a=t.get("panItems");if(a){if(n=a[0],r=a[0].getParent(),n&&1===a.length&&r&&!c.shape){const n=t.get("panItemDelegation").getBBox(),a=r.getBBox();o.rectRectCrossAlgorithm(n,a)&&(e.update(r,{padding:i.groupBackgroundPadding.map(t=>t-8),style:i.dragNodeLeaveFromGroupStyle}),s=!0)}s||(n=void 0,r=void 0)}},i.outFromGroupDelayTime))}),e.behaviourOn("dragenter",t=>{n&&r&&(r===t.item&&e.update(r,{padding:i.groupBackgroundPadding.map(t=>t+4),style:i.dragNodeHoverToGroupStyle}),s=!1)}),e.on("drop",t=>{r&&n&&!t.shape&&(e.update(n,{parent:void 0}),e.update(r,{style:void 0}),c())}),e.on("dragend",()=>{c()}),e.behaviourOn("canvas:mouseleave",()=>{c()})})},function(t,e,n){const r=n(1),i=n(2),o=n(5);r.registerBehaviour("processAddEdge",t=>{const e=t.getGraph();function n(){t.setSignal("dragEdge",!1),t.set("addEdgeConfig",{addModel:void 0,delegation:void 0,startPoint:void 0,sourceItem:void 0})}e.behaviourOn("mousemove",n=>{const r=t.get("addEdgeConfig");if(!r)return;const{addModel:o,delegation:a,startPoint:s,sourceItem:c}=r;a&&i.dragingEdgeEndPoint({endPointType:"target",edgeModel:o,graph:e,delegation:a,startPoint:s,ev:n,sourceItem:c})}),e.behaviourOn("mouseup",r=>{const a=t.get("addEdgeConfig");if(!a)return;const{addModel:s,delegation:c,sourceItem:u}=a,h=t.editor;if(!c)return void n();e.getNodes().forEach(e=>{t.clearAnchor(e)}),t.clearAnchor(u),t.setActived(u,!1),t.setSelected(u,!1),t.css({cursor:o.cursor.beforePanCanvas}),c.remove();i.dropUpdateEdge({ev:r,endPointType:"target",model:s,diagram:t})&&(h?h.executeCommand("add",{type:"edge",addModel:s}):e.add("edge",s)),e.draw(),t.endAdd(),n()}),e.behaviourOn("canvas:mouseleave",()=>{const r=t.get("addEdgeConfig");if(!r)return;const{delegation:i,sourceItem:o}=r;if(!i)return void n();e.getNodes().forEach(e=>{t.clearAnchor(e)}),t.setActived(o,!1),t.clearAnchor(o),i.remove(),t.cancelAdd(),e.draw(),n()})})},function(t,e,n){n(1).registerBehaviour("hoverNodeAddOutter",t=>{const e=t.getGraph();let n;e.behaviourOn("node:mouseenter",({item:e})=>{t.getSignal("dragEdge")&&(n=e,t.addOutterShape(e,{stroke:"#52C41A",strokeOpacity:.45,lineWidth:4}))}),e.behaviourOn("node:mouseleave",()=>{n&&t.clearOutterShape(n)}),e.behaviourOn("beforedropedge",()=>{n&&t.clearOutterShape(n)})})},function(t,e,n){const r=n(1),i=n(5),o=n(2);r.registerBehaviour("orbit",t=>{const e=t.getGraph();let n;e.behaviourOn("beforepanitem",()=>{t.hideOrbit()}),e.behaviourOn("node:mouseenter",({item:e})=>{t.getSignal("panningItem")||t.getSignal("dragEdge")||(n=e,t.showOrbit(e))}),e.on("beforeviewportchange",()=>{t.hideOrbit()}),e.behaviourOn("mousemove",({item:r,x:a,y:s})=>{if(!n)return;const c=n.getBBox(),u=o.euclideanDistance.pointPoint({x:c.centerX,y:c.centerY},{x:a,y:s}),h=e.getMatrix()[0];r!==n&&u>c.width/2+i.orbitGap/h&&(t.hideOrbit(),n=void 0),n&&t.layoutOrbit(n,{x:a,y:s})})})},function(t,e,n){const r=n(11);n(96),t.exports=r},function(t,e,n){n(97),n(98),n(99),n(100),n(101)},function(t,e,n){const r=n(11);r.registerNode("flow-base",{}),r.registerNode("flow-html",{},["html"]),r.registerNode("flow-rect",{},"flow-base"),r.registerNode("flow-capsule",{},"capsule"),r.registerNode("flow-circle",{},"circle"),r.registerNode("flow-rhombus",{},"rhombus")},function(t,e,n){n(11).registerEdge("flow-base",{})},function(t,e,n){const r=n(19),i=n(11);function o(t,e,n,r){const i=r?r/2:30,o=r;if(t<=e&&e<=n||t>=e&&e>=n){const r=(n-e)/2,a=Math.abs(r);if(0===r)return t===e?0:(e-t)/Math.abs(e-t)*i;if(a>o){const t=r/a*o;return Math.abs(t)<i?r/a*i:t}return a<i?r/a*i:r}let a=i;return a=Math.abs(e-n)<2*Math.abs(e-t)?r*Math.abs(e-n)/(2*Math.abs(e-t)):r,a>o&&(a=o),a<i&&(a=i),e>t?a:-a}function a(t,e,n,r){const i=t.bbox,a=function(t,e){const n=Math.abs(t.x-e.centerX),r=Math.abs(t.y-e.centerY);return n/e.width>r/e.height}(e,i);let s,c;s=c=0;let u=Math.min(i.height,i.width);return r&&r.bbox&&(u=Math.min(u,r.bbox.height,r.bbox.width)),a?s=o(i.centerX,e.x,n.x,u):c=o(i.centerY,e.y,n.y,u),{x:e.x+s,y:e.y+c}}function s(t,e){const n=t.x,r=t.y;return{x:n+.1*(e.x-n),y:r+.1*(e.y-r)}}function c(t,e,n){const i=t[0],o=t[t.length-1],c=["M",i.x,i.y],u=function(t,e,n,r){return[n&&n.bbox?a(n,t,e,r):s(t,e),r&&r.bbox?a(r,e,t,n):s(e,t)]}(i,o,e,n),h=["C"],l=[c];return r.each(u,(function(t){h.push(t.x,t.y)})),h.push(o.x,o.y),l.push(h),l}i.registerEdge("flow-smooth",{getPathByPoints:({points:t,source:e,target:n})=>c(t,e,n)},"flow-edge")},function(t,e,n){const r=n(19),i=n(11),o={offset:16,borderRadius:5};function a(t,e){const n=Math.min(t.minX,e.minX),r=Math.min(t.minY,e.minY),i=Math.max(t.maxX,e.maxX),o=Math.max(t.maxY,e.maxY);return{centerX:(n+i)/2,centerY:(r+o)/2,minX:n,minY:r,maxX:i,maxY:o,height:o-r,width:i-n}}function s(t,e){return 2*Math.abs(t.centerX-e.centerX)<t.width+e.width&&2*Math.abs(t.centerY-e.centerY)<t.height+e.height}function c(t){const{x:e,y:n}=t;return{centerX:e,centerY:n,minX:e,minY:n,maxX:e,maxY:n,height:0,width:0}}function u(t,e){return 0===t.width&&0===t.height?t:{centerX:t.centerX,centerY:t.centerY,minX:t.minX-e,minY:t.minY-e,maxX:t.maxX+e,maxY:t.maxY+e,height:t.height+2*e,width:t.width+2*e}}function h(t,e){return function(t,e){const n=Math.abs(t.x-e.centerX),r=Math.abs(t.y-e.centerY);return n/e.width>r/e.height}(e,t)?{x:e.x>t.centerX?t.maxX:t.minX,y:e.y}:{x:e.x,y:e.y>t.centerY?t.maxY:t.minY}}function l(t){const{minX:e,minY:n,maxX:r,maxY:i}=t;return[{x:e,y:n},{x:r,y:n},{x:r,y:i},{x:e,y:i}]}function d(t,e){const{x:n,y:r}=t;return n<e.minX||n>e.maxX||r<e.minY||r>e.maxY}function f(t,e,n,r){const i=e.x-t.x,o=e.y-t.y,a=r.x-n.x,s=r.y-n.y,c=(-o*(t.x-n.x)+i*(t.y-n.y))/(-a*o+i*s),u=(a*(t.y-n.y)-s*(t.x-n.x))/(-a*o+i*s);return c>=0&&c<=1&&u>=0&&u<=1}function g(t,e,n){if(n.width===n.height===0)return!1;const[r,i,o,a]=l(n);return f(t,e,r,i)||f(t,e,r,a)||f(t,e,i,o)||f(t,e,o,a)}function p(t){return t=v(t)}function m(t,e){return[t,{x:t.x,y:e.y},e]}function v(t){const e=[],n={};return t.forEach(t=>{const e=t.id=`${t.x}-${t.y}`;n[e]=t}),r.each(n,t=>{e.push(t)}),e}function x(t,e){return Math.abs(t.x-e.x)+Math.abs(t.y-e.y)}function y(t,e,n,r,i){return x(t,e)+x(t,n)+function(t,e){let n=0;return e.forEach(e=>{e&&(t.x===e.x&&(n+=-2),t.y===e.y&&(n+=-2))}),n}(t,[e,n,r,i])}function b(t,e){const n=t.indexOf(e);n>-1&&t.splice(n,1)}function w(t,e,n,r){const i=[];return t.forEach(t=>{t!==e&&(t.x!==e.x&&t.y!==e.y||g(t,e,n)||g(t,e,r)||i.push(t))}),v(i)}function M(t,e,n,r,i=0){t.unshift(e[r]),n[r]&&n[r]!==r&&i<=100&&M(t,e,n,n[r],i+1)}function _(t,e,n,r,i){const o=n&&n.bbox?n.bbox:c(t),f=r&&r.bbox?r.bbox:c(e);if(s(o,f))return p(m(t,e));const g=u(o,i),_=u(f,i);if(s(g,_))return p(m(t,e));const S=h(g,t),A=h(_,e),E=function(t=[]){const e=[],n=[];t.forEach(t=>{e.push(t.x),n.push(t.y)});const r=Math.min.apply(Math,e),i=Math.max.apply(Math,e),o=Math.min.apply(Math,n),a=Math.max.apply(Math,n);return{centerX:(r+i)/2,centerY:(o+a)/2,maxX:i,maxY:a,minX:r,minY:o,height:a-o,width:i-r}}([S,A]),P=(a(g,_),a(g,E)),C=a(_,E);let O=[];O=O.concat(l(P)),O=O.concat(l(C));const I={x:(t.x+e.x)/2,y:(t.y+e.y)/2};[E,P,C].forEach(t=>{O=O.concat(function(t,e){return function(t,e){return e<t.minX||e>t.maxX?[]:[{x:e,y:t.minY},{x:e,y:t.maxY}]}(t,e.x).concat(function(t,e){return e<t.minY||e>t.maxY?[]:[{x:t.minX,y:e},{x:t.maxX,y:e}]}(t,e.y))}(t,I).filter(t=>d(t,g)&&d(t,_)))}),[{x:S.x,y:A.y},{x:A.x,y:S.y}].forEach(t=>{d(t,g)&&d(t,_)&&O.push(t)}),O.unshift(S),O.push(A),O=v(O);const k=function(t,e,n,r,i,o,a){const s=[],c=[e],u={},h={},l={};h[e.id]=0,l[e.id]=y(e,n,e);const d={};for(t.forEach(t=>{d[t.id]=t});c.length;){let f,g=1/0;if(c.forEach(t=>{l[t.id]<g&&(g=l[t.id],f=t)}),f===n){const t=[];return M(t,d,u,n.id),t}b(c,f),s.push(f),w(t,f,r,i).forEach(t=>{if(-1!==s.indexOf(t))return;-1===c.indexOf(t)&&c.push(t);const r=l[f.id]+x(f,t);h[t.id]&&r>=h[t.id]||(u[t.id]=f.id,h[t.id]=r,l[t.id]=h[t.id]+y(t,n,e,o,a))})}return console.error("cannot find path: ",t,e,n),[e,n]}(O,S,A,o,f,t,e);return k.unshift(t),k.push(e),p(k)}function S(t,e){const n=[],r=t[0];return n.push(`M${r.x} ${r.y}`),t.forEach((r,i)=>{const o=t[i+1],a=t[i+2];if(o&&a)if(function(t,e,n){return!(t.x===e.x===n.x||t.y===e.y===n.y)}(r,o,a)){const[t,i]=function(t,e,n,r){const i=x(t,e),o=x(n,e);return i<r&&(r=i),o<r&&(r=o),[{x:e.x-r/i*(e.x-t.x),y:e.y-r/i*(e.y-t.y)},{x:e.x-r/o*(e.x-n.x),y:e.y-r/o*(e.y-n.y)}]}(r,o,a,e);n.push(`L${t.x} ${t.y}`),n.push(`Q${o.x} ${o.y} ${i.x} ${i.y}`),n.push(`L${i.x} ${i.y}`)}else n.push(`L${o.x} ${o.y}`);else o&&n.push(`L${o.x} ${o.y}`)}),n.join("")}i.registerEdge("flow-polyline",{getPathByPoints({points:t,source:e,target:n}){const{offset:i}=o,a=_(t[0],t[t.length-1],e,n,i);return r.pointsToPolygon(a)}}),i.registerEdge("flow-polyline-round",{getPathByPoints({points:t,source:e,target:n}){const{offset:r,borderRadius:i}=o;return S(p(_(t[0],t[t.length-1],e,n,r)),i)}})},function(t,e,n){n(11).registerGroup("flow-base",{})},function(t,e,n){const r=n(17);n(103),t.exports=r},function(t,e,n){n(104),n(105),n(106)},function(t,e,n){n(17).registerNode("koni-base",{defaultFillPalette:5,defaultStrokePalette:5,activedFillPalette:4,activedStrokePalette:6,selectedFillPalette:5,selectedStrokePalette:6,anchor:null},"circle")},function(t,e,n){const r=n(17),i=n(24),{vec2:o}=i;r.registerEdge("koni-base",{getDefaultLabelRectPadding:()=>i.toAllPadding([0,2]),getPathByPoints({points:t,source:e,target:n,item:r}){if(e&&n){const t=i.getParallelEdges(n,e);let a=i.getParallelEdges(e,n),s=a.indexOf(r);return e===n?(a=a.filter(t=>{const r=t.getModel();return r.source===e.id&&r.target===n.id}),s=a.indexOf(r),function(t,e){const n=t.getBBox(),r=[n.centerX,n.centerY],i=n.width/2,a=50*(e+1)+50,s=[r[0]-i/2,r[1]-Math.sqrt(3)/2*i],c=[s[0]-r[0],s[1]-r[1]],u=o.scale([],c,(i+a)/i),h=[r[0]+u[0],r[1]+u[1]],l=[r[0]+i/2,r[1]-Math.sqrt(3)/2*i],d=[l[0]-r[0],l[1]-r[1]],f=o.scale([],d,(i+a)/i),g=[r[0]+f[0],r[1]+f[1]];return[["M",s[0],s[1]],["C",h[0],h[1],g[0],g[1],l[0],l[1]]]}(e,s)):(0===t.length&&s--,function(t,e,n){const r=t.getBBox(),i=e.getBBox(),a=r.centerX,s=r.centerY,c=20*(n+1),u=[.5*(i.centerX+a)-a,.5*(i.centerY+s)-s],h=[-u[1],u[0]],l=o.length(h);o.scale(h,h,c/l);const d={x:u[0]+h[0]+a,y:u[1]+h[1]+s},f=t.getLinkPoints(d)[0],g=e.getLinkPoints(d)[0];return[["M",f.x,f.y],["Q",d.x,d.y,g.x,g.y]]}(e,n,s))}return i.pointsToPolygon(t)}})},function(t,e,n){n(17).registerGroup("koni-base",{})},function(t,e,n){const r=n(8);r.Util=n(10),n(108),n(112),n(120),t.exports=r},function(t,e,n){n(109),n(110),n(111)},function(t,e,n){const r=n(1),i=n(10);r.registerBehaviour("panMindNode",t=>{const e=t.getGraph();let n,r,o;function a(){n.nth=r;const i=e.add("node",n);t.setSelected(i,!0),o&&e.remove(o.id)}function s(){e.emit("panitemend"),n=void 0,o=void 0,r=void 0}e.behaviourOn("beforeshowdelegation",()=>{t.clearSelected(),t.clearActived()}),e.behaviourOn("node:dragstart",t=>{if(2===t.button)return;const i=t.item;n=i.getModel(),!n.parent||t.shape.isCollapsedButton||t.shape.isExpandedButton?s():(r=e.getNth(i),e.remove(i))}),e.behaviourOn("itempanning",n=>{if(n.shape&&n.shape.isPlaceholder)return;const r=t.getHotArea(n),i=t.getRoot();if(o&&(r?o.id!==r.id&&e.remove(e.find(o.id)):e.remove(e.find(o.id))),o=r,r){const t=r.parent;if(!e.find(r.id)){const n={id:r.id,parent:t.id,isPlaceholder:!0,parentModel:t,baseline:o.parent.id===i.id?"center":void 0,shape:"mind-placeholder",nth:r.nth};r.side&&(n.side=r.side),e.add("node",n)}}}),e.behaviourOn("drop",()=>{if(n)if(o){const a=i.clone(n);e.remove(o.id),t.executeCommand("moveMindNode",{model:a,newParentId:o.parent.id,newNth:o.nth,newSide:o.side,originParentId:n.parent,originNth:r,originSide:n.side})}else a();s()}),e.behaviourOn("canvas:mouseleave",()=>{n&&(a(),s())})},["startPanItem","processPanItem","endPanItem"])},function(t,e,n){n(1).registerBehaviour("keydownMoveSelection",t=>{t.getGraph().on("keydown",e=>{t._moveItemSelection(e)})})},function(t,e,n){n(1).registerBehaviour("keydownEditLabel",t=>{t.getGraph().behaviourOn("keydown",e=>{t.showLabelEditor(e)})})},function(t,e,n){n(113),n(114),n(115),n(116),n(117),n(118),n(119)},function(t,e,n){const r=n(8),i=n(10),o={fill:"#000",textAlign:"left",textBaseline:"top"},a={stroke:"#959EA6",strokeOpacity:0,fill:"#959EA6",cursor:"pointer"},s={stroke:"#434B54",fill:"#fff",cursor:"pointer"};r.registerNode("mind-base",{dy:4,afterDraw(t){const e=t.getModel();e.children&&e.children.length>0&&e.collapsed&&this.drawExpandedButton(t)},debugDrawLayoutPoint(t){const e=t.getModel();t.getGraphicGroup().addShape("circle",{attrs:{x:e.x,y:e.y,r:5,fill:"red"}})},drawExpandedButton(t){const e=t.getKeyShape().getBBox(),n=t.getGraphicGroup().addGroup(),r=n.addShape("path",{attrs:{path:i.getRectPath(0,0,16,7,3),...a}}),o=r.getBBox(),s=i.getMindNodeSide(t),c=this.getButtonPositon(e,o,s),u={fill:"white",r:1};n.addShape("circle",{attrs:{...u,x:4,y:3.5},capture:!1}),n.addShape("circle",{attrs:{...u,x:8,y:3.5},capture:!1}),n.addShape("circle",{attrs:{...u,x:12,y:3.5},capture:!1}),r.attr("lineAppendWidth",20),n.translate(c.x,c.y),r.isExpandedButton=!0,r.isButton=!0},drawCollapsedButton(t){const e=t.getKeyShape().getBBox(),n=t.getGraphicGroup().addShape("path",{attrs:{path:i.getCollapsedButtonPath(),...s}}),r=n.getBBox(),o=i.getMindNodeSide(t),a=this.getButtonPositon(e,r,o);n.translate(a.x,a.y),n.isCollapsedButton=!0,n.isButton=!0},getButtonPositon:(t,e,n)=>"right"===n?{x:t.maxX+2,y:t.maxY-(e.maxY-e.minY)/2}:{x:t.minX-(e.maxX-e.minX)-2,y:t.maxY-(e.maxY-e.minY)/2},getLabel:t=>t.getModel().label,getPadding:()=>[4,8,4,8],getSize(t){const e=t.getModel(),n=t.getGraphicGroup(),r=e.size;if(e.size){if(i.isArray(r))return r;if(i.isNumber(r))return[r,r]}const o=n.findByClass("label")[0],a=this.getPadding(t),s=o.getBBox();return[s.width+a[1]+a[3],s.height+a[0]+a[2]]},getPath(t){const e=this.getSize(t),n=this.getStyle(t);return i.getRectPath(-e[0]/2,-e[1]/2+this.dy,e[0],e[1],n.radius)},drawLabel(t){const e=t.getGraphicGroup();let n=this.getLabel(t);const r=this.getLabelStyle(t);n||(n=" ");const a=i.mix(!0,{},o,r,{x:0,y:0});i.isObject(n)?i.mix(a,n):a.text=n;const s=e.addShape("text",{class:"label",attrs:a});return this.adjustLabelText(s),this.adjustLabelPosition(t,s),s},adjustLabelText(t){let e=t.attr("text");const n=t.getBBox();if(n.maxX-n.minX>400){const n=t.attr("font");e=i.getLabelTextByTextLineWidth(e,n),t.attr("text",e)}},adjustLabelPosition(t,e){const n=this.getSize(t),r=this.getPadding(),i=n[0],o=e.getBBox();e.attr({x:-i/2+r[3],y:-o.height/2+this.dy})},getLabelStyle:()=>({fill:"rgba(38,38,38,0.85)",lineHeight:18,fontSize:12}),getStyle:()=>({fill:"#ccc",fillOpacity:0,radius:4,lineWidth:2}),getActivedStyle:()=>({stroke:"#44C0FF",lineWidth:2}),getSelectedStyle:()=>({stroke:"#1AA7EE",lineWidth:2}),anchor:[[0,1],[1,1]]})},function(t,e,n){n(8).registerNode("mind-first-sub",{dy:0,getPadding:()=>[6,12,8,12],getLabelStyle:()=>({fill:"rgba(38,38,38,0.85)",fontWeight:500,fontSize:14,lineHeight:20})})},function(t,e,n){n(8).registerNode("mind-second-sub",{dy:0,getPadding:()=>[8,4,8,4],getLabelStyle:()=>({fill:"rgba(38,38,38,0.85)",fontSize:12,lineHeight:20})})},function(t,e,n){const r=n(8),i=n(10);r.registerNode("mind-root",{adjustLabelPosition(t,e){const n=e.getBBox();e.attr({x:-n.width/2,y:-n.height/2-1})},getPath(t){const e=this.getSize(t),n=this.getStyle(t);return i.getRectPath(-e[0]/2,-e[1]/2,e[0],e[1],n.radius)},getButtonPositon:(t,e,n)=>"right"===n?{x:t.maxX+2,y:(t.maxY+t.minY)/2-(e.maxY-e.minY)/2}:{x:t.minX-(e.maxX-e.minX)-2,y:(t.maxY+t.minY)/2-(e.maxY-e.minY)/2},getPadding:()=>i.toAllPadding([12,24]),getStyle:()=>({fill:"#587EF7",stroke:"#587EF7",fillOpacity:1,radius:4}),getLabelStyle:()=>({fontSize:20,fill:"white",lineHeight:28}),drawExpandedButton(){},drawCollapsedButton(){},panAble:!1,anchor:[[.45,.5],[.55,.5]]},"mind-first-sub")},function(t,e,n){const r=n(8),i=n(10);r.registerNode("mind-placeholder",{afterDraw(t){t.getKeyShape().isPlaceholder=!0},getPath(t){const e=t.getModel(),{parentModel:n}=e,r=this.getStyle(t);let o,a=0;return n.hierarchy<=2?o=28:(o=20,a=4),i.getRectPath(-27.5,-o/2+a,55,o,r.radius)},getStyle:()=>({fill:"#91D5FF",radius:4,lineWidth:3}),drawExpandedButton(){},drawCollapsedButton(){},anchor:()=>[[0,1],[1,1]]})},function(t,e,n){n(8).registerEdge("mind-edge",{getEdetal:t=>t.children&&t.children.length>0&&!t.collapsed?2===t.hierarchy?24:18:0,getPath(t){const e=t.getPoints(),n=t.getSource(),r=t.getTarget(),i=n.getBBox(),o=r.getBBox(),a=r.getModel();let s=14,c=4;if(2===a.hierarchy&&(s=66,c=30),e[0].y===e[1].y){const t=3===a.hierarchy?24:18,n=this.getEdetal(a);return i.centerX<o.centerX?[["M",e[0].x+t,e[0].y],["L",o.maxX+n,o.maxY]]:[["M",e[0].x+2,e[0].y],["L",o.minX-n,o.maxY]]}if(a.hierarchy>=3){const t=3===a.hierarchy?24:18,n=this.getEdetal(a);if(i.centerX<o.centerX){const r=e[0].x+t;return[["M",e[0].x,e[0].y],["M",r,e[0].y],["C",r+c,e[0].y,o.minX-s,o.maxY,o.minX,o.maxY],["L",o.maxX+n,o.maxY]]}const r=e[0].x-t;return[["M",e[0].x,e[0].y],["M",r,e[0].y],["C",r-c,e[0].y,o.maxX+s,o.maxY,o.maxX,o.maxY],["L",o.minX-n,o.maxY]]}const u=this.getEdetal(a);return i.centerX<o.centerX?[["M",e[0].x,e[0].y],["C",e[0].x+c,e[0].y,o.minX-s,o.maxY,o.minX,o.maxY],["L",o.maxX+u,o.maxY]]:[["M",e[0].x,e[0].y],["C",e[0].x-c,e[0].y,o.maxX+s,o.maxY,o.maxX,o.maxY],["L",o.minX-u,o.maxY]]},getStyle(t){const e=t.getTarget();let n=1;if(e){const t=e.getModel();n=t.hierarchy<=3?3:t.hierarchy<=5?2:1}return{stroke:"#959EA6",lineWidth:n}}})},function(t,e,n){n(8).registerEdge("mind-placeholder-edge",{getOriginShapeObject:t=>t.getGraph().getShapeObj("edge",{shape:"mind-edge"}),getPath(t){return this.getOriginShapeObject(t).getPath(t)},getStyle(t){return{...this.getOriginShapeObject(t).getStyle(t),stroke:"#91D5FF"}}})},function(t,e,n){const r=n(15),i=n(10);function o(t,e,n){const r=t.getGraph(),i=e.getModel(),o=t.getFirstChildrenBySide("left"),a=o[0]&&r.find(o[0].id);return r.add("node",{id:n,parent:e.id,label:"新建节点",side:i.children.length>2?"left":"right",nth:a?r.getNth(a):void 0})}r.registerCommand("append",{enable(t){const e=t.getCurrentPage(),n=e.getSelected();return e.isMind&&1===n.length},getItem(t){const e=t.getCurrentPage(),n=e.getGraph();return this.selectedItemId?n.find(this.selectedItemId):e.getSelected()[0]},execute(t){const e=t.getCurrentPage(),n=e.getGraph(),r=e.getRoot(),i=this.getItem(t),a=i.getModel(),s=a.hierarchy,c=i.getParent();let u;if(i.isRoot)u=o(e,i,this.addItemId);else{const t=n.getNth(i);u=n.add("node",{id:this.addItemId,parent:c.id,side:2===s&&3===r.children.length?"left":a.side,label:"新建节点",nth:"left"===a.side&&2===s?t:t+1})}e.clearSelected(),e.clearActived(),e.setSelected(u,!0),1===this.executeTimes&&(this.selectedItemId=i.id,this.addItemId=u.id,e.beginEditLabel(u))},back(t){const e=t.getCurrentPage();e.getGraph().remove(this.addItemId),e.clearSelected(),e.clearActived(),e.setSelected(this.selectedItemId,!0)},shortcutCodes:["Enter"]}),r.registerCommand("appendChild",{enable:function(t){const e=t.getCurrentPage(),n=e.getSelected();return e.isMind&&n.length>0},getItem(t){const e=t.getCurrentPage(),n=e.getGraph();return this.selectedItemId?n.find(this.selectedItemId):e.getSelected()[0]},execute(t){const e=t.getCurrentPage(),n=e.getGraph(),r=this.getItem(t);let i;i=r.isRoot?o(e,r,this.addItemId):n.add("node",{id:this.addItemId,parent:r.id,label:"新建节点"}),e.clearSelected(),e.clearActived(),e.setSelected(i,!0),1===this.executeTimes&&(this.selectedItemId=r.id,this.addItemId=i.id,e.beginEditLabel(i))},back(t){const e=t.getCurrentPage();e.getGraph().remove(this.addItemId),e.clearSelected(),e.clearActived(),e.setSelected(this.selectedItemId,!0)},shortcutCodes:["Tab"]}),r.registerCommand("moveMindNode",{enable(t){const e=t.getCurrentPage(),n=e.get("panItems");return e.isMind&&n&&n.length>0},execute(t){const e=t.getCurrentPage(),n=e.getGraph(),r=this.newParentId,o=this.newNth,a=this.newSide,s=i.clone(this.model);delete s.shape,delete s.side,n.remove(s.id),i.mix(s,{parent:r,nth:o,side:a});const c=n.add("node",s);e.clearSelected(),e.setSelected(c,!0)},back(t){const e=t.getCurrentPage(),n=e.getGraph(),r=this.originParentId,o=this.originNth,a=this.originSide,s=i.clone(this.model);delete s.shape,delete s.side,n.remove(s.id),i.mix(s,{parent:r,nth:o,side:a});const c=n.add("node",s);e.clearSelected(),e.setSelected(c,!0)}})},function(t,e,n){const r=n(6),i=n(9);t.exports=class extends i{getDefaultCfg(){return{type:"toolbar",container:null}}init(){this._initContainer()}_initContainer(){let t=this.container;if(!t)throw new Error("please set the container for the toolbar !");r.isString(t)&&(t=document.getElementById(t));const e=t.getElementsByClassName("command");this.commands=e}getCommandDoms(){return this.commands}}},function(t,e,n){const r=n(6),i=n(9);t.exports=class extends i{getDefaultCfg(){return{type:"contextmenu",container:null}}init(){this._initContainer()}_initContainer(){let t=this.container;if(!t)throw new Error("please set the container for the tontextmenu !");r.isString(t)&&(t=document.getElementById(t));const e=t.getElementsByClassName("command");t.style.position="absolute",t.style["z-index"]=2,t.style.top="0px",t.style.left="0px",this.commands=e,this.containerDom=t}bindEvent(){const t=this.commands;r.each(t,t=>{r.addEventListener(t,"click",()=>{-1===t.className.indexOf("disable")&&this.hide()})})}switch(t){const e=this.containerDom.getElementsByClassName("menu");r.each(e,e=>{e.dataset.status===t?e.style.display="block":e.style.display="none"})}getCommandDoms(){return this.commands}show(){const t=this.containerDom;this.editor.getCurrentPage().setSignal("preventWheelPan",!0),t.style.display="block"}hide(){const t=this.containerDom;this.editor.getCurrentPage().setSignal("preventWheelPan",!1),t.style.display="none"}move(t,e){const n=this.containerDom,i=r.getBoundingClientRect(n),o=parseFloat(r.getStyle(n,"top")),a=parseFloat(r.getStyle(n,"left"));n.style.left=a+(t-i.left)+"px",n.style.top=o+(e-i.top)+"px"}}},function(t,e,n){const r=n(12);n(124),n(127),t.exports=r},function(t,e,n){n(125),n(126)},function(t,e,n){const{mouseEnterEdge:r,startMove:i,mouseLeaveEdge:o,mouseMoveEdge:a,endMove:s}=n(20);let c,u;n(12).registerBehaviour("bpmnMoveEdgeController",t=>{const e=t.getGraph(),n=e.getRootGroup();let h;function l(){t.set("panItemDelegation",void 0),t.set("panItemStartBox",void 0),t.set("panItemStartPoint",void 0),h=void 0}e.behaviourOn("edge:mouseenter",n=>{!c&&n.item&&(u=n.item,r({graph:e,bpmn:t,ev:n,backUpCursor:!0}))}),e.behaviourOn("edge:mousedown",t=>{const n=t.item;i(e,t),c=n}),e.behaviourOn("mouseup",()=>{c&&(s({graph:e,item:c}),c=void 0)}),e.behaviourOn("mousemove",n=>{c?a(e,c,n):u&&r({graph:e,bpmn:t,ev:{...n,item:u},backUpCursor:!1})}),e.behaviourOn("edge:mouseleave",()=>{c||u&&(o({graph:e,bpmn:t,item:u}),u=void 0)}),e.behaviourOn("node:dragstart",e=>{const r=e.item.getBBox();h=t.getDelegation([r],n),t.set("bpmnNodePanDelegation",h),t.set("bpmnNodePanStartBox",r),t.set("bpmnNodePanStartPoint",{x:e.x,y:e.y}),t.set("bpmnNodePanStartItem",e.item)}),e.behaviourOn("node:dragend",n=>{const r=t.get("bpmnNodePanDelegation"),i=t.get("bpmnNodePanStartPoint"),o=t.get("bpmnNodePanStartItem");o&&o.getEdges().forEach(t=>{e.update(t,{nodeMoved:{item:o.id,start:i,delta:{x:n.x-i.x,y:n.y-i.y}}})}),r.remove(),l()})},["startPanItem","processPanItem","endPanItem"])},function(t,e,n){n(12).registerBehaviour("hoverNodeShowArrowController",t=>{const e=t.getGraph(),n=t.get("arrowController"),{long:r,thickness:i}=n;let o;e.on("node:mouseenter",a=>{if(t.getSignal("panningItem")||t.getSignal("dragEdge"))return;const{topArrow:s,bottomArrow:c,leftArrow:u,rightArrow:h}=n;o=a.item;const l=o.getBBox(),d=e.getDomPoint({x:l.centerX,y:l.minY}),f=e.getDomPoint({x:l.minX,y:l.centerY}),g=e.getDomPoint({x:l.centerX,y:l.maxY}),p=e.getDomPoint({x:l.maxX,y:l.centerY});s.css({top:d.y-(r+10)+"px",left:d.x-i/2+"px",transform:"rotate(-90deg)"}),c.css({top:g.y+10+"px",left:g.x-i/2+"px",transform:"rotate(90deg)"}),u.css({top:f.y-i/2+"px",left:f.x-(r+10)+"px",transform:"rotate(180deg)"}),h.css({top:p.y-i/2+"px",left:p.x+10+"px"}),s.setAttribute("anchorIndex",0),c.setAttribute("anchorIndex",2),u.setAttribute("anchorIndex",3),h.setAttribute("anchorIndex",1),t.showArrowController(o)}),e.behaviourOn("mousemove",({x:e,y:n})=>{if(!o)return;const i=o.getBBox(),a=r+10,s=i.minX-a,c=i.minY-a,u=i.maxX+a,h=i.maxY+a;(e<s||n<c||e>u||n>h)&&(t.hideArrowController(),o=void 0)})})},function(t,e,n){n(128);n(12).registerNode("bpmn-base",{anchor:null})},function(t,e,n){"use strict";n.r(e);var r=n(12),i=n.n(r),o=n(0);function a({bbox:t,shape:e="ROUNDED_RECT",point:n,vertical:r}){r=!!r;const i={true:"x",false:"y"},o={true:"minX",false:"minY"},a={true:"maxX",false:"maxY"};switch(e){case"ROUNDED_RECT":if(n[i[r]]>=t[o[r]]+4&&n[i[r]]<=t[a[r]]-4)return{added:void 0,joint:{x:r?n.x:n.x>t.centerX?t.maxX:t.minX,y:r?n.y>t.centerY?t.maxY:t.minY:n.y}};if(n[i[r]]>=t[o[r]]&&n[i[r]]<t[o[r]]+4)return{added:void 0,joint:{x:r?n.x:n.x>t.centerX?t.maxX-4+Math.sqrt(16-Math.pow(t.minY+4-n.y,2)):t.minX+4-Math.sqrt(16-Math.pow(t.minY+4-n.y,2)),y:r?n.y>t.centerY?t.maxY-4+Math.sqrt(16-Math.pow(t.minX+4-n.x,2)):t.minY+4-Math.sqrt(16-Math.pow(t.minX+4-n.x,2)):n.y}};if(n[i[r]]>=t[a[r]]-4&&n[i[r]]<=t[a[r]])return{added:void 0,joint:{x:r?n.x:n.x>t.centerX?t.maxX-4+Math.sqrt(16-Math.pow(n.y-t.maxY+4,2)):t.minX+4-Math.sqrt(16-Math.pow(n.y-t.maxY+4,2)),y:r?n.y>t.centerY?t.maxY-4+Math.sqrt(16-Math.pow(n.x-t.maxX+4,2)):t.minY+4-Math.sqrt(16-Math.pow(n.x-t.maxX+4,2)):n.y}};break;case"CIRCLE":if(n[i[r]]>=t[o[r]]&&n[i[r]]<=t[a[r]])return{added:void 0,joint:{x:r?n.x:n.x>t.centerX?t.centerX+Math.sqrt(16-Math.pow(t.centerY-n.y)):t.centerX-Math.sqrt(16-Math.pow(t.centerY-n.y)),y:r?n.y>t.centerY?t.centerY+Math.sqrt(16-Math.pow(t.centerX-n.x)):t.centerY-Math.sqrt(16-Math.pow(t.centerX-n.x)):n.y}};break;case"RHOMEBUS":if(n[i[r]]>=t[o[r]]&&n[i[r]]<=t[a[r]])return{added:void 0,joint:{x:r?n.x:n.x>t.centerX?n.y<t.centerY?(n.y-t.minY)*(t.maxX-t.centerX)/(t.centerY-t.minY)+t.centerX:(t.maxY-n.y)*(t.maxX-t.centerX)/(t.maxY-t.centerY)+t.centerX:n.y<t.centerY?t.centerX-(n.y-t.minY)*(t.centerX-t.minX)/(t.centerY-t.minY):t.centerX-(t.maxY-n.y)*(t.centerX-t.minX)/(t.maxY-t.centerY),y:r?n.y>t.centerY?n.x<t.centerX?(n.x-t.minX)*(t.maxY-t.centerY)/(t.centerX-t.minX)+t.centerY:(t.maxX-n.x)*(t.maxY-t.centerY)/(t.maxX-t.centerX)+t.centerY:n.x<t.centerX?t.centerY-(n.x-t.minX)*(t.centerY-t.minY)/(t.centerX-t.minX):t.centerY-(t.maxX-n.x)*(t.centerY-t.minY)/(t.maxX-t.centerX):n.y}};break;case"RECT":default:if(n[i[r]]>=t[o[r]]&&n[i[r]]<=t[a[r]])return{added:void 0,joint:{x:r?n.x:n.x>t.centerX?t.maxX:t.minX,y:r?n.y>t.centerY?t.maxY:t.minY:n.y}}}return r?n.x<t.centerX?{added:{x:n.x,y:t.centerY},joint:{x:t.minX,y:t.centerY}}:{added:{x:n.x,y:t.centerY},joint:{x:t.maxX,y:t.centerY}}:n.y<t.centerY?{added:{x:t.centerX,y:n.y},joint:{x:t.centerX,y:t.minY}}:{added:{x:t.centerX,y:n.y},joint:{x:t.centerX,y:t.maxY}}}var s=n(20);i.a.registerEdge("bpmn-base",{getPath(t){const e=t.getSource(),n=t.getTarget(),r=t.model;let i;if(r.edgeMoved&&r.lastMouse){const c=r.controlPoints,u=r.hold.index,h=[{x:c[u].x+r.edgeMoved.x,y:c[u].y+r.edgeMoved.y},{x:c[u+1].x+r.edgeMoved.x,y:c[u+1].y+r.edgeMoved.y}],l=Object(o.j)(h,0);let d,f,g,p;e&&({added:d,joint:f}=a({bbox:e.getBBox(),point:l,vertical:r.hold.vertical,shape:e.model.shape})),0===u&&e&&(h[0]=f,d&&(h.splice(1,0,d),t.model.hold.index+=1)),n&&({added:g,joint:p}=a({bbox:n.getBBox(),point:l,vertical:r.hold.vertical,shape:n.model.shape})),u===c.length-2&&n&&(d&&0===u?(h[2]=p,g&&h.splice(2,0,g)):(h[1]=p,g&&h.splice(1,0,g))),r.controlPoints.splice(u,2,...h),e&&Object(o.l)(f,c,r.hold.index)&&(c.splice(0,r.hold.index),r.hold.index=0,c[0]=f),n&&Object(o.l)(p,c,r.hold.index)&&(r.controlPoints.splice(r.hold.index+1),c[r.hold.index+1]=p),i=Object(s.mergeLine)(t,u),function(t,e,n){const r=t.controlPoints;if(e){const{point:n,index:i}=Object(o.f)(r[0],e.getBBox());t.sourceJoint={index:i,delta:{x:r[0].x-n.x,y:r[0].y-n.y}}}if(n){const{point:e,index:i}=Object(o.f)(r[r.length-1],n.getBBox());t.targetJoint={index:i,delta:{x:r[r.length-1].x-e.x,y:r[r.length-1].y-e.y}}}}(r,e,n),r.lastMouse={x:r.lastMouse.x+r.edgeMoved.x,y:r.lastMouse.y+r.edgeMoved.y}}else if(r.modifiedByMouse&&r.nodeMoved)!function(t,e,n){if(!t.nodeMoved)return;const r=t.nodeMoved.item===e.id,i=t.nodeMoved.item===n.id,a=r?e.getBBox():n.getBBox(),s=t.nodeMoved.delta,c={minX:a.minX-s.x,maxX:a.maxX-s.x,centerX:a.centerX-s.x,minY:a.minY-s.y,maxY:a.maxY-s.y,centerY:a.centerY+s.y,height:a.height,width:a.width},u=t.controlPoints;if(2===u.length){const{sourcePoint:r,targetPoint:i}=Object(o.d)(e,n);t.sourceJoint&&r.index===t.sourceJoint.index&&(r.point=Object(o.c)(e.getBBox())[r.index],r.point.x+=t.sourceJoint.delta.x,r.point.y+=t.sourceJoint.delta.y),t.targetJoint&&i.index===t.targetJoint.index&&(i.point=Object(o.c)(n.getBBox())[i.index],i.point.x+=t.targetJoint.delta.x,i.point.y+=t.targetJoint.delta.y);const a=Object(o.h)(r,i);t.controlPoints=a}else{let s;s=r?1:u.length-3;const h=Object(o.i)(u,s),l=Object(o.a)(c,u,s),d=Object(o.a)(a,u,s),f=r?t.sourceJoint:t.targetJoint;if(l===d){const e=Object(o.c)(a)[f.index],n={x:e.x+f.delta.x,y:e.y+f.delta.y},c=Object(o.g)(n,u,s);r?t.controlPoints.splice(0,2,n,c):i&&t.controlPoints.splice(s+1,2,c,n)}else if(0===d)if(3===u.length){const{sourcePoint:r,targetPoint:i}=Object(o.d)(e,n),a=Object(o.h)(r,i);t.controlPoints=a}else{const e=Object(o.j)(u,s);let n;n=h?e.y<a.centerY?0:2:e.x<a.centerX?3:1;const c=Object(o.c)(a)[n];if(r){const e=Object(o.g)(c,u,s+1);t.controlPoints.splice(0,3,c,e),t.sourceJoint={index:n,delta:{x:0,y:0}}}else if(i){const e=Object(o.g)(c,u,s-1);t.controlPoints.splice(s,3,e,c),t.targetJoint={index:n,delta:{x:0,y:0}}}}else{const e=Object(o.k)(f.index),n=Object(o.c)(a)[e],c=Object(o.g)(n,u,s);r?(t.controlPoints.splice(0,2,n,c),t.sourceJoint={index:e,delta:{x:0,y:0}}):i&&(t.controlPoints.splice(s+1,2,c,n),t.targetJoint={index:e,delta:{x:0,y:0}})}}}(r,e,n);else if(!r.modifiedByMouse){const i=r.anchorIndex,{sourcePoint:a,targetPoint:s}=Object(o.d)(e,n,!r.initialed&&i),c=Object(o.h)(a,s);t.model.controlPoints=c}return r.nodeMoved=void 0,{path:this.getPathByPoints({points:r.controlPoints}),helpLine:i}},draw(t){const e=t.getGraphicGroup(),n=t.model,{path:r,helpLine:i}=this.getPath(t),a=this.getStyle(t),s=Object(o.b)(e,r,a);if(null!=n.hold){const t=Object(o.j)(n.controlPoints,n.hold.index);e.addShape("circle",{attrs:{x:t.x,y:t.y,r:3,fill:"rgb(0,182,239)"}})}return i&&(n.helpLine=i,n.helpLineTime=(new Date).getTime()),!i&&(new Date).getTime()-n.helpLineTime>=150&&(n.helpLine=void 0,n.helpLineTime=void 0),n.helpLine&&e.addShape("path",{attrs:{path:[["M",n.helpLine[0].x,n.helpLine[0].y],["L",n.helpLine[1].x,n.helpLine[1].y]],lineAppendWidth:8,lineWidth:1,strokeOpacity:.92,stroke:"rgba(255,139,48)"}}),s}})}])})); \ No newline at end of file diff --git a/saga/seata-saga-statemachine-designer/package-lock.json b/saga/seata-saga-statemachine-designer/package-lock.json index d10ae78231120df3cfd7a1a72b0e0ec191e991de..9dc55edcaeaa9f87ae0e2abba13a5564f7fb1700 100644 --- a/saga/seata-saga-statemachine-designer/package-lock.json +++ b/saga/seata-saga-statemachine-designer/package-lock.json @@ -1,6 +1,6 @@ { - "name": "gg-editor", - "version": "2.0.4", + "name": "seata-saga-statemachine-designer", + "version": "0.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -9,7 +9,7 @@ "resolved": "https://registry.npmjs.org/@antv/attr/-/attr-0.0.7.tgz", "integrity": "sha512-dgvJ2j6Sn7of8AET9ykTseS8mjwisLcAGf/UCkEaMLCduCr6hQtwAEBIZnEpk0b04QlD5pu0kqV93B1ItnvCPw==", "requires": { - "@antv/util": "1.2.5" + "@antv/util": "~1.2.5" }, "dependencies": { "@antv/util": { @@ -17,7 +17,7 @@ "resolved": "https://registry.npmjs.org/@antv/util/-/util-1.2.5.tgz", "integrity": "sha512-yz1AjXSEjNu9O5kK9pqKq69f/Iliu/IA3XXljUcfrlbUtmUJ0CH1tB5I60vPqfaKaUPhz+/35K+56yqaCsGmqA==", "requires": { - "@antv/gl-matrix": "2.7.1" + "@antv/gl-matrix": "^2.7.1" } } } @@ -27,10 +27,10 @@ "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.0.9.tgz", "integrity": "sha512-AcI6oG0Ot9svKieA3AowQuGmwsIjQpC2XJv71FRua/3b0IaWnF3K93vyJnmsWej+CQnXPE68JZaIjdgtAcgTwg==", "requires": { - "@antv/attr": "0.0.7", - "@antv/g": "3.2.2", - "@antv/util": "1.2.5", - "wolfy87-eventemitter": "5.1.0" + "@antv/attr": "~0.0.7", + "@antv/g": "~3.2.2", + "@antv/util": "~1.2.5", + "wolfy87-eventemitter": "~5.1.0" }, "dependencies": { "@antv/g": { @@ -38,12 +38,12 @@ "resolved": "https://registry.npmjs.org/@antv/g/-/g-3.2.2.tgz", "integrity": "sha512-mBuFnoWS6zIRy+MhpGDJxq1tHJj0o1mp0ifWPRiIFO3rlZLcNHf0D/Ww+UoC5+d8GZTz+6JqIzmxCZ3EZ4LmdQ==", "requires": { - "@antv/gl-matrix": "2.7.1", - "@antv/util": "1.2.5", - "d3-ease": "1.0.6", - "d3-interpolate": "1.1.6", - "d3-timer": "1.0.10", - "wolfy87-eventemitter": "5.1.0" + "@antv/gl-matrix": "~2.7.1", + "@antv/util": "~1.2.3", + "d3-ease": "~1.0.3", + "d3-interpolate": "~1.1.5", + "d3-timer": "~1.0.6", + "wolfy87-eventemitter": "~5.1.0" } }, "@antv/util": { @@ -51,7 +51,7 @@ "resolved": "https://registry.npmjs.org/@antv/util/-/util-1.2.5.tgz", "integrity": "sha512-yz1AjXSEjNu9O5kK9pqKq69f/Iliu/IA3XXljUcfrlbUtmUJ0CH1tB5I60vPqfaKaUPhz+/35K+56yqaCsGmqA==", "requires": { - "@antv/gl-matrix": "2.7.1" + "@antv/gl-matrix": "^2.7.1" } }, "wolfy87-eventemitter": { @@ -66,11 +66,11 @@ "resolved": "https://registry.npmjs.org/@antv/g/-/g-3.4.6.tgz", "integrity": "sha512-S7eXmMZSZmIbm+9E5zMHLtpDDa9JmfUmm7GJg1zXg2Ow8F8i3ekTZsYkgk8TA2ZPTGWfcmkSTifyqctZmdmqFw==", "requires": { - "@antv/gl-matrix": "2.7.1", - "@antv/util": "1.3.1", - "d3-ease": "1.0.6", - "d3-interpolate": "1.1.6", - "d3-timer": "1.0.10" + "@antv/gl-matrix": "~2.7.1", + "@antv/util": "~1.3.1", + "d3-ease": "~1.0.3", + "d3-interpolate": "~1.1.5", + "d3-timer": "~1.0.6" } }, "@antv/g6": { @@ -78,18 +78,18 @@ "resolved": "https://registry.npmjs.org/@antv/g6/-/g6-2.2.6.tgz", "integrity": "sha512-xxuXYjxw7o97PRo94e3pXHbsdHYdd+oKzy20ig91F61Bb7ddlHZg0I6ReU+skfS83cffqozgS+eZ9GWAUkS9UQ==", "requires": { - "@antv/component": "0.0.9", - "@antv/g": "3.4.6", - "@antv/hierarchy": "0.3.15", - "@antv/scale": "0.0.1", - "@antv/util": "1.3.1", - "d3": "5.14.2", - "d3-sankey": "0.7.1", - "d3-svg-legend": "2.25.6", - "dagre": "0.8.4", - "dom-to-image": "2.6.0", - "lodash": "4.17.15", - "wolfy87-eventemitter": "5.2.8" + "@antv/component": "~0.0.4", + "@antv/g": "^3.3.0", + "@antv/hierarchy": "~0.3.13", + "@antv/scale": "^0.0.1", + "@antv/util": "^1.2.0", + "d3": "^5.4.0", + "d3-sankey": "^0.7.1", + "d3-svg-legend": "^2.25.6", + "dagre": "~0.8.2", + "dom-to-image": "^2.6.0", + "lodash": "~4.17.4", + "wolfy87-eventemitter": "~5.2.4" } }, "@antv/gl-matrix": { @@ -102,7 +102,7 @@ "resolved": "https://registry.npmjs.org/@antv/hierarchy/-/hierarchy-0.3.15.tgz", "integrity": "sha512-TxgrQrNayVLgimfbWti+QIMVEEt+Pc8dodMC4ypMSAsJ6Yj8JXmcibgego7j7dFRqnlzyUdaiNCQUMBgl2cQvQ==", "requires": { - "@antv/util": "1.3.1" + "@antv/util": "^1.2.4" } }, "@antv/scale": { @@ -110,8 +110,8 @@ "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.0.1.tgz", "integrity": "sha512-SZ5nRe57tYq1dOJLPwwc+8iQFeHXXMTq3Me9UKYmnSvy9uh0GMoe0OwqkwJuFDsGJjJ4iyM/JNuvb0mwCC+Nhw==", "requires": { - "@antv/util": "1.0.12", - "fecha": "2.3.3" + "@antv/util": "~1.0.6", + "fecha": "~2.3.3" }, "dependencies": { "@antv/util": { @@ -126,24 +126,32 @@ "resolved": "https://registry.npmjs.org/@antv/util/-/util-1.3.1.tgz", "integrity": "sha512-cbUta0hIJrKEaW3eKoGarz3Ita+9qUPF2YzTj8A6wds/nNiy20G26ztIWHU+5ThLc13B1n5Ik52LbaCaeg9enA==", "requires": { - "@antv/gl-matrix": "2.7.1" + "@antv/gl-matrix": "^2.7.1" } }, "@babel/cli": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.7.0.tgz", - "integrity": "sha512-jECEqAq6Ngf3pOhLSg7od9WKyrIacyh1oNNYtRXNn+ummSHCTXBamGywOAtiae34Vk7zKuQNnLvo2BKTMCoV4A==", - "dev": true, - "requires": { - "chokidar": "2.1.8", - "commander": "2.20.3", - "convert-source-map": "1.7.0", - "fs-readdir-recursive": "1.1.0", - "glob": "7.1.6", - "lodash": "4.17.15", - "make-dir": "2.1.0", - "slash": "2.0.0", - "source-map": "0.5.7" + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/cli/download/@babel/cli-7.10.4.tgz?cache=0&sync_timestamp=1593523627481&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcli%2Fdownload%2F%40babel%2Fcli-7.10.4.tgz", + "integrity": "sha1-ujitbQtLdypnsQaTS3wz1lYDGJY=", + "dev": true, + "requires": { + "chokidar": "^2.1.8", + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.13", + "make-dir": "^2.1.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/commander/download/commander-4.1.1.tgz?cache=0&sync_timestamp=1592632033071&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-4.1.1.tgz", + "integrity": "sha1-n9YCvZNilOnp70aj9NaWQESxgGg=", + "dev": true + } } }, "@babel/code-frame": { @@ -152,295 +160,413 @@ "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", "dev": true, "requires": { - "@babel/highlight": "7.5.0" + "@babel/highlight": "^7.0.0" + } + }, + "@babel/compat-data": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/compat-data/download/@babel/compat-data-7.10.4.tgz?cache=0&sync_timestamp=1593521048204&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcompat-data%2Fdownload%2F%40babel%2Fcompat-data-7.10.4.tgz", + "integrity": "sha1-cGpkhO5vkQtxm2lqkZT42n16wkE=", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "semver": "^5.5.0" + }, + "dependencies": { + "browserslist": { + "version": "4.12.2", + "resolved": "https://registry.npm.taobao.org/browserslist/download/browserslist-4.12.2.tgz?cache=0&sync_timestamp=1593190408386&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowserslist%2Fdownload%2Fbrowserslist-4.12.2.tgz", + "integrity": "sha1-dmU9fkxXyqihooUT4vThl9wRpxE=", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001088", + "electron-to-chromium": "^1.3.483", + "escalade": "^3.0.1", + "node-releases": "^1.1.58" + } + }, + "caniuse-lite": { + "version": "1.0.30001093", + "resolved": "https://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30001093.tgz?cache=0&sync_timestamp=1593641273200&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcaniuse-lite%2Fdownload%2Fcaniuse-lite-1.0.30001093.tgz", + "integrity": "sha1-gz6A9ksaBFXLzu0qSjuvGeSr0xI=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.484", + "resolved": "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.484.tgz?cache=0&sync_timestamp=1593660932805&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron-to-chromium%2Fdownload%2Felectron-to-chromium-1.3.484.tgz", + "integrity": "sha1-dfWh7uX+MWh1i3ws83Wuc8HM9eY=", + "dev": true + }, + "node-releases": { + "version": "1.1.58", + "resolved": "https://registry.npm.taobao.org/node-releases/download/node-releases-1.1.58.tgz?cache=0&sync_timestamp=1591162286391&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-releases%2Fdownload%2Fnode-releases-1.1.58.tgz", + "integrity": "sha1-juIO7zD6YOUnVfzAlC3vWnNP6TU=", + "dev": true + } } }, "@babel/core": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.2.tgz", - "integrity": "sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==", - "dev": true, - "requires": { - "@babel/code-frame": "7.5.5", - "@babel/generator": "7.7.2", - "@babel/helpers": "7.7.0", - "@babel/parser": "7.7.3", - "@babel/template": "7.7.0", - "@babel/traverse": "7.7.2", - "@babel/types": "7.7.2", - "convert-source-map": "1.7.0", - "debug": "4.1.1", - "json5": "2.1.1", - "lodash": "4.17.15", - "resolve": "1.12.0", - "semver": "5.7.1", - "source-map": "0.5.7" + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/core/download/@babel/core-7.10.4.tgz?cache=0&sync_timestamp=1593521230897&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcore%2Fdownload%2F%40babel%2Fcore-7.10.4.tgz", + "integrity": "sha1-eA6Lg+SWFS+N199jiSsuBSvx1R0=", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" }, "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.10.4.tgz?cache=0&sync_timestamp=1593522826253&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcode-frame%2Fdownload%2F%40babel%2Fcode-frame-7.10.4.tgz", + "integrity": "sha1-Fo2ho26Q2miujUnA8bSMfGJJITo=", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/highlight/download/@babel/highlight-7.10.4.tgz", + "integrity": "sha1-fRvf1ldTU4+r5sOFls23bZrGAUM=", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, "debug": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.1" } }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", "dev": true } } }, "@babel/generator": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.2.tgz", - "integrity": "sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/generator/download/@babel/generator-7.10.4.tgz", + "integrity": "sha1-5J7u2f4RS2L6WxgYVqQ6XjL18kM=", "dev": true, "requires": { - "@babel/types": "7.7.2", - "jsesc": "2.5.2", - "lodash": "4.17.15", - "source-map": "0.5.7" + "@babel/types": "^7.10.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" } }, "@babel/helper-annotate-as-pure": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz", - "integrity": "sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-annotate-as-pure/download/@babel/helper-annotate-as-pure-7.10.4.tgz", + "integrity": "sha1-W/DUlaP3V6w72ki1vzs7ownHK6M=", "dev": true, "requires": { - "@babel/types": "7.7.2" + "@babel/types": "^7.10.4" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.0.tgz", - "integrity": "sha512-Cd8r8zs4RKDwMG/92lpZcnn5WPQ3LAMQbCw42oqUh4s7vsSN5ANUZjMel0OOnxDLq57hoDDbai+ryygYfCTOsw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-builder-binary-assignment-operator-visitor/download/@babel/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha1-uwt18xv5jL+f8UPBrleLhydK4aM=", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "7.7.0", - "@babel/types": "7.7.2" + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-builder-react-jsx": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.0.tgz", - "integrity": "sha512-LSln3cexwInTMYYoFeVLKnYPPMfWNJ8PubTBs3hkh7wCu9iBaqq1OOyW+xGmEdLxT1nhsl+9SJ+h2oUDYz0l2A==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-builder-react-jsx/download/@babel/helper-builder-react-jsx-7.10.4.tgz", + "integrity": "sha1-gJXN2/+Fjm+pwyba7lSi8nMsHV0=", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-builder-react-jsx-experimental": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-builder-react-jsx-experimental/download/@babel/helper-builder-react-jsx-experimental-7.10.4.tgz?cache=0&sync_timestamp=1593522974577&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-builder-react-jsx-experimental%2Fdownload%2F%40babel%2Fhelper-builder-react-jsx-experimental-7.10.4.tgz", + "integrity": "sha1-0P+4dRhNdJxj/+H09lvhUUPsMi0=", "dev": true, "requires": { - "@babel/types": "7.7.2", - "esutils": "2.0.3" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-module-imports": "^7.10.4", + "@babel/types": "^7.10.4" } }, - "@babel/helper-call-delegate": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.7.0.tgz", - "integrity": "sha512-Su0Mdq7uSSWGZayGMMQ+z6lnL00mMCnGAbO/R0ZO9odIdB/WNU/VfQKqMQU0fdIsxQYbRjDM4BixIa93SQIpvw==", + "@babel/helper-compilation-targets": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-compilation-targets/download/@babel/helper-compilation-targets-7.10.4.tgz?cache=0&sync_timestamp=1593521085687&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-compilation-targets%2Fdownload%2F%40babel%2Fhelper-compilation-targets-7.10.4.tgz", + "integrity": "sha1-gEro4/BDdmB8x5G51H1UAnYzK9I=", "dev": true, "requires": { - "@babel/helper-hoist-variables": "7.7.0", - "@babel/traverse": "7.7.2", - "@babel/types": "7.7.2" + "@babel/compat-data": "^7.10.4", + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "levenary": "^1.1.1", + "semver": "^5.5.0" + }, + "dependencies": { + "browserslist": { + "version": "4.12.2", + "resolved": "https://registry.npm.taobao.org/browserslist/download/browserslist-4.12.2.tgz?cache=0&sync_timestamp=1593190408386&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowserslist%2Fdownload%2Fbrowserslist-4.12.2.tgz", + "integrity": "sha1-dmU9fkxXyqihooUT4vThl9wRpxE=", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001088", + "electron-to-chromium": "^1.3.483", + "escalade": "^3.0.1", + "node-releases": "^1.1.58" + } + }, + "caniuse-lite": { + "version": "1.0.30001093", + "resolved": "https://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30001093.tgz?cache=0&sync_timestamp=1593641273200&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcaniuse-lite%2Fdownload%2Fcaniuse-lite-1.0.30001093.tgz", + "integrity": "sha1-gz6A9ksaBFXLzu0qSjuvGeSr0xI=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.484", + "resolved": "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.484.tgz?cache=0&sync_timestamp=1593660932805&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron-to-chromium%2Fdownload%2Felectron-to-chromium-1.3.484.tgz", + "integrity": "sha1-dfWh7uX+MWh1i3ws83Wuc8HM9eY=", + "dev": true + }, + "node-releases": { + "version": "1.1.58", + "resolved": "https://registry.npm.taobao.org/node-releases/download/node-releases-1.1.58.tgz?cache=0&sync_timestamp=1591162286391&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-releases%2Fdownload%2Fnode-releases-1.1.58.tgz", + "integrity": "sha1-juIO7zD6YOUnVfzAlC3vWnNP6TU=", + "dev": true + } } }, "@babel/helper-create-class-features-plugin": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.0.tgz", - "integrity": "sha512-MZiB5qvTWoyiFOgootmRSDV1udjIqJW/8lmxgzKq6oDqxdmHUjeP2ZUOmgHdYjmUVNABqRrHjYAYRvj8Eox/UA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-create-class-features-plugin/download/@babel/helper-create-class-features-plugin-7.10.4.tgz", + "integrity": "sha1-LUAV0BNr0xQQOnDYSnGD5LNEo1U=", "dev": true, "requires": { - "@babel/helper-function-name": "7.7.0", - "@babel/helper-member-expression-to-functions": "7.7.0", - "@babel/helper-optimise-call-expression": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-replace-supers": "7.7.0", - "@babel/helper-split-export-declaration": "7.7.0" + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.2.tgz", - "integrity": "sha512-pAil/ZixjTlrzNpjx+l/C/wJk002Wo7XbbZ8oujH/AoJ3Juv0iN/UTcPUHXKMFLqsfS0Hy6Aow8M31brUYBlQQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-create-regexp-features-plugin/download/@babel/helper-create-regexp-features-plugin-7.10.4.tgz?cache=0&sync_timestamp=1593522952175&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-create-regexp-features-plugin%2Fdownload%2F%40babel%2Fhelper-create-regexp-features-plugin-7.10.4.tgz", + "integrity": "sha1-/dYNiFJGWaC2lZwFeZJeQlcU87g=", "dev": true, "requires": { - "@babel/helper-regex": "7.5.5", - "regexpu-core": "4.6.0" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-regex": "^7.10.4", + "regexpu-core": "^4.7.0" } }, "@babel/helper-define-map": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.7.0.tgz", - "integrity": "sha512-kPKWPb0dMpZi+ov1hJiwse9dWweZsz3V9rP4KdytnX1E7z3cTNmFGglwklzFPuqIcHLIY3bgKSs4vkwXXdflQA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-define-map/download/@babel/helper-define-map-7.10.4.tgz", + "integrity": "sha1-8DeteUJk9yntoYifTuIQuHCZkJI=", "dev": true, "requires": { - "@babel/helper-function-name": "7.7.0", - "@babel/types": "7.7.2", - "lodash": "4.17.15" + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.4", + "lodash": "^4.17.13" } }, "@babel/helper-explode-assignable-expression": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.0.tgz", - "integrity": "sha512-CDs26w2shdD1urNUAji2RJXyBFCaR+iBEGnFz3l7maizMkQe3saVw9WtjG1tz8CwbjvlFnaSLVhgnu1SWaherg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-explode-assignable-expression/download/@babel/helper-explode-assignable-expression-7.10.4.tgz?cache=0&sync_timestamp=1593522841702&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-explode-assignable-expression%2Fdownload%2F%40babel%2Fhelper-explode-assignable-expression-7.10.4.tgz", + "integrity": "sha1-QKHNkXv/Eoj2malKdbN6Gi29jHw=", "dev": true, "requires": { - "@babel/traverse": "7.7.2", - "@babel/types": "7.7.2" + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-function-name": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz", - "integrity": "sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-function-name/download/@babel/helper-function-name-7.10.4.tgz?cache=0&sync_timestamp=1593521218775&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-function-name%2Fdownload%2F%40babel%2Fhelper-function-name-7.10.4.tgz", + "integrity": "sha1-0tOyDFmtjEcRL6fSqUvAnV74Lxo=", "dev": true, "requires": { - "@babel/helper-get-function-arity": "7.7.0", - "@babel/template": "7.7.0", - "@babel/types": "7.7.2" + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-get-function-arity": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz", - "integrity": "sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-get-function-arity/download/@babel/helper-get-function-arity-7.10.4.tgz?cache=0&sync_timestamp=1593522827189&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-get-function-arity%2Fdownload%2F%40babel%2Fhelper-get-function-arity-7.10.4.tgz", + "integrity": "sha1-mMHL6g4jMvM/mkZhuM4VBbLBm6I=", "dev": true, "requires": { - "@babel/types": "7.7.2" + "@babel/types": "^7.10.4" } }, "@babel/helper-hoist-variables": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.0.tgz", - "integrity": "sha512-LUe/92NqsDAkJjjCEWkNe+/PcpnisvnqdlRe19FahVapa4jndeuJ+FBiTX1rcAKWKcJGE+C3Q3tuEuxkSmCEiQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-hoist-variables/download/@babel/helper-hoist-variables-7.10.4.tgz?cache=0&sync_timestamp=1593521259807&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-hoist-variables%2Fdownload%2F%40babel%2Fhelper-hoist-variables-7.10.4.tgz", + "integrity": "sha1-1JsAHR1aaMpeZgTdoBpil/fJOB4=", "dev": true, "requires": { - "@babel/types": "7.7.2" + "@babel/types": "^7.10.4" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.0.tgz", - "integrity": "sha512-QaCZLO2RtBcmvO/ekOLp8p7R5X2JriKRizeDpm5ChATAFWrrYDcDxPuCIBXKyBjY+i1vYSdcUTMIb8psfxHDPA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-member-expression-to-functions/download/@babel/helper-member-expression-to-functions-7.10.4.tgz?cache=0&sync_timestamp=1593522926997&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-member-expression-to-functions%2Fdownload%2F%40babel%2Fhelper-member-expression-to-functions-7.10.4.tgz", + "integrity": "sha1-fNBLV9/Pgvzprq59TkRS+jG4x8Q=", "dev": true, "requires": { - "@babel/types": "7.7.2" + "@babel/types": "^7.10.4" } }, "@babel/helper-module-imports": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.0.tgz", - "integrity": "sha512-Dv3hLKIC1jyfTkClvyEkYP2OlkzNvWs5+Q8WgPbxM5LMeorons7iPP91JM+DU7tRbhqA1ZeooPaMFvQrn23RHw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-module-imports/download/@babel/helper-module-imports-7.10.4.tgz", + "integrity": "sha1-TFxUvgS9MWcKc4J5fXW5+i5bViA=", "dev": true, "requires": { - "@babel/types": "7.7.2" + "@babel/types": "^7.10.4" } }, "@babel/helper-module-transforms": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.7.0.tgz", - "integrity": "sha512-rXEefBuheUYQyX4WjV19tuknrJFwyKw0HgzRwbkyTbB+Dshlq7eqkWbyjzToLrMZk/5wKVKdWFluiAsVkHXvuQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-module-transforms/download/@babel/helper-module-transforms-7.10.4.tgz", + "integrity": "sha1-yh8B/bhOSMJNdQa7gYyWHx2ogF0=", "dev": true, "requires": { - "@babel/helper-module-imports": "7.7.0", - "@babel/helper-simple-access": "7.7.0", - "@babel/helper-split-export-declaration": "7.7.0", - "@babel/template": "7.7.0", - "@babel/types": "7.7.2", - "lodash": "4.17.15" + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4", + "lodash": "^4.17.13" } }, "@babel/helper-optimise-call-expression": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.0.tgz", - "integrity": "sha512-48TeqmbazjNU/65niiiJIJRc5JozB8acui1OS7bSd6PgxfuovWsvjfWSzlgx+gPFdVveNzUdpdIg5l56Pl5jqg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-optimise-call-expression/download/@babel/helper-optimise-call-expression-7.10.4.tgz?cache=0&sync_timestamp=1593522827576&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-optimise-call-expression%2Fdownload%2F%40babel%2Fhelper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha1-UNyWQT1ZT5lad5BZBbBYk813lnM=", "dev": true, "requires": { - "@babel/types": "7.7.2" + "@babel/types": "^7.10.4" } }, "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-plugin-utils/download/@babel/helper-plugin-utils-7.10.4.tgz?cache=0&sync_timestamp=1593521123680&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-plugin-utils%2Fdownload%2F%40babel%2Fhelper-plugin-utils-7.10.4.tgz", + "integrity": "sha1-L3WoMSadT2d95JmG3/WZJ1M883U=", "dev": true }, "@babel/helper-regex": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", - "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-regex/download/@babel/helper-regex-7.10.4.tgz?cache=0&sync_timestamp=1593521091742&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-regex%2Fdownload%2F%40babel%2Fhelper-regex-7.10.4.tgz", + "integrity": "sha1-WbNz2q80WOV0feznG7r0X5Z2r20=", "dev": true, "requires": { - "lodash": "4.17.15" + "lodash": "^4.17.13" } }, "@babel/helper-remap-async-to-generator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz", - "integrity": "sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-remap-async-to-generator/download/@babel/helper-remap-async-to-generator-7.10.4.tgz?cache=0&sync_timestamp=1593521228698&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-remap-async-to-generator%2Fdownload%2F%40babel%2Fhelper-remap-async-to-generator-7.10.4.tgz", + "integrity": "sha1-/Oi+pOlpC76SMFbe0h5UtOi2jtU=", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "7.7.0", - "@babel/helper-wrap-function": "7.7.0", - "@babel/template": "7.7.0", - "@babel/traverse": "7.7.2", - "@babel/types": "7.7.2" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-replace-supers": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.7.0.tgz", - "integrity": "sha512-5ALYEul5V8xNdxEeWvRsBzLMxQksT7MaStpxjJf9KsnLxpAKBtfw5NeMKZJSYDa0lKdOcy0g+JT/f5mPSulUgg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-replace-supers/download/@babel/helper-replace-supers-7.10.4.tgz", + "integrity": "sha1-1YXNk4jqBuYDHkzUS2cTy+rZ5s8=", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "7.7.0", - "@babel/helper-optimise-call-expression": "7.7.0", - "@babel/traverse": "7.7.2", - "@babel/types": "7.7.2" + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-simple-access": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.7.0.tgz", - "integrity": "sha512-AJ7IZD7Eem3zZRuj5JtzFAptBw7pMlS3y8Qv09vaBWoFsle0d1kAn5Wq6Q9MyBXITPOKnxwkZKoAm4bopmv26g==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-simple-access/download/@babel/helper-simple-access-7.10.4.tgz?cache=0&sync_timestamp=1593521217867&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-simple-access%2Fdownload%2F%40babel%2Fhelper-simple-access-7.10.4.tgz", + "integrity": "sha1-D1zNopRSd6KnotOoIeFTle3PNGE=", "dev": true, "requires": { - "@babel/template": "7.7.0", - "@babel/types": "7.7.2" + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-split-export-declaration": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz", - "integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-split-export-declaration/download/@babel/helper-split-export-declaration-7.10.4.tgz?cache=0&sync_timestamp=1593522826673&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-split-export-declaration%2Fdownload%2F%40babel%2Fhelper-split-export-declaration-7.10.4.tgz", + "integrity": "sha1-LHBXbqo7VgmyTLmdsoiMw/xCUdE=", "dev": true, "requires": { - "@babel/types": "7.7.2" + "@babel/types": "^7.10.4" } }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha1-p4x6clHgH2FlEtMbEK3PUq2l4NI=", + "dev": true + }, "@babel/helper-wrap-function": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz", - "integrity": "sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helper-wrap-function/download/@babel/helper-wrap-function-7.10.4.tgz?cache=0&sync_timestamp=1593522949000&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-wrap-function%2Fdownload%2F%40babel%2Fhelper-wrap-function-7.10.4.tgz", + "integrity": "sha1-im9wHqsP8592W1oc/vQJmQ5iS4c=", "dev": true, "requires": { - "@babel/helper-function-name": "7.7.0", - "@babel/template": "7.7.0", - "@babel/traverse": "7.7.2", - "@babel/types": "7.7.2" + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helpers": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.0.tgz", - "integrity": "sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/helpers/download/@babel/helpers-7.10.4.tgz", + "integrity": "sha1-Kr6w1yGv98Cpc3a54fb2XXpHUEQ=", "dev": true, "requires": { - "@babel/template": "7.7.0", - "@babel/traverse": "7.7.2", - "@babel/types": "7.7.2" + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/highlight": { @@ -449,662 +575,882 @@ "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", "dev": true, "requires": { - "chalk": "2.4.2", - "esutils": "2.0.3", - "js-tokens": "4.0.0" + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" } }, "@babel/parser": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.3.tgz", - "integrity": "sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.10.4.tgz?cache=0&sync_timestamp=1593521035480&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.10.4.tgz", + "integrity": "sha1-nu3yfhmY2Hc5+1AopRIFV8BqGmQ=", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz", - "integrity": "sha512-ot/EZVvf3mXtZq0Pd0+tSOfGWMizqmOohXmNZg6LNFjHOV+wOPv7BvVYh8oPR8LhpIP3ye8nNooKL50YRWxpYA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-async-generator-functions/download/@babel/plugin-proposal-async-generator-functions-7.10.4.tgz?cache=0&sync_timestamp=1593521231856&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-async-generator-functions%2Fdownload%2F%40babel%2Fplugin-proposal-async-generator-functions-7.10.4.tgz", + "integrity": "sha1-S2Wrs9m6zGxleqpBPlZpb58XD8Y=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-remap-async-to-generator": "7.7.0", - "@babel/plugin-syntax-async-generators": "7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0" } }, "@babel/plugin-proposal-class-properties": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.7.0.tgz", - "integrity": "sha512-tufDcFA1Vj+eWvwHN+jvMN6QsV5o+vUlytNKrbMiCeDL0F2j92RURzUsUMWE5EJkLyWxjdUslCsMQa9FWth16A==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-class-properties/download/@babel/plugin-proposal-class-properties-7.10.4.tgz", + "integrity": "sha1-ozv2Mto5ClnHqMVwBF0RFc13iAc=", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.0.tgz", - "integrity": "sha512-7poL3Xi+QFPC7sGAzEIbXUyYzGJwbc2+gSD0AkiC5k52kH2cqHdqxm5hNFfLW3cRSTcx9bN0Fl7/6zWcLLnKAQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-dynamic-import/download/@babel/plugin-proposal-dynamic-import-7.10.4.tgz?cache=0&sync_timestamp=1593521117836&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-dynamic-import%2Fdownload%2F%40babel%2Fplugin-proposal-dynamic-import-7.10.4.tgz", + "integrity": "sha1-uleibLmLN3QenVvKG4sN34KR8X4=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-dynamic-import": "7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", - "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-json-strings/download/@babel/plugin-proposal-json-strings-7.10.4.tgz", + "integrity": "sha1-WT5ZxjUoFgIzvTIbGuvgggwjQds=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-nullish-coalescing-operator/download/@babel/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz?cache=0&sync_timestamp=1593522818985&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-nullish-coalescing-operator%2Fdownload%2F%40babel%2Fplugin-proposal-nullish-coalescing-operator-7.10.4.tgz", + "integrity": "sha1-AqfpYfwy5tWy2wZJ4Bv4Dd7n4Eo=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-numeric-separator/download/@babel/plugin-proposal-numeric-separator-7.10.4.tgz", + "integrity": "sha1-zhWQ/wplrRKXCmCdeIVemkwa7wY=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-json-strings": "7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz", - "integrity": "sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.10.4.tgz", + "integrity": "sha1-UBKawha5pqVbOFP92SPnS/VTpMA=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-object-rest-spread": "7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.10.4" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-optional-catch-binding/download/@babel/plugin-proposal-optional-catch-binding-7.10.4.tgz", + "integrity": "sha1-Mck4MJ0kp4pJ1o/av/qoY3WFVN0=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-optional-chaining/download/@babel/plugin-proposal-optional-chaining-7.10.4.tgz?cache=0&sync_timestamp=1593521131942&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-optional-chaining%2Fdownload%2F%40babel%2Fplugin-proposal-optional-chaining-7.10.4.tgz", + "integrity": "sha1-dQ8SVekwofgtjN3kUDH4Gg0K3/c=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-private-methods/download/@babel/plugin-proposal-private-methods-7.10.4.tgz?cache=0&sync_timestamp=1593522940799&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-private-methods%2Fdownload%2F%40babel%2Fplugin-proposal-private-methods-7.10.4.tgz", + "integrity": "sha1-sWDZcrj9ulx9ERoUX8jEIfwqaQk=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "7.2.0" + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz", - "integrity": "sha512-mk34H+hp7kRBWJOOAR0ZMGCydgKMD4iN9TpDRp3IIcbunltxEY89XSimc6WbtSLCDrwcdy/EEw7h5CFCzxTchw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-unicode-property-regex/download/@babel/plugin-proposal-unicode-property-regex-7.10.4.tgz", + "integrity": "sha1-RIPNpTBBzjQTt/4vAAImZd36p10=", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "7.7.2", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-async-generators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", - "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "version": "7.8.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-async-generators/download/@babel/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha1-qYP7Gusuw/btBCohD2QOkOeG/g0=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-class-properties/download/@babel/plugin-syntax-class-properties-7.10.4.tgz?cache=0&sync_timestamp=1593521086484&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-class-properties%2Fdownload%2F%40babel%2Fplugin-syntax-class-properties-7.10.4.tgz", + "integrity": "sha1-ZkTmoLqlWmH54yMfbJ7rbuRsEkw=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-dynamic-import": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", - "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-dynamic-import/download/@babel/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha1-Yr+Ysto80h1iYVT8lu5bPLaOrLM=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", - "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-json-strings/download/@babel/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha1-AcohtmjNghjJ5kDLbdiMVBKyyWo=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-jsx": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz", - "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-jsx/download/@babel/plugin-syntax-jsx-7.10.4.tgz?cache=0&sync_timestamp=1593522939386&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-jsx%2Fdownload%2F%40babel%2Fplugin-syntax-jsx-7.10.4.tgz", + "integrity": "sha1-Oauq48v3EMQ3PYQpSE5rohNAFmw=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-nullish-coalescing-operator/download/@babel/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha1-Fn7XA2iIYIH3S1w2xlqIwDtm0ak=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-numeric-separator/download/@babel/plugin-syntax-numeric-separator-7.10.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-numeric-separator%2Fdownload%2F%40babel%2Fplugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha1-ubBws+M1cM2f0Hun+pHA3Te5r5c=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-object-rest-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", - "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-object-rest-spread/download/@babel/plugin-syntax-object-rest-spread-7.8.3.tgz?cache=0&sync_timestamp=1578950070697&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-object-rest-spread%2Fdownload%2F%40babel%2Fplugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha1-YOIl7cvZimQDMqLnLdPmbxr1WHE=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-optional-catch-binding/download/@babel/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha1-YRGiZbz7Ag6579D9/X0mQCue1sE=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-optional-chaining/download/@babel/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha1-T2nCq5UWfgGAzVM2YT+MV4j31Io=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-top-level-await": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.0.tgz", - "integrity": "sha512-hi8FUNiFIY1fnUI2n1ViB1DR0R4QeK4iHcTlW6aJkrPoTdb8Rf1EMQ6GT3f67DDkYyWgew9DFoOZ6gOoEsdzTA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-top-level-await/download/@babel/plugin-syntax-top-level-await-7.10.4.tgz", + "integrity": "sha1-S764kXtU/PdoNk4KgfVg4zo+9X0=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", - "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-arrow-functions/download/@babel/plugin-transform-arrow-functions-7.10.4.tgz?cache=0&sync_timestamp=1593522807583&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-arrow-functions%2Fdownload%2F%40babel%2Fplugin-transform-arrow-functions-7.10.4.tgz", + "integrity": "sha1-4ilg135pfHT0HFAdRNc9v4pqZM0=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.0.tgz", - "integrity": "sha512-vLI2EFLVvRBL3d8roAMqtVY0Bm9C1QzLkdS57hiKrjUBSqsQYrBsMCeOg/0KK7B0eK9V71J5mWcha9yyoI2tZw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-async-to-generator/download/@babel/plugin-transform-async-to-generator-7.10.4.tgz?cache=0&sync_timestamp=1593522851748&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-async-to-generator%2Fdownload%2F%40babel%2Fplugin-transform-async-to-generator-7.10.4.tgz", + "integrity": "sha1-QaUBfknrbzzak5KlHu8pQFskWjc=", "dev": true, "requires": { - "@babel/helper-module-imports": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-remap-async-to-generator": "7.7.0" + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", - "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-block-scoped-functions/download/@babel/plugin-transform-block-scoped-functions-7.10.4.tgz?cache=0&sync_timestamp=1593521910347&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-block-scoped-functions%2Fdownload%2F%40babel%2Fplugin-transform-block-scoped-functions-7.10.4.tgz", + "integrity": "sha1-GvpZV0T3XkOpGvc7DZmOz+Trwug=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz", - "integrity": "sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.10.4.tgz?cache=0&sync_timestamp=1593522918894&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-block-scoping%2Fdownload%2F%40babel%2Fplugin-transform-block-scoping-7.10.4.tgz", + "integrity": "sha1-pnDRNku1AZpiG56iABSCh21zR4c=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "lodash": "4.17.15" + "@babel/helper-plugin-utils": "^7.10.4", + "lodash": "^4.17.13" } }, "@babel/plugin-transform-classes": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.0.tgz", - "integrity": "sha512-/b3cKIZwGeUesZheU9jNYcwrEA7f/Bo4IdPmvp7oHgvks2majB5BoT5byAql44fiNQYOPzhk2w8DbgfuafkMoA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-classes/download/@babel/plugin-transform-classes-7.10.4.tgz?cache=0&sync_timestamp=1593521236444&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-classes%2Fdownload%2F%40babel%2Fplugin-transform-classes-7.10.4.tgz", + "integrity": "sha1-QFE2rys+IYvEoZJiKLyRerGgrcc=", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "7.7.0", - "@babel/helper-define-map": "7.7.0", - "@babel/helper-function-name": "7.7.0", - "@babel/helper-optimise-call-expression": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-replace-supers": "7.7.0", - "@babel/helper-split-export-declaration": "7.7.0", - "globals": "11.12.0" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", - "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-computed-properties/download/@babel/plugin-transform-computed-properties-7.10.4.tgz?cache=0&sync_timestamp=1593522921161&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-computed-properties%2Fdownload%2F%40babel%2Fplugin-transform-computed-properties-7.10.4.tgz", + "integrity": "sha1-ne2DqBboLe0o1S1LTsvdgQzfwOs=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-destructuring": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz", - "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-destructuring/download/@babel/plugin-transform-destructuring-7.10.4.tgz", + "integrity": "sha1-cN3Ss9G+qD0BUJ6bsl3bOnT8heU=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.0.tgz", - "integrity": "sha512-3QQlF7hSBnSuM1hQ0pS3pmAbWLax/uGNCbPBND9y+oJ4Y776jsyujG2k0Sn2Aj2a0QwVOiOFL5QVPA7spjvzSA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-dotall-regex/download/@babel/plugin-transform-dotall-regex-7.10.4.tgz", + "integrity": "sha1-RpwgYhBcHragQOr0+sS0iAeDle4=", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "7.7.2", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", - "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-duplicate-keys/download/@babel/plugin-transform-duplicate-keys-7.10.4.tgz", + "integrity": "sha1-aX5Qyf7hQ4D+hD0fMGspVhdDHkc=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", - "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-exponentiation-operator/download/@babel/plugin-transform-exponentiation-operator-7.10.4.tgz?cache=0&sync_timestamp=1593521230232&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-exponentiation-operator%2Fdownload%2F%40babel%2Fplugin-transform-exponentiation-operator-7.10.4.tgz", + "integrity": "sha1-WuM4xX+M9AAb2zVgeuZrktZlry4=", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-for-of": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", - "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-for-of/download/@babel/plugin-transform-for-of-7.10.4.tgz", + "integrity": "sha1-wIiS6IGdOl2ykDGxFa9RHbv+uuk=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-function-name": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.0.tgz", - "integrity": "sha512-P5HKu0d9+CzZxP5jcrWdpe7ZlFDe24bmqP6a6X8BHEBl/eizAsY8K6LX8LASZL0Jxdjm5eEfzp+FIrxCm/p8bA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-function-name/download/@babel/plugin-transform-function-name-7.10.4.tgz", + "integrity": "sha1-akZ4gOD8ljhRS6NpERgR3b4mRLc=", "dev": true, "requires": { - "@babel/helper-function-name": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", - "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-literals/download/@babel/plugin-transform-literals-7.10.4.tgz", + "integrity": "sha1-n0K6CEEQChNfInEtDjkcRi9XHzw=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", - "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-member-expression-literals/download/@babel/plugin-transform-member-expression-literals-7.10.4.tgz", + "integrity": "sha1-sexE/PGVr8uNssYs2OVRyIG6+Lc=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", - "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-amd/download/@babel/plugin-transform-modules-amd-7.10.4.tgz", + "integrity": "sha1-y0B8aLhi5MHROi/HOMfsXtdfxSA=", "dev": true, "requires": { - "@babel/helper-module-transforms": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0", - "babel-plugin-dynamic-import-node": "2.3.0" + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.0.tgz", - "integrity": "sha512-KEMyWNNWnjOom8vR/1+d+Ocz/mILZG/eyHHO06OuBQ2aNhxT62fr4y6fGOplRx+CxCSp3IFwesL8WdINfY/3kg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-commonjs/download/@babel/plugin-transform-modules-commonjs-7.10.4.tgz", + "integrity": "sha1-ZmZ8Pu2h6/eJbUHx8WsXEFovvKA=", "dev": true, "requires": { - "@babel/helper-module-transforms": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-simple-access": "7.7.0", - "babel-plugin-dynamic-import-node": "2.3.0" + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.0.tgz", - "integrity": "sha512-ZAuFgYjJzDNv77AjXRqzQGlQl4HdUM6j296ee4fwKVZfhDR9LAGxfvXjBkb06gNETPnN0sLqRm9Gxg4wZH6dXg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-systemjs/download/@babel/plugin-transform-modules-systemjs-7.10.4.tgz?cache=0&sync_timestamp=1593522937122&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-systemjs%2Fdownload%2F%40babel%2Fplugin-transform-modules-systemjs-7.10.4.tgz", + "integrity": "sha1-j1dq/ZQ6wveJs13tCmMS+SnGM/k=", "dev": true, "requires": { - "@babel/helper-hoist-variables": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0", - "babel-plugin-dynamic-import-node": "2.3.0" + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.0.tgz", - "integrity": "sha512-u7eBA03zmUswQ9LQ7Qw0/ieC1pcAkbp5OQatbWUzY1PaBccvuJXUkYzoN1g7cqp7dbTu6Dp9bXyalBvD04AANA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-umd/download/@babel/plugin-transform-modules-umd-7.10.4.tgz?cache=0&sync_timestamp=1593522937615&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-umd%2Fdownload%2F%40babel%2Fplugin-transform-modules-umd-7.10.4.tgz", + "integrity": "sha1-moSB/oG4JGVLOgtl2j34nz0hg54=", "dev": true, "requires": { - "@babel/helper-module-transforms": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.0.tgz", - "integrity": "sha512-+SicSJoKouPctL+j1pqktRVCgy+xAch1hWWTMy13j0IflnyNjaoskj+DwRQFimHbLqO3sq2oN2CXMvXq3Bgapg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-named-capturing-groups-regex/download/@babel/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", + "integrity": "sha1-eLTZeIELbzvPA/njGPL8DtQa7LY=", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "7.7.2" + "@babel/helper-create-regexp-features-plugin": "^7.10.4" } }, "@babel/plugin-transform-new-target": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", - "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-new-target/download/@babel/plugin-transform-new-target-7.10.4.tgz?cache=0&sync_timestamp=1593522495673&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-new-target%2Fdownload%2F%40babel%2Fplugin-transform-new-target-7.10.4.tgz", + "integrity": "sha1-kJfXU8t7Aky3OBo7LlLpUTqcaIg=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-object-super": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", - "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-object-super/download/@babel/plugin-transform-object-super-7.10.4.tgz", + "integrity": "sha1-1xRsTROUM+emUm+IjGZ+MUoJOJQ=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-replace-supers": "7.7.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4" } }, "@babel/plugin-transform-parameters": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", - "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-parameters/download/@babel/plugin-transform-parameters-7.10.4.tgz?cache=0&sync_timestamp=1593522848395&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-parameters%2Fdownload%2F%40babel%2Fplugin-transform-parameters-7.10.4.tgz", + "integrity": "sha1-e00TfIfqetwqDz6/UyZocdqm/O0=", "dev": true, "requires": { - "@babel/helper-call-delegate": "7.7.0", - "@babel/helper-get-function-arity": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-property-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", - "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-property-literals/download/@babel/plugin-transform-property-literals-7.10.4.tgz", + "integrity": "sha1-9v5UtlkDUimHhbg+3YFdIUxC48A=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-react-display-name": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz", - "integrity": "sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-display-name/download/@babel/plugin-transform-react-display-name-7.10.4.tgz?cache=0&sync_timestamp=1593522925495&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-display-name%2Fdownload%2F%40babel%2Fplugin-transform-react-display-name-7.10.4.tgz", + "integrity": "sha1-tXlfTj4xQEGcNhG3oqODK5rvMo0=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-react-jsx": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.0.tgz", - "integrity": "sha512-mXhBtyVB1Ujfy+0L6934jeJcSXj/VCg6whZzEcgiiZHNS0PGC7vUCsZDQCxxztkpIdF+dY1fUMcjAgEOC3ZOMQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-jsx/download/@babel/plugin-transform-react-jsx-7.10.4.tgz?cache=0&sync_timestamp=1593522836746&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-jsx%2Fdownload%2F%40babel%2Fplugin-transform-react-jsx-7.10.4.tgz", + "integrity": "sha1-ZzyfkTlIdkpEIWg7K+8pNpaP3fI=", + "dev": true, + "requires": { + "@babel/helper-builder-react-jsx": "^7.10.4", + "@babel/helper-builder-react-jsx-experimental": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-jsx-development/download/@babel/plugin-transform-react-jsx-development-7.10.4.tgz?cache=0&sync_timestamp=1593521335160&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-jsx-development%2Fdownload%2F%40babel%2Fplugin-transform-react-jsx-development-7.10.4.tgz", + "integrity": "sha1-bskPJEOUYEYjiA4V68PDTDViWLo=", "dev": true, "requires": { - "@babel/helper-builder-react-jsx": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-jsx": "7.2.0" + "@babel/helper-builder-react-jsx-experimental": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" } }, "@babel/plugin-transform-react-jsx-self": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.2.0.tgz", - "integrity": "sha512-v6S5L/myicZEy+jr6ielB0OR8h+EH/1QFx/YJ7c7Ua+7lqsjj/vW6fD5FR9hB/6y7mGbfT4vAURn3xqBxsUcdg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-jsx-self/download/@babel/plugin-transform-react-jsx-self-7.10.4.tgz?cache=0&sync_timestamp=1593522826499&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-jsx-self%2Fdownload%2F%40babel%2Fplugin-transform-react-jsx-self-7.10.4.tgz", + "integrity": "sha1-zTAaX+2JiMGC7QudVem9bbC9k2k=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-jsx": "7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" } }, "@babel/plugin-transform-react-jsx-source": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.5.0.tgz", - "integrity": "sha512-58Q+Jsy4IDCZx7kqEZuSDdam/1oW8OdDX8f+Loo6xyxdfg1yF0GE2XNJQSTZCaMol93+FBzpWiPEwtbMloAcPg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-jsx-source/download/@babel/plugin-transform-react-jsx-source-7.10.4.tgz?cache=0&sync_timestamp=1593522826500&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-jsx-source%2Fdownload%2F%40babel%2Fplugin-transform-react-jsx-source-7.10.4.tgz", + "integrity": "sha1-hrrw/Mz+WAhOBkRqgIWOHero8pE=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-pure-annotations/download/@babel/plugin-transform-react-pure-annotations-7.10.4.tgz?cache=0&sync_timestamp=1593521328616&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-pure-annotations%2Fdownload%2F%40babel%2Fplugin-transform-react-pure-annotations-7.10.4.tgz", + "integrity": "sha1-Pu+7c9uUr7wHXwl1I+RFNUocZQE=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-syntax-jsx": "7.2.0" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-regenerator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.0.tgz", - "integrity": "sha512-AXmvnC+0wuj/cFkkS/HFHIojxH3ffSXE+ttulrqWjZZRaUOonfJc60e1wSNT4rV8tIunvu/R3wCp71/tLAa9xg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-regenerator/download/@babel/plugin-transform-regenerator-7.10.4.tgz?cache=0&sync_timestamp=1593521089707&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-regenerator%2Fdownload%2F%40babel%2Fplugin-transform-regenerator-7.10.4.tgz", + "integrity": "sha1-IBXlnYOQdOdoON4hWdtCGWb9i2M=", "dev": true, "requires": { - "regenerator-transform": "0.14.1" + "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", - "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-reserved-words/download/@babel/plugin-transform-reserved-words-7.10.4.tgz?cache=0&sync_timestamp=1593522496981&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-reserved-words%2Fdownload%2F%40babel%2Fplugin-transform-reserved-words-7.10.4.tgz", + "integrity": "sha1-jyaCvNzvntMn4bCGFYXXAT+KVN0=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-runtime": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.6.2.tgz", - "integrity": "sha512-cqULw/QB4yl73cS5Y0TZlQSjDvNkzDbu0FurTZyHlJpWE5T3PCMdnyV+xXoH1opr1ldyHODe3QAX3OMAii5NxA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-runtime/download/@babel/plugin-transform-runtime-7.10.4.tgz?cache=0&sync_timestamp=1593522940963&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-runtime%2Fdownload%2F%40babel%2Fplugin-transform-runtime-7.10.4.tgz", + "integrity": "sha1-WU+1NFPqG28HeczrSM4HGKRH/rc=", "dev": true, "requires": { - "@babel/helper-module-imports": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0", - "resolve": "1.12.0", - "semver": "5.7.1" + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "resolve": "^1.8.1", + "semver": "^5.5.1" } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", - "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-shorthand-properties/download/@babel/plugin-transform-shorthand-properties-7.10.4.tgz", + "integrity": "sha1-n9Jexc3VVbt/Rz5ebuHJce7eTdY=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-spread": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz", - "integrity": "sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-spread/download/@babel/plugin-transform-spread-7.10.4.tgz?cache=0&sync_timestamp=1593522927458&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-spread%2Fdownload%2F%40babel%2Fplugin-transform-spread-7.10.4.tgz", + "integrity": "sha1-TiyF6g1quu4bJNz7uuQm/o1nTP8=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", - "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-sticky-regex/download/@babel/plugin-transform-sticky-regex-7.10.4.tgz", + "integrity": "sha1-jziJ7oZXWBEwop2cyR18c7fEoo0=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/helper-regex": "7.5.5" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" } }, "@babel/plugin-transform-template-literals": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", - "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-template-literals/download/@babel/plugin-transform-template-literals-7.10.4.tgz?cache=0&sync_timestamp=1593522854232&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-template-literals%2Fdownload%2F%40babel%2Fplugin-transform-template-literals-7.10.4.tgz", + "integrity": "sha1-5jdUB7MPy3/P27o7uY7z6dNt97w=", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", - "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-typeof-symbol/download/@babel/plugin-transform-typeof-symbol-7.10.4.tgz", + "integrity": "sha1-lQnxp+7DHE7b/+E3wWzDP/C8W/w=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-unicode-escapes/download/@babel/plugin-transform-unicode-escapes-7.10.4.tgz", + "integrity": "sha1-/q5SM5HHZR3awRXa4KnQaFeJIAc=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.0.tgz", - "integrity": "sha512-RrThb0gdrNwFAqEAAx9OWgtx6ICK69x7i9tCnMdVrxQwSDp/Abu9DXFU5Hh16VP33Rmxh04+NGW28NsIkFvFKA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-unicode-regex/download/@babel/plugin-transform-unicode-regex-7.10.4.tgz?cache=0&sync_timestamp=1593522855498&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-unicode-regex%2Fdownload%2F%40babel%2Fplugin-transform-unicode-regex-7.10.4.tgz", + "integrity": "sha1-5W1x+SgvrG2wnIJ0IFVXbV5tgKg=", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "7.7.2", - "@babel/helper-plugin-utils": "7.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/polyfill": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.7.0.tgz", - "integrity": "sha512-/TS23MVvo34dFmf8mwCisCbWGrfhbiWZSwBo6HkADTBhUa2Q/jWltyY/tpofz/b6/RIhqaqQcquptCirqIhOaQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/polyfill/download/@babel/polyfill-7.10.4.tgz", + "integrity": "sha1-kV5b/mFJCsAZkAjjXKnX0VGo5Fo=", "dev": true, "requires": { - "core-js": "2.6.10", - "regenerator-runtime": "0.13.3" + "core-js": "^2.6.5", + "regenerator-runtime": "^0.13.4" }, "dependencies": { "core-js": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", - "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==", + "version": "2.6.11", + "resolved": "https://registry.npm.taobao.org/core-js/download/core-js-2.6.11.tgz?cache=0&sync_timestamp=1586450269267&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-2.6.11.tgz", + "integrity": "sha1-OIMUafmSK97Y7iHJ3EaYXgOZMIw=", "dev": true } } }, "@babel/preset-env": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.7.1.tgz", - "integrity": "sha512-/93SWhi3PxcVTDpSqC+Dp4YxUu3qZ4m7I76k0w73wYfn7bGVuRIO4QUz95aJksbS+AD1/mT1Ie7rbkT0wSplaA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "7.7.0", - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-proposal-async-generator-functions": "7.7.0", - "@babel/plugin-proposal-dynamic-import": "7.7.0", - "@babel/plugin-proposal-json-strings": "7.2.0", - "@babel/plugin-proposal-object-rest-spread": "7.6.2", - "@babel/plugin-proposal-optional-catch-binding": "7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "7.7.0", - "@babel/plugin-syntax-async-generators": "7.2.0", - "@babel/plugin-syntax-dynamic-import": "7.2.0", - "@babel/plugin-syntax-json-strings": "7.2.0", - "@babel/plugin-syntax-object-rest-spread": "7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "7.2.0", - "@babel/plugin-syntax-top-level-await": "7.7.0", - "@babel/plugin-transform-arrow-functions": "7.2.0", - "@babel/plugin-transform-async-to-generator": "7.7.0", - "@babel/plugin-transform-block-scoped-functions": "7.2.0", - "@babel/plugin-transform-block-scoping": "7.6.3", - "@babel/plugin-transform-classes": "7.7.0", - "@babel/plugin-transform-computed-properties": "7.2.0", - "@babel/plugin-transform-destructuring": "7.6.0", - "@babel/plugin-transform-dotall-regex": "7.7.0", - "@babel/plugin-transform-duplicate-keys": "7.5.0", - "@babel/plugin-transform-exponentiation-operator": "7.2.0", - "@babel/plugin-transform-for-of": "7.4.4", - "@babel/plugin-transform-function-name": "7.7.0", - "@babel/plugin-transform-literals": "7.2.0", - "@babel/plugin-transform-member-expression-literals": "7.2.0", - "@babel/plugin-transform-modules-amd": "7.5.0", - "@babel/plugin-transform-modules-commonjs": "7.7.0", - "@babel/plugin-transform-modules-systemjs": "7.7.0", - "@babel/plugin-transform-modules-umd": "7.7.0", - "@babel/plugin-transform-named-capturing-groups-regex": "7.7.0", - "@babel/plugin-transform-new-target": "7.4.4", - "@babel/plugin-transform-object-super": "7.5.5", - "@babel/plugin-transform-parameters": "7.4.4", - "@babel/plugin-transform-property-literals": "7.2.0", - "@babel/plugin-transform-regenerator": "7.7.0", - "@babel/plugin-transform-reserved-words": "7.2.0", - "@babel/plugin-transform-shorthand-properties": "7.2.0", - "@babel/plugin-transform-spread": "7.6.2", - "@babel/plugin-transform-sticky-regex": "7.2.0", - "@babel/plugin-transform-template-literals": "7.4.4", - "@babel/plugin-transform-typeof-symbol": "7.2.0", - "@babel/plugin-transform-unicode-regex": "7.7.0", - "@babel/types": "7.7.2", - "browserslist": "4.7.3", - "core-js-compat": "3.4.1", - "invariant": "2.2.4", - "js-levenshtein": "1.1.6", - "semver": "5.7.1" + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.10.4.tgz?cache=0&sync_timestamp=1593521234560&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fpreset-env%2Fdownload%2F%40babel%2Fpreset-env-7.10.4.tgz", + "integrity": "sha1-+/V/moA6/Zf08y5PeYu2Lksr718=", + "dev": true, + "requires": { + "@babel/compat-data": "^7.10.4", + "@babel/helper-compilation-targets": "^7.10.4", + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-proposal-async-generator-functions": "^7.10.4", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-dynamic-import": "^7.10.4", + "@babel/plugin-proposal-json-strings": "^7.10.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", + "@babel/plugin-proposal-numeric-separator": "^7.10.4", + "@babel/plugin-proposal-object-rest-spread": "^7.10.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", + "@babel/plugin-proposal-optional-chaining": "^7.10.4", + "@babel/plugin-proposal-private-methods": "^7.10.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.10.4", + "@babel/plugin-transform-arrow-functions": "^7.10.4", + "@babel/plugin-transform-async-to-generator": "^7.10.4", + "@babel/plugin-transform-block-scoped-functions": "^7.10.4", + "@babel/plugin-transform-block-scoping": "^7.10.4", + "@babel/plugin-transform-classes": "^7.10.4", + "@babel/plugin-transform-computed-properties": "^7.10.4", + "@babel/plugin-transform-destructuring": "^7.10.4", + "@babel/plugin-transform-dotall-regex": "^7.10.4", + "@babel/plugin-transform-duplicate-keys": "^7.10.4", + "@babel/plugin-transform-exponentiation-operator": "^7.10.4", + "@babel/plugin-transform-for-of": "^7.10.4", + "@babel/plugin-transform-function-name": "^7.10.4", + "@babel/plugin-transform-literals": "^7.10.4", + "@babel/plugin-transform-member-expression-literals": "^7.10.4", + "@babel/plugin-transform-modules-amd": "^7.10.4", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-modules-systemjs": "^7.10.4", + "@babel/plugin-transform-modules-umd": "^7.10.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", + "@babel/plugin-transform-new-target": "^7.10.4", + "@babel/plugin-transform-object-super": "^7.10.4", + "@babel/plugin-transform-parameters": "^7.10.4", + "@babel/plugin-transform-property-literals": "^7.10.4", + "@babel/plugin-transform-regenerator": "^7.10.4", + "@babel/plugin-transform-reserved-words": "^7.10.4", + "@babel/plugin-transform-shorthand-properties": "^7.10.4", + "@babel/plugin-transform-spread": "^7.10.4", + "@babel/plugin-transform-sticky-regex": "^7.10.4", + "@babel/plugin-transform-template-literals": "^7.10.4", + "@babel/plugin-transform-typeof-symbol": "^7.10.4", + "@babel/plugin-transform-unicode-escapes": "^7.10.4", + "@babel/plugin-transform-unicode-regex": "^7.10.4", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.10.4", + "browserslist": "^4.12.0", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + }, + "dependencies": { + "browserslist": { + "version": "4.12.2", + "resolved": "https://registry.npm.taobao.org/browserslist/download/browserslist-4.12.2.tgz?cache=0&sync_timestamp=1593190408386&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowserslist%2Fdownload%2Fbrowserslist-4.12.2.tgz", + "integrity": "sha1-dmU9fkxXyqihooUT4vThl9wRpxE=", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001088", + "electron-to-chromium": "^1.3.483", + "escalade": "^3.0.1", + "node-releases": "^1.1.58" + } + }, + "caniuse-lite": { + "version": "1.0.30001093", + "resolved": "https://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30001093.tgz?cache=0&sync_timestamp=1593641273200&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcaniuse-lite%2Fdownload%2Fcaniuse-lite-1.0.30001093.tgz", + "integrity": "sha1-gz6A9ksaBFXLzu0qSjuvGeSr0xI=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.484", + "resolved": "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.484.tgz?cache=0&sync_timestamp=1593660932805&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron-to-chromium%2Fdownload%2Felectron-to-chromium-1.3.484.tgz", + "integrity": "sha1-dfWh7uX+MWh1i3ws83Wuc8HM9eY=", + "dev": true + }, + "node-releases": { + "version": "1.1.58", + "resolved": "https://registry.npm.taobao.org/node-releases/download/node-releases-1.1.58.tgz?cache=0&sync_timestamp=1591162286391&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-releases%2Fdownload%2Fnode-releases-1.1.58.tgz", + "integrity": "sha1-juIO7zD6YOUnVfzAlC3vWnNP6TU=", + "dev": true + } + } + }, + "@babel/preset-modules": { + "version": "0.1.3", + "resolved": "https://registry.npm.taobao.org/@babel/preset-modules/download/@babel/preset-modules-0.1.3.tgz", + "integrity": "sha1-EyQrU7XvjIg8PPfd3VWzbOgPvHI=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" } }, "@babel/preset-react": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.7.0.tgz", - "integrity": "sha512-IXXgSUYBPHUGhUkH+89TR6faMcBtuMW0h5OHbMuVbL3/5wK2g6a2M2BBpkLa+Kw0sAHiZ9dNVgqJMDP/O4GRBA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/preset-react/download/@babel/preset-react-7.10.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fpreset-react%2Fdownload%2F%40babel%2Fpreset-react-7.10.4.tgz", + "integrity": "sha1-kuimbYFvmRHRHUzJNb5nrfyC288=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.0.0", - "@babel/plugin-transform-react-display-name": "7.2.0", - "@babel/plugin-transform-react-jsx": "7.7.0", - "@babel/plugin-transform-react-jsx-self": "7.2.0", - "@babel/plugin-transform-react-jsx-source": "7.5.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-transform-react-display-name": "^7.10.4", + "@babel/plugin-transform-react-jsx": "^7.10.4", + "@babel/plugin-transform-react-jsx-development": "^7.10.4", + "@babel/plugin-transform-react-jsx-self": "^7.10.4", + "@babel/plugin-transform-react-jsx-source": "^7.10.4", + "@babel/plugin-transform-react-pure-annotations": "^7.10.4" } }, "@babel/runtime": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", - "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/runtime/download/@babel/runtime-7.10.4.tgz?cache=0&sync_timestamp=1593521086699&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fruntime%2Fdownload%2F%40babel%2Fruntime-7.10.4.tgz", + "integrity": "sha1-pnJPGmuNL26lI22/5Yx9fqnF65k=", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/runtime-corejs3/download/@babel/runtime-corejs3-7.10.4.tgz?cache=0&sync_timestamp=1593522791446&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fruntime-corejs3%2Fdownload%2F%40babel%2Fruntime-corejs3-7.10.4.tgz", + "integrity": "sha1-8p/BmQMHxMV7ENvWzmZ7JxWdng0=", "dev": true, "requires": { - "regenerator-runtime": "0.13.3" + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" } }, "@babel/template": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.0.tgz", - "integrity": "sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/template/download/@babel/template-7.10.4.tgz", + "integrity": "sha1-MlGZbEIA68cdGo/EBfupQPNrong=", "dev": true, "requires": { - "@babel/code-frame": "7.5.5", - "@babel/parser": "7.7.3", - "@babel/types": "7.7.2" + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.10.4.tgz?cache=0&sync_timestamp=1593522826253&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcode-frame%2Fdownload%2F%40babel%2Fcode-frame-7.10.4.tgz", + "integrity": "sha1-Fo2ho26Q2miujUnA8bSMfGJJITo=", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/highlight/download/@babel/highlight-7.10.4.tgz", + "integrity": "sha1-fRvf1ldTU4+r5sOFls23bZrGAUM=", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + } } }, "@babel/traverse": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.2.tgz", - "integrity": "sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==", - "dev": true, - "requires": { - "@babel/code-frame": "7.5.5", - "@babel/generator": "7.7.2", - "@babel/helper-function-name": "7.7.0", - "@babel/helper-split-export-declaration": "7.7.0", - "@babel/parser": "7.7.3", - "@babel/types": "7.7.2", - "debug": "4.1.1", - "globals": "11.12.0", - "lodash": "4.17.15" + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/traverse/download/@babel/traverse-7.10.4.tgz?cache=0&sync_timestamp=1593522841483&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftraverse%2Fdownload%2F%40babel%2Ftraverse-7.10.4.tgz", + "integrity": "sha1-5kLlOVo7CcyVyOdKJ0MrSEtpeBg=", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" }, "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.10.4.tgz?cache=0&sync_timestamp=1593522826253&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcode-frame%2Fdownload%2F%40babel%2Fcode-frame-7.10.4.tgz", + "integrity": "sha1-Fo2ho26Q2miujUnA8bSMfGJJITo=", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/highlight/download/@babel/highlight-7.10.4.tgz", + "integrity": "sha1-fRvf1ldTU4+r5sOFls23bZrGAUM=", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, "debug": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.1" } }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", "dev": true } } }, "@babel/types": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.2.tgz", - "integrity": "sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==", + "version": "7.10.4", + "resolved": "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.10.4.tgz?cache=0&sync_timestamp=1593521074992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftypes%2Fdownload%2F%40babel%2Ftypes-7.10.4.tgz", + "integrity": "sha1-NpUXGINS4YIZmB79FWv9sZn/8e4=", "dev": true, "requires": { - "esutils": "2.0.3", - "lodash": "4.17.15", - "to-fast-properties": "2.0.0" + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" } }, "@csstools/convert-colors": { @@ -1118,230 +1464,234 @@ "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-1.0.10.tgz", "integrity": "sha1-3PsN3837GtJq6kNRMjdx4a6pboQ=" }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true - }, "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "version": "7.1.2", + "resolved": "https://registry.npm.taobao.org/@types/glob/download/@types/glob-7.1.2.tgz?cache=0&sync_timestamp=1591314114348&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fglob%2Fdownload%2F%40types%2Fglob-7.1.2.tgz", + "integrity": "sha1-BsomUhNTpUXZSgrcdPOKWdIyyYc=", "dev": true, "requires": { - "@types/events": "3.0.0", - "@types/minimatch": "3.0.3", - "@types/node": "12.12.11" + "@types/minimatch": "*", + "@types/node": "*" } }, + "@types/json-schema": { + "version": "7.0.5", + "resolved": "https://registry.npm.taobao.org/@types/json-schema/download/@types/json-schema-7.0.5.tgz?cache=0&sync_timestamp=1591720889158&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fjson-schema%2Fdownload%2F%40types%2Fjson-schema-7.0.5.tgz", + "integrity": "sha1-3M5EMOZLRDuolF8CkPtWStW6xt0=", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npm.taobao.org/@types/json5/download/@types/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "resolved": "https://registry.npm.taobao.org/@types/minimatch/download/@types/minimatch-3.0.3.tgz", + "integrity": "sha1-PcoOPzOyAPx9ETnAzZbBJoyt/Z0=", "dev": true }, "@types/node": { - "version": "12.12.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.11.tgz", - "integrity": "sha512-O+x6uIpa6oMNTkPuHDa9MhMMehlxLAd5QcOvKRjAFsBVpeFWTOPnXbDvILvFgFFZfQ1xh1EZi1FbXxUix+zpsQ==", + "version": "14.0.14", + "resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-14.0.14.tgz?cache=0&sync_timestamp=1592989417189&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-14.0.14.tgz", + "integrity": "sha1-JKC1lZ8WrBQa6wxbPNehW3xky84=", "dev": true }, "@webassemblyjs/ast": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", - "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/ast/download/@webassemblyjs/ast-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fast%2Fdownload%2F%40webassemblyjs%2Fast-1.9.0.tgz", + "integrity": "sha1-vYUGBLQEJFmlpBzX0zjL7Wle2WQ=", "dev": true, "requires": { - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5" + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", - "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/floating-point-hex-parser/download/@webassemblyjs/floating-point-hex-parser-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Ffloating-point-hex-parser%2Fdownload%2F%40webassemblyjs%2Ffloating-point-hex-parser-1.9.0.tgz", + "integrity": "sha1-PD07Jxvd/ITesA9xNEQ4MR1S/7Q=", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", - "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-api-error/download/@webassemblyjs/helper-api-error-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-api-error%2Fdownload%2F%40webassemblyjs%2Fhelper-api-error-1.9.0.tgz", + "integrity": "sha1-ID9nbjM7lsnaLuqzzO8zxFkotqI=", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", - "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-buffer/download/@webassemblyjs/helper-buffer-1.9.0.tgz?cache=0&sync_timestamp=1580600188490&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-buffer%2Fdownload%2F%40webassemblyjs%2Fhelper-buffer-1.9.0.tgz", + "integrity": "sha1-oUQtJpxf6yP8vJ73WdrDVH8p3gA=", "dev": true }, "@webassemblyjs/helper-code-frame": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", - "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-code-frame/download/@webassemblyjs/helper-code-frame-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-code-frame%2Fdownload%2F%40webassemblyjs%2Fhelper-code-frame-1.9.0.tgz", + "integrity": "sha1-ZH+Iks0gQ6gqwMjF51w28dkVnyc=", "dev": true, "requires": { - "@webassemblyjs/wast-printer": "1.8.5" + "@webassemblyjs/wast-printer": "1.9.0" } }, "@webassemblyjs/helper-fsm": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", - "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-fsm/download/@webassemblyjs/helper-fsm-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-fsm%2Fdownload%2F%40webassemblyjs%2Fhelper-fsm-1.9.0.tgz", + "integrity": "sha1-wFJWtxJEIUZx9LCOwQitY7cO3bg=", "dev": true }, "@webassemblyjs/helper-module-context": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", - "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-module-context/download/@webassemblyjs/helper-module-context-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-module-context%2Fdownload%2F%40webassemblyjs%2Fhelper-module-context-1.9.0.tgz", + "integrity": "sha1-JdiIS3aDmHGgimxvgGw5ee9xLwc=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "mamacro": "0.0.3" + "@webassemblyjs/ast": "1.9.0" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", - "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-wasm-bytecode/download/@webassemblyjs/helper-wasm-bytecode-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-wasm-bytecode%2Fdownload%2F%40webassemblyjs%2Fhelper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha1-T+2L6sm4wU+MWLcNEk1UndH+V5A=", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", - "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-wasm-section/download/@webassemblyjs/helper-wasm-section-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-wasm-section%2Fdownload%2F%40webassemblyjs%2Fhelper-wasm-section-1.9.0.tgz", + "integrity": "sha1-WkE41aYpK6GLBMWuSXF+QWeWU0Y=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" } }, "@webassemblyjs/ieee754": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", - "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/ieee754/download/@webassemblyjs/ieee754-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fieee754%2Fdownload%2F%40webassemblyjs%2Fieee754-1.9.0.tgz", + "integrity": "sha1-Fceg+6roP7JhQ7us9tbfFwKtOeQ=", "dev": true, "requires": { - "@xtuc/ieee754": "1.2.0" + "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", - "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/leb128/download/@webassemblyjs/leb128-1.9.0.tgz", + "integrity": "sha1-8Zygt2ptxVYjoJz/p2noOPoeHJU=", "dev": true, "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", - "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/utf8/download/@webassemblyjs/utf8-1.9.0.tgz", + "integrity": "sha1-BNM7Y2945qaBMifoJAL3Y3tiKas=", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", - "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-edit/download/@webassemblyjs/wasm-edit-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwasm-edit%2Fdownload%2F%40webassemblyjs%2Fwasm-edit-1.9.0.tgz", + "integrity": "sha1-P+bXnT8PkiGDqoYALELdJWz+6c8=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/helper-wasm-section": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-opt": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "@webassemblyjs/wast-printer": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" } }, "@webassemblyjs/wasm-gen": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", - "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-gen/download/@webassemblyjs/wasm-gen-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwasm-gen%2Fdownload%2F%40webassemblyjs%2Fwasm-gen-1.9.0.tgz", + "integrity": "sha1-ULxw7Gje2OJ2OwGhQYv0NJGnpJw=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" } }, "@webassemblyjs/wasm-opt": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", - "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-opt/download/@webassemblyjs/wasm-opt-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwasm-opt%2Fdownload%2F%40webassemblyjs%2Fwasm-opt-1.9.0.tgz", + "integrity": "sha1-IhEYHlsxMmRDzIES658LkChyGmE=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" } }, "@webassemblyjs/wasm-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", - "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-parser/download/@webassemblyjs/wasm-parser-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwasm-parser%2Fdownload%2F%40webassemblyjs%2Fwasm-parser-1.9.0.tgz", + "integrity": "sha1-nUjkSCbfSmWYKUqmyHRp1kL/9l4=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" } }, "@webassemblyjs/wast-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", - "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wast-parser/download/@webassemblyjs/wast-parser-1.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwast-parser%2Fdownload%2F%40webassemblyjs%2Fwast-parser-1.9.0.tgz", + "integrity": "sha1-MDERXXmsW9JhVWzsw/qQo+9FGRQ=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/floating-point-hex-parser": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-code-frame": "1.8.5", - "@webassemblyjs/helper-fsm": "1.8.5", + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/wast-printer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", - "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "version": "1.9.0", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wast-printer/download/@webassemblyjs/wast-printer-1.9.0.tgz?cache=0&sync_timestamp=1580599638157&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwast-printer%2Fdownload%2F%40webassemblyjs%2Fwast-printer-1.9.0.tgz", + "integrity": "sha1-STXVTIX+9jewDOn1I3dFHQDUeJk=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5", + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", "@xtuc/long": "4.2.2" } }, "@xtuc/ieee754": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "resolved": "https://registry.npm.taobao.org/@xtuc/ieee754/download/@xtuc/ieee754-1.2.0.tgz", + "integrity": "sha1-7vAUoxRa5Hehy8AM0eVSM23Ot5A=", "dev": true }, "@xtuc/long": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "resolved": "https://registry.npm.taobao.org/@xtuc/long/download/@xtuc/long-4.2.2.tgz", + "integrity": "sha1-0pHGpOl5ibXGHZrPOWrk/hM6cY0=", "dev": true }, "accepts": { "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "resolved": "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz", + "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=", "dev": true, "requires": { - "mime-types": "2.1.25", + "mime-types": "~2.1.24", "negotiator": "0.6.2" } }, @@ -1363,10 +1713,10 @@ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { - "fast-deep-equal": "2.0.1", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.4.1", - "uri-js": "4.2.2" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, "ajv-errors": { @@ -1383,8 +1733,8 @@ }, "ansi-colors": { "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "resolved": "https://registry.npm.taobao.org/ansi-colors/download/ansi-colors-3.2.4.tgz", + "integrity": "sha1-46PaS/uubIapwoViXeEkojQCb78=", "dev": true }, "ansi-escapes": { @@ -1395,7 +1745,7 @@ }, "ansi-html": { "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "resolved": "https://registry.npm.taobao.org/ansi-html/download/ansi-html-0.0.7.tgz", "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", "dev": true }, @@ -1411,42 +1761,34 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "1.9.3" - } - }, - "ant-design-palettes": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/ant-design-palettes/-/ant-design-palettes-1.1.3.tgz", - "integrity": "sha512-UpkkTp8egEN21KZNvY7sTcabLlkHvLvS71EVPk4CYi77Z9AaGGCaVn7i72tbOgWDrQp2wjIg8WgMbKBdK7GtWA==", - "requires": { - "tinycolor2": "1.4.1" + "color-convert": "^1.9.0" } }, "anymatch": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-2.0.0.tgz", + "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", "dev": true, "requires": { - "micromatch": "3.1.10", - "normalize-path": "2.1.1" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" }, "dependencies": { "normalize-path": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "1.1.0" + "remove-trailing-separator": "^1.0.1" } } } }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "resolved": "https://registry.npm.taobao.org/aproba/download/aproba-1.2.0.tgz", + "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=", "dev": true }, "argparse": { @@ -1455,74 +1797,204 @@ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "aria-query": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", - "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "version": "4.2.2", + "resolved": "https://registry.npm.taobao.org/aria-query/download/aria-query-4.2.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faria-query%2Fdownload%2Faria-query-4.2.2.tgz", + "integrity": "sha1-DSymyazrVriXfp/tau1+FbvS+Ds=", "dev": true, "requires": { - "ast-types-flow": "0.0.7", - "commander": "2.20.3" + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" } }, "arr-diff": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/arr-diff/download/arr-diff-4.0.0.tgz", "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, "arr-flatten": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "resolved": "https://registry.npm.taobao.org/arr-flatten/download/arr-flatten-1.1.0.tgz", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", "dev": true }, "arr-union": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/arr-union/download/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, "array-flatten": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "resolved": "https://registry.npm.taobao.org/array-flatten/download/array-flatten-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray-flatten%2Fdownload%2Farray-flatten-2.1.2.tgz", + "integrity": "sha1-JO+AoowaiTYX4hSbDG0NeIKTsJk=", "dev": true }, "array-includes": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", - "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/array-includes/download/array-includes-3.1.1.tgz", + "integrity": "sha1-zdZ+aFK9+cEhVGB4ZzIlXtJFk0g=", "dev": true, "requires": { - "define-properties": "1.1.3", - "es-abstract": "1.16.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } } }, "array-union": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/array-union/download/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "1.0.3" + "array-uniq": "^1.0.1" } }, "array-uniq": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "resolved": "https://registry.npm.taobao.org/array-uniq/download/array-uniq-1.0.3.tgz", "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", "dev": true }, "array-unique": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "resolved": "https://registry.npm.taobao.org/array-unique/download/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npm.taobao.org/array.prototype.flat/download/array.prototype.flat-1.2.3.tgz", + "integrity": "sha1-DegrQmsDGNv9uUAInjiwQ9N/bHs=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "array.prototype.flatmap": { + "version": "1.2.3", + "resolved": "https://registry.npm.taobao.org/array.prototype.flatmap/download/array.prototype.flatmap-1.2.3.tgz", + "integrity": "sha1-HBP4SheFZgQt1j3kQURA25Ii5EM=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -1530,44 +2002,52 @@ }, "asn1": { "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "resolved": "https://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz", + "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", "dev": true, "optional": true, "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": "~2.1.0" } }, "asn1.js": { "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "resolved": "https://registry.npm.taobao.org/asn1.js/download/asn1.js-4.10.1.tgz", + "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=", "dev": true, "requires": { - "bn.js": "4.11.8", - "inherits": "2.0.4", - "minimalistic-assert": "1.0.1" + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=", + "dev": true + } } }, "assert": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "resolved": "https://registry.npm.taobao.org/assert/download/assert-1.5.0.tgz", + "integrity": "sha1-VcEJqvbgrv2z3EtxJAxwv1dLGOs=", "dev": true, "requires": { - "object-assign": "4.1.1", + "object-assign": "^4.1.1", "util": "0.10.3" }, "dependencies": { "inherits": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.1.tgz", "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", "dev": true }, "util": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "https://registry.npm.taobao.org/util/download/util-0.10.3.tgz?cache=0&sync_timestamp=1588238457176&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Futil%2Fdownload%2Futil-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -1578,19 +2058,20 @@ }, "assert-plus": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "dev": true, + "optional": true }, "assign-symbols": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/assign-symbols/download/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, "ast-types-flow": { "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "resolved": "https://registry.npm.taobao.org/ast-types-flow/download/ast-types-flow-0.0.7.tgz", "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", "dev": true }, @@ -1602,36 +2083,36 @@ }, "async": { "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "resolved": "https://registry.npm.taobao.org/async/download/async-2.6.3.tgz", + "integrity": "sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8=", "dev": true, "requires": { - "lodash": "4.17.15" + "lodash": "^4.17.14" } }, "async-each": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "resolved": "https://registry.npm.taobao.org/async-each/download/async-each-1.0.3.tgz", + "integrity": "sha1-tyfb+H12UWAvBvTUrDh/R9kbDL8=", "dev": true }, "async-limiter": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "resolved": "https://registry.npm.taobao.org/async-limiter/download/async-limiter-1.0.1.tgz?cache=0&sync_timestamp=1574272018408&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fasync-limiter%2Fdownload%2Fasync-limiter-1.0.1.tgz", + "integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=", "dev": true }, "asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true, "optional": true }, "atob": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "resolved": "https://registry.npm.taobao.org/atob/download/atob-2.1.2.tgz", + "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", "dev": true }, "autoprefixer": { @@ -1640,13 +2121,13 @@ "integrity": "sha512-LCAfcdej1182uVvPOZnytbq61AhnOZ/4JelDaJGDeNwewyU1AMaNthcHsyz1NRjTmd2FkurMckLWfkHg3Z//KA==", "dev": true, "requires": { - "browserslist": "4.7.3", - "caniuse-lite": "1.0.30001011", - "chalk": "2.4.2", - "normalize-range": "0.1.2", - "num2fraction": "1.2.2", - "postcss": "7.0.23", - "postcss-value-parser": "4.0.2" + "browserslist": "^4.7.3", + "caniuse-lite": "^1.0.30001010", + "chalk": "^2.4.2", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.23", + "postcss-value-parser": "^4.0.2" }, "dependencies": { "postcss-value-parser": { @@ -1659,79 +2140,157 @@ }, "aws-sign2": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "resolved": "https://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true, "optional": true }, "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "version": "1.10.0", + "resolved": "https://registry.npm.taobao.org/aws4/download/aws4-1.10.0.tgz", + "integrity": "sha1-oXs6jqgRBg501H0wYSJACtRJeuI=", "dev": true, "optional": true }, + "axe-core": { + "version": "3.5.5", + "resolved": "https://registry.npm.taobao.org/axe-core/download/axe-core-3.5.5.tgz?cache=0&sync_timestamp=1593618499473&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faxe-core%2Fdownload%2Faxe-core-3.5.5.tgz", + "integrity": "sha1-hDFQc7U/o8DFFnbFiNWdoJoZIic=", + "dev": true + }, "axobject-query": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", - "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", - "dev": true, - "requires": { - "ast-types-flow": "0.0.7" - } + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/axobject-query/download/axobject-query-2.2.0.tgz?cache=0&sync_timestamp=1592785103417&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faxobject-query%2Fdownload%2Faxobject-query-2.2.0.tgz", + "integrity": "sha1-lD1H4QwLcEqkInXiDt83ImSJib4=", + "dev": true }, "babel-eslint": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz", - "integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==", + "version": "10.1.0", + "resolved": "https://registry.npm.taobao.org/babel-eslint/download/babel-eslint-10.1.0.tgz", + "integrity": "sha1-aWjlaKkQt4+zd5zdi2rC9HmUMjI=", "dev": true, "requires": { - "@babel/code-frame": "7.5.5", - "@babel/parser": "7.7.3", - "@babel/traverse": "7.7.2", - "@babel/types": "7.7.2", - "eslint-visitor-keys": "1.1.0", - "resolve": "1.12.0" + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" } }, "babel-loader": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", - "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", - "dev": true, - "requires": { - "find-cache-dir": "2.1.0", - "loader-utils": "1.2.3", - "mkdirp": "0.5.1", - "pify": "4.0.1" - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", - "dev": true, - "requires": { - "object.assign": "4.1.0" - } - }, - "babel-plugin-module-resolver": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.2.0.tgz", - "integrity": "sha512-tjR0GvSndzPew/Iayf4uICWZqjBwnlMWjSx6brryfQ81F9rxBVqwDJtFCV8oOs0+vJeefK9TmdZtkIFdFe1UnA==", + "version": "8.1.0", + "resolved": "https://registry.npm.taobao.org/babel-loader/download/babel-loader-8.1.0.tgz?cache=0&sync_timestamp=1584715910722&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-loader%2Fdownload%2Fbabel-loader-8.1.0.tgz", + "integrity": "sha1-xhHVESvVIJq+i5+oTD5NolJ18cM=", "dev": true, "requires": { - "find-babel-config": "1.2.0", - "glob": "7.1.6", - "pkg-up": "2.0.0", - "reselect": "3.0.1", - "resolve": "1.12.0" - } - }, - "babel-plugin-transform-inline-environment-variables": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-environment-variables/-/babel-plugin-transform-inline-environment-variables-0.4.3.tgz", - "integrity": "sha1-o7CYgzU76LXiM24/8e+KXZP5xIk=", + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "ajv": { + "version": "6.12.2", + "resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.2.tgz?cache=0&sync_timestamp=1587338610933&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.2.tgz", + "integrity": "sha1-xinF7O0XuvMUQ3kY0tqIyZ1ZWM0=", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz", + "integrity": "sha1-VXBmIEatKeLpFucariYKvf9Pang=", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz?cache=0&sync_timestamp=1591599604098&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffast-deep-equal%2Fdownload%2Ffast-deep-equal-3.1.3.tgz", + "integrity": "sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz?cache=0&sync_timestamp=1586046271069&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-1.0.1.tgz", + "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-1.4.0.tgz", + "integrity": "sha1-xXm140yzSxp07cbB+za/o3HVphM=", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1587535418745&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz", + "integrity": "sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=", + "dev": true, + "requires": { + "minimist": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz", + "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=", + "dev": true + } + } + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.7.0.tgz", + "integrity": "sha1-FxUfdtjq5n+793lgwzxnatn078c=", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npm.taobao.org/babel-plugin-dynamic-import-node/download/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha1-hP2hnJduxcbe/vV/lCez3vZuF6M=", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-module-resolver": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.2.0.tgz", + "integrity": "sha512-tjR0GvSndzPew/Iayf4uICWZqjBwnlMWjSx6brryfQ81F9rxBVqwDJtFCV8oOs0+vJeefK9TmdZtkIFdFe1UnA==", + "dev": true, + "requires": { + "find-babel-config": "^1.1.0", + "glob": "^7.1.2", + "pkg-up": "^2.0.0", + "reselect": "^3.0.1", + "resolve": "^1.4.0" + } + }, + "babel-plugin-transform-inline-environment-variables": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-environment-variables/-/babel-plugin-transform-inline-environment-variables-0.4.3.tgz", + "integrity": "sha1-o7CYgzU76LXiM24/8e+KXZP5xIk=", "dev": true }, "balanced-match": { @@ -1742,79 +2301,79 @@ }, "base": { "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "resolved": "https://registry.npm.taobao.org/base/download/base-0.11.2.tgz", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.3.0", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.2", - "pascalcase": "0.1.1" + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" }, "dependencies": { "define-property": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } }, "base64-js": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "resolved": "https://registry.npm.taobao.org/base64-js/download/base64-js-1.3.1.tgz", + "integrity": "sha1-WOzoy3XdB+ce0IxzarxfrE2/jfE=", "dev": true }, "batch": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "resolved": "https://registry.npm.taobao.org/batch/download/batch-0.6.1.tgz", "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", "dev": true }, "bcrypt-pbkdf": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "big.js": { @@ -1825,66 +2384,76 @@ }, "binary-extensions": { "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-1.13.1.tgz?cache=0&sync_timestamp=1593261331793&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbinary-extensions%2Fdownload%2Fbinary-extensions-1.13.1.tgz", + "integrity": "sha1-WYr+VHVbKGilMw0q/51Ou1Mgm2U=", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npm.taobao.org/bindings/download/bindings-1.5.0.tgz", + "integrity": "sha1-EDU8npRTNLwFEabZCzj7x8nFBN8=", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bluebird": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", - "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==", + "version": "3.7.2", + "resolved": "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz", + "integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=", "dev": true }, "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "version": "5.1.2", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-5.1.2.tgz", + "integrity": "sha1-yWhpAtPJoncp9DqxD515wgBNp7A=", "dev": true }, "body-parser": { "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "resolved": "https://registry.npm.taobao.org/body-parser/download/body-parser-1.19.0.tgz", + "integrity": "sha1-lrJwnlfJxOCab9Zqj9l5hE9p8Io=", "dev": true, "requires": { "bytes": "3.1.0", - "content-type": "1.0.4", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.2", + "depd": "~1.1.2", "http-errors": "1.7.2", "iconv-lite": "0.4.24", - "on-finished": "2.3.0", + "on-finished": "~2.3.0", "qs": "6.7.0", "raw-body": "2.4.0", - "type-is": "1.6.18" + "type-is": "~1.6.17" }, "dependencies": { "bytes": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbytes%2Fdownload%2Fbytes-3.1.0.tgz", + "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY=", "dev": true }, "qs": { "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz", + "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=", "dev": true } } }, "bonjour": { "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "resolved": "https://registry.npm.taobao.org/bonjour/download/bonjour-3.5.0.tgz", "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", "dev": true, "requires": { - "array-flatten": "2.1.2", - "deep-equal": "1.1.1", - "dns-equal": "1.0.0", - "dns-txt": "2.0.2", - "multicast-dns": "6.2.3", - "multicast-dns-service-types": "1.1.0" + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" } }, "brace-expansion": { @@ -1893,114 +2462,143 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "braces": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "repeat-element": "1.1.3", - "snapdragon": "0.8.2", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" + "resolved": "https://registry.npm.taobao.org/braces/download/braces-2.3.2.tgz", + "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" }, "dependencies": { "extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } }, "brorand": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/brorand/download/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, "browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "resolved": "https://registry.npm.taobao.org/browserify-aes/download/browserify-aes-1.2.0.tgz", + "integrity": "sha1-Mmc0ZC9APavDADIJhTu3CtQo70g=", "dev": true, "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "inherits": "2.0.4", - "safe-buffer": "5.1.2" + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "browserify-cipher": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "resolved": "https://registry.npm.taobao.org/browserify-cipher/download/browserify-cipher-1.0.1.tgz", + "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=", "dev": true, "requires": { - "browserify-aes": "1.2.0", - "browserify-des": "1.0.2", - "evp_bytestokey": "1.0.3" + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" } }, "browserify-des": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "resolved": "https://registry.npm.taobao.org/browserify-des/download/browserify-des-1.0.2.tgz", + "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=", "dev": true, "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.1", - "inherits": "2.0.4", - "safe-buffer": "5.1.2" + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/browserify-rsa/download/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { - "bn.js": "4.11.8", - "randombytes": "2.1.0" + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=", + "dev": true + } } }, "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "elliptic": "6.5.1", - "inherits": "2.0.4", - "parse-asn1": "5.1.5" + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/browserify-sign/download/browserify-sign-4.2.0.tgz", + "integrity": "sha1-VF0LGwfmssmSEQgr8bEsznoLDhE=", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.2", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz", + "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz", + "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=", + "dev": true + } } }, "browserify-zlib": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "resolved": "https://registry.npm.taobao.org/browserify-zlib/download/browserify-zlib-0.2.0.tgz", + "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", "dev": true, "requires": { - "pako": "1.0.10" + "pako": "~1.0.5" } }, "browserslist": { @@ -2009,90 +2607,90 @@ "integrity": "sha512-jWvmhqYpx+9EZm/FxcZSbUZyDEvDTLDi3nSAKbzEkyWvtI0mNSmUosey+5awDW1RUlrgXbQb5A6qY1xQH9U6MQ==", "dev": true, "requires": { - "caniuse-lite": "1.0.30001011", - "electron-to-chromium": "1.3.309", - "node-releases": "1.1.40" + "caniuse-lite": "^1.0.30001010", + "electron-to-chromium": "^1.3.306", + "node-releases": "^1.1.40" } }, "buffer": { "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "resolved": "https://registry.npm.taobao.org/buffer/download/buffer-4.9.2.tgz?cache=0&sync_timestamp=1588706716358&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbuffer%2Fdownload%2Fbuffer-4.9.2.tgz", + "integrity": "sha1-Iw6tNEACmIZEhBqwJEr4xEu+Pvg=", "dev": true, "requires": { - "base64-js": "1.3.1", - "ieee754": "1.1.13", - "isarray": "1.0.0" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" } }, "buffer-from": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "resolved": "https://registry.npm.taobao.org/buffer-from/download/buffer-from-1.1.1.tgz", + "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=", "dev": true }, "buffer-indexof": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "resolved": "https://registry.npm.taobao.org/buffer-indexof/download/buffer-indexof-1.1.1.tgz", + "integrity": "sha1-Uvq8xqYG0aADAoAmSO9o9jnaJow=", "dev": true }, "buffer-xor": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "resolved": "https://registry.npm.taobao.org/buffer-xor/download/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, "builtin-status-codes": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/builtin-status-codes/download/builtin-status-codes-3.0.0.tgz", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, "bytes": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbytes%2Fdownload%2Fbytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, "cacache": { - "version": "12.0.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", - "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", - "dev": true, - "requires": { - "bluebird": "3.7.1", - "chownr": "1.1.3", - "figgy-pudding": "3.5.1", - "glob": "7.1.6", - "graceful-fs": "4.2.3", - "infer-owner": "1.0.4", - "lru-cache": "5.1.1", - "mississippi": "3.0.0", - "mkdirp": "0.5.1", - "move-concurrently": "1.0.1", - "promise-inflight": "1.0.1", - "rimraf": "2.7.1", - "ssri": "6.0.1", - "unique-filename": "1.1.1", - "y18n": "4.0.0" + "version": "12.0.4", + "resolved": "https://registry.npm.taobao.org/cacache/download/cacache-12.0.4.tgz?cache=0&sync_timestamp=1591142705598&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcacache%2Fdownload%2Fcacache-12.0.4.tgz", + "integrity": "sha1-ZovL0QWutfHZL+JVcOyVJcj6pAw=", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" } }, "cache-base": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "resolved": "https://registry.npm.taobao.org/cache-base/download/cache-base-1.0.1.tgz", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.3.0", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.1", - "to-object-path": "0.3.0", - "union-value": "1.0.1", - "unset-value": "1.0.0" + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" } }, "caller-callsite": { @@ -2101,7 +2699,7 @@ "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", "dev": true, "requires": { - "callsites": "2.0.0" + "callsites": "^2.0.0" }, "dependencies": { "callsites": { @@ -2118,7 +2716,7 @@ "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", "dev": true, "requires": { - "caller-callsite": "2.0.0" + "caller-callsite": "^2.0.0" } }, "callsites": { @@ -2141,7 +2739,7 @@ }, "caseless": { "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "resolved": "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true, "optional": true @@ -2152,9 +2750,9 @@ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.5.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "chardet": { @@ -2165,68 +2763,68 @@ }, "chokidar": { "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-2.1.8.tgz?cache=0&sync_timestamp=1587911196018&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-2.1.8.tgz", + "integrity": "sha1-gEs6e2qZNYw8XGHnHYco8EHP+Rc=", "dev": true, "requires": { - "anymatch": "2.0.0", - "async-each": "1.0.3", - "braces": "2.3.2", - "fsevents": "1.2.9", - "glob-parent": "3.1.0", - "inherits": "2.0.4", - "is-binary-path": "1.0.1", - "is-glob": "4.0.1", - "normalize-path": "3.0.0", - "path-is-absolute": "1.0.1", - "readdirp": "2.2.1", - "upath": "1.2.0" + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" } }, "chownr": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", - "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", + "version": "1.1.4", + "resolved": "https://registry.npm.taobao.org/chownr/download/chownr-1.1.4.tgz", + "integrity": "sha1-b8nXtC0ypYNZYzdmbn0ICE2izGs=", "dev": true }, "chrome-trace-event": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "resolved": "https://registry.npm.taobao.org/chrome-trace-event/download/chrome-trace-event-1.0.2.tgz", + "integrity": "sha1-I0CQ7pfH1K0aLEvq4nUF3v/GCKQ=", "dev": true, "requires": { - "tslib": "1.10.0" + "tslib": "^1.9.0" } }, "cipher-base": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "resolved": "https://registry.npm.taobao.org/cipher-base/download/cipher-base-1.0.4.tgz", + "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", "dev": true, "requires": { - "inherits": "2.0.4", - "safe-buffer": "5.1.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "class-utils": { "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "resolved": "https://registry.npm.taobao.org/class-utils/download/class-utils-0.3.6.tgz", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" }, "dependencies": { "define-property": { "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } } } @@ -2242,7 +2840,7 @@ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "2.0.0" + "restore-cursor": "^2.0.0" } }, "cli-width": { @@ -2253,39 +2851,39 @@ }, "cliui": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "resolved": "https://registry.npm.taobao.org/cliui/download/cliui-5.0.0.tgz?cache=0&sync_timestamp=1573942320052&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcliui%2Fdownload%2Fcliui-5.0.0.tgz", + "integrity": "sha1-3u/P2y6AB4SqNPRvoI4GhRx7u8U=", "dev": true, "requires": { - "string-width": "3.1.0", - "strip-ansi": "5.2.0", - "wrap-ansi": "5.1.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" }, "dependencies": { "ansi-regex": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-4.1.0.tgz", + "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=", "dev": true }, "string-width": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", "dev": true, "requires": { - "emoji-regex": "7.0.3", - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "5.2.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "strip-ansi": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz", + "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=", "dev": true, "requires": { - "ansi-regex": "4.1.0" + "ansi-regex": "^4.1.0" } } } @@ -2296,25 +2894,19 @@ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, "codemirror": { - "version": "5.49.2", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.49.2.tgz", - "integrity": "sha512-dwJ2HRPHm8w51WB5YTF9J7m6Z5dtkqbU9ntMZ1dqXyFB9IpjoUFDj80ahRVEoVanfIp6pfASJbOlbWdEf8FOzQ==" + "version": "5.55.0", + "resolved": "https://registry.npm.taobao.org/codemirror/download/codemirror-5.55.0.tgz?cache=0&sync_timestamp=1592745428423&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcodemirror%2Fdownload%2Fcodemirror-5.55.0.tgz", + "integrity": "sha1-I3MfZBKI8gKmhY/ch48xSeDgQ2M=" }, "collection-visit": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/collection-visit/download/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" } }, "color-convert": { @@ -2334,11 +2926,12 @@ }, "combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "resolved": "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz", + "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", "dev": true, + "optional": true, "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "commander": { @@ -2348,38 +2941,38 @@ }, "commondir": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/commondir/download/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, "component-emitter": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "resolved": "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.3.0.tgz", + "integrity": "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A=", "dev": true }, "compressible": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", - "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==", + "version": "2.0.18", + "resolved": "https://registry.npm.taobao.org/compressible/download/compressible-2.0.18.tgz?cache=0&sync_timestamp=1578286264482&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcompressible%2Fdownload%2Fcompressible-2.0.18.tgz", + "integrity": "sha1-r1PMprBw1MPAdQ+9dyhqbXzEb7o=", "dev": true, "requires": { - "mime-db": "1.42.0" + "mime-db": ">= 1.43.0 < 2" } }, "compression": { "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "resolved": "https://registry.npm.taobao.org/compression/download/compression-1.7.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcompression%2Fdownload%2Fcompression-1.7.4.tgz", + "integrity": "sha1-lVI+/xcMpXwpoMpB5v4TH0Hlu48=", "dev": true, "requires": { - "accepts": "1.3.7", + "accepts": "~1.3.5", "bytes": "3.0.0", - "compressible": "2.0.17", + "compressible": "~2.0.16", "debug": "2.6.9", - "on-headers": "1.0.2", + "on-headers": "~1.0.2", "safe-buffer": "5.1.2", - "vary": "1.1.2" + "vary": "~1.1.2" } }, "concat-map": { @@ -2390,14 +2983,14 @@ }, "concat-stream": { "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "resolved": "https://registry.npm.taobao.org/concat-stream/download/concat-stream-1.6.2.tgz", + "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", "dev": true, "requires": { - "buffer-from": "1.1.1", - "inherits": "2.0.4", - "readable-stream": "2.3.6", - "typedarray": "0.0.6" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, "confusing-browser-globals": { @@ -2408,32 +3001,32 @@ }, "connect-history-api-fallback": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "resolved": "https://registry.npm.taobao.org/connect-history-api-fallback/download/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha1-izIIk1kwjRERFdgcrT/Oq4iPl7w=", "dev": true }, "console-browserify": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "resolved": "https://registry.npm.taobao.org/console-browserify/download/console-browserify-1.2.0.tgz", + "integrity": "sha1-ZwY871fOts9Jk6KrOlWECujEkzY=", "dev": true }, "constants-browserify": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/constants-browserify/download/constants-browserify-1.0.0.tgz", "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", "dev": true }, "contains-path": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/contains-path/download/contains-path-0.1.0.tgz", "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, "content-disposition": { "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "resolved": "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcontent-disposition%2Fdownload%2Fcontent-disposition-0.5.3.tgz", + "integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=", "dev": true, "requires": { "safe-buffer": "5.1.2" @@ -2441,8 +3034,8 @@ }, "content-type": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "resolved": "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", "dev": true }, "conventional-commit-types": { @@ -2453,71 +3046,107 @@ }, "convert-source-map": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "resolved": "https://registry.npm.taobao.org/convert-source-map/download/convert-source-map-1.7.0.tgz", + "integrity": "sha1-F6LLiC1/d9NJBYXizmxSRCSjpEI=", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.1" } }, "cookie": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "resolved": "https://registry.npm.taobao.org/cookie/download/cookie-0.4.0.tgz", + "integrity": "sha1-vrQ35wIrO21JAZ0IhmUwPr6cFLo=", "dev": true }, "cookie-signature": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "resolved": "https://registry.npm.taobao.org/cookie-signature/download/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, "copy-concurrently": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "resolved": "https://registry.npm.taobao.org/copy-concurrently/download/copy-concurrently-1.0.5.tgz", + "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=", "dev": true, "requires": { - "aproba": "1.2.0", - "fs-write-stream-atomic": "1.0.10", - "iferr": "0.1.5", - "mkdirp": "0.5.1", - "rimraf": "2.7.1", - "run-queue": "1.0.3" + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" } }, "copy-descriptor": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/copy-descriptor/download/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, "core-js": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.4.1.tgz", - "integrity": "sha512-KX/dnuY/J8FtEwbnrzmAjUYgLqtk+cxM86hfG60LGiW3MmltIc2yAmDgBgEkfm0blZhUrdr1Zd84J2Y14mLxzg==" + "version": "3.6.5", + "resolved": "https://registry.npm.taobao.org/core-js/download/core-js-3.6.5.tgz?cache=0&sync_timestamp=1586450269267&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-3.6.5.tgz", + "integrity": "sha1-c5XcJzrzf7LlDpvT2f6EEoUjHRo=" }, "core-js-compat": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.4.1.tgz", - "integrity": "sha512-YdeJI26gLc0CQJ9asLE5obEgBz2I0+CIgnoTbS2T0d5IPQw/OCgCIFR527RmpduxjrB3gSEHoGOCTq9sigOyfw==", + "version": "3.6.5", + "resolved": "https://registry.npm.taobao.org/core-js-compat/download/core-js-compat-3.6.5.tgz?cache=0&sync_timestamp=1586535809290&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js-compat%2Fdownload%2Fcore-js-compat-3.6.5.tgz", + "integrity": "sha1-KlHZpOJd/W5pAlGqgfmePAVIHxw=", "dev": true, "requires": { - "browserslist": "4.7.3", - "semver": "6.3.0" + "browserslist": "^4.8.5", + "semver": "7.0.0" }, "dependencies": { + "browserslist": { + "version": "4.12.2", + "resolved": "https://registry.npm.taobao.org/browserslist/download/browserslist-4.12.2.tgz?cache=0&sync_timestamp=1593190408386&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowserslist%2Fdownload%2Fbrowserslist-4.12.2.tgz", + "integrity": "sha1-dmU9fkxXyqihooUT4vThl9wRpxE=", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001088", + "electron-to-chromium": "^1.3.483", + "escalade": "^3.0.1", + "node-releases": "^1.1.58" + } + }, + "caniuse-lite": { + "version": "1.0.30001093", + "resolved": "https://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30001093.tgz?cache=0&sync_timestamp=1593641273200&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcaniuse-lite%2Fdownload%2Fcaniuse-lite-1.0.30001093.tgz", + "integrity": "sha1-gz6A9ksaBFXLzu0qSjuvGeSr0xI=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.484", + "resolved": "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.484.tgz?cache=0&sync_timestamp=1593660932805&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron-to-chromium%2Fdownload%2Felectron-to-chromium-1.3.484.tgz", + "integrity": "sha1-dfWh7uX+MWh1i3ws83Wuc8HM9eY=", + "dev": true + }, + "node-releases": { + "version": "1.1.58", + "resolved": "https://registry.npm.taobao.org/node-releases/download/node-releases-1.1.58.tgz?cache=0&sync_timestamp=1591162286391&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-releases%2Fdownload%2Fnode-releases-1.1.58.tgz", + "integrity": "sha1-juIO7zD6YOUnVfzAlC3vWnNP6TU=", + "dev": true + }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.0.0", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-7.0.0.tgz", + "integrity": "sha1-XzyjV2HkfgWyBsba/yz4FPAxa44=", "dev": true } } }, + "core-js-pure": { + "version": "3.6.5", + "resolved": "https://registry.npm.taobao.org/core-js-pure/download/core-js-pure-3.6.5.tgz", + "integrity": "sha1-x5519eONvIWmYtke6lK4JW1TuBM=", + "dev": true + }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, @@ -2527,10 +3156,10 @@ "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", "dev": true, "requires": { - "import-fresh": "2.0.0", - "is-directory": "0.3.1", - "js-yaml": "3.13.1", - "parse-json": "4.0.0" + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" }, "dependencies": { "import-fresh": { @@ -2539,8 +3168,8 @@ "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", "dev": true, "requires": { - "caller-path": "2.0.0", - "resolve-from": "3.0.0" + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" } }, "parse-json": { @@ -2549,8 +3178,8 @@ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "1.3.2", - "json-parse-better-errors": "1.0.2" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, "resolve-from": { @@ -2563,39 +3192,47 @@ }, "create-ecdh": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "resolved": "https://registry.npm.taobao.org/create-ecdh/download/create-ecdh-4.0.3.tgz", + "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=", "dev": true, "requires": { - "bn.js": "4.11.8", - "elliptic": "6.5.1" + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=", + "dev": true + } } }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "resolved": "https://registry.npm.taobao.org/create-hash/download/create-hash-1.2.0.tgz", + "integrity": "sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY=", "dev": true, "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.4", - "md5.js": "1.3.5", - "ripemd160": "2.0.2", - "sha.js": "2.4.11" + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" } }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "resolved": "https://registry.npm.taobao.org/create-hmac/download/create-hmac-1.1.7.tgz", + "integrity": "sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8=", "dev": true, "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "inherits": "2.0.4", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.2", - "sha.js": "2.4.11" + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "create-react-class": { @@ -2603,9 +3240,9 @@ "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz", "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==", "requires": { - "fbjs": "0.8.17", - "loose-envify": "1.4.0", - "object-assign": "4.1.1" + "fbjs": "^0.8.9", + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" } }, "cross-env": { @@ -2614,7 +3251,7 @@ "integrity": "sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ==", "dev": true, "requires": { - "cross-spawn": "6.0.5" + "cross-spawn": "^6.0.5" } }, "cross-spawn": { @@ -2623,30 +3260,30 @@ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "nice-try": "1.0.5", - "path-key": "2.0.1", - "semver": "5.7.1", - "shebang-command": "1.2.0", - "which": "1.3.1" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, "crypto-browserify": { "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "resolved": "https://registry.npm.taobao.org/crypto-browserify/download/crypto-browserify-3.12.0.tgz", + "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", "dev": true, "requires": { - "browserify-cipher": "1.0.1", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.3", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "diffie-hellman": "5.0.3", - "inherits": "2.0.4", - "pbkdf2": "3.0.17", - "public-encrypt": "4.0.3", - "randombytes": "2.1.0", - "randomfill": "1.0.4" + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" } }, "css-blank-pseudo": { @@ -2655,7 +3292,7 @@ "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.5" } }, "css-has-pseudo": { @@ -2664,8 +3301,8 @@ "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-selector-parser": "5.0.0" + "postcss": "^7.0.6", + "postcss-selector-parser": "^5.0.0-rc.4" }, "dependencies": { "cssesc": { @@ -2680,9 +3317,9 @@ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "dev": true, "requires": { - "cssesc": "2.0.0", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } } } @@ -2693,17 +3330,17 @@ "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", "dev": true, "requires": { - "camelcase": "5.3.1", - "icss-utils": "4.1.1", - "loader-utils": "1.2.3", - "normalize-path": "3.0.0", - "postcss": "7.0.23", - "postcss-modules-extract-imports": "2.0.0", - "postcss-modules-local-by-default": "2.0.6", - "postcss-modules-scope": "2.1.0", - "postcss-modules-values": "2.0.0", - "postcss-value-parser": "3.3.1", - "schema-utils": "1.0.0" + "camelcase": "^5.2.0", + "icss-utils": "^4.1.0", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.14", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^2.0.6", + "postcss-modules-scope": "^2.1.0", + "postcss-modules-values": "^2.0.0", + "postcss-value-parser": "^3.3.0", + "schema-utils": "^1.0.0" } }, "css-prefers-color-scheme": { @@ -2712,7 +3349,7 @@ "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.5" } }, "cssdb": { @@ -2729,7 +3366,7 @@ }, "cyclist": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/cyclist/download/cyclist-1.0.1.tgz", "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, @@ -2739,11 +3376,11 @@ "integrity": "sha1-L0vHOQ4yROTfKT5ro1Hkx0Cnx2Q=", "dev": true, "requires": { - "conventional-commit-types": "2.3.0", - "lodash.map": "4.6.0", - "longest": "1.0.1", - "right-pad": "1.0.1", - "word-wrap": "1.2.3" + "conventional-commit-types": "^2.0.0", + "lodash.map": "^4.5.1", + "longest": "^1.0.1", + "right-pad": "^1.0.1", + "word-wrap": "^1.0.3" } }, "d3": { @@ -2751,37 +3388,37 @@ "resolved": "https://registry.npmjs.org/d3/-/d3-5.14.2.tgz", "integrity": "sha512-Ccipa9XrYW5N0QkP6u0Qb8kU6WekIXBiDenmZm1zLvuq/9pBBhRCJLCICEOsH5Og4B0Xw02bhqGkK5VN/oPH0w==", "requires": { - "d3-array": "1.2.4", - "d3-axis": "1.0.12", - "d3-brush": "1.1.5", - "d3-chord": "1.0.6", - "d3-collection": "1.0.7", - "d3-color": "1.4.0", - "d3-contour": "1.3.2", - "d3-dispatch": "1.0.6", - "d3-drag": "1.2.5", - "d3-dsv": "1.2.0", - "d3-ease": "1.0.6", - "d3-fetch": "1.1.2", - "d3-force": "1.2.1", - "d3-format": "1.4.2", - "d3-geo": "1.11.9", - "d3-hierarchy": "1.1.9", - "d3-interpolate": "1.1.6", - "d3-path": "1.0.9", - "d3-polygon": "1.0.6", - "d3-quadtree": "1.0.7", - "d3-random": "1.1.2", - "d3-scale": "2.2.2", - "d3-scale-chromatic": "1.5.0", - "d3-selection": "1.4.1", - "d3-shape": "1.3.7", - "d3-time": "1.1.0", - "d3-time-format": "2.2.2", - "d3-timer": "1.0.10", - "d3-transition": "1.3.2", - "d3-voronoi": "1.1.4", - "d3-zoom": "1.8.3" + "d3-array": "1", + "d3-axis": "1", + "d3-brush": "1", + "d3-chord": "1", + "d3-collection": "1", + "d3-color": "1", + "d3-contour": "1", + "d3-dispatch": "1", + "d3-drag": "1", + "d3-dsv": "1", + "d3-ease": "1", + "d3-fetch": "1", + "d3-force": "1", + "d3-format": "1", + "d3-geo": "1", + "d3-hierarchy": "1", + "d3-interpolate": "1", + "d3-path": "1", + "d3-polygon": "1", + "d3-quadtree": "1", + "d3-random": "1", + "d3-scale": "2", + "d3-scale-chromatic": "1", + "d3-selection": "1", + "d3-shape": "1", + "d3-time": "1", + "d3-time-format": "2", + "d3-timer": "1", + "d3-transition": "1", + "d3-voronoi": "1", + "d3-zoom": "1" } }, "d3-array": { @@ -2799,11 +3436,11 @@ "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.5.tgz", "integrity": "sha512-rEaJ5gHlgLxXugWjIkolTA0OyMvw8UWU1imYXy1v642XyyswmI1ybKOv05Ft+ewq+TFmdliD3VuK0pRp1VT/5A==", "requires": { - "d3-dispatch": "1.0.6", - "d3-drag": "1.2.5", - "d3-interpolate": "1.1.6", - "d3-selection": "1.4.1", - "d3-transition": "1.3.2" + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" } }, "d3-chord": { @@ -2811,8 +3448,8 @@ "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", "requires": { - "d3-array": "1.2.4", - "d3-path": "1.0.9" + "d3-array": "1", + "d3-path": "1" } }, "d3-collection": { @@ -2830,7 +3467,7 @@ "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", "requires": { - "d3-array": "1.2.4" + "d3-array": "^1.1.1" } }, "d3-dispatch": { @@ -2843,8 +3480,8 @@ "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", "requires": { - "d3-dispatch": "1.0.6", - "d3-selection": "1.4.1" + "d3-dispatch": "1", + "d3-selection": "1" } }, "d3-dsv": { @@ -2852,9 +3489,9 @@ "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", "requires": { - "commander": "2.20.3", - "iconv-lite": "0.4.24", - "rw": "1.3.3" + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" } }, "d3-ease": { @@ -2867,7 +3504,7 @@ "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.1.2.tgz", "integrity": "sha512-S2loaQCV/ZeyTyIF2oP8D1K9Z4QizUzW7cWeAOAS4U88qOt3Ucf6GsmgthuYSdyB2HyEm4CeGvkQxWsmInsIVA==", "requires": { - "d3-dsv": "1.2.0" + "d3-dsv": "1" } }, "d3-force": { @@ -2875,10 +3512,10 @@ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", "requires": { - "d3-collection": "1.0.7", - "d3-dispatch": "1.0.6", - "d3-quadtree": "1.0.7", - "d3-timer": "1.0.10" + "d3-collection": "1", + "d3-dispatch": "1", + "d3-quadtree": "1", + "d3-timer": "1" } }, "d3-format": { @@ -2891,7 +3528,7 @@ "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.11.9.tgz", "integrity": "sha512-9edcH6J3s/Aa3KJITWqFJbyB/8q3mMlA9Fi7z6yy+FAYMnRaxmC7jBhUnsINxVWD14GmqX3DK8uk7nV6/Ekt4A==", "requires": { - "d3-array": "1.2.4" + "d3-array": "1" } }, "d3-hierarchy": { @@ -2904,7 +3541,7 @@ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz", "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==", "requires": { - "d3-color": "1.4.0" + "d3-color": "1" } }, "d3-path": { @@ -2932,9 +3569,9 @@ "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.7.1.tgz", "integrity": "sha1-0imDImj8aaf+yEgD6WwiVqYUxSE=", "requires": { - "d3-array": "1.2.4", - "d3-collection": "1.0.7", - "d3-shape": "1.3.7" + "d3-array": "1", + "d3-collection": "1", + "d3-shape": "^1.2.0" } }, "d3-scale": { @@ -2942,12 +3579,12 @@ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", "requires": { - "d3-array": "1.2.4", - "d3-collection": "1.0.7", - "d3-format": "1.4.2", - "d3-interpolate": "1.1.6", - "d3-time": "1.1.0", - "d3-time-format": "2.2.2" + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" } }, "d3-scale-chromatic": { @@ -2955,8 +3592,8 @@ "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", "requires": { - "d3-color": "1.4.0", - "d3-interpolate": "1.1.6" + "d3-color": "1", + "d3-interpolate": "1" } }, "d3-selection": { @@ -2969,7 +3606,7 @@ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", "requires": { - "d3-path": "1.0.9" + "d3-path": "1" } }, "d3-svg-legend": { @@ -3006,13 +3643,13 @@ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.3.tgz", "integrity": "sha1-T56PDMLqDzkl/wSsJ63AkEX6TJA=", "requires": { - "d3-array": "1.0.1", - "d3-collection": "1.0.7", - "d3-color": "1.4.0", - "d3-format": "1.0.2", - "d3-interpolate": "1.1.6", - "d3-time": "1.1.0", - "d3-time-format": "2.2.2" + "d3-array": "1", + "d3-collection": "1", + "d3-color": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" } }, "d3-selection": { @@ -3025,12 +3662,12 @@ "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.0.3.tgz", "integrity": "sha1-kdyYa92zCXNjkyCoXbcs5KsaJ7s=", "requires": { - "d3-color": "1.4.0", - "d3-dispatch": "1.0.1", - "d3-ease": "1.0.6", - "d3-interpolate": "1.1.6", - "d3-selection": "1.0.2", - "d3-timer": "1.0.10" + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-timer": "1" } } } @@ -3045,7 +3682,7 @@ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.2.2.tgz", "integrity": "sha512-pweL2Ri2wqMY+wlW/wpkl8T3CUzKAha8S9nmiQlMABab8r5MJN0PD1V4YyRNVaKQfeh4Z0+VO70TLw6ESVOYzw==", "requires": { - "d3-time": "1.1.0" + "d3-time": "1" } }, "d3-timer": { @@ -3058,12 +3695,12 @@ "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", "requires": { - "d3-color": "1.4.0", - "d3-dispatch": "1.0.6", - "d3-ease": "1.0.6", - "d3-interpolate": "1.1.6", - "d3-selection": "1.4.1", - "d3-timer": "1.0.10" + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" } }, "d3-voronoi": { @@ -3076,11 +3713,11 @@ "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", "requires": { - "d3-dispatch": "1.0.6", - "d3-drag": "1.2.5", - "d3-interpolate": "1.1.6", - "d3-selection": "1.4.1", - "d3-transition": "1.3.2" + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" } }, "dagre": { @@ -3088,30 +3725,30 @@ "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.4.tgz", "integrity": "sha512-Dj0csFDrWYKdavwROb9FccHfTC4fJbyF/oJdL9LNZJ8WUvl968P6PAKEriGqfbdArVJEmmfA+UyumgWEwcHU6A==", "requires": { - "graphlib": "2.1.7", - "lodash": "4.17.15" + "graphlib": "^2.1.7", + "lodash": "^4.17.4" } }, "damerau-levenshtein": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz", - "integrity": "sha512-CBCRqFnpu715iPmw1KrdOrzRqbdFwQTwAWyyyYS42+iAgHCuXZ+/TdMgQkUENPomxEz9z1BEzuQU2Xw0kUuAgA==", + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/damerau-levenshtein/download/damerau-levenshtein-1.0.6.tgz?cache=0&sync_timestamp=1580133385754&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdamerau-levenshtein%2Fdownload%2Fdamerau-levenshtein-1.0.6.tgz", + "integrity": "sha1-FDwWQcs9hcYMMjKeJoma3qhwF5E=", "dev": true }, "dashdash": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "resolved": "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "optional": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -3119,28 +3756,28 @@ }, "decamelize": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/decamelize/download/decamelize-1.2.0.tgz?cache=0&sync_timestamp=1580010393599&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdecamelize%2Fdownload%2Fdecamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "decode-uri-component": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/decode-uri-component/download/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, "deep-equal": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "resolved": "https://registry.npm.taobao.org/deep-equal/download/deep-equal-1.1.1.tgz", + "integrity": "sha1-tcmMlCzv+vfLBR4k4UNKJaLmB2o=", "dev": true, "requires": { - "is-arguments": "1.0.4", - "is-date-object": "1.0.1", - "is-regex": "1.0.4", - "object-is": "1.0.1", - "object-keys": "1.1.1", - "regexp.prototype.flags": "1.2.0" + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" } }, "deep-is": { @@ -3151,12 +3788,12 @@ }, "default-gateway": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", - "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "resolved": "https://registry.npm.taobao.org/default-gateway/download/default-gateway-4.2.0.tgz?cache=0&sync_timestamp=1590419212936&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdefault-gateway%2Fdownload%2Fdefault-gateway-4.2.0.tgz", + "integrity": "sha1-FnEEx1AMIRX23WmwpTa7jtcgVSs=", "dev": true, "requires": { - "execa": "1.0.0", - "ip-regex": "2.1.0" + "execa": "^1.0.0", + "ip-regex": "^2.1.0" } }, "define-properties": { @@ -3165,139 +3802,148 @@ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { - "object-keys": "1.1.1" + "object-keys": "^1.0.12" } }, "define-property": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-2.0.2.tgz", + "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", "dev": true, "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" }, "dependencies": { "is-accessor-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } }, "del": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "resolved": "https://registry.npm.taobao.org/del/download/del-4.1.1.tgz", + "integrity": "sha1-no8RciLqRKMf86FWwEm5kFKp8LQ=", "dev": true, "requires": { - "@types/glob": "7.1.1", - "globby": "6.1.0", - "is-path-cwd": "2.2.0", - "is-path-in-cwd": "2.1.0", - "p-map": "2.1.0", - "pify": "4.0.1", - "rimraf": "2.7.1" + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" } }, "delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "dev": true, + "optional": true }, "depd": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, "des.js": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "resolved": "https://registry.npm.taobao.org/des.js/download/des.js-1.0.1.tgz", + "integrity": "sha1-U4IULhvcU/hdhtU+X0qn3rkeCEM=", "dev": true, "requires": { - "inherits": "2.0.4", - "minimalistic-assert": "1.0.1" + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, "destroy": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "resolved": "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "dev": true }, "detect-file": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/detect-file/download/detect-file-1.0.0.tgz", "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true }, "detect-node": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", - "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "resolved": "https://registry.npm.taobao.org/detect-node/download/detect-node-2.0.4.tgz", + "integrity": "sha1-AU7o+PZpxcWAI9pkuBecCDooxGw=", "dev": true }, "diffie-hellman": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "resolved": "https://registry.npm.taobao.org/diffie-hellman/download/diffie-hellman-5.0.3.tgz", + "integrity": "sha1-QOjumPVaIUlgcUaSHGPhrl89KHU=", "dev": true, "requires": { - "bn.js": "4.11.8", - "miller-rabin": "4.0.1", - "randombytes": "2.1.0" + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=", + "dev": true + } } }, "dns-equal": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/dns-equal/download/dns-equal-1.0.0.tgz", "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", "dev": true }, "dns-packet": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", - "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "resolved": "https://registry.npm.taobao.org/dns-packet/download/dns-packet-1.3.1.tgz", + "integrity": "sha1-EqpCaYEHW+UAuRDu3NC0fdfe2lo=", "dev": true, "requires": { - "ip": "1.1.5", - "safe-buffer": "5.1.2" + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" } }, "dns-txt": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/dns-txt/download/dns-txt-2.0.2.tgz", "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", "dev": true, "requires": { - "buffer-indexof": "1.1.1" + "buffer-indexof": "^1.0.0" } }, "doctrine": { @@ -3306,7 +3952,7 @@ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { - "esutils": "2.0.3" + "esutils": "^2.0.2" } }, "dom-to-image": { @@ -3316,36 +3962,36 @@ }, "domain-browser": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "resolved": "https://registry.npm.taobao.org/domain-browser/download/domain-browser-1.2.0.tgz", + "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=", "dev": true }, "duplexify": { "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "resolved": "https://registry.npm.taobao.org/duplexify/download/duplexify-3.7.1.tgz", + "integrity": "sha1-Kk31MX9sz9kfhtb9JdjYoQO4gwk=", "dev": true, "requires": { - "end-of-stream": "1.4.4", - "inherits": "2.0.4", - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" } }, "ecc-jsbn": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, "optional": true, "requires": { - "jsbn": "0.1.1", - "safer-buffer": "2.1.2" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, "ee-first": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, @@ -3356,18 +4002,26 @@ "dev": true }, "elliptic": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", - "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "version": "6.5.3", + "resolved": "https://registry.npm.taobao.org/elliptic/download/elliptic-6.5.3.tgz?cache=0&sync_timestamp=1592492805287&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felliptic%2Fdownload%2Felliptic-6.5.3.tgz", + "integrity": "sha1-y1nrLv2vc6C9eMzXAVpirW4Pk9Y=", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0", - "hash.js": "1.1.7", - "hmac-drbg": "1.0.1", - "inherits": "2.0.4", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=", + "dev": true + } } }, "emoji-regex": { @@ -3384,7 +4038,7 @@ }, "encodeurl": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, @@ -3393,48 +4047,48 @@ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", "requires": { - "iconv-lite": "0.4.24" + "iconv-lite": "~0.4.13" } }, "end-of-stream": { "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "resolved": "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.4.tgz", + "integrity": "sha1-WuZKX0UFe682JuwU2gyl5LJDHrA=", "dev": true, "requires": { - "once": "1.4.0" + "once": "^1.4.0" } }, "enhanced-resolve": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", - "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/enhanced-resolve/download/enhanced-resolve-4.2.0.tgz?cache=0&sync_timestamp=1592387355340&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenhanced-resolve%2Fdownload%2Fenhanced-resolve-4.2.0.tgz", + "integrity": "sha1-XUO9pKD9RHyw675xvvje/4gFrQ0=", "dev": true, "requires": { - "graceful-fs": "4.2.3", - "memory-fs": "0.5.0", - "tapable": "1.1.3" + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" }, "dependencies": { "memory-fs": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "resolved": "https://registry.npm.taobao.org/memory-fs/download/memory-fs-0.5.0.tgz?cache=0&sync_timestamp=1570537491040&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmemory-fs%2Fdownload%2Fmemory-fs-0.5.0.tgz", + "integrity": "sha1-MkwBKIuIZSlm0WHbd4OHIIRajjw=", "dev": true, "requires": { - "errno": "0.1.7", - "readable-stream": "2.3.6" + "errno": "^0.1.3", + "readable-stream": "^2.0.1" } } } }, "errno": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "resolved": "https://registry.npm.taobao.org/errno/download/errno-0.1.7.tgz", + "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", "dev": true, "requires": { - "prr": "1.0.1" + "prr": "~1.0.1" } }, "error-ex": { @@ -3443,7 +4097,7 @@ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { - "is-arrayish": "0.2.1" + "is-arrayish": "^0.2.1" } }, "es-abstract": { @@ -3452,16 +4106,16 @@ "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", "dev": true, "requires": { - "es-to-primitive": "1.2.1", - "function-bind": "1.1.1", - "has": "1.0.3", - "has-symbols": "1.0.1", - "is-callable": "1.1.4", - "is-regex": "1.0.4", - "object-inspect": "1.7.0", - "object-keys": "1.1.1", - "string.prototype.trimleft": "2.1.0", - "string.prototype.trimright": "2.1.0" + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" } }, "es-to-primitive": { @@ -3470,14 +4124,20 @@ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "requires": { - "is-callable": "1.1.4", - "is-date-object": "1.0.1", - "is-symbol": "1.0.3" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" } }, + "escalade": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/escalade/download/escalade-3.0.1.tgz", + "integrity": "sha1-UlaKd0Q/aSfNCrnHMSkTdTPJZe0=", + "dev": true + }, "escape-html": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "resolved": "https://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", "dev": true }, @@ -3493,42 +4153,42 @@ "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", "dev": true, "requires": { - "@babel/code-frame": "7.5.5", - "ajv": "6.10.2", - "chalk": "2.4.2", - "cross-spawn": "6.0.5", - "debug": "4.1.1", - "doctrine": "3.0.0", - "eslint-scope": "4.0.3", - "eslint-utils": "1.4.3", - "eslint-visitor-keys": "1.1.0", - "espree": "5.0.1", - "esquery": "1.0.1", - "esutils": "2.0.3", - "file-entry-cache": "5.0.1", - "functional-red-black-tree": "1.0.1", - "glob": "7.1.6", - "globals": "11.12.0", - "ignore": "4.0.6", - "import-fresh": "3.2.1", - "imurmurhash": "0.1.4", - "inquirer": "6.5.2", - "js-yaml": "3.13.1", - "json-stable-stringify-without-jsonify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.15", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.3", - "path-is-inside": "1.0.2", - "progress": "2.0.3", - "regexpp": "2.0.1", - "semver": "5.7.1", - "strip-ansi": "4.0.0", - "strip-json-comments": "2.0.1", - "table": "5.4.6", - "text-table": "0.2.0" + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" }, "dependencies": { "debug": { @@ -3537,7 +4197,7 @@ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.1" } }, "ms": { @@ -3554,9 +4214,9 @@ "integrity": "sha512-xCu//8a/aWqagKljt+1/qAM62BYZeNq04HmdevG5yUGWpja0I/xhqd6GdLRch5oetEGFiJAnvtGuTEAese53Qg==", "dev": true, "requires": { - "eslint-config-airbnb-base": "13.2.0", - "object.assign": "4.1.0", - "object.entries": "1.1.0" + "eslint-config-airbnb-base": "^13.2.0", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0" } }, "eslint-config-airbnb-base": { @@ -3565,157 +4225,245 @@ "integrity": "sha512-1mg/7eoB4AUeB0X1c/ho4vb2gYkNH8Trr/EgCT/aGmKhhG+F6vF5s8+iRBlWAzFIAphxIdp3YfEKgEl0f9Xg+w==", "dev": true, "requires": { - "confusing-browser-globals": "1.0.9", - "object.assign": "4.1.0", - "object.entries": "1.1.0" + "confusing-browser-globals": "^1.0.5", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0" } }, "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "version": "0.3.4", + "resolved": "https://registry.npm.taobao.org/eslint-import-resolver-node/download/eslint-import-resolver-node-0.3.4.tgz?cache=0&sync_timestamp=1592327223893&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-import-resolver-node%2Fdownload%2Feslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha1-hf+oGULCUBLYIxCW3fZ5wDBCxxc=", "dev": true, "requires": { - "debug": "2.6.9", - "resolve": "1.12.0" + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.17.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.17.0.tgz", + "integrity": "sha1-sllBtUloIxzC0bt2p5y38sC/hEQ=", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } } }, "eslint-module-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", - "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "version": "2.6.0", + "resolved": "https://registry.npm.taobao.org/eslint-module-utils/download/eslint-module-utils-2.6.0.tgz", + "integrity": "sha1-V569CU9Wr3eX0ZyYZsnJSGYpv6Y=", "dev": true, "requires": { - "debug": "2.6.9", - "pkg-dir": "2.0.0" + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" }, "dependencies": { "find-up": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } }, "locate-path": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" } }, "p-limit": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-1.3.0.tgz", + "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", "dev": true, "requires": { - "p-try": "1.0.0" + "p-try": "^1.0.0" } }, "p-locate": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "1.3.0" + "p-limit": "^1.1.0" } }, "p-try": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, "pkg-dir": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-2.0.0.tgz", "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "find-up": "2.1.0" + "find-up": "^2.1.0" } } } }, "eslint-plugin-import": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", - "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "version": "2.22.0", + "resolved": "https://registry.npm.taobao.org/eslint-plugin-import/download/eslint-plugin-import-2.22.0.tgz?cache=0&sync_timestamp=1593237431320&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-import%2Fdownload%2Feslint-plugin-import-2.22.0.tgz", + "integrity": "sha1-kvdzb+H94+Led2I8g43Zkv9f+34=", "dev": true, "requires": { - "array-includes": "3.0.3", - "contains-path": "0.1.0", - "debug": "2.6.9", + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "0.3.2", - "eslint-module-utils": "2.4.1", - "has": "1.0.3", - "minimatch": "3.0.4", - "object.values": "1.1.0", - "read-pkg-up": "2.0.0", - "resolve": "1.12.0" + "eslint-import-resolver-node": "^0.3.3", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" }, "dependencies": { "doctrine": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "resolved": "https://registry.npm.taobao.org/doctrine/download/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "esutils": "2.0.3", - "isarray": "1.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.17.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.17.0.tgz", + "integrity": "sha1-sllBtUloIxzC0bt2p5y38sC/hEQ=", + "dev": true, + "requires": { + "path-parse": "^1.0.6" } } } }, "eslint-plugin-jsx-a11y": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.3.tgz", - "integrity": "sha512-CawzfGt9w83tyuVekn0GDPU9ytYtxyxyFZ3aSWROmnRRFQFT2BiPJd7jvRdzNDi6oLWaS2asMeYSNMjWTV4eNg==", - "dev": true, - "requires": { - "@babel/runtime": "7.7.2", - "aria-query": "3.0.0", - "array-includes": "3.0.3", - "ast-types-flow": "0.0.7", - "axobject-query": "2.0.2", - "damerau-levenshtein": "1.0.5", - "emoji-regex": "7.0.3", - "has": "1.0.3", - "jsx-ast-utils": "2.2.3" + "version": "6.3.1", + "resolved": "https://registry.npm.taobao.org/eslint-plugin-jsx-a11y/download/eslint-plugin-jsx-a11y-6.3.1.tgz?cache=0&sync_timestamp=1592629539885&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-jsx-a11y%2Fdownload%2Feslint-plugin-jsx-a11y-6.3.1.tgz", + "integrity": "sha1-me9+l/VnzGpbjdWrlalKZwWKJmA=", + "dev": true, + "requires": { + "@babel/runtime": "^7.10.2", + "aria-query": "^4.2.2", + "array-includes": "^3.1.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^3.5.4", + "axobject-query": "^2.1.2", + "damerau-levenshtein": "^1.0.6", + "emoji-regex": "^9.0.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1", + "language-tags": "^1.0.5" + }, + "dependencies": { + "emoji-regex": { + "version": "9.0.0", + "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-9.0.0.tgz", + "integrity": "sha1-SKIwnMih0unSO8amfDm2MDLnbqQ=", + "dev": true + } } }, "eslint-plugin-react": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.16.0.tgz", - "integrity": "sha512-GacBAATewhhptbK3/vTP09CbFrgUJmBSaaRcWdbQLFvUZy9yVcQxigBNHGPU/KE2AyHpzj3AWXpxoMTsIDiHug==", - "dev": true, - "requires": { - "array-includes": "3.0.3", - "doctrine": "2.1.0", - "has": "1.0.3", - "jsx-ast-utils": "2.2.3", - "object.entries": "1.1.0", - "object.fromentries": "2.0.1", - "object.values": "1.1.0", - "prop-types": "15.7.2", - "resolve": "1.12.0" + "version": "7.20.3", + "resolved": "https://registry.npm.taobao.org/eslint-plugin-react/download/eslint-plugin-react-7.20.3.tgz?cache=0&sync_timestamp=1593549287847&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-react%2Fdownload%2Feslint-plugin-react-7.20.3.tgz", + "integrity": "sha1-BZBSXn64OJDOcfc8LPg2KErYwvE=", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1", + "object.entries": "^1.1.2", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.17.0", + "string.prototype.matchall": "^4.0.2" }, "dependencies": { "doctrine": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "resolved": "https://registry.npm.taobao.org/doctrine/download/doctrine-2.1.0.tgz", + "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "object.entries": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/object.entries/download/object.entries-1.1.2.tgz", + "integrity": "sha1-vHPwCstra7FsIDQ0sQ+afnl9Ot0=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "has": "^1.0.3" + } + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.17.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.17.0.tgz", + "integrity": "sha1-sllBtUloIxzC0bt2p5y38sC/hEQ=", "dev": true, "requires": { - "esutils": "2.0.3" + "path-parse": "^1.0.6" } } } @@ -3726,8 +4474,8 @@ "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, "requires": { - "esrecurse": "4.2.1", - "estraverse": "4.3.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, "eslint-utils": { @@ -3736,7 +4484,7 @@ "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", "dev": true, "requires": { - "eslint-visitor-keys": "1.1.0" + "eslint-visitor-keys": "^1.1.0" } }, "eslint-visitor-keys": { @@ -3751,9 +4499,9 @@ "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", "dev": true, "requires": { - "acorn": "6.3.0", - "acorn-jsx": "5.1.0", - "eslint-visitor-keys": "1.1.0" + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" } }, "esprima": { @@ -3768,7 +4516,7 @@ "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { - "estraverse": "4.3.0" + "estraverse": "^4.0.0" } }, "esrecurse": { @@ -3777,7 +4525,7 @@ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "4.3.0" + "estraverse": "^4.1.0" } }, "estraverse": { @@ -3794,176 +4542,176 @@ }, "etag": { "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "resolved": "https://registry.npm.taobao.org/etag/download/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, "eventemitter3": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", - "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", + "version": "4.0.4", + "resolved": "https://registry.npm.taobao.org/eventemitter3/download/eventemitter3-4.0.4.tgz?cache=0&sync_timestamp=1589283150629&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feventemitter3%2Fdownload%2Feventemitter3-4.0.4.tgz", + "integrity": "sha1-tUY6zmNaCD0Bi9x8kXtMXxCoU4Q=", "dev": true }, "events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/events/download/events-3.1.0.tgz?cache=0&sync_timestamp=1578498298945&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fevents%2Fdownload%2Fevents-3.1.0.tgz", + "integrity": "sha1-hCea8bNMt1qoi/X/KR9tC9mzGlk=", "dev": true }, "eventsource": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", - "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "resolved": "https://registry.npm.taobao.org/eventsource/download/eventsource-1.0.7.tgz", + "integrity": "sha1-j7xyyT/NNAiAkLwKTmT0tc7m2NA=", "dev": true, "requires": { - "original": "1.0.2" + "original": "^1.0.0" } }, "evp_bytestokey": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "resolved": "https://registry.npm.taobao.org/evp_bytestokey/download/evp_bytestokey-1.0.3.tgz", + "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", "dev": true, "requires": { - "md5.js": "1.3.5", - "safe-buffer": "5.1.2" + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, "execa": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "resolved": "https://registry.npm.taobao.org/execa/download/execa-1.0.0.tgz", + "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=", "dev": true, "requires": { - "cross-spawn": "6.0.5", - "get-stream": "4.1.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" } }, "expand-brackets": { "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "resolved": "https://registry.npm.taobao.org/expand-brackets/download/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "define-property": { "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } }, "expand-tilde": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/expand-tilde/download/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "1.0.3" + "homedir-polyfill": "^1.0.1" } }, "express": { "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "resolved": "https://registry.npm.taobao.org/express/download/express-4.17.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fexpress%2Fdownload%2Fexpress-4.17.1.tgz", + "integrity": "sha1-RJH8OGBc9R+GKdOcK10Cb5ikwTQ=", "dev": true, "requires": { - "accepts": "1.3.7", + "accepts": "~1.3.7", "array-flatten": "1.1.1", "body-parser": "1.19.0", "content-disposition": "0.5.3", - "content-type": "1.0.4", + "content-type": "~1.0.4", "cookie": "0.4.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.2", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", - "finalhandler": "1.1.2", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.3", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.5", + "proxy-addr": "~2.0.5", "qs": "6.7.0", - "range-parser": "1.2.1", + "range-parser": "~1.2.1", "safe-buffer": "5.1.2", "send": "0.17.1", "serve-static": "1.14.1", "setprototypeof": "1.1.1", - "statuses": "1.5.0", - "type-is": "1.6.18", + "statuses": "~1.5.0", + "type-is": "~1.6.18", "utils-merge": "1.0.1", - "vary": "1.1.2" + "vary": "~1.1.2" }, "dependencies": { "array-flatten": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/array-flatten/download/array-flatten-1.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray-flatten%2Fdownload%2Farray-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, "qs": { "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz", + "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=", "dev": true } } }, "extend": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "resolved": "https://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz", + "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=", "dev": true, "optional": true }, "extend-shallow": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -3974,81 +4722,82 @@ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, "requires": { - "chardet": "0.7.0", - "iconv-lite": "0.4.24", - "tmp": "0.0.33" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" } }, "extglob": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "resolved": "https://registry.npm.taobao.org/extglob/download/extglob-2.0.4.tgz", + "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "define-property": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "is-accessor-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } }, "extsprintf": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "dev": true, + "optional": true }, "fast-deep-equal": { "version": "2.0.1", @@ -4070,11 +4819,11 @@ }, "faye-websocket": { "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "resolved": "https://registry.npm.taobao.org/faye-websocket/download/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { - "websocket-driver": "0.7.3" + "websocket-driver": ">=0.5.1" } }, "fbjs": { @@ -4082,13 +4831,13 @@ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", "requires": { - "core-js": "1.2.7", - "isomorphic-fetch": "2.2.1", - "loose-envify": "1.4.0", - "object-assign": "4.1.1", - "promise": "7.3.1", - "setimmediate": "1.0.5", - "ua-parser-js": "0.7.20" + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" }, "dependencies": { "core-js": { @@ -4104,9 +4853,9 @@ "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" }, "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "version": "3.5.2", + "resolved": "https://registry.npm.taobao.org/figgy-pudding/download/figgy-pudding-3.5.2.tgz", + "integrity": "sha1-tO7oFIq7Adzx0aw0Nn1Z4S+mHW4=", "dev": true }, "figures": { @@ -4115,7 +4864,7 @@ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5" + "escape-string-regexp": "^1.0.5" } }, "file-entry-cache": { @@ -4124,45 +4873,52 @@ "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "requires": { - "flat-cache": "2.0.1" + "flat-cache": "^2.0.1" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/file-uri-to-path/download/file-uri-to-path-1.0.0.tgz", + "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=", + "dev": true, + "optional": true + }, "fill-range": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" }, "dependencies": { "extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } }, "finalhandler": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "resolved": "https://registry.npm.taobao.org/finalhandler/download/finalhandler-1.1.2.tgz", + "integrity": "sha1-t+fQAP/RGTjQ/bBTUG9uur6fWH0=", "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.3", - "statuses": "1.5.0", - "unpipe": "1.0.0" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" } }, "find-babel-config": { @@ -4171,8 +4927,8 @@ "integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==", "dev": true, "requires": { - "json5": "0.5.1", - "path-exists": "3.0.0" + "json5": "^0.5.1", + "path-exists": "^3.0.0" }, "dependencies": { "json5": { @@ -4185,34 +4941,34 @@ }, "find-cache-dir": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-2.1.0.tgz?cache=0&sync_timestamp=1583734591888&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-cache-dir%2Fdownload%2Ffind-cache-dir-2.1.0.tgz", + "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=", "dev": true, "requires": { - "commondir": "1.0.1", - "make-dir": "2.1.0", - "pkg-dir": "3.0.0" + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" } }, "find-up": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", "dev": true, "requires": { - "locate-path": "3.0.0" + "locate-path": "^3.0.0" } }, "findup-sync": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "resolved": "https://registry.npm.taobao.org/findup-sync/download/findup-sync-3.0.0.tgz", + "integrity": "sha1-F7EI+e5RLft6XH88iyfqnhqcCNE=", "dev": true, "requires": { - "detect-file": "1.0.0", - "is-glob": "4.0.1", - "micromatch": "3.1.10", - "resolve-dir": "1.0.1" + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" } }, "flat-cache": { @@ -4221,7 +4977,7 @@ "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", "dev": true, "requires": { - "flatted": "2.0.1", + "flatted": "^2.0.0", "rimraf": "2.6.3", "write": "1.0.3" }, @@ -4232,7 +4988,7 @@ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "glob": "7.1.6" + "glob": "^7.1.3" } } } @@ -4251,112 +5007,92 @@ }, "flush-write-stream": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "resolved": "https://registry.npm.taobao.org/flush-write-stream/download/flush-write-stream-1.1.1.tgz", + "integrity": "sha1-jdfYc6G6vCB9lOrQwuDkQnbr8ug=", "dev": true, "requires": { - "inherits": "2.0.4", - "readable-stream": "2.3.6" + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" } }, "follow-redirects": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.9.0.tgz", - "integrity": "sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==", - "dev": true, - "requires": { - "debug": "3.2.6" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } + "version": "1.12.1", + "resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.12.1.tgz?cache=0&sync_timestamp=1592518281721&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffollow-redirects%2Fdownload%2Ffollow-redirects-1.12.1.tgz", + "integrity": "sha1-3lSmIFMRuT1gOY68Ac9wFWgjErY=", + "dev": true }, "for-in": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, "forever-agent": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "resolved": "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true, "optional": true }, "form-data": { "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "resolved": "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz?cache=0&sync_timestamp=1573027118125&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fform-data%2Fdownload%2Fform-data-2.3.3.tgz", + "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=", "dev": true, "optional": true, "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.8", - "mime-types": "2.1.25" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" } }, "forwarded": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/forwarded/download/forwarded-0.1.2.tgz", "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", "dev": true }, "fragment-cache": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "resolved": "https://registry.npm.taobao.org/fragment-cache/download/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "0.2.2" + "map-cache": "^0.2.2" } }, "fresh": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "resolved": "https://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, "from2": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/from2/download/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", "dev": true, "requires": { - "inherits": "2.0.4", - "readable-stream": "2.3.6" + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" } }, "fs-readdir-recursive": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "resolved": "https://registry.npm.taobao.org/fs-readdir-recursive/download/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha1-4y/AMKLM7kSmtTcTCNpUvgs5fSc=", "dev": true }, "fs-write-stream-atomic": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "resolved": "https://registry.npm.taobao.org/fs-write-stream-atomic/download/fs-write-stream-atomic-1.0.10.tgz", "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", "dev": true, "requires": { - "graceful-fs": "4.2.3", - "iferr": "0.1.5", - "imurmurhash": "0.1.4", - "readable-stream": "2.3.6" + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" } }, "fs.realpath": { @@ -4366,532 +5102,14 @@ "dev": true }, "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "version": "1.2.13", + "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.13.tgz?cache=0&sync_timestamp=1588787369955&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffsevents%2Fdownload%2Ffsevents-1.2.13.tgz", + "integrity": "sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=", "dev": true, "optional": true, "requires": { - "nan": "2.14.0", - "node-pre-gyp": "0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "2.3.5" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.3" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "5.1.2", - "yallist": "3.0.3" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "2.3.5" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "4.1.1", - "iconv-lite": "0.4.24", - "sax": "1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "1.0.3", - "mkdirp": "0.5.1", - "needle": "2.3.0", - "nopt": "4.0.1", - "npm-packlist": "1.4.1", - "npmlog": "4.1.2", - "rc": "1.2.8", - "rimraf": "2.6.3", - "semver": "5.7.0", - "tar": "4.4.8" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.6" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.5", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "0.6.0", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "1.1.1", - "fs-minipass": "1.2.5", - "minipass": "2.3.5", - "minizlib": "1.2.1", - "mkdirp": "0.5.1", - "safe-buffer": "5.1.2", - "yallist": "3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true - } + "bindings": "^1.5.0", + "nan": "^2.12.1" } }, "function-bind": { @@ -4906,45 +5124,41 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npm.taobao.org/gensync/download/gensync-1.0.0-beta.1.tgz", + "integrity": "sha1-WPQ2H/mH5f9uHnohCCeqNx6qwmk=", + "dev": true + }, "get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "resolved": "https://registry.npm.taobao.org/get-caller-file/download/get-caller-file-2.0.5.tgz", + "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34=", "dev": true }, "get-stream": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "resolved": "https://registry.npm.taobao.org/get-stream/download/get-stream-4.1.0.tgz", + "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", "dev": true, "requires": { - "pump": "3.0.0" + "pump": "^3.0.0" } }, "get-value": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "resolved": "https://registry.npm.taobao.org/get-value/download/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, "getpass": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "resolved": "https://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "optional": true, "requires": { - "assert-plus": "1.0.0" - } - }, - "gg-editor-core": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/gg-editor-core/-/gg-editor-core-1.3.4.tgz", - "integrity": "sha512-h2ALYh/os7XphrhR967HQoc48tX8+OoG+bCoDEphwLDwqOieoIAEngqjy7DBv1874fxhw7ry1F0bKHdzCvrVIQ==", - "requires": { - "@antv/g6": "2.2.6", - "ant-design-palettes": "1.1.3", - "wolfy87-eventemitter": "5.2.8" + "assert-plus": "^1.0.0" } }, "glob": { @@ -4953,68 +5167,68 @@ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.4", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "glob-parent": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" }, "dependencies": { "is-glob": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.0" } } } }, "global-modules": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "resolved": "https://registry.npm.taobao.org/global-modules/download/global-modules-2.0.0.tgz", + "integrity": "sha1-mXYFrSNF8n9RU5vqJldEISFcd4A=", "dev": true, "requires": { - "global-prefix": "3.0.0" + "global-prefix": "^3.0.0" }, "dependencies": { "global-prefix": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "resolved": "https://registry.npm.taobao.org/global-prefix/download/global-prefix-3.0.0.tgz", + "integrity": "sha1-/IX3MGTfafUEIfR/iD/luRO6m5c=", "dev": true, "requires": { - "ini": "1.3.5", - "kind-of": "6.0.2", - "which": "1.3.1" + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" } } } }, "global-prefix": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/global-prefix/download/global-prefix-1.0.2.tgz", "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "homedir-polyfill": "1.0.3", - "ini": "1.3.5", - "is-windows": "1.0.2", - "which": "1.3.1" + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" } }, "globals": { @@ -5025,29 +5239,29 @@ }, "globby": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/globby/download/globby-6.1.0.tgz?cache=0&sync_timestamp=1591083812416&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglobby%2Fdownload%2Fglobby-6.1.0.tgz", "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", "dev": true, "requires": { - "array-union": "1.0.2", - "glob": "7.1.6", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "version": "4.2.4", + "resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz?cache=0&sync_timestamp=1588086876757&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgraceful-fs%2Fdownload%2Fgraceful-fs-4.2.4.tgz", + "integrity": "sha1-Ila94U02MpWMRl68ltxGfKB6Kfs=", "dev": true }, "graphlib": { @@ -5055,31 +5269,31 @@ "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.7.tgz", "integrity": "sha512-TyI9jIy2J4j0qgPmOOrHTCtpPqJGN/aurBwc6ZT+bRii+di1I+Wv3obRhVrmBEXet+qkMaEX67dXrwsd3QQM6w==", "requires": { - "lodash": "4.17.15" + "lodash": "^4.17.5" } }, "handle-thing": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", - "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/handle-thing/download/handle-thing-2.0.1.tgz", + "integrity": "sha1-hX95zjWVgMNA1DCBzGSJcNC7I04=", "dev": true }, "har-schema": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz", "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", "dev": true, "optional": true }, "har-validator": { "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "resolved": "https://registry.npm.taobao.org/har-validator/download/har-validator-5.1.3.tgz", + "integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=", "dev": true, "optional": true, "requires": { - "ajv": "6.10.2", - "har-schema": "2.0.0" + "ajv": "^6.5.5", + "har-schema": "^2.0.0" } }, "has": { @@ -5088,7 +5302,7 @@ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "function-bind": "1.1.1" + "function-bind": "^1.1.1" } }, "has-flag": { @@ -5105,171 +5319,185 @@ }, "has-value": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/has-value/download/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" } }, "has-values": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/has-values/download/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { "kind-of": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } }, "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/hash-base/download/hash-base-3.1.0.tgz", + "integrity": "sha1-VcOB2eBuHSmXqIO0o/3f5/DTrzM=", "dev": true, "requires": { - "inherits": "2.0.4", - "safe-buffer": "5.1.2" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz", + "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz", + "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=", + "dev": true + } } }, "hash.js": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "resolved": "https://registry.npm.taobao.org/hash.js/download/hash.js-1.1.7.tgz", + "integrity": "sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I=", "dev": true, "requires": { - "inherits": "2.0.4", - "minimalistic-assert": "1.0.1" + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" } }, "hmac-drbg": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/hmac-drbg/download/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { - "hash.js": "1.1.7", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" } }, "homedir-polyfill": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "resolved": "https://registry.npm.taobao.org/homedir-polyfill/download/homedir-polyfill-1.0.3.tgz", + "integrity": "sha1-dDKYzvTlrz4ZQWH7rcwhUdOgWOg=", "dev": true, "requires": { - "parse-passwd": "1.0.0" + "parse-passwd": "^1.0.0" } }, "hosted-git-info": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", - "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", + "version": "2.8.8", + "resolved": "https://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.8.8.tgz?cache=0&sync_timestamp=1583017392137&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhosted-git-info%2Fdownload%2Fhosted-git-info-2.8.8.tgz", + "integrity": "sha1-dTm9S8Hg4KiVgVouAmJCCxKFhIg=", "dev": true }, "hpack.js": { "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "resolved": "https://registry.npm.taobao.org/hpack.js/download/hpack.js-2.1.6.tgz", "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", "dev": true, "requires": { - "inherits": "2.0.4", - "obuf": "1.1.2", - "readable-stream": "2.3.6", - "wbuf": "1.7.3" + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" } }, "html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/html-entities/download/html-entities-1.3.1.tgz", + "integrity": "sha1-+5oaS1sUxdq6gtPjTGrk/nAaDkQ=", "dev": true }, "http-deceiver": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "resolved": "https://registry.npm.taobao.org/http-deceiver/download/http-deceiver-1.2.7.tgz", "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", "dev": true }, "http-errors": { "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.2.tgz?cache=0&sync_timestamp=1593407647372&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.7.2.tgz", + "integrity": "sha1-T1ApzxMjnzEDblsuVSkrz7zIXI8=", "dev": true, "requires": { - "depd": "1.1.2", + "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.1", - "statuses": "1.5.0", + "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" }, "dependencies": { "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true } } }, - "http-parser-js": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", - "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", - "dev": true - }, "http-proxy": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", - "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", + "version": "1.18.1", + "resolved": "https://registry.npm.taobao.org/http-proxy/download/http-proxy-1.18.1.tgz", + "integrity": "sha1-QBVB8FNIhLv5UmAzTnL4juOXZUk=", "dev": true, "requires": { - "eventemitter3": "4.0.0", - "follow-redirects": "1.9.0", - "requires-port": "1.0.0" + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" } }, "http-proxy-middleware": { "version": "0.19.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", - "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "resolved": "https://registry.npm.taobao.org/http-proxy-middleware/download/http-proxy-middleware-0.19.1.tgz?cache=0&sync_timestamp=1589915518285&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-proxy-middleware%2Fdownload%2Fhttp-proxy-middleware-0.19.1.tgz", + "integrity": "sha1-GDx9xKoUeRUDBkmMIQza+WCApDo=", "dev": true, "requires": { - "http-proxy": "1.18.0", - "is-glob": "4.0.1", - "lodash": "4.17.15", - "micromatch": "3.1.10" + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" } }, "http-signature": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "optional": true, "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.16.1" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "https-browserify": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/https-browserify/download/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, @@ -5278,7 +5506,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": ">= 2.1.2 < 3" } }, "icss-replace-symbols": { @@ -5293,18 +5521,18 @@ "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.14" } }, "ieee754": { "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "resolved": "https://registry.npm.taobao.org/ieee754/download/ieee754-1.1.13.tgz", + "integrity": "sha1-7BaFWOlaoYH9h9N/VcMrvLZwi4Q=", "dev": true }, "iferr": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "resolved": "https://registry.npm.taobao.org/iferr/download/iferr-0.1.5.tgz", "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, @@ -5316,7 +5544,7 @@ }, "image-size": { "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "resolved": "https://registry.npm.taobao.org/image-size/download/image-size-0.5.5.tgz", "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", "dev": true, "optional": true @@ -5327,7 +5555,7 @@ "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", "dev": true, "requires": { - "import-from": "2.1.0" + "import-from": "^2.1.0" } }, "import-fresh": { @@ -5336,8 +5564,8 @@ "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", "dev": true, "requires": { - "parent-module": "1.0.1", - "resolve-from": "4.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, "import-from": { @@ -5346,7 +5574,7 @@ "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", "dev": true, "requires": { - "resolve-from": "3.0.0" + "resolve-from": "^3.0.0" }, "dependencies": { "resolve-from": { @@ -5359,12 +5587,12 @@ }, "import-local": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "resolved": "https://registry.npm.taobao.org/import-local/download/import-local-2.0.0.tgz", + "integrity": "sha1-VQcL44pZk88Y72236WH1vuXFoJ0=", "dev": true, "requires": { - "pkg-dir": "3.0.0", - "resolve-cwd": "2.0.0" + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" } }, "imurmurhash": { @@ -5381,8 +5609,8 @@ }, "infer-owner": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "resolved": "https://registry.npm.taobao.org/infer-owner/download/infer-owner-1.0.4.tgz", + "integrity": "sha1-xM78qo5RBRwqQLos6KPScpWvlGc=", "dev": true }, "inflight": { @@ -5391,8 +5619,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -5403,8 +5631,8 @@ }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "resolved": "https://registry.npm.taobao.org/ini/download/ini-1.3.5.tgz", + "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", "dev": true }, "inquirer": { @@ -5413,19 +5641,19 @@ "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", "dev": true, "requires": { - "ansi-escapes": "3.2.0", - "chalk": "2.4.2", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "3.1.0", - "figures": "2.0.0", - "lodash": "4.17.15", + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rxjs": "6.5.3", - "string-width": "2.1.1", - "strip-ansi": "5.2.0", - "through": "2.3.8" + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" }, "dependencies": { "ansi-regex": { @@ -5440,90 +5668,131 @@ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "4.1.0" + "ansi-regex": "^4.1.0" } } } }, "internal-ip": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", - "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "resolved": "https://registry.npm.taobao.org/internal-ip/download/internal-ip-4.3.0.tgz", + "integrity": "sha1-hFRSuq2dLKO2nGNaE3rLmg2tCQc=", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + } + }, + "internal-slot": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/internal-slot/download/internal-slot-1.0.2.tgz", + "integrity": "sha1-nC6fs82OXkJWxvRf4xAGf8+jeKM=", "dev": true, "requires": { - "default-gateway": "4.2.0", - "ipaddr.js": "1.9.0" + "es-abstract": "^1.17.0-next.1", + "has": "^1.0.3", + "side-channel": "^1.0.2" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } } }, "interpret": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/interpret/download/interpret-1.4.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finterpret%2Fdownload%2Finterpret-1.4.0.tgz", + "integrity": "sha1-Zlq4vE2iendKQFhOgS4+D6RbGh4=", "dev": true }, "invariant": { "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "resolved": "https://registry.npm.taobao.org/invariant/download/invariant-2.2.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finvariant%2Fdownload%2Finvariant-2.2.4.tgz", + "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", "dev": true, "requires": { - "loose-envify": "1.4.0" + "loose-envify": "^1.0.0" } }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, "ip": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "resolved": "https://registry.npm.taobao.org/ip/download/ip-1.1.5.tgz", "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, "ip-regex": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/ip-regex/download/ip-regex-2.1.0.tgz", "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", "dev": true }, "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "version": "1.9.1", + "resolved": "https://registry.npm.taobao.org/ipaddr.js/download/ipaddr.js-1.9.1.tgz", + "integrity": "sha1-v/OFQ+64mEglB5/zoqjmy9RngbM=", "dev": true }, "is-absolute-url": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "resolved": "https://registry.npm.taobao.org/is-absolute-url/download/is-absolute-url-3.0.3.tgz?cache=0&sync_timestamp=1569736493122&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-absolute-url%2Fdownload%2Fis-absolute-url-3.0.3.tgz", + "integrity": "sha1-lsaiK2ojkpsR6gr7GDbDatSl1pg=", "dev": true }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } }, "is-arguments": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "resolved": "https://registry.npm.taobao.org/is-arguments/download/is-arguments-1.0.4.tgz", + "integrity": "sha1-P6+WbHy6D/Q3+zH2JQCC/PBEjPM=", "dev": true }, "is-arrayish": { @@ -5534,17 +5803,17 @@ }, "is-binary-path": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "1.13.1" + "binary-extensions": "^1.0.0" } }, "is-buffer": { "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", "dev": true }, "is-callable": { @@ -5555,20 +5824,20 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -5581,19 +5850,19 @@ }, "is-descriptor": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "dependencies": { "kind-of": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } @@ -5606,13 +5875,13 @@ }, "is-extendable": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz", "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "dev": true }, "is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, @@ -5624,64 +5893,64 @@ }, "is-glob": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz", + "integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.1" } }, "is-number": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-number/download/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } }, "is-path-cwd": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "resolved": "https://registry.npm.taobao.org/is-path-cwd/download/is-path-cwd-2.2.0.tgz?cache=0&sync_timestamp=1562347283002&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-path-cwd%2Fdownload%2Fis-path-cwd-2.2.0.tgz", + "integrity": "sha1-Z9Q7gmZKe1GR/ZEZEn6zAASKn9s=", "dev": true }, "is-path-in-cwd": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "resolved": "https://registry.npm.taobao.org/is-path-in-cwd/download/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha1-v+Lcomxp85cmWkAJljYCk1oFOss=", "dev": true, "requires": { - "is-path-inside": "2.1.0" + "is-path-inside": "^2.1.0" } }, "is-path-inside": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "resolved": "https://registry.npm.taobao.org/is-path-inside/download/is-path-inside-2.1.0.tgz", + "integrity": "sha1-fJgQWH1lmkDSe8201WFuqwWUlLI=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "path-is-inside": "^1.0.2" } }, "is-plain-object": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "resolved": "https://registry.npm.taobao.org/is-plain-object/download/is-plain-object-2.0.4.tgz?cache=0&sync_timestamp=1593243689869&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-plain-object%2Fdownload%2Fis-plain-object-2.0.4.tgz", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" } }, "is-promise": { @@ -5696,7 +5965,7 @@ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "has": "1.0.3" + "has": "^1.0.1" } }, "is-stream": { @@ -5704,37 +5973,43 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/is-string/download/is-string-1.0.5.tgz", + "integrity": "sha1-QEk+0ZjvP/R3uMf5L2ROyCpc06Y=", + "dev": true + }, "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "dev": true, "requires": { - "has-symbols": "1.0.1" + "has-symbols": "^1.0.1" } }, "is-typedarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true, "optional": true }, "is-windows": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "resolved": "https://registry.npm.taobao.org/is-windows/download/is-windows-1.0.2.tgz", + "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", "dev": true }, "is-wsl": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-wsl/download/is-wsl-1.1.0.tgz?cache=0&sync_timestamp=1588494180082&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-wsl%2Fdownload%2Fis-wsl-1.1.0.tgz", "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", "dev": true }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, @@ -5746,7 +6021,7 @@ }, "isobject": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/isobject/download/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, @@ -5755,23 +6030,17 @@ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", "requires": { - "node-fetch": "1.7.3", - "whatwg-fetch": "3.0.0" + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" } }, "isstream": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true, "optional": true }, - "js-levenshtein": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", - "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", - "dev": true - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5783,20 +6052,21 @@ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { - "argparse": "1.0.10", - "esprima": "4.0.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, "jsbn": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true + "dev": true, + "optional": true }, "jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "resolved": "https://registry.npm.taobao.org/jsesc/download/jsesc-2.5.2.tgz", + "integrity": "sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q=", "dev": true }, "json-parse-better-errors": { @@ -5807,7 +6077,7 @@ }, "json-schema": { "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "resolved": "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz", "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true, "optional": true @@ -5826,29 +6096,37 @@ }, "json-stringify-safe": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true, "optional": true }, "json3": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", - "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "resolved": "https://registry.npm.taobao.org/json3/download/json3-3.3.3.tgz", + "integrity": "sha1-f8EON1/FrkLEcFpcwKpvYr4wW4E=", "dev": true }, "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "version": "2.1.3", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-2.1.3.tgz?cache=0&sync_timestamp=1586046271069&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-2.1.3.tgz", + "integrity": "sha1-ybD3+pIzv+WAf+ZvzzpWF+1ZfUM=", "dev": true, "requires": { - "minimist": "1.2.0" + "minimist": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz", + "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=", + "dev": true + } } }, "jsprim": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "resolved": "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, "optional": true, @@ -5860,57 +6138,64 @@ } }, "jsx-ast-utils": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz", - "integrity": "sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==", + "version": "2.4.1", + "resolved": "https://registry.npm.taobao.org/jsx-ast-utils/download/jsx-ast-utils-2.4.1.tgz?cache=0&sync_timestamp=1591928158443&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsx-ast-utils%2Fdownload%2Fjsx-ast-utils-2.4.1.tgz", + "integrity": "sha1-ERSkwSCUgdsGxpDCtPSIzGZfZX4=", "dev": true, "requires": { - "array-includes": "3.0.3", - "object.assign": "4.1.0" + "array-includes": "^3.1.1", + "object.assign": "^4.1.0" } }, "killable": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", - "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "resolved": "https://registry.npm.taobao.org/killable/download/killable-1.0.1.tgz", + "integrity": "sha1-TIzkQRh6Bhx0dPuHygjipjgZSJI=", "dev": true }, "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "version": "6.0.3", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz", + "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=", "dev": true }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "language-subtag-registry": { + "version": "0.3.20", + "resolved": "https://registry.npm.taobao.org/language-subtag-registry/download/language-subtag-registry-0.3.20.tgz", + "integrity": "sha1-oAo3EhiU8iT3YyaOQxxVVWsMB1U=", + "dev": true + }, + "language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/language-tags/download/language-tags-1.0.5.tgz", + "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", "dev": true, "requires": { - "invert-kv": "2.0.0" + "language-subtag-registry": "~0.3.2" } }, "less": { - "version": "3.10.3", - "resolved": "https://registry.npmjs.org/less/-/less-3.10.3.tgz", - "integrity": "sha512-vz32vqfgmoxF1h3K4J+yKCtajH0PWmjkIFgbs5d78E/c/e+UQTnI+lWK+1eQRE95PXM2mC3rJlLSSP9VQHnaow==", - "dev": true, - "requires": { - "clone": "2.1.2", - "errno": "0.1.7", - "graceful-fs": "4.2.3", - "image-size": "0.5.5", - "mime": "1.6.0", - "mkdirp": "0.5.1", - "promise": "7.3.1", - "request": "2.88.0", - "source-map": "0.6.1" + "version": "3.11.3", + "resolved": "https://registry.npm.taobao.org/less/download/less-3.11.3.tgz", + "integrity": "sha1-LYU5VPz+AWmor4aWILyqFlY9zBw=", + "dev": true, + "requires": { + "clone": "^2.1.2", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "promise": "^7.1.1", + "request": "^2.83.0", + "source-map": "~0.6.0", + "tslib": "^1.10.0" }, "dependencies": { "source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "optional": true } @@ -5922,9 +6207,9 @@ "integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==", "dev": true, "requires": { - "clone": "2.1.2", - "loader-utils": "1.2.3", - "pify": "3.0.0" + "clone": "^2.1.1", + "loader-utils": "^1.1.0", + "pify": "^3.0.0" }, "dependencies": { "pify": { @@ -5935,31 +6220,46 @@ } } }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/leven/download/leven-3.1.0.tgz", + "integrity": "sha1-d4kd6DQGTMy6gq54QrtrFKE+1/I=", + "dev": true + }, + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/levenary/download/levenary-1.1.1.tgz", + "integrity": "sha1-hCqe6Y0gdap/ru2+MmeekgX0b3c=", + "dev": true, + "requires": { + "leven": "^3.1.0" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "load-json-file": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { - "graceful-fs": "4.2.3", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" }, "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -5967,8 +6267,8 @@ }, "loader-runner": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "resolved": "https://registry.npm.taobao.org/loader-runner/download/loader-runner-2.4.0.tgz", + "integrity": "sha1-7UcGa/5TTX6ExMe5mYwqdWB9k1c=", "dev": true }, "loader-utils": { @@ -5977,9 +6277,9 @@ "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", "dev": true, "requires": { - "big.js": "5.2.2", - "emojis-list": "2.1.0", - "json5": "1.0.1" + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" }, "dependencies": { "json5": { @@ -5988,19 +6288,19 @@ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "minimist": "1.2.0" + "minimist": "^1.2.0" } } } }, "locate-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", "dev": true, "requires": { - "p-locate": "3.0.0", - "path-exists": "3.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, "lodash": { @@ -6036,8 +6336,8 @@ "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", "dev": true, "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.templatesettings": "4.2.0" + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" } }, "lodash.templatesettings": { @@ -6046,13 +6346,13 @@ "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", "dev": true, "requires": { - "lodash._reinterpolate": "3.0.0" + "lodash._reinterpolate": "^3.0.0" } }, "loglevel": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.6.tgz", - "integrity": "sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ==", + "version": "1.6.8", + "resolved": "https://registry.npm.taobao.org/loglevel/download/loglevel-1.6.8.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floglevel%2Fdownload%2Floglevel-1.6.8.tgz", + "integrity": "sha1-iiX7ddCSIw7NRFcnDYC1TigBEXE=", "dev": true }, "longest": { @@ -6066,166 +6366,140 @@ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "requires": { - "js-tokens": "4.0.0" + "js-tokens": "^3.0.0 || ^4.0.0" } }, "lru-cache": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-5.1.1.tgz", + "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=", "dev": true, "requires": { - "yallist": "3.1.1" + "yallist": "^3.0.2" } }, "make-dir": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "4.0.1", - "semver": "5.7.1" - } - }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", - "dev": true - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz?cache=0&sync_timestamp=1587567610342&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmake-dir%2Fdownload%2Fmake-dir-2.1.0.tgz", + "integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=", "dev": true, "requires": { - "p-defer": "1.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" } }, "map-cache": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "resolved": "https://registry.npm.taobao.org/map-cache/download/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, "map-visit": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/map-visit/download/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "1.0.1" + "object-visit": "^1.0.0" } }, "md5.js": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "resolved": "https://registry.npm.taobao.org/md5.js/download/md5.js-1.3.5.tgz", + "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=", "dev": true, "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.4", - "safe-buffer": "5.1.2" + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "0.1.3", - "mimic-fn": "2.1.0", - "p-is-promise": "2.1.0" - }, - "dependencies": { - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - } - } - }, "memory-fs": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "resolved": "https://registry.npm.taobao.org/memory-fs/download/memory-fs-0.4.1.tgz?cache=0&sync_timestamp=1570537491040&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmemory-fs%2Fdownload%2Fmemory-fs-0.4.1.tgz", "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, "requires": { - "errno": "0.1.7", - "readable-stream": "2.3.6" + "errno": "^0.1.3", + "readable-stream": "^2.0.1" } }, "merge-descriptors": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/merge-descriptors/download/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", "dev": true }, "methods": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", "dev": true }, "micromatch": { "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "resolved": "https://registry.npm.taobao.org/micromatch/download/micromatch-3.1.10.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmicromatch%2Fdownload%2Fmicromatch-3.1.10.tgz", + "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.13", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, "miller-rabin": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "resolved": "https://registry.npm.taobao.org/miller-rabin/download/miller-rabin-4.0.1.tgz", + "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0" + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=", + "dev": true + } } }, "mime": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "resolved": "https://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz?cache=0&sync_timestamp=1590596706367&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime%2Fdownload%2Fmime-1.6.0.tgz", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", "dev": true }, "mime-db": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", - "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==", + "version": "1.44.0", + "resolved": "https://registry.npm.taobao.org/mime-db/download/mime-db-1.44.0.tgz?cache=0&sync_timestamp=1587603398892&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-db%2Fdownload%2Fmime-db-1.44.0.tgz", + "integrity": "sha1-+hHF6wrKEzS0Izy01S8QxaYnL5I=", "dev": true }, "mime-types": { - "version": "2.1.25", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", - "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", + "version": "2.1.27", + "resolved": "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.27.tgz?cache=0&sync_timestamp=1587700357177&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-types%2Fdownload%2Fmime-types-2.1.27.tgz", + "integrity": "sha1-R5SfmOJ56lMRn1ci4PNOUpvsAJ8=", "dev": true, "requires": { - "mime-db": "1.42.0" + "mime-db": "1.44.0" } }, "mimic-fn": { @@ -6236,13 +6510,13 @@ }, "minimalistic-assert": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "resolved": "https://registry.npm.taobao.org/minimalistic-assert/download/minimalistic-assert-1.0.1.tgz", + "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=", "dev": true }, "minimalistic-crypto-utils": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/minimalistic-crypto-utils/download/minimalistic-crypto-utils-1.0.1.tgz", "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", "dev": true }, @@ -6252,7 +6526,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -6263,39 +6537,39 @@ }, "mississippi": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "resolved": "https://registry.npm.taobao.org/mississippi/download/mississippi-3.0.0.tgz", + "integrity": "sha1-6goykfl+C16HdrNj1fChLZTGcCI=", "dev": true, "requires": { - "concat-stream": "1.6.2", - "duplexify": "3.7.1", - "end-of-stream": "1.4.4", - "flush-write-stream": "1.1.1", - "from2": "2.3.0", - "parallel-transform": "1.2.0", - "pump": "3.0.0", - "pumpify": "1.5.1", - "stream-each": "1.2.3", - "through2": "2.0.5" + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" } }, "mixin-deep": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "resolved": "https://registry.npm.taobao.org/mixin-deep/download/mixin-deep-1.3.2.tgz", + "integrity": "sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY=", "dev": true, "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -6319,37 +6593,37 @@ }, "move-concurrently": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz", "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", "dev": true, "requires": { - "aproba": "1.2.0", - "copy-concurrently": "1.0.5", - "fs-write-stream-atomic": "1.0.10", - "mkdirp": "0.5.1", - "rimraf": "2.7.1", - "run-queue": "1.0.3" + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" } }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, "multicast-dns": { "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "resolved": "https://registry.npm.taobao.org/multicast-dns/download/multicast-dns-6.2.3.tgz?cache=0&sync_timestamp=1585239065356&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmulticast-dns%2Fdownload%2Fmulticast-dns-6.2.3.tgz", + "integrity": "sha1-oOx72QVcQoL3kMPIL04o2zsxsik=", "dev": true, "requires": { - "dns-packet": "1.3.1", - "thunky": "1.1.0" + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" } }, "multicast-dns-service-types": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/multicast-dns-service-types/download/multicast-dns-service-types-1.1.0.tgz", "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, @@ -6360,29 +6634,29 @@ "dev": true }, "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "version": "2.14.1", + "resolved": "https://registry.npm.taobao.org/nan/download/nan-2.14.1.tgz", + "integrity": "sha1-174036MQW5FJTDFHCJMV7/iHSwE=", "dev": true, "optional": true }, "nanomatch": { "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "resolved": "https://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz", + "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "fragment-cache": "0.2.1", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" } }, "natural-compare": { @@ -6393,14 +6667,14 @@ }, "negotiator": { "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "resolved": "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz", + "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs=", "dev": true }, "neo-async": { "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "resolved": "https://registry.npm.taobao.org/neo-async/download/neo-async-2.6.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fneo-async%2Fdownload%2Fneo-async-2.6.1.tgz", + "integrity": "sha1-rCetpmFn+ohJpq3dg39rGJrSCBw=", "dev": true }, "nice-try": { @@ -6414,50 +6688,50 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", "requires": { - "encoding": "0.1.12", - "is-stream": "1.1.0" + "encoding": "^0.1.11", + "is-stream": "^1.0.1" } }, "node-forge": { "version": "0.9.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", - "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==", + "resolved": "https://registry.npm.taobao.org/node-forge/download/node-forge-0.9.0.tgz?cache=0&sync_timestamp=1569524669712&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-forge%2Fdownload%2Fnode-forge-0.9.0.tgz", + "integrity": "sha1-1iQFDtu0SHStyhK7mlLsY8t4JXk=", "dev": true }, "node-libs-browser": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "requires": { - "assert": "1.5.0", - "browserify-zlib": "0.2.0", - "buffer": "4.9.2", - "console-browserify": "1.2.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "domain-browser": "1.2.0", - "events": "3.0.0", - "https-browserify": "1.0.0", - "os-browserify": "0.3.0", + "resolved": "https://registry.npm.taobao.org/node-libs-browser/download/node-libs-browser-2.2.1.tgz", + "integrity": "sha1-tk9RPRgzhiX5A0bSew0jXmMfZCU=", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", "path-browserify": "0.0.1", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "readable-stream": "2.3.6", - "stream-browserify": "2.0.2", - "stream-http": "2.8.3", - "string_decoder": "1.1.1", - "timers-browserify": "2.0.11", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.11.1", - "vm-browserify": "1.1.2" + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" }, "dependencies": { "punycode": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true } @@ -6469,7 +6743,7 @@ "integrity": "sha512-r4LPcC5b/bS8BdtWH1fbeK88ib/wg9aqmg6/s3ngNLn2Ewkn/8J6Iw3P9RTlfIAdSdvYvQl2thCY5Y+qTAQ2iQ==", "dev": true, "requires": { - "semver": "6.3.0" + "semver": "^6.3.0" }, "dependencies": { "semver": { @@ -6482,14 +6756,14 @@ }, "normalize-package-data": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "resolved": "https://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.5.0.tgz", + "integrity": "sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg=", "dev": true, "requires": { - "hosted-git-info": "2.8.5", - "resolve": "1.12.0", - "semver": "5.7.1", - "validate-npm-package-license": "3.0.4" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "normalize-path": { @@ -6506,11 +6780,11 @@ }, "npm-run-path": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "path-key": "2.0.1" + "path-key": "^2.0.0" } }, "num2fraction": { @@ -6519,16 +6793,10 @@ "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", "dev": true }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, "oauth-sign": { "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "resolved": "https://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz", + "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=", "dev": true, "optional": true }, @@ -6539,31 +6807,31 @@ }, "object-copy": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/object-copy/download/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "dependencies": { "define-property": { "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "kind-of": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6575,10 +6843,50 @@ "dev": true }, "object-is": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/object-is/download/object-is-1.1.2.tgz?cache=0&sync_timestamp=1586894009620&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject-is%2Fdownload%2Fobject-is-1.1.2.tgz", + "integrity": "sha1-xdLof/nhGfeLegiEQVGeLuwVc7Y=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } }, "object-keys": { "version": "1.1.1", @@ -6588,11 +6896,11 @@ }, "object-visit": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/object-visit/download/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.0" } }, "object.assign": { @@ -6601,10 +6909,10 @@ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dev": true, "requires": { - "define-properties": "1.1.3", - "function-bind": "1.1.1", - "has-symbols": "1.0.1", - "object-keys": "1.1.1" + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" } }, "object.entries": { @@ -6613,54 +6921,126 @@ "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", "dev": true, "requires": { - "define-properties": "1.1.3", - "es-abstract": "1.16.0", - "function-bind": "1.1.1", - "has": "1.0.3" + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" } }, "object.fromentries": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.1.tgz", - "integrity": "sha512-PUQv8Hbg3j2QX0IQYv3iAGCbGcu4yY4KQ92/dhA4sFSixBmSmp13UpDLs6jGK8rBtbmhNNIK99LD2k293jpiGA==", + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/object.fromentries/download/object.fromentries-2.0.2.tgz", + "integrity": "sha1-SgnJubs4Q90PiazbUXp5TU81Wsk=", "dev": true, "requires": { - "define-properties": "1.1.3", - "es-abstract": "1.16.0", - "function-bind": "1.1.1", - "has": "1.0.3" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } } }, "object.pick": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/object.pick/download/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" } }, "object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/object.values/download/object.values-1.1.1.tgz", + "integrity": "sha1-aKmezeNWt+kpWjxeDOMdyMlT3l4=", "dev": true, "requires": { - "define-properties": "1.1.3", - "es-abstract": "1.16.0", - "function-bind": "1.1.1", - "has": "1.0.3" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } } }, "obuf": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "resolved": "https://registry.npm.taobao.org/obuf/download/obuf-1.1.2.tgz", + "integrity": "sha1-Cb6jND1BhZ69RGKS0RydTbYZCE4=", "dev": true }, "on-finished": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dev": true, "requires": { @@ -6669,8 +7049,8 @@ }, "on-headers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "resolved": "https://registry.npm.taobao.org/on-headers/download/on-headers-1.0.2.tgz", + "integrity": "sha1-dysK5qqlJcOZ5Imt+tkMQD6zwo8=", "dev": true }, "once": { @@ -6679,7 +7059,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "onetime": { @@ -6688,16 +7068,16 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "1.2.0" + "mimic-fn": "^1.0.0" } }, "opn": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "resolved": "https://registry.npm.taobao.org/opn/download/opn-5.5.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fopn%2Fdownload%2Fopn-5.5.0.tgz", + "integrity": "sha1-/HFk+rVtI1kExRw7J9pnWMo7m/w=", "dev": true, "requires": { - "is-wsl": "1.1.0" + "is-wsl": "^1.1.0" } }, "optionator": { @@ -6706,118 +7086,95 @@ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "word-wrap": "1.2.3" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" } }, "original": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", - "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "resolved": "https://registry.npm.taobao.org/original/download/original-1.0.2.tgz", + "integrity": "sha1-5EKmHP/hxf0gpl8yYcJmY7MD8l8=", "dev": true, "requires": { - "url-parse": "1.4.7" + "url-parse": "^1.4.3" } }, "os-browserify": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/os-browserify/download/os-browserify-0.3.0.tgz", "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "1.0.0", - "lcid": "2.0.0", - "mem": "4.3.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, "p-finally": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz", + "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=", "dev": true, "requires": { - "p-try": "2.2.0" + "p-try": "^2.0.0" } }, "p-locate": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", "dev": true, "requires": { - "p-limit": "2.2.1" + "p-limit": "^2.0.0" } }, "p-map": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "resolved": "https://registry.npm.taobao.org/p-map/download/p-map-2.1.0.tgz", + "integrity": "sha1-MQko/u+cnsxltosXaTAYpmXOoXU=", "dev": true }, "p-retry": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", - "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "resolved": "https://registry.npm.taobao.org/p-retry/download/p-retry-3.0.1.tgz", + "integrity": "sha1-MWtMiJPiyNwc+okfQGxLQivr8yg=", "dev": true, "requires": { - "retry": "0.12.0" + "retry": "^0.12.0" } }, "p-try": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=", "dev": true }, "pako": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", - "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", + "version": "1.0.11", + "resolved": "https://registry.npm.taobao.org/pako/download/pako-1.0.11.tgz", + "integrity": "sha1-bJWZ00DVTf05RjgCUqNXBaa5kr8=", "dev": true }, "parallel-transform": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "resolved": "https://registry.npm.taobao.org/parallel-transform/download/parallel-transform-1.2.0.tgz", + "integrity": "sha1-kEnKN9bLIYLDsdLHIL6U0UpYFPw=", "dev": true, "requires": { - "cyclist": "1.0.1", - "inherits": "2.0.4", - "readable-stream": "2.3.6" + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" } }, "parent-module": { @@ -6826,59 +7183,59 @@ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "requires": { - "callsites": "3.1.0" + "callsites": "^3.0.0" } }, "parse-asn1": { "version": "5.1.5", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", - "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "resolved": "https://registry.npm.taobao.org/parse-asn1/download/parse-asn1-5.1.5.tgz", + "integrity": "sha1-ADJxND2ljclMrOSU+u89IUfs6g4=", "dev": true, "requires": { - "asn1.js": "4.10.1", - "browserify-aes": "1.2.0", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.17", - "safe-buffer": "5.1.2" + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" } }, "parse-json": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.2" + "error-ex": "^1.2.0" } }, "parse-passwd": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/parse-passwd/download/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, "parseurl": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "resolved": "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz", + "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=", "dev": true }, "pascalcase": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, "path-browserify": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "resolved": "https://registry.npm.taobao.org/path-browserify/download/path-browserify-0.0.1.tgz", + "integrity": "sha1-5sTd1+06onxoogzE5Q4aTug7vEo=", "dev": true }, "path-dirname": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/path-dirname/download/path-dirname-1.0.2.tgz", "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, @@ -6914,75 +7271,82 @@ }, "path-to-regexp": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "resolved": "https://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", "dev": true }, "path-type": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/path-type/download/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { - "pify": "2.3.0" + "pify": "^2.0.0" }, "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/pbkdf2/download/pbkdf2-3.1.1.tgz", + "integrity": "sha1-y4cksPramEWWhW0abrr9NYRlS5Q=", "dev": true, "requires": { - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.2", - "sha.js": "2.4.11" + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "performance-now": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true, "optional": true }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npm.taobao.org/picomatch/download/picomatch-2.2.2.tgz", + "integrity": "sha1-IfMz6ba46v8CRo9RRupAbTRfTa0=", + "dev": true, + "optional": true + }, "pify": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz", + "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=", "dev": true }, "pinkie": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "resolved": "https://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true }, "pinkie-promise": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "pkg-dir": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-3.0.0.tgz", + "integrity": "sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM=", "dev": true, "requires": { - "find-up": "3.0.0" + "find-up": "^3.0.0" } }, "pkg-up": { @@ -6991,7 +7355,7 @@ "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", "dev": true, "requires": { - "find-up": "2.1.0" + "find-up": "^2.1.0" }, "dependencies": { "find-up": { @@ -7000,7 +7364,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } }, "locate-path": { @@ -7009,8 +7373,8 @@ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" } }, "p-limit": { @@ -7019,7 +7383,7 @@ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "requires": { - "p-try": "1.0.0" + "p-try": "^1.0.0" } }, "p-locate": { @@ -7028,7 +7392,7 @@ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "1.3.0" + "p-limit": "^1.1.0" } }, "p-try": { @@ -7040,36 +7404,36 @@ } }, "portfinder": { - "version": "1.0.25", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", - "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==", + "version": "1.0.26", + "resolved": "https://registry.npm.taobao.org/portfinder/download/portfinder-1.0.26.tgz", + "integrity": "sha1-R1ZY1WyjC+1yrH8TeO01C9G2TnA=", "dev": true, "requires": { - "async": "2.6.3", - "debug": "3.2.6", - "mkdirp": "0.5.1" + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.1" }, "dependencies": { "debug": { "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.1" } }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", "dev": true } } }, "posix-character-classes": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/posix-character-classes/download/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, @@ -7079,9 +7443,9 @@ "integrity": "sha512-hOlMf3ouRIFXD+j2VJecwssTwbvsPGJVMzupptg+85WA+i7MwyrydmQAgY3R+m0Bc0exunhbJmijy8u8+vufuQ==", "dev": true, "requires": { - "chalk": "2.4.2", - "source-map": "0.6.1", - "supports-color": "6.1.0" + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" }, "dependencies": { "source-map": { @@ -7096,7 +7460,7 @@ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } } } @@ -7107,8 +7471,8 @@ "integrity": "sha512-L2YKB3vF4PetdTIthQVeT+7YiSzMoNMLLYxPXXppOOP7NoazEAy45sh2LvJ8leCQjfBcfkYQs8TtCcQjeZTp8A==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-selector-parser": "5.0.0" + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0" }, "dependencies": { "cssesc": { @@ -7123,9 +7487,9 @@ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "dev": true, "requires": { - "cssesc": "2.0.0", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } } } @@ -7136,8 +7500,8 @@ "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-values-parser": "2.0.1" + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" } }, "postcss-color-gray": { @@ -7146,9 +7510,9 @@ "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", "dev": true, "requires": { - "@csstools/convert-colors": "1.4.0", - "postcss": "7.0.23", - "postcss-values-parser": "2.0.1" + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" } }, "postcss-color-hex-alpha": { @@ -7157,8 +7521,8 @@ "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-values-parser": "2.0.1" + "postcss": "^7.0.14", + "postcss-values-parser": "^2.0.1" } }, "postcss-color-mod-function": { @@ -7167,9 +7531,9 @@ "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", "dev": true, "requires": { - "@csstools/convert-colors": "1.4.0", - "postcss": "7.0.23", - "postcss-values-parser": "2.0.1" + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" } }, "postcss-color-rebeccapurple": { @@ -7178,8 +7542,8 @@ "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-values-parser": "2.0.1" + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" } }, "postcss-custom-media": { @@ -7188,7 +7552,7 @@ "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.14" } }, "postcss-custom-properties": { @@ -7197,8 +7561,8 @@ "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-values-parser": "2.0.1" + "postcss": "^7.0.17", + "postcss-values-parser": "^2.0.1" } }, "postcss-custom-selectors": { @@ -7207,8 +7571,8 @@ "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-selector-parser": "5.0.0" + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" }, "dependencies": { "cssesc": { @@ -7223,9 +7587,9 @@ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "dev": true, "requires": { - "cssesc": "2.0.0", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } } } @@ -7236,8 +7600,8 @@ "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-selector-parser": "5.0.0" + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" }, "dependencies": { "cssesc": { @@ -7252,9 +7616,9 @@ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "dev": true, "requires": { - "cssesc": "2.0.0", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } } } @@ -7265,8 +7629,8 @@ "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-values-parser": "2.0.1" + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" } }, "postcss-env-function": { @@ -7275,8 +7639,8 @@ "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-values-parser": "2.0.1" + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" } }, "postcss-focus-visible": { @@ -7285,7 +7649,7 @@ "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.2" } }, "postcss-focus-within": { @@ -7294,7 +7658,7 @@ "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.2" } }, "postcss-font-variant": { @@ -7303,7 +7667,7 @@ "integrity": "sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.2" } }, "postcss-gap-properties": { @@ -7312,7 +7676,7 @@ "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.2" } }, "postcss-image-set-function": { @@ -7321,8 +7685,8 @@ "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-values-parser": "2.0.1" + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" } }, "postcss-initial": { @@ -7331,8 +7695,8 @@ "integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==", "dev": true, "requires": { - "lodash.template": "4.5.0", - "postcss": "7.0.23" + "lodash.template": "^4.5.0", + "postcss": "^7.0.2" } }, "postcss-lab-function": { @@ -7341,9 +7705,9 @@ "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", "dev": true, "requires": { - "@csstools/convert-colors": "1.4.0", - "postcss": "7.0.23", - "postcss-values-parser": "2.0.1" + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" } }, "postcss-load-config": { @@ -7352,8 +7716,8 @@ "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", "dev": true, "requires": { - "cosmiconfig": "5.2.1", - "import-cwd": "2.1.0" + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" } }, "postcss-loader": { @@ -7362,10 +7726,10 @@ "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", "dev": true, "requires": { - "loader-utils": "1.2.3", - "postcss": "7.0.23", - "postcss-load-config": "2.1.0", - "schema-utils": "1.0.0" + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" } }, "postcss-logical": { @@ -7374,7 +7738,7 @@ "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.2" } }, "postcss-media-minmax": { @@ -7383,7 +7747,7 @@ "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.2" } }, "postcss-modules-extract-imports": { @@ -7392,7 +7756,7 @@ "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.5" } }, "postcss-modules-local-by-default": { @@ -7401,9 +7765,9 @@ "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-selector-parser": "6.0.2", - "postcss-value-parser": "3.3.1" + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0", + "postcss-value-parser": "^3.3.1" } }, "postcss-modules-scope": { @@ -7412,8 +7776,8 @@ "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-selector-parser": "6.0.2" + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" } }, "postcss-modules-values": { @@ -7422,8 +7786,8 @@ "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", "dev": true, "requires": { - "icss-replace-symbols": "1.1.0", - "postcss": "7.0.23" + "icss-replace-symbols": "^1.1.0", + "postcss": "^7.0.6" } }, "postcss-nesting": { @@ -7432,7 +7796,7 @@ "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.2" } }, "postcss-overflow-shorthand": { @@ -7441,7 +7805,7 @@ "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.2" } }, "postcss-page-break": { @@ -7450,7 +7814,7 @@ "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.2" } }, "postcss-place": { @@ -7459,8 +7823,8 @@ "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-values-parser": "2.0.1" + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" } }, "postcss-preset-env": { @@ -7469,43 +7833,43 @@ "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", "dev": true, "requires": { - "autoprefixer": "9.7.2", - "browserslist": "4.7.3", - "caniuse-lite": "1.0.30001011", - "css-blank-pseudo": "0.1.4", - "css-has-pseudo": "0.10.0", - "css-prefers-color-scheme": "3.1.1", - "cssdb": "4.4.0", - "postcss": "7.0.23", - "postcss-attribute-case-insensitive": "4.0.1", - "postcss-color-functional-notation": "2.0.1", - "postcss-color-gray": "5.0.0", - "postcss-color-hex-alpha": "5.0.3", - "postcss-color-mod-function": "3.0.3", - "postcss-color-rebeccapurple": "4.0.1", - "postcss-custom-media": "7.0.8", - "postcss-custom-properties": "8.0.11", - "postcss-custom-selectors": "5.1.2", - "postcss-dir-pseudo-class": "5.0.0", - "postcss-double-position-gradients": "1.0.0", - "postcss-env-function": "2.0.2", - "postcss-focus-visible": "4.0.0", - "postcss-focus-within": "3.0.0", - "postcss-font-variant": "4.0.0", - "postcss-gap-properties": "2.0.0", - "postcss-image-set-function": "3.0.1", - "postcss-initial": "3.0.2", - "postcss-lab-function": "2.0.1", - "postcss-logical": "3.0.0", - "postcss-media-minmax": "4.0.0", - "postcss-nesting": "7.0.1", - "postcss-overflow-shorthand": "2.0.0", - "postcss-page-break": "2.0.0", - "postcss-place": "4.0.1", - "postcss-pseudo-class-any-link": "6.0.0", - "postcss-replace-overflow-wrap": "3.0.0", - "postcss-selector-matches": "4.0.0", - "postcss-selector-not": "4.0.0" + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", + "css-blank-pseudo": "^0.1.4", + "css-has-pseudo": "^0.10.0", + "css-prefers-color-scheme": "^3.1.1", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", + "postcss-attribute-case-insensitive": "^4.0.1", + "postcss-color-functional-notation": "^2.0.1", + "postcss-color-gray": "^5.0.0", + "postcss-color-hex-alpha": "^5.0.3", + "postcss-color-mod-function": "^3.0.3", + "postcss-color-rebeccapurple": "^4.0.1", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", + "postcss-custom-selectors": "^5.1.2", + "postcss-dir-pseudo-class": "^5.0.0", + "postcss-double-position-gradients": "^1.0.0", + "postcss-env-function": "^2.0.2", + "postcss-focus-visible": "^4.0.0", + "postcss-focus-within": "^3.0.0", + "postcss-font-variant": "^4.0.0", + "postcss-gap-properties": "^2.0.0", + "postcss-image-set-function": "^3.0.1", + "postcss-initial": "^3.0.0", + "postcss-lab-function": "^2.0.1", + "postcss-logical": "^3.0.0", + "postcss-media-minmax": "^4.0.0", + "postcss-nesting": "^7.0.0", + "postcss-overflow-shorthand": "^2.0.0", + "postcss-page-break": "^2.0.0", + "postcss-place": "^4.0.1", + "postcss-pseudo-class-any-link": "^6.0.0", + "postcss-replace-overflow-wrap": "^3.0.0", + "postcss-selector-matches": "^4.0.0", + "postcss-selector-not": "^4.0.0" } }, "postcss-pseudo-class-any-link": { @@ -7514,8 +7878,8 @@ "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", "dev": true, "requires": { - "postcss": "7.0.23", - "postcss-selector-parser": "5.0.0" + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" }, "dependencies": { "cssesc": { @@ -7530,9 +7894,9 @@ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "dev": true, "requires": { - "cssesc": "2.0.0", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } } } @@ -7543,7 +7907,7 @@ "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", "dev": true, "requires": { - "postcss": "7.0.23" + "postcss": "^7.0.2" } }, "postcss-selector-matches": { @@ -7552,8 +7916,8 @@ "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", "dev": true, "requires": { - "balanced-match": "1.0.0", - "postcss": "7.0.23" + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" } }, "postcss-selector-not": { @@ -7562,8 +7926,8 @@ "integrity": "sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==", "dev": true, "requires": { - "balanced-match": "1.0.0", - "postcss": "7.0.23" + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" } }, "postcss-selector-parser": { @@ -7572,9 +7936,9 @@ "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", "dev": true, "requires": { - "cssesc": "3.0.0", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } }, "postcss-value-parser": { @@ -7589,9 +7953,9 @@ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", "dev": true, "requires": { - "flatten": "1.0.3", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } }, "prelude-ls": { @@ -7600,22 +7964,16 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, "process": { "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "resolved": "https://registry.npm.taobao.org/process/download/process-0.11.10.tgz", "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", "dev": true }, "process-nextick-args": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz", + "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=", "dev": true }, "progress": { @@ -7629,12 +7987,12 @@ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "requires": { - "asap": "2.0.6" + "asap": "~2.0.3" } }, "promise-inflight": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/promise-inflight/download/promise-inflight-1.0.1.tgz", "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, @@ -7643,77 +8001,85 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", "requires": { - "loose-envify": "1.4.0", - "object-assign": "4.1.1", - "react-is": "16.12.0" + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" } }, "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "version": "2.0.6", + "resolved": "https://registry.npm.taobao.org/proxy-addr/download/proxy-addr-2.0.6.tgz", + "integrity": "sha1-/cIzZQVEfT8vLGOO0nLK9hS7sr8=", "dev": true, "requires": { - "forwarded": "0.1.2", - "ipaddr.js": "1.9.0" + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" } }, "prr": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/prr/download/prr-1.0.1.tgz", "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, "psl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", - "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==", + "version": "1.8.0", + "resolved": "https://registry.npm.taobao.org/psl/download/psl-1.8.0.tgz?cache=0&sync_timestamp=1585142991033&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpsl%2Fdownload%2Fpsl-1.8.0.tgz", + "integrity": "sha1-kyb4vPsBOtzABf3/BWrM4CDlHCQ=", "dev": true, "optional": true }, "public-encrypt": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "resolved": "https://registry.npm.taobao.org/public-encrypt/download/public-encrypt-4.0.3.tgz", + "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=", "dev": true, "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "parse-asn1": "5.1.5", - "randombytes": "2.1.0", - "safe-buffer": "5.1.2" + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=", + "dev": true + } } }, "pump": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "resolved": "https://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz", + "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", "dev": true, "requires": { - "end-of-stream": "1.4.4", - "once": "1.4.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, "pumpify": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "resolved": "https://registry.npm.taobao.org/pumpify/download/pumpify-1.5.1.tgz?cache=0&sync_timestamp=1569938200736&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpumpify%2Fdownload%2Fpumpify-1.5.1.tgz", + "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", "dev": true, "requires": { - "duplexify": "3.7.1", - "inherits": "2.0.4", - "pump": "2.0.1" + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" }, "dependencies": { "pump": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "resolved": "https://registry.npm.taobao.org/pump/download/pump-2.0.1.tgz", + "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", "dev": true, "requires": { - "end-of-stream": "1.4.4", - "once": "1.4.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } } } @@ -7726,58 +8092,58 @@ }, "qs": { "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz", + "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=", "dev": true, "optional": true }, "querystring": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/querystring/download/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "dev": true }, "querystring-es3": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "resolved": "https://registry.npm.taobao.org/querystring-es3/download/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, "querystringify": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", - "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", + "resolved": "https://registry.npm.taobao.org/querystringify/download/querystringify-2.1.1.tgz", + "integrity": "sha1-YOWl/WSn+L+k0qsu1v30yFutFU4=", "dev": true }, "randombytes": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "resolved": "https://registry.npm.taobao.org/randombytes/download/randombytes-2.1.0.tgz", + "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "^5.1.0" } }, "randomfill": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "resolved": "https://registry.npm.taobao.org/randomfill/download/randomfill-1.0.4.tgz", + "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=", "dev": true, "requires": { - "randombytes": "2.1.0", - "safe-buffer": "5.1.2" + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, "range-parser": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "resolved": "https://registry.npm.taobao.org/range-parser/download/range-parser-1.2.1.tgz", + "integrity": "sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE=", "dev": true }, "raw-body": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "resolved": "https://registry.npm.taobao.org/raw-body/download/raw-body-2.4.0.tgz", + "integrity": "sha1-oc5vucm8NWylLoklarWQWeE9AzI=", "dev": true, "requires": { "bytes": "3.1.0", @@ -7788,8 +8154,8 @@ "dependencies": { "bytes": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbytes%2Fdownload%2Fbytes-3.1.0.tgz", + "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY=", "dev": true } } @@ -7799,12 +8165,12 @@ "resolved": "https://registry.npmjs.org/react-codemirror/-/react-codemirror-1.0.0.tgz", "integrity": "sha1-kUZ7U7H12A2Rai/QtMetuFqQAbo=", "requires": { - "classnames": "2.2.6", - "codemirror": "5.49.2", - "create-react-class": "15.6.3", - "lodash.debounce": "4.0.8", - "lodash.isequal": "4.5.0", - "prop-types": "15.7.2" + "classnames": "^2.2.5", + "codemirror": "^5.18.2", + "create-react-class": "^15.5.1", + "lodash.debounce": "^4.0.8", + "lodash.isequal": "^4.5.0", + "prop-types": "^15.5.4" } }, "react-is": { @@ -7814,143 +8180,180 @@ }, "read-pkg": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/read-pkg/download/read-pkg-2.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fread-pkg%2Fdownload%2Fread-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", "dev": true, "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.5.0", - "path-type": "2.0.0" + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" } }, "read-pkg-up": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-2.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fread-pkg-up%2Fdownload%2Fread-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", "dev": true, "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" }, "dependencies": { "find-up": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } }, "locate-path": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" } }, "p-limit": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-1.3.0.tgz", + "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", "dev": true, "requires": { - "p-try": "1.0.0" + "p-try": "^1.0.0" } }, "p-locate": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "1.3.0" + "p-limit": "^1.1.0" } }, "p-try": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true } } }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.4", - "isarray": "1.0.0", - "process-nextick-args": "2.0.1", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "readdirp": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz?cache=0&sync_timestamp=1584985910691&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-2.2.1.tgz", + "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=", "dev": true, "requires": { - "graceful-fs": "4.2.3", - "micromatch": "3.1.10", - "readable-stream": "2.3.6" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" } }, "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "version": "1.4.1", + "resolved": "https://registry.npm.taobao.org/regenerate/download/regenerate-1.4.1.tgz", + "integrity": "sha1-ytkq2Oa1kXc0hfvgWkhcr09Ffm8=", "dev": true }, "regenerate-unicode-properties": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", - "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", + "version": "8.2.0", + "resolved": "https://registry.npm.taobao.org/regenerate-unicode-properties/download/regenerate-unicode-properties-8.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerate-unicode-properties%2Fdownload%2Fregenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha1-5d5xEdZV57pgwFfb6f83yH5lzew=", "dev": true, "requires": { - "regenerate": "1.4.0" + "regenerate": "^1.4.0" } }, "regenerator-runtime": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "version": "0.13.5", + "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.5.tgz?cache=0&sync_timestamp=1584052597708&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.13.5.tgz", + "integrity": "sha1-2Hih0JS0MG0QuQlkhLM+vVXiZpc=", "dev": true }, "regenerator-transform": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", - "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "version": "0.14.5", + "resolved": "https://registry.npm.taobao.org/regenerator-transform/download/regenerator-transform-0.14.5.tgz?cache=0&sync_timestamp=1593557570099&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-transform%2Fdownload%2Fregenerator-transform-0.14.5.tgz", + "integrity": "sha1-yY2hVGg2ccnE3LFuznNlF+G3/rQ=", "dev": true, "requires": { - "private": "0.1.8" + "@babel/runtime": "^7.8.4" } }, "regex-not": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "resolved": "https://registry.npm.taobao.org/regex-not/download/regex-not-1.0.2.tgz", + "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", "dev": true, "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" } }, "regexp.prototype.flags": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", - "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/regexp.prototype.flags/download/regexp.prototype.flags-1.3.0.tgz?cache=0&sync_timestamp=1576388379660&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregexp.prototype.flags%2Fdownload%2Fregexp.prototype.flags-1.3.0.tgz", + "integrity": "sha1-erqJs8E6ZFCdq888qNn7ub31y3U=", "dev": true, "requires": { - "define-properties": "1.1.3" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } } }, "regexpp": { @@ -7960,37 +8363,37 @@ "dev": true }, "regexpu-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", - "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", + "version": "4.7.0", + "resolved": "https://registry.npm.taobao.org/regexpu-core/download/regexpu-core-4.7.0.tgz?cache=0&sync_timestamp=1583949899397&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregexpu-core%2Fdownload%2Fregexpu-core-4.7.0.tgz", + "integrity": "sha1-/L9FjFBDGwu3tF1pZ7gZLZHz2Tg=", "dev": true, "requires": { - "regenerate": "1.4.0", - "regenerate-unicode-properties": "8.1.0", - "regjsgen": "0.5.1", - "regjsparser": "0.6.0", - "unicode-match-property-ecmascript": "1.0.4", - "unicode-match-property-value-ecmascript": "1.1.0" + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" } }, "regjsgen": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", - "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", + "version": "0.5.2", + "resolved": "https://registry.npm.taobao.org/regjsgen/download/regjsgen-0.5.2.tgz", + "integrity": "sha1-kv8pX7He7L9uzaslQ9IH6RqjNzM=", "dev": true }, "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "version": "0.6.4", + "resolved": "https://registry.npm.taobao.org/regjsparser/download/regjsparser-0.6.4.tgz", + "integrity": "sha1-p2n4aEMIQBpm6bUp0kNv9NBmYnI=", "dev": true, "requires": { - "jsesc": "0.5.0" + "jsesc": "~0.5.0" }, "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "https://registry.npm.taobao.org/jsesc/download/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } @@ -7998,66 +8401,66 @@ }, "remove-trailing-separator": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz", "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", "dev": true }, "repeat-element": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "resolved": "https://registry.npm.taobao.org/repeat-element/download/repeat-element-1.1.3.tgz", + "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=", "dev": true }, "repeat-string": { "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "resolved": "https://registry.npm.taobao.org/repeat-string/download/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "version": "2.88.2", + "resolved": "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz", + "integrity": "sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM=", "dev": true, "optional": true, "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.8.0", - "caseless": "0.12.0", - "combined-stream": "1.0.8", - "extend": "3.0.2", - "forever-agent": "0.6.1", - "form-data": "2.3.3", - "har-validator": "5.1.3", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.25", - "oauth-sign": "0.9.0", - "performance-now": "2.1.0", - "qs": "6.5.2", - "safe-buffer": "5.1.2", - "tough-cookie": "2.4.3", - "tunnel-agent": "0.6.0", - "uuid": "3.3.3" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" } }, "require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/require-directory/download/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "resolved": "https://registry.npm.taobao.org/require-main-filename/download/require-main-filename-2.0.0.tgz", + "integrity": "sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs=", "dev": true }, "requires-port": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/requires-port/download/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, @@ -8073,21 +8476,21 @@ "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", "dev": true, "requires": { - "path-parse": "1.0.6" + "path-parse": "^1.0.6" } }, "resolve-cwd": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/resolve-cwd/download/resolve-cwd-2.0.0.tgz", "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "requires": { - "resolve-from": "3.0.0" + "resolve-from": "^3.0.0" }, "dependencies": { "resolve-from": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/resolve-from/download/resolve-from-3.0.0.tgz", "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true } @@ -8095,23 +8498,23 @@ }, "resolve-dir": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/resolve-dir/download/resolve-dir-1.0.1.tgz", "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "global-modules": "1.0.0" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" }, "dependencies": { "global-modules": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "resolved": "https://registry.npm.taobao.org/global-modules/download/global-modules-1.0.0.tgz", + "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { - "global-prefix": "1.0.2", - "is-windows": "1.0.2", - "resolve-dir": "1.0.1" + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" } } } @@ -8124,7 +8527,7 @@ }, "resolve-url": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "resolved": "https://registry.npm.taobao.org/resolve-url/download/resolve-url-0.2.1.tgz?cache=0&sync_timestamp=1585438700247&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve-url%2Fdownload%2Fresolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, @@ -8134,19 +8537,19 @@ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" } }, "ret": { "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "resolved": "https://registry.npm.taobao.org/ret/download/ret-0.1.15.tgz", + "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", "dev": true }, "retry": { "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "resolved": "https://registry.npm.taobao.org/retry/download/retry-0.12.0.tgz", "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", "dev": true }, @@ -8162,17 +8565,17 @@ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { - "glob": "7.1.6" + "glob": "^7.1.3" } }, "ripemd160": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "resolved": "https://registry.npm.taobao.org/ripemd160/download/ripemd160-2.0.2.tgz", + "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=", "dev": true, "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.4" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, "run-async": { @@ -8181,16 +8584,16 @@ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "is-promise": "2.1.0" + "is-promise": "^2.1.0" } }, "run-queue": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "resolved": "https://registry.npm.taobao.org/run-queue/download/run-queue-1.0.3.tgz", "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", "dev": true, "requires": { - "aproba": "1.2.0" + "aproba": "^1.1.1" } }, "rw": { @@ -8204,22 +8607,22 @@ "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", "dev": true, "requires": { - "tslib": "1.10.0" + "tslib": "^1.9.0" } }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", "dev": true }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "0.1.15" + "ret": "~0.1.10" } }, "safer-buffer": { @@ -8233,21 +8636,21 @@ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "ajv": "6.10.2", - "ajv-errors": "1.0.1", - "ajv-keywords": "3.4.1" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, "select-hose": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/select-hose/download/select-hose-2.0.0.tgz", "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", "dev": true }, "selfsigned": { "version": "1.10.7", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz", - "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==", + "resolved": "https://registry.npm.taobao.org/selfsigned/download/selfsigned-1.10.7.tgz", + "integrity": "sha1-2lgZ/QSdVXTyjoipvMbbxubzkGs=", "dev": true, "requires": { "node-forge": "0.9.0" @@ -8261,117 +8664,120 @@ }, "send": { "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "resolved": "https://registry.npm.taobao.org/send/download/send-0.17.1.tgz", + "integrity": "sha1-wdiwWfeQD3Rm3Uk4vcROEd2zdsg=", "dev": true, "requires": { "debug": "2.6.9", - "depd": "1.1.2", - "destroy": "1.0.4", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.7.2", + "http-errors": "~1.7.2", "mime": "1.6.0", "ms": "2.1.1", - "on-finished": "2.3.0", - "range-parser": "1.2.1", - "statuses": "1.5.0" + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" }, "dependencies": { "ms": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.1.tgz", + "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", "dev": true } } }, "serialize-javascript": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", - "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", - "dev": true + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-3.1.0.tgz", + "integrity": "sha1-i/OpFwcSZk7yVhtEtpHq/jmSFOo=", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } }, "serve-index": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "resolved": "https://registry.npm.taobao.org/serve-index/download/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, "requires": { - "accepts": "1.3.7", + "accepts": "~1.3.4", "batch": "0.6.1", "debug": "2.6.9", - "escape-html": "1.0.3", - "http-errors": "1.6.3", - "mime-types": "2.1.25", - "parseurl": "1.3.3" + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" }, "dependencies": { "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.6.3.tgz?cache=0&sync_timestamp=1593407647372&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { - "depd": "1.1.2", + "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", - "statuses": "1.5.0" + "statuses": ">= 1.4.0 < 2" } }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "setprototypeof": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz?cache=0&sync_timestamp=1563425414995&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsetprototypeof%2Fdownload%2Fsetprototypeof-1.1.0.tgz", + "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=", "dev": true } } }, "serve-static": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "resolved": "https://registry.npm.taobao.org/serve-static/download/serve-static-1.14.1.tgz", + "integrity": "sha1-Zm5jbcTwEPfvKZcKiKZ0MgiYsvk=", "dev": true, "requires": { - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "parseurl": "1.3.3", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", "send": "0.17.1" } }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "set-value": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "resolved": "https://registry.npm.taobao.org/set-value/download/set-value-2.0.1.tgz?cache=0&sync_timestamp=1585775409029&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fset-value%2Fdownload%2Fset-value-2.0.1.tgz", + "integrity": "sha1-oY1AUw5vB95CKMfe/kInr4ytAFs=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" }, "dependencies": { "extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -8383,18 +8789,18 @@ }, "setprototypeof": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz?cache=0&sync_timestamp=1563425414995&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsetprototypeof%2Fdownload%2Fsetprototypeof-1.1.1.tgz", + "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM=", "dev": true }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "resolved": "https://registry.npm.taobao.org/sha.js/download/sha.js-2.4.11.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsha.js%2Fdownload%2Fsha.js-2.4.11.tgz", + "integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=", "dev": true, "requires": { - "inherits": "2.0.4", - "safe-buffer": "5.1.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "shebang-command": { @@ -8403,7 +8809,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "1.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { @@ -8412,6 +8818,52 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "side-channel": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/side-channel/download/side-channel-1.0.2.tgz", + "integrity": "sha1-310auttOS/SvHNiFK/Ey0veHaUc=", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "object-inspect": "^1.7.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -8420,8 +8872,8 @@ }, "slash": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "resolved": "https://registry.npm.taobao.org/slash/download/slash-2.0.0.tgz", + "integrity": "sha1-3lUoUaF1nfOo8gZTVEL17E3eq0Q=", "dev": true }, "slice-ansi": { @@ -8430,328 +8882,329 @@ "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "astral-regex": "1.0.0", - "is-fullwidth-code-point": "2.0.0" + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" } }, "snapdragon": { "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.2", - "use": "3.1.1" + "resolved": "https://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz", + "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" }, "dependencies": { "define-property": { "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } }, "snapdragon-node": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "resolved": "https://registry.npm.taobao.org/snapdragon-node/download/snapdragon-node-2.1.1.tgz", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" }, "dependencies": { "define-property": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } }, "snapdragon-util": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "resolved": "https://registry.npm.taobao.org/snapdragon-util/download/snapdragon-util-3.0.1.tgz", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.2.0" }, "dependencies": { "kind-of": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } }, "sockjs": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", - "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "version": "0.3.20", + "resolved": "https://registry.npm.taobao.org/sockjs/download/sockjs-0.3.20.tgz", + "integrity": "sha1-smooPsVi74smh7RAM6Tuzqx12FU=", "dev": true, "requires": { - "faye-websocket": "0.10.0", - "uuid": "3.3.3" + "faye-websocket": "^0.10.0", + "uuid": "^3.4.0", + "websocket-driver": "0.6.5" } }, "sockjs-client": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz", - "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==", + "resolved": "https://registry.npm.taobao.org/sockjs-client/download/sockjs-client-1.4.0.tgz", + "integrity": "sha1-yfJWjhnI/YFztJl+o0IOC7MGx9U=", "dev": true, "requires": { - "debug": "3.2.6", - "eventsource": "1.0.7", - "faye-websocket": "0.11.3", - "inherits": "2.0.4", - "json3": "3.3.3", - "url-parse": "1.4.7" + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" }, "dependencies": { "debug": { "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.1" } }, "faye-websocket": { "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "resolved": "https://registry.npm.taobao.org/faye-websocket/download/faye-websocket-0.11.3.tgz", + "integrity": "sha1-XA6aiWjokSwoZjn96XeosgnyUI4=", "dev": true, "requires": { - "websocket-driver": "0.7.3" + "websocket-driver": ">=0.5.1" } }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", "dev": true } } }, "source-list-map": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "resolved": "https://registry.npm.taobao.org/source-list-map/download/source-list-map-2.0.1.tgz", + "integrity": "sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ=", "dev": true }, "source-map": { "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "version": "0.5.3", + "resolved": "https://registry.npm.taobao.org/source-map-resolve/download/source-map-resolve-0.5.3.tgz?cache=0&sync_timestamp=1584831908370&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map-resolve%2Fdownload%2Fsource-map-resolve-0.5.3.tgz", + "integrity": "sha1-GQhmvs51U+H48mei7oLGBrVQmho=", "dev": true, "requires": { - "atob": "2.1.2", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "version": "0.5.19", + "resolved": "https://registry.npm.taobao.org/source-map-support/download/source-map-support-0.5.19.tgz?cache=0&sync_timestamp=1587719517036&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map-support%2Fdownload%2Fsource-map-support-0.5.19.tgz", + "integrity": "sha1-qYti+G3K9PZzmWSMCFKRq56P7WE=", "dev": true, "requires": { - "buffer-from": "1.1.1", - "source-map": "0.6.1" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" }, "dependencies": { "source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } }, "source-map-url": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "resolved": "https://registry.npm.taobao.org/source-map-url/download/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.1.tgz?cache=0&sync_timestamp=1590161967473&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fspdx-correct%2Fdownload%2Fspdx-correct-3.1.1.tgz", + "integrity": "sha1-3s6BrJweZxPl99G28X1Gj6U9iak=", "dev": true, "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.5" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz?cache=0&sync_timestamp=1587422410312&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fspdx-exceptions%2Fdownload%2Fspdx-exceptions-2.3.0.tgz", + "integrity": "sha1-PyjOGnegA3JoPq3kpDMYNSeiFj0=", "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/spdx-expression-parse/download/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha1-z3D1BILu/cmOPOCmgz5KU87rpnk=", "dev": true, "requires": { - "spdx-exceptions": "2.2.0", - "spdx-license-ids": "3.0.5" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "resolved": "https://registry.npm.taobao.org/spdx-license-ids/download/spdx-license-ids-3.0.5.tgz", + "integrity": "sha1-NpS1gEVnpFjTyARYQqY1hjL2JlQ=", "dev": true }, "spdy": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.1.tgz", - "integrity": "sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==", + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/spdy/download/spdy-4.0.2.tgz", + "integrity": "sha1-t09GYgOj7aRSwCSSuR+56EonZ3s=", "dev": true, "requires": { - "debug": "4.1.1", - "handle-thing": "2.0.0", - "http-deceiver": "1.2.7", - "select-hose": "2.0.0", - "spdy-transport": "3.0.0" + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" }, "dependencies": { "debug": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.1" } }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", "dev": true } } }, "spdy-transport": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "resolved": "https://registry.npm.taobao.org/spdy-transport/download/spdy-transport-3.0.0.tgz", + "integrity": "sha1-ANSGOmQArXXfkzYaFghgXl3NzzE=", "dev": true, "requires": { - "debug": "4.1.1", - "detect-node": "2.0.4", - "hpack.js": "2.1.6", - "obuf": "1.1.2", - "readable-stream": "3.4.0", - "wbuf": "1.7.3" + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" }, "dependencies": { "debug": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.1" } }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", "dev": true }, "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "version": "3.6.0", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz", + "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", "dev": true, "requires": { - "inherits": "2.0.4", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } } } }, "split-string": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "resolved": "https://registry.npm.taobao.org/split-string/download/split-string-3.1.0.tgz", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { - "extend-shallow": "3.0.2" + "extend-shallow": "^3.0.0" } }, "sprintf-js": { @@ -8762,95 +9215,95 @@ }, "sshpk": { "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "resolved": "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz", + "integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=", "dev": true, "optional": true, "requires": { - "asn1": "0.2.4", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.2", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.2", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "safer-buffer": "2.1.2", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" } }, "ssri": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "resolved": "https://registry.npm.taobao.org/ssri/download/ssri-6.0.1.tgz", + "integrity": "sha1-KjxBso3UW2K2Nnbst0ABJlrp7dg=", "dev": true, "requires": { - "figgy-pudding": "3.5.1" + "figgy-pudding": "^3.5.1" } }, "static-extend": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/static-extend/download/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" }, "dependencies": { "define-property": { "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } } } }, "statuses": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "resolved": "https://registry.npm.taobao.org/statuses/download/statuses-1.5.0.tgz?cache=0&sync_timestamp=1587328859420&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstatuses%2Fdownload%2Fstatuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, "stream-browserify": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "resolved": "https://registry.npm.taobao.org/stream-browserify/download/stream-browserify-2.0.2.tgz?cache=0&sync_timestamp=1587041519870&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstream-browserify%2Fdownload%2Fstream-browserify-2.0.2.tgz", + "integrity": "sha1-h1IdOKRKp+6RzhzSpH3wy0ndZgs=", "dev": true, "requires": { - "inherits": "2.0.4", - "readable-stream": "2.3.6" + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" } }, "stream-each": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "resolved": "https://registry.npm.taobao.org/stream-each/download/stream-each-1.2.3.tgz", + "integrity": "sha1-6+J6DDibBPvMIzZClS4Qcxr6m64=", "dev": true, "requires": { - "end-of-stream": "1.4.4", - "stream-shift": "1.0.0" + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" } }, "stream-http": { "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "resolved": "https://registry.npm.taobao.org/stream-http/download/stream-http-2.8.3.tgz?cache=0&sync_timestamp=1588701035785&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstream-http%2Fdownload%2Fstream-http-2.8.3.tgz", + "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=", "dev": true, "requires": { - "builtin-status-codes": "3.0.0", - "inherits": "2.0.4", - "readable-stream": "2.3.6", - "to-arraybuffer": "1.0.1", - "xtend": "4.0.2" + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" } }, "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/stream-shift/download/stream-shift-1.0.1.tgz?cache=0&sync_timestamp=1576147145118&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstream-shift%2Fdownload%2Fstream-shift-1.0.1.tgz", + "integrity": "sha1-1wiCgVWasneEJCebCHfaPDktWj0=", "dev": true }, "string-width": { @@ -8859,8 +9312,104 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string.prototype.matchall": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/string.prototype.matchall/download/string.prototype.matchall-4.0.2.tgz", + "integrity": "sha1-SLtRAyb7n962ozzqqBpuoE73ZI4=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.2" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/string.prototype.trimend/download/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha1-hYEqa4R6wAInD1gIFGBkyZX7aRM=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } } }, "string.prototype.trimleft": { @@ -8869,8 +9418,8 @@ "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", "dev": true, "requires": { - "define-properties": "1.1.3", - "function-bind": "1.1.1" + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" } }, "string.prototype.trimright": { @@ -8879,17 +9428,63 @@ "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", "dev": true, "requires": { - "define-properties": "1.1.3", - "function-bind": "1.1.1" + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/string.prototype.trimstart/download/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha1-FK9tnzSwU/fPyJty+PLuFLkDmlQ=", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.6.tgz?cache=0&sync_timestamp=1592109199190&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.6.tgz", + "integrity": "sha1-kUIHFweFeyysx7iey2cDFsPi1So=", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz?cache=0&sync_timestamp=1591427607174&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=", + "dev": true + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } } }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -8898,18 +9493,18 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } }, "strip-bom": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/strip-bom/download/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, @@ -8925,8 +9520,8 @@ "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", "dev": true, "requires": { - "loader-utils": "1.2.3", - "schema-utils": "1.0.0" + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" } }, "supports-color": { @@ -8935,7 +9530,7 @@ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } }, "table": { @@ -8944,10 +9539,10 @@ "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", "dev": true, "requires": { - "ajv": "6.10.2", - "lodash": "4.17.15", - "slice-ansi": "2.1.0", - "string-width": "3.1.0" + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" }, "dependencies": { "ansi-regex": { @@ -8962,9 +9557,9 @@ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "emoji-regex": "7.0.3", - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "5.2.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "strip-ansi": { @@ -8973,57 +9568,57 @@ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "4.1.0" + "ansi-regex": "^4.1.0" } } } }, "tapable": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "resolved": "https://registry.npm.taobao.org/tapable/download/tapable-1.1.3.tgz", + "integrity": "sha1-ofzMBrWNth/XpF2i2kT186Pme6I=", "dev": true }, "terser": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.0.tgz", - "integrity": "sha512-oDG16n2WKm27JO8h4y/w3iqBGAOSCtq7k8dRmrn4Wf9NouL0b2WpMHGChFGZq4nFAQy1FsNJrVQHfurXOSTmOA==", + "version": "4.8.0", + "resolved": "https://registry.npm.taobao.org/terser/download/terser-4.8.0.tgz?cache=0&sync_timestamp=1592448432005&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser%2Fdownload%2Fterser-4.8.0.tgz", + "integrity": "sha1-YwVjQ9fHC7KfOvZlhlpG/gOg3xc=", "dev": true, "requires": { - "commander": "2.20.3", - "source-map": "0.6.1", - "source-map-support": "0.5.16" + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" }, "dependencies": { "source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } }, "terser-webpack-plugin": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz", - "integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==", - "dev": true, - "requires": { - "cacache": "12.0.3", - "find-cache-dir": "2.1.0", - "is-wsl": "1.1.0", - "schema-utils": "1.0.0", - "serialize-javascript": "1.9.1", - "source-map": "0.6.1", - "terser": "4.4.0", - "webpack-sources": "1.4.3", - "worker-farm": "1.7.0" + "version": "1.4.4", + "resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-1.4.4.tgz?cache=0&sync_timestamp=1592492230913&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser-webpack-plugin%2Fdownload%2Fterser-webpack-plugin-1.4.4.tgz", + "integrity": "sha1-LGNUQ0cyS6r6mla6rd8WNMir/C8=", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^3.1.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" }, "dependencies": { "source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } @@ -9042,120 +9637,129 @@ }, "through2": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "resolved": "https://registry.npm.taobao.org/through2/download/through2-2.0.5.tgz?cache=0&sync_timestamp=1593478693312&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fthrough2%2Fdownload%2Fthrough2-2.0.5.tgz", + "integrity": "sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0=", "dev": true, "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.2" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, "thunky": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "resolved": "https://registry.npm.taobao.org/thunky/download/thunky-1.1.0.tgz?cache=0&sync_timestamp=1571043401546&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fthunky%2Fdownload%2Fthunky-1.1.0.tgz", + "integrity": "sha1-Wrr3FKlAXbBQRzK7zNLO3Z75U30=", "dev": true }, "timers-browserify": { "version": "2.0.11", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", - "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "resolved": "https://registry.npm.taobao.org/timers-browserify/download/timers-browserify-2.0.11.tgz", + "integrity": "sha1-gAsfPu4nLlvFPuRloE0OgEwxIR8=", "dev": true, "requires": { - "setimmediate": "1.0.5" + "setimmediate": "^1.0.4" } }, - "tinycolor2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", - "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "os-tmpdir": "1.0.2" + "os-tmpdir": "~1.0.2" } }, "to-arraybuffer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/to-arraybuffer/download/to-arraybuffer-1.0.1.tgz", "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, "to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, "to-object-path": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/to-object-path/download/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } }, "to-regex": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "resolved": "https://registry.npm.taobao.org/to-regex/download/to-regex-3.0.2.tgz", + "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", "dev": true, "requires": { - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "regex-not": "1.0.2", - "safe-regex": "1.1.0" + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" } }, "to-regex-range": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } }, "toidentifier": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "resolved": "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz", + "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=", "dev": true }, "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "version": "2.5.0", + "resolved": "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.5.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftough-cookie%2Fdownload%2Ftough-cookie-2.5.0.tgz", + "integrity": "sha1-zZ+yoKodWhK0c72fuW+j3P9lreI=", "dev": true, "optional": true, "requires": { - "psl": "1.4.0", - "punycode": "1.4.1" + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npm.taobao.org/tsconfig-paths/download/tsconfig-paths-3.9.0.tgz", + "integrity": "sha1-CYVHpsREiAfo/Ljq4IEGTumjyQs=", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" }, "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz?cache=0&sync_timestamp=1586046271069&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-1.0.1.tgz", + "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", "dev": true, - "optional": true + "requires": { + "minimist": "^1.2.0" + } } } }, @@ -9167,25 +9771,26 @@ }, "tty-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/tty-browserify/download/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, "tunnel-agent": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "resolved": "https://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "optional": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "resolved": "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true + "dev": true, + "optional": true }, "type-check": { "version": "0.3.2", @@ -9193,22 +9798,22 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "type-is": { "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "resolved": "https://registry.npm.taobao.org/type-is/download/type-is-1.6.18.tgz", + "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=", "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.25" + "mime-types": "~2.1.24" } }, "typedarray": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "resolved": "https://registry.npm.taobao.org/typedarray/download/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, @@ -9219,42 +9824,42 @@ }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "resolved": "https://registry.npm.taobao.org/unicode-canonical-property-names-ecmascript/download/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha1-JhmADEyCWADv3YNDr33Zkzy+KBg=", "dev": true }, "unicode-match-property-ecmascript": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "resolved": "https://registry.npm.taobao.org/unicode-match-property-ecmascript/download/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw=", "dev": true, "requires": { - "unicode-canonical-property-names-ecmascript": "1.0.4", - "unicode-property-aliases-ecmascript": "1.0.5" + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" } }, "unicode-match-property-value-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", - "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/unicode-match-property-value-ecmascript/download/unicode-match-property-value-ecmascript-1.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funicode-match-property-value-ecmascript%2Fdownload%2Funicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha1-DZH2AO7rMJaqlisdb8iIduZOpTE=", "dev": true }, "unicode-property-aliases-ecmascript": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", - "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/unicode-property-aliases-ecmascript/download/unicode-property-aliases-ecmascript-1.1.0.tgz?cache=0&sync_timestamp=1583945805856&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funicode-property-aliases-ecmascript%2Fdownload%2Funicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha1-3Vepn2IHvt/0Yoq++5TFDblByPQ=", "dev": true }, "union-value": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "resolved": "https://registry.npm.taobao.org/union-value/download/union-value-1.0.1.tgz", + "integrity": "sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc=", "dev": true, "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "2.0.1" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" } }, "uniq": { @@ -9265,52 +9870,52 @@ }, "unique-filename": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "resolved": "https://registry.npm.taobao.org/unique-filename/download/unique-filename-1.1.1.tgz", + "integrity": "sha1-HWl2k2mtoFgxA6HmrodoG1ZXMjA=", "dev": true, "requires": { - "unique-slug": "2.0.2" + "unique-slug": "^2.0.0" } }, "unique-slug": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "resolved": "https://registry.npm.taobao.org/unique-slug/download/unique-slug-2.0.2.tgz", + "integrity": "sha1-uqvOkQg/xk6UWw861hPiZPfNTmw=", "dev": true, "requires": { - "imurmurhash": "0.1.4" + "imurmurhash": "^0.1.4" } }, "unpipe": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, "unset-value": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/unset-value/download/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" + "has-value": "^0.3.1", + "isobject": "^3.0.0" }, "dependencies": { "has-value": { "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "resolved": "https://registry.npm.taobao.org/has-value/download/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" }, "dependencies": { "isobject": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/isobject/download/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "requires": { @@ -9321,7 +9926,7 @@ }, "has-values": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "resolved": "https://registry.npm.taobao.org/has-values/download/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true } @@ -9329,8 +9934,8 @@ }, "upath": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "resolved": "https://registry.npm.taobao.org/upath/download/upath-1.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fupath%2Fdownload%2Fupath-1.2.0.tgz", + "integrity": "sha1-j2bbzVWog6za5ECK+LA1pQRMGJQ=", "dev": true }, "uri-js": { @@ -9339,18 +9944,18 @@ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "requires": { - "punycode": "2.1.1" + "punycode": "^2.1.0" } }, "urix": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/urix/download/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, "url": { "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "resolved": "https://registry.npm.taobao.org/url/download/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, "requires": { @@ -9360,7 +9965,7 @@ "dependencies": { "punycode": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true } @@ -9368,24 +9973,24 @@ }, "url-parse": { "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "resolved": "https://registry.npm.taobao.org/url-parse/download/url-parse-1.4.7.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Furl-parse%2Fdownload%2Furl-parse-1.4.7.tgz", + "integrity": "sha1-qKg1NejACjFuQDpdtKwbm4U64ng=", "dev": true, "requires": { - "querystringify": "2.1.1", - "requires-port": "1.0.0" + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" } }, "use": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "resolved": "https://registry.npm.taobao.org/use/download/use-3.1.1.tgz", + "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=", "dev": true }, "util": { "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "resolved": "https://registry.npm.taobao.org/util/download/util-0.11.1.tgz?cache=0&sync_timestamp=1588238457176&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Futil%2Fdownload%2Futil-0.11.1.tgz", + "integrity": "sha1-MjZzNyDsZLsn9uJvQhqqLhtYjWE=", "dev": true, "requires": { "inherits": "2.0.3" @@ -9393,7 +9998,7 @@ "dependencies": { "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true } @@ -9401,408 +10006,464 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, "utils-merge": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", "dev": true }, "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", + "version": "3.4.0", + "resolved": "https://registry.npm.taobao.org/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1592944373333&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz", + "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=", "dev": true }, "v8-compile-cache": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz", - "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==", + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/v8-compile-cache/download/v8-compile-cache-2.1.1.tgz?cache=0&sync_timestamp=1590872707384&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fv8-compile-cache%2Fdownload%2Fv8-compile-cache-2.1.1.tgz", + "integrity": "sha1-VLw83UMxe8qR413K8wWxpyN950U=", "dev": true }, "validate-npm-package-license": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "resolved": "https://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", "dev": true, "requires": { - "spdx-correct": "3.1.0", - "spdx-expression-parse": "3.0.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, "vary": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true }, "verror": { "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "resolved": "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "optional": true, "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" } }, "vm-browserify": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "resolved": "https://registry.npm.taobao.org/vm-browserify/download/vm-browserify-1.1.2.tgz?cache=0&sync_timestamp=1572870776965&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvm-browserify%2Fdownload%2Fvm-browserify-1.1.2.tgz", + "integrity": "sha1-eGQcSIuObKkadfUR56OzKobl3aA=", "dev": true }, "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "version": "1.7.2", + "resolved": "https://registry.npm.taobao.org/watchpack/download/watchpack-1.7.2.tgz", + "integrity": "sha1-wC5NTUmRPD5+EiwzJTZa+dMx6ao=", + "dev": true, + "requires": { + "chokidar": "^3.4.0", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-3.1.1.tgz", + "integrity": "sha1-xV7PAhheJGklk5kxDBc84xIzsUI=", + "dev": true, + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-2.1.0.tgz?cache=0&sync_timestamp=1593261331793&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbinary-extensions%2Fdownload%2Fbinary-extensions-2.1.0.tgz", + "integrity": "sha1-MPpAyef+B9vIlWeM0ocCTeokHdk=", + "dev": true, + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz", + "integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc=", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.4.0", + "resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-3.4.0.tgz?cache=0&sync_timestamp=1587911196018&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-3.4.0.tgz", + "integrity": "sha1-swYRQjzjdjV8dlubj5BLn7o8C+g=", + "dev": true, + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz", + "integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA=", + "dev": true, + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-2.1.3.tgz?cache=0&sync_timestamp=1588787369955&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffsevents%2Fdownload%2Ffsevents-2.1.3.tgz", + "integrity": "sha1-+3OHA66NL5/pAMM4Nt3r7ouX8j4=", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-5.1.1.tgz", + "integrity": "sha1-tsHvQXxOVmPqSY8cRa+saRa7wik=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-2.1.0.tgz", + "integrity": "sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz", + "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-3.4.0.tgz?cache=0&sync_timestamp=1584985910691&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-3.4.0.tgz", + "integrity": "sha1-n9zN+ekVWAVEkiGsZF6DA6tbmto=", + "dev": true, + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-5.0.1.tgz", + "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=", + "dev": true, + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/watchpack-chokidar2/download/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha1-mUihhmy71suCTeoTp+1pH2yN3/A=", "dev": true, + "optional": true, "requires": { - "chokidar": "2.1.8", - "graceful-fs": "4.2.3", - "neo-async": "2.6.1" + "chokidar": "^2.1.8" } }, "wbuf": { "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "resolved": "https://registry.npm.taobao.org/wbuf/download/wbuf-1.7.3.tgz", + "integrity": "sha1-wdjRSTFtPqhShIiVy2oL/oh7h98=", "dev": true, "requires": { - "minimalistic-assert": "1.0.1" + "minimalistic-assert": "^1.0.0" } }, "webpack": { - "version": "4.41.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz", - "integrity": "sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/wasm-edit": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "6.3.0", - "ajv": "6.10.2", - "ajv-keywords": "3.4.1", - "chrome-trace-event": "1.0.2", - "enhanced-resolve": "4.1.1", - "eslint-scope": "4.0.3", - "json-parse-better-errors": "1.0.2", - "loader-runner": "2.4.0", - "loader-utils": "1.2.3", - "memory-fs": "0.4.1", - "micromatch": "3.1.10", - "mkdirp": "0.5.1", - "neo-async": "2.6.1", - "node-libs-browser": "2.2.1", - "schema-utils": "1.0.0", - "tapable": "1.1.3", - "terser-webpack-plugin": "1.4.1", - "watchpack": "1.6.0", - "webpack-sources": "1.4.3" + "version": "4.43.0", + "resolved": "https://registry.npm.taobao.org/webpack/download/webpack-4.43.0.tgz?cache=0&sync_timestamp=1593446690098&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack%2Fdownload%2Fwebpack-4.43.0.tgz", + "integrity": "sha1-xIVHsR1WMiTFYdrRFyyKoLimeOY=", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.6.1", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npm.taobao.org/acorn/download/acorn-6.4.1.tgz?cache=0&sync_timestamp=1591869432510&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn%2Fdownload%2Facorn-6.4.1.tgz", + "integrity": "sha1-Ux5Yuj9RudrLmmZGyk3r9bFMpHQ=", + "dev": true + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz", + "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1587535418745&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz", + "integrity": "sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } } }, "webpack-cli": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.10.tgz", - "integrity": "sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg==", - "dev": true, - "requires": { - "chalk": "2.4.2", - "cross-spawn": "6.0.5", - "enhanced-resolve": "4.1.0", - "findup-sync": "3.0.0", - "global-modules": "2.0.0", - "import-local": "2.0.0", - "interpret": "1.2.0", - "loader-utils": "1.2.3", - "supports-color": "6.1.0", - "v8-compile-cache": "2.0.3", - "yargs": "13.2.4" + "version": "3.3.12", + "resolved": "https://registry.npm.taobao.org/webpack-cli/download/webpack-cli-3.3.12.tgz?cache=0&sync_timestamp=1592482091989&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-cli%2Fdownload%2Fwebpack-cli-3.3.12.tgz", + "integrity": "sha1-lOmtoIFFPNCqYJyZ5QABL9OtLUo=", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.1", + "findup-sync": "^3.0.0", + "global-modules": "^2.0.0", + "import-local": "^2.0.0", + "interpret": "^1.4.0", + "loader-utils": "^1.4.0", + "supports-color": "^6.1.0", + "v8-compile-cache": "^2.1.1", + "yargs": "^13.3.2" }, "dependencies": { - "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz", + "integrity": "sha1-VXBmIEatKeLpFucariYKvf9Pang=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz?cache=0&sync_timestamp=1586046271069&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-1.0.1.tgz", + "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-1.4.0.tgz", + "integrity": "sha1-xXm140yzSxp07cbB+za/o3HVphM=", "dev": true, "requires": { - "graceful-fs": "4.2.3", - "memory-fs": "0.4.1", - "tapable": "1.1.3" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" } }, "supports-color": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-6.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-6.1.0.tgz", + "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } } } }, "webpack-dev-middleware": { "version": "3.7.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", - "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", + "resolved": "https://registry.npm.taobao.org/webpack-dev-middleware/download/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha1-ABnD23FuP6XOy/ZPKriKdLqzMfM=", "dev": true, "requires": { - "memory-fs": "0.4.1", - "mime": "2.4.4", - "mkdirp": "0.5.1", - "range-parser": "1.2.1", - "webpack-log": "2.0.0" + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" }, "dependencies": { "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "version": "2.4.6", + "resolved": "https://registry.npm.taobao.org/mime/download/mime-2.4.6.tgz?cache=0&sync_timestamp=1590596706367&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime%2Fdownload%2Fmime-2.4.6.tgz", + "integrity": "sha1-5bQHyQ20QvK+tbFiNz0Htpr/pNE=", "dev": true } } }, "webpack-dev-server": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.9.0.tgz", - "integrity": "sha512-E6uQ4kRrTX9URN9s/lIbqTAztwEPdvzVrcmHE8EQ9YnuT9J8Es5Wrd8n9BKg1a0oZ5EgEke/EQFgUsp18dSTBw==", + "version": "3.11.0", + "resolved": "https://registry.npm.taobao.org/webpack-dev-server/download/webpack-dev-server-3.11.0.tgz", + "integrity": "sha1-jxVKO84bz9HMYY705wMniFXn/4w=", "dev": true, "requires": { "ansi-html": "0.0.7", - "bonjour": "3.5.0", - "chokidar": "2.1.8", - "compression": "1.7.4", - "connect-history-api-fallback": "1.6.0", - "debug": "4.1.1", - "del": "4.1.1", - "express": "4.17.1", - "html-entities": "1.2.1", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", "http-proxy-middleware": "0.19.1", - "import-local": "2.0.0", - "internal-ip": "4.3.0", - "ip": "1.1.5", - "is-absolute-url": "3.0.3", - "killable": "1.0.1", - "loglevel": "1.6.6", - "opn": "5.5.0", - "p-retry": "3.0.1", - "portfinder": "1.0.25", - "schema-utils": "1.0.0", - "selfsigned": "1.10.7", - "semver": "6.3.0", - "serve-index": "1.9.1", - "sockjs": "0.3.19", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.7", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "0.3.20", "sockjs-client": "1.4.0", - "spdy": "4.0.1", - "strip-ansi": "3.0.1", - "supports-color": "6.1.0", - "url": "0.11.0", - "webpack-dev-middleware": "3.7.2", - "webpack-log": "2.0.0", - "ws": "6.2.1", - "yargs": "12.0.5" + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" }, "dependencies": { "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, "debug": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "ms": "^2.1.1" } }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", "dev": true }, "semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-6.3.0.tgz", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", "dev": true }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "supports-color": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "4.1.0", - "decamelize": "1.2.0", - "find-up": "3.0.0", - "get-caller-file": "1.0.3", - "os-locale": "3.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "4.0.0", - "yargs-parser": "11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-6.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-6.1.0.tgz", + "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", "dev": true, "requires": { - "camelcase": "5.3.1", - "decamelize": "1.2.0" + "has-flag": "^3.0.0" } } } }, "webpack-log": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "resolved": "https://registry.npm.taobao.org/webpack-log/download/webpack-log-2.0.0.tgz", + "integrity": "sha1-W3ko4GN1k/EZ0y9iJ8HgrDHhtH8=", "dev": true, "requires": { - "ansi-colors": "3.2.4", - "uuid": "3.3.3" + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" } }, "webpack-sources": { "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "resolved": "https://registry.npm.taobao.org/webpack-sources/download/webpack-sources-1.4.3.tgz", + "integrity": "sha1-7t2OwLko+/HL/plOItLYkPMwqTM=", "dev": true, "requires": { - "source-list-map": "2.0.1", - "source-map": "0.6.1" + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" }, "dependencies": { "source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } }, "websocket-driver": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", - "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", + "version": "0.6.5", + "resolved": "https://registry.npm.taobao.org/websocket-driver/download/websocket-driver-0.6.5.tgz?cache=0&sync_timestamp=1591288600527&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebsocket-driver%2Fdownload%2Fwebsocket-driver-0.6.5.tgz", + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", "dev": true, "requires": { - "http-parser-js": "0.4.10", - "safe-buffer": "5.1.2", - "websocket-extensions": "0.1.3" + "websocket-extensions": ">=0.1.1" } }, "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "version": "0.1.4", + "resolved": "https://registry.npm.taobao.org/websocket-extensions/download/websocket-extensions-0.1.4.tgz", + "integrity": "sha1-f4RzvIOd/YdgituV1+sHUhFXikI=", "dev": true }, "whatwg-fetch": { @@ -9816,12 +10477,12 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "which-module": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/which-module/download/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, @@ -9838,48 +10499,48 @@ }, "worker-farm": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "resolved": "https://registry.npm.taobao.org/worker-farm/download/worker-farm-1.7.0.tgz", + "integrity": "sha1-JqlMU5G7ypJhUgAvabhKS/dy5ag=", "dev": true, "requires": { - "errno": "0.1.7" + "errno": "~0.1.7" } }, "wrap-ansi": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-5.1.0.tgz?cache=0&sync_timestamp=1587574768060&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwrap-ansi%2Fdownload%2Fwrap-ansi-5.1.0.tgz", + "integrity": "sha1-H9H2cjXVttD+54EFYAG/tpTAOwk=", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "string-width": "3.1.0", - "strip-ansi": "5.2.0" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" }, "dependencies": { "ansi-regex": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-4.1.0.tgz", + "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=", "dev": true }, "string-width": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", "dev": true, "requires": { - "emoji-regex": "7.0.3", - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "5.2.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "strip-ansi": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz", + "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=", "dev": true, "requires": { - "ansi-regex": "4.1.0" + "ansi-regex": "^4.1.0" } } } @@ -9896,91 +10557,90 @@ "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", "dev": true, "requires": { - "mkdirp": "0.5.1" + "mkdirp": "^0.5.1" } }, "ws": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "resolved": "https://registry.npm.taobao.org/ws/download/ws-6.2.1.tgz", + "integrity": "sha1-RC/fCkftZPWbal2P8TD0dI7VJPs=", "dev": true, "requires": { - "async-limiter": "1.0.1" + "async-limiter": "~1.0.0" } }, "xtend": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "resolved": "https://registry.npm.taobao.org/xtend/download/xtend-4.0.2.tgz", + "integrity": "sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q=", "dev": true }, "y18n": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "resolved": "https://registry.npm.taobao.org/y18n/download/y18n-4.0.0.tgz", + "integrity": "sha1-le+U+F7MgdAHwmThkKEg8KPIVms=", "dev": true }, "yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-3.1.1.tgz", + "integrity": "sha1-27fa+b/YusmrRev2ArjLrQ1dCP0=", "dev": true }, "yargs": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", - "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", - "dev": true, - "requires": { - "cliui": "5.0.0", - "find-up": "3.0.0", - "get-caller-file": "2.0.5", - "os-locale": "3.1.0", - "require-directory": "2.1.1", - "require-main-filename": "2.0.0", - "set-blocking": "2.0.0", - "string-width": "3.1.0", - "which-module": "2.0.0", - "y18n": "4.0.0", - "yargs-parser": "13.1.1" + "version": "13.3.2", + "resolved": "https://registry.npm.taobao.org/yargs/download/yargs-13.3.2.tgz?cache=0&sync_timestamp=1593578283566&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs%2Fdownload%2Fyargs-13.3.2.tgz", + "integrity": "sha1-rX/+/sGqWVZayRX4Lcyzipwxot0=", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" }, "dependencies": { "ansi-regex": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-4.1.0.tgz", + "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=", "dev": true }, "string-width": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", "dev": true, "requires": { - "emoji-regex": "7.0.3", - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "5.2.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "strip-ansi": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz", + "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=", "dev": true, "requires": { - "ansi-regex": "4.1.0" + "ansi-regex": "^4.1.0" } } } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "13.1.2", + "resolved": "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-13.1.2.tgz", + "integrity": "sha1-Ew8JcC667vJlDVTObj5XBvek+zg=", "dev": true, "requires": { - "camelcase": "5.3.1", - "decamelize": "1.2.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } diff --git a/saga/seata-saga-statemachine-designer/package.json b/saga/seata-saga-statemachine-designer/package.json index 76a7412bc1fc8fe60fd1ac76a6a6ef8ce5270a3b..2efa0c77429a4b9e8494d6deb440aadca0526d58 100644 --- a/saga/seata-saga-statemachine-designer/package.json +++ b/saga/seata-saga-statemachine-designer/package.json @@ -49,24 +49,23 @@ }, "dependencies": { "@antv/g6": "^2.2.6", - "codemirror": "^5.49.2", - "core-js": "^3.0.0", - "gg-editor-core": "1.3.4", + "codemirror": "^5.55.0", + "core-js": "^3.6.5", "lodash": "^4.17.10", "react-codemirror": "^1.0.0" }, "devDependencies": { - "@babel/cli": "^7.2.3", - "@babel/core": "^7.2.2", - "@babel/plugin-proposal-class-properties": "^7.2.3", - "@babel/plugin-transform-modules-commonjs": "^7.2.0", - "@babel/plugin-transform-runtime": "^7.2.0", - "@babel/polyfill": "^7.2.5", - "@babel/preset-env": "^7.2.3", - "@babel/preset-react": "^7.0.0", - "@babel/runtime": "^7.2.0", - "babel-eslint": "^10.0.1", - "babel-loader": "^8.0.4", + "@babel/cli": "^7.10.4", + "@babel/core": "^7.10.4", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-runtime": "^7.10.4", + "@babel/polyfill": "^7.10.4", + "@babel/preset-env": "^7.10.4", + "@babel/preset-react": "^7.10.4", + "@babel/runtime": "^7.10.4", + "babel-eslint": "^10.1.0", + "babel-loader": "^8.1.0", "babel-plugin-module-resolver": "^3.1.1", "babel-plugin-transform-inline-environment-variables": "^0.4.3", "cross-env": "^5.2.0", @@ -74,22 +73,22 @@ "cz-conventional-changelog": "^2.1.0", "eslint": "^5.11.1", "eslint-config-airbnb": "^17.1.0", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-jsx-a11y": "^6.1.2", - "eslint-plugin-react": "^7.11.1", - "less": "^3.9.0", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-jsx-a11y": "^6.3.1", + "eslint-plugin-react": "^7.20.3", + "less": "^3.11.3", "less-loader": "^4.1.0", "postcss-loader": "^3.0.0", "postcss-preset-env": "^6.5.0", "rimraf": "^2.6.2", "style-loader": "^0.23.1", - "webpack": "^4.28.2", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.14" + "webpack": "^4.43.0", + "webpack-cli": "^3.3.12", + "webpack-dev-server": "^3.11.0" }, "config": { "commitizen": { "path": "./node_modules/cz-conventional-changelog" } } -} \ No newline at end of file +} diff --git a/saga/seata-saga-statemachine-designer/src/Flow/WorkSpace.js b/saga/seata-saga-statemachine-designer/src/Flow/WorkSpace.js index 7b19f45e5ff38caabccdbf49bfc7c20655daf765..cd9d26c25e4e9f7ccd3a0e7627daf310241c6468 100644 --- a/saga/seata-saga-statemachine-designer/src/Flow/WorkSpace.js +++ b/saga/seata-saga-statemachine-designer/src/Flow/WorkSpace.js @@ -8,6 +8,7 @@ import 'codemirror/mode/javascript/javascript' const nodeIndexes = { Start: 1, ServiceTask: 1, + ScriptTask: 1, Compensation: 1, Choice: 1, Succeed: 1, @@ -38,7 +39,7 @@ class WorkSpaceBase extends React.Component { const { executeCommand, update } = propsAPI; if (param.action == 'add' && param.item.type == 'edge') { - // Default polyline-round type + // Default polyline-round type @FIXME polyline-round has a bug if (param.item.target && param.item.target.model && param.item.source @@ -88,6 +89,7 @@ class WorkSpaceBase extends React.Component { param.item.model.stateId = param.item.model.stateId + nodeIndexes[param.item.model.stateType]++; if (param.item.model.stateType == 'ServiceTask' || param.item.model.stateType == 'Compensation' + || param.item.model.stateType == 'ScriptTask' || param.item.model.stateType == 'SubStateMachine') { param.item.model.label = param.item.model.stateId; } diff --git a/saga/seata-saga-statemachine-designer/src/components/EditorItemPanel/FlowItemPanel.js b/saga/seata-saga-statemachine-designer/src/components/EditorItemPanel/FlowItemPanel.js index 9df887cbe0b18ef659181ab1ea44a5c2e7c56c13..7b38602c99e00fb68ebb816c526633f610618213 100644 --- a/saga/seata-saga-statemachine-designer/src/components/EditorItemPanel/FlowItemPanel.js +++ b/saga/seata-saga-statemachine-designer/src/components/EditorItemPanel/FlowItemPanel.js @@ -23,6 +23,15 @@ const serviceTaskPropsTemplate = { "Retry": [ ] }; +const scriptTaskPropsTemplate = { + "ScriptType": "groovy", + "ScriptContent": "", + "Input": [ + {} + ], + "Output": { + } +}; const compensationPropsTemplate = { "ServiceName": "", "ServiceMethod": "", @@ -79,6 +88,19 @@ const FlowItemPanel = () => { }} src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTE4IiBoZWlnaHQ9IjU2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48ZGVmcz48cmVjdCBpZD0iYiIgeD0iMCIgeT0iMCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI0OCIgcng9IjQiLz48ZmlsdGVyIHg9Ii04LjglIiB5PSItMTAuNCUiIHdpZHRoPSIxMTcuNSUiIGhlaWdodD0iMTI5LjIlIiBmaWx0ZXJVbml0cz0ib2JqZWN0Qm91bmRpbmdCb3giIGlkPSJhIj48ZmVPZmZzZXQgZHk9IjIiIGluPSJTb3VyY2VBbHBoYSIgcmVzdWx0PSJzaGFkb3dPZmZzZXRPdXRlcjEiLz48ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIyIiBpbj0ic2hhZG93T2Zmc2V0T3V0ZXIxIiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb21wb3NpdGUgaW49InNoYWRvd0JsdXJPdXRlcjEiIGluMj0iU291cmNlQWxwaGEiIG9wZXJhdG9yPSJvdXQiIHJlc3VsdD0ic2hhZG93Qmx1ck91dGVyMSIvPjxmZUNvbG9yTWF0cml4IHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMC4wNCAwIiBpbj0ic2hhZG93Qmx1ck91dGVyMSIvPjwvZmlsdGVyPjwvZGVmcz48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQgMikiPjx1c2UgZmlsbD0iIzAwMCIgZmlsdGVyPSJ1cmwoI2EpIiB4bGluazpocmVmPSIjYiIvPjx1c2UgZmlsbC1vcGFjaXR5PSIuOTIiIGZpbGw9IiNFNkY3RkYiIHhsaW5rOmhyZWY9IiNiIi8+PHJlY3Qgc3Ryb2tlPSIjMTg5MEZGIiB4PSIuNSIgeT0iLjUiIHdpZHRoPSIxMDkiIGhlaWdodD0iNDciIHJ4PSI0Ii8+PC9nPjx0ZXh0IGZvbnQtZmFtaWx5PSJQaW5nRmFuZ1NDLVJlZ3VsYXIsIFBpbmdGYW5nIFNDIiBmb250LXNpemU9IjEyIiBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9Ii42NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNCAyKSI+PHRzcGFuIHg9IjIxIiB5PSIyOSI+U2VydmljZVRhc2s8L3RzcGFuPjwvdGV4dD48L2c+PC9zdmc+" /> + <Item + type="node" + size="110*48" + shape="flow-rect" + model={{ + color: '#13C2C2', + label: 'ScriptTask', + stateId: 'ScriptTask', + stateType: 'ScriptTask', + stateProps: scriptTaskPropsTemplate, + }} + src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTE4IiBoZWlnaHQ9IjU2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48ZGVmcz48cmVjdCBpZD0iYiIgeD0iMCIgeT0iMCIgd2lkdGg9IjExMCIgaGVpZ2h0PSI0OCIgcng9IjQiLz48ZmlsdGVyIHg9Ii04LjglIiB5PSItMTAuNCUiIHdpZHRoPSIxMTcuNSUiIGhlaWdodD0iMTI5LjIlIiBmaWx0ZXJVbml0cz0ib2JqZWN0Qm91bmRpbmdCb3giIGlkPSJhIj48ZmVPZmZzZXQgZHk9IjIiIGluPSJTb3VyY2VBbHBoYSIgcmVzdWx0PSJzaGFkb3dPZmZzZXRPdXRlcjEiLz48ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIyIiBpbj0ic2hhZG93T2Zmc2V0T3V0ZXIxIiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb21wb3NpdGUgaW49InNoYWRvd0JsdXJPdXRlcjEiIGluMj0iU291cmNlQWxwaGEiIG9wZXJhdG9yPSJvdXQiIHJlc3VsdD0ic2hhZG93Qmx1ck91dGVyMSIvPjxmZUNvbG9yTWF0cml4IHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMC4wNCAwIiBpbj0ic2hhZG93Qmx1ck91dGVyMSIvPjwvZmlsdGVyPjwvZGVmcz48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQgMikiPjx1c2UgZmlsbD0iIzAwMCIgZmlsdGVyPSJ1cmwoI2EpIiB4bGluazpocmVmPSIjYiIvPjx1c2UgZmlsbC1vcGFjaXR5PSIuOTIiIGZpbGw9IiNFNkZGRkIiIHhsaW5rOmhyZWY9IiNiIi8+PHJlY3Qgc3Ryb2tlPSIjNUNEQkQzIiB4PSIuNSIgeT0iLjUiIHdpZHRoPSIxMDkiIGhlaWdodD0iNDciIHJ4PSI0Ii8+PC9nPjx0ZXh0IGZvbnQtZmFtaWx5PSJQaW5nRmFuZ1NDLVJlZ3VsYXIsIFBpbmdGYW5nIFNDIiBmb250LXNpemU9IjEyIiBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9Ii42NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNCAyKSI+PHRzcGFuIHg9IjI0IiB5PSIyOSI+U2NyaXB0VGFzazwvdHNwYW4+PC90ZXh0PjwvZz48L3N2Zz4=" + /> <Item type="node" size="80*72" diff --git a/saga/seata-saga-statemachine-designer/tools/webpack.config.base.js b/saga/seata-saga-statemachine-designer/tools/webpack.config.base.js index 52cdcc729f9d8984dbfd8222b9b6a6f140b691db..68970d6d22d76b0aed9ca6a8d66874afeee2fff1 100644 --- a/saga/seata-saga-statemachine-designer/tools/webpack.config.base.js +++ b/saga/seata-saga-statemachine-designer/tools/webpack.config.base.js @@ -4,6 +4,7 @@ const rules = [{ test: /\.js$/, exclude: [ path.resolve(__dirname, 'node_modules'), + path.resolve(__dirname, '../ggeditor/gg-editor-core/bundle.js'), ], use: { loader: 'babel-loader', diff --git a/saga/seata-saga-tm/src/main/java/io/seata/saga/tm/DefaultSagaTransactionalTemplate.java b/saga/seata-saga-tm/src/main/java/io/seata/saga/tm/DefaultSagaTransactionalTemplate.java index 88ddf977e795d3bac5249301248e6cdc3dffbc69..a07a05c4faf3ae92bba6279c4b1f636b3881e9b2 100644 --- a/saga/seata-saga-tm/src/main/java/io/seata/saga/tm/DefaultSagaTransactionalTemplate.java +++ b/saga/seata-saga-tm/src/main/java/io/seata/saga/tm/DefaultSagaTransactionalTemplate.java @@ -21,9 +21,9 @@ import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; import io.seata.core.model.GlobalStatus; -import io.seata.core.rpc.netty.RmRpcClient; -import io.seata.core.rpc.netty.ShutdownHook; -import io.seata.core.rpc.netty.TmRpcClient; +import io.seata.core.rpc.netty.RmNettyRemotingClient; +import io.seata.core.rpc.ShutdownHook; +import io.seata.core.rpc.netty.TmNettyRemotingClient; import io.seata.rm.DefaultResourceManager; import io.seata.rm.RMClient; import io.seata.saga.rm.SagaResource; @@ -246,8 +246,8 @@ public class DefaultSagaTransactionalTemplate ((ConfigurableApplicationContext)applicationContext).registerShutdownHook(); ShutdownHook.removeRuntimeShutdownHook(); } - ShutdownHook.getInstance().addDisposable(TmRpcClient.getInstance(applicationId, txServiceGroup)); - ShutdownHook.getInstance().addDisposable(RmRpcClient.getInstance(applicationId, txServiceGroup)); + ShutdownHook.getInstance().addDisposable(TmNettyRemotingClient.getInstance(applicationId, txServiceGroup)); + ShutdownHook.getInstance().addDisposable(RmNettyRemotingClient.getInstance(applicationId, txServiceGroup)); } @Override diff --git a/script/client/at/db/mysql.sql b/script/client/at/db/mysql.sql index 6dac3a096de870cc888c06b9b3271cf5f7dac355..c55fcb984f35d25d8e83770505559fd0fbac04c1 100644 --- a/script/client/at/db/mysql.sql +++ b/script/client/at/db/mysql.sql @@ -1,16 +1,14 @@ -- for AT mode you must to init this sql for you business database. the seata server not need it. CREATE TABLE IF NOT EXISTS `undo_log` ( - `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'increment id', `branch_id` BIGINT(20) NOT NULL COMMENT 'branch transaction id', `xid` VARCHAR(100) NOT NULL COMMENT 'global transaction id', `context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization', `rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info', `log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status', - `log_created` DATETIME NOT NULL COMMENT 'create datetime', - `log_modified` DATETIME NOT NULL COMMENT 'modify datetime', - PRIMARY KEY (`id`), + `log_created` DATETIME(6) NOT NULL COMMENT 'create datetime', + `log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime', UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) ) ENGINE = InnoDB AUTO_INCREMENT = 1 - DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table'; \ No newline at end of file + DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table'; diff --git a/script/client/conf/file.conf b/script/client/conf/file.conf index da40097ca737f5bc2a04ea2daa4dab114cee2e1c..7bd2c91196536e43c052982e8d8578b61f559854 100644 --- a/script/client/conf/file.conf +++ b/script/client/conf/file.conf @@ -55,9 +55,13 @@ client { tm { commitRetryCount = 5 rollbackRetryCount = 5 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 } undo { dataValidation = true + onlyCareUpdateColumns = true logSerialization = "jackson" logTable = "undo_log" } diff --git a/script/client/conf/registry.conf b/script/client/conf/registry.conf index cd2b7ac3315c295b69b9d7f2363919eb571aab8e..9ddc61ae806e270e77bd5214b3be68e44bd3ed90 100644 --- a/script/client/conf/registry.conf +++ b/script/client/conf/registry.conf @@ -4,7 +4,8 @@ registry { nacos { application = "seata-server" - serverAddr = "localhost" + serverAddr = "127.0.0.1:8848" + group = "SEATA_GROUP" namespace = "" username = "" password = "" @@ -49,7 +50,7 @@ config { type = "file" nacos { - serverAddr = "localhost" + serverAddr = "127.0.0.1:8848" namespace = "" group = "SEATA_GROUP" username = "" diff --git a/script/client/spring/application.properties b/script/client/spring/application.properties index c514d4fd830296462715854cc53961bf05d6badf..ec51e58f04618620125d7d84c8459351ab9a1dc7 100755 --- a/script/client/spring/application.properties +++ b/script/client/spring/application.properties @@ -30,8 +30,12 @@ seata.client.rm.lock.retry-times=30 seata.client.rm.lock.retry-policy-branch-rollback-on-conflict=true seata.client.tm.commit-retry-count=5 seata.client.tm.rollback-retry-count=5 +seata.client.tm.degrade-check=false +seata.client.tm.degrade-check-allow-times=10 +seata.client.tm.degrade-check-period=2000 seata.client.undo.data-validation=true seata.client.undo.log-serialization=jackson +seata.client.undo.only-care-update-columns=true seata.client.undo.log-table=undo_log seata.client.log.exceptionRate=100 seata.service.vgroup-mapping.my_test_tx_group=default @@ -66,7 +70,7 @@ seata.config.apollo.namespace=application seata.config.etcd3.server-addr=http://localhost:2379 seata.config.nacos.namespace= -seata.config.nacos.serverAddr=localhost +seata.config.nacos.serverAddr=127.0.0.1:8848 seata.config.nacos.group=SEATA_GROUP seata.config.nacos.username= seata.config.nacos.password= @@ -87,7 +91,8 @@ seata.registry.eureka.weight=1 seata.registry.eureka.service-url=http://localhost:8761/eureka seata.registry.nacos.application=seata-server -seata.registry.nacos.server-addr=localhost +seata.registry.nacos.server-addr=127.0.0.1:8848 +seata.registry.nacos.group=SEATA_GROUP seata.registry.nacos.namespace= seata.registry.nacos.username= seata.registry.nacos.password= diff --git a/script/client/spring/application.yml b/script/client/spring/application.yml index 16511e9bf01d653f8a714e607fe41c7c8ac204b3..a355698c6bfce14731b4726f8919a93e6705e882 100755 --- a/script/client/spring/application.yml +++ b/script/client/spring/application.yml @@ -17,12 +17,16 @@ seata: retry-times: 30 retry-policy-branch-rollback-on-conflict: true tm: + degrade-check: false + degrade-check-period: 2000 + degrade-check-allow-times: 10 commit-retry-count: 5 rollback-retry-count: 5 undo: data-validation: true log-serialization: jackson log-table: undo_log + only-care-update-columns: true log: exceptionRate: 100 service: @@ -63,9 +67,9 @@ seata: server-addr: http://localhost:2379 nacos: namespace: - serverAddr: localhost + serverAddr: 127.0.0.1:8848 group: SEATA_GROUP - userName: "" + username: "" password: "" zk: server-addr: 127.0.0.1:2181 @@ -84,9 +88,10 @@ seata: service-url: http://localhost:8761/eureka nacos: application: seata-server - server-addr: localhost + server-addr: 127.0.0.1:8848 + group : "SEATA_GROUP" namespace: - userName: "" + username: "" password: "" redis: server-addr: localhost:6379 diff --git a/script/config-center/README.md b/script/config-center/README.md index 32344e9f3cde320c773a0fec0c85e003619e3f9a..a0f7e6b1e80f586ba970b2451916374662bd2b35 100644 --- a/script/config-center/README.md +++ b/script/config-center/README.md @@ -17,7 +17,7 @@ you only need to follow the instructions below and keep the corresponding config ## Nacos shell: ```bash -sh ${SEATAPATH}/script/config-center/nacos/nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 5a3c7d6c-f497-4d68-a71a-2e5e3340b3ca +sh ${SEATAPATH}/script/config-center/nacos/nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 5a3c7d6c-f497-4d68-a71a-2e5e3340b3ca -u username -w password ``` Parameter Description: @@ -30,6 +30,10 @@ Parameter Description: -t: Tenant information, corresponding to the namespace ID field of Nacos, the default value is ''. +-u: username, nacos 1.2.0+ on permission control, the default value is ''. + +-w: password, nacos 1.2.0+ on permission control, the default value is ''. + python: ```bash python ${SEATAPATH}/script/config-center/nacos/nacos-config.py localhost:8848 diff --git a/script/config-center/config.txt b/script/config-center/config.txt index 02a9517a609354ea6a157b491851ce95fda87551..66d974b58c262b537614b7dd75751be4e868a461 100644 --- a/script/config-center/config.txt +++ b/script/config-center/config.txt @@ -27,6 +27,9 @@ client.rm.reportSuccessEnable=false client.rm.sagaBranchRegisterEnable=false client.tm.commitRetryCount=5 client.tm.rollbackRetryCount=5 +client.tm.degradeCheck=false +client.tm.degradeCheckAllowTimes=10 +client.tm.degradeCheckPeriod=2000 store.mode=file store.file.dir=file_store/data store.file.maxBranchSessionSize=16384 @@ -47,6 +50,13 @@ store.db.branchTable=branch_table store.db.queryLimit=100 store.db.lockTable=lock_table store.db.maxWait=5000 +store.redis.host=127.0.0.1 +store.redis.port=6379 +store.redis.maxConn=10 +store.redis.minConn=1 +store.redis.database=0 +store.redis.password=null +store.redis.queryLimit=100 server.recovery.committingRetryPeriod=1000 server.recovery.asynCommittingRetryPeriod=1000 server.recovery.rollbackingRetryPeriod=1000 @@ -56,6 +66,7 @@ server.maxRollbackRetryTimeout=-1 server.rollbackRetryTimeoutUnlockEnable=false client.undo.dataValidation=true client.undo.logSerialization=jackson +client.undo.onlyCareUpdateColumns=true server.undo.logSaveDays=7 server.undo.logDeletePeriod=86400000 client.undo.logTable=undo_log diff --git a/script/config-center/nacos/nacos-config.sh b/script/config-center/nacos/nacos-config.sh index 19ef696a72c296f61e850c587585942ee69db197..0f47b52e851e88059f12b8cd3abc33af1dab102f 100644 --- a/script/config-center/nacos/nacos-config.sh +++ b/script/config-center/nacos/nacos-config.sh @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -while getopts ":h:p:g:t:" opt +while getopts ":h:p:g:t:u:w:" opt do case $opt in h) @@ -28,8 +28,14 @@ do t) tenant=$OPTARG ;; + u) + username=$OPTARG + ;; + w) + password=$OPTARG + ;; ?) - echo " USAGE OPTION: $0 [-h host] [-p port] [-g group] [-t tenant] " + echo " USAGE OPTION: $0 [-h host] [-p port] [-g group] [-t tenant] [-u username] [-w password] " exit 1 ;; esac @@ -47,6 +53,12 @@ fi if [[ -z ${tenant} ]]; then tenant="" fi +if [[ -z ${username} ]]; then + username="" +fi +if [[ -z ${password} ]]; then + password="" +fi nacosAddr=$host:$port contentType="content-type:application/json;charset=UTF-8" @@ -57,15 +69,15 @@ echo "set group=$group" failCount=0 tempLog=$(mktemp -u) function addConfig() { - curl -X POST -H "${1}" "http://$2/nacos/v1/cs/configs?dataId=$3&group=$group&content=$4&tenant=$tenant" >"${tempLog}" 2>/dev/null + curl -X POST -H "${contentType}" "http://$nacosAddr/nacos/v1/cs/configs?dataId=$1&group=$group&content=$2&tenant=$tenant&username=$username&password=$password" >"${tempLog}" 2>/dev/null if [[ -z $(cat "${tempLog}") ]]; then echo " Please check the cluster status. " exit 1 fi if [[ $(cat "${tempLog}") =~ "true" ]]; then - echo "Set $3=$4 successfully " + echo "Set $1=$2 successfully " else - echo "Set $3=$4 failure " + echo "Set $1=$2 failure " (( failCount++ )) fi } @@ -74,8 +86,8 @@ count=0 for line in $(cat $(dirname "$PWD")/config.txt | sed s/[[:space:]]//g); do (( count++ )) key=${line%%=*} - value=${line#*=} - addConfig "${contentType}" "${nacosAddr}" "${key}" "${value}" + value=${line#*=} + addConfig "${key}" "${value}" done echo "=========================================================================" diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/StarterConstants.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/StarterConstants.java index 079320d0cfc772d0fb226ab0698f0cfacb4579f6..b5c137c33a409044bf6a8185efc31664925e484f 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/StarterConstants.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/StarterConstants.java @@ -17,22 +17,22 @@ package io.seata.spring.boot.autoconfigure; import java.util.HashMap; -import io.seata.spring.boot.autoconfigure.properties.file.LockProperties; -import io.seata.spring.boot.autoconfigure.properties.file.LogProperties; -import io.seata.spring.boot.autoconfigure.properties.file.RmProperties; -import io.seata.spring.boot.autoconfigure.properties.file.ServiceProperties; -import io.seata.spring.boot.autoconfigure.properties.file.ShutdownProperties; -import io.seata.spring.boot.autoconfigure.properties.file.ThreadFactoryProperties; -import io.seata.spring.boot.autoconfigure.properties.file.TmProperties; -import io.seata.spring.boot.autoconfigure.properties.file.TransportProperties; -import io.seata.spring.boot.autoconfigure.properties.file.UndoProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigApolloProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigConsulProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigEtcd3Properties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigFileProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigNacosProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigZooKeeperProperties; +import io.seata.spring.boot.autoconfigure.properties.client.LockProperties; +import io.seata.spring.boot.autoconfigure.properties.client.LogProperties; +import io.seata.spring.boot.autoconfigure.properties.client.RmProperties; +import io.seata.spring.boot.autoconfigure.properties.client.ServiceProperties; +import io.seata.spring.boot.autoconfigure.properties.client.ShutdownProperties; +import io.seata.spring.boot.autoconfigure.properties.client.ThreadFactoryProperties; +import io.seata.spring.boot.autoconfigure.properties.client.TmProperties; +import io.seata.spring.boot.autoconfigure.properties.client.TransportProperties; +import io.seata.spring.boot.autoconfigure.properties.client.UndoProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigApolloProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigConsulProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigEtcd3Properties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigFileProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigNacosProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigZooKeeperProperties; import io.seata.spring.boot.autoconfigure.properties.registry.RegistryConsulProperties; import io.seata.spring.boot.autoconfigure.properties.registry.RegistryEtcd3Properties; import io.seata.spring.boot.autoconfigure.properties.registry.RegistryEurekaProperties; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/SeataProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/SeataProperties.java index f63ca6125b1b7d95c359bf289f760fd82924332f..31b56f1365354dc8b6140c8f2c4237c1fff29ff9 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/SeataProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/SeataProperties.java @@ -65,7 +65,7 @@ public class SeataProperties { } public String getApplicationId() { - if (null == applicationId) { + if (applicationId == null) { applicationId = springCloudAlibabaConfiguration.getApplicationId(); } return applicationId; @@ -77,7 +77,7 @@ public class SeataProperties { } public String getTxServiceGroup() { - if (null == txServiceGroup) { + if (txServiceGroup == null) { txServiceGroup = springCloudAlibabaConfiguration.getTxServiceGroup(); } return txServiceGroup; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/SpringCloudAlibabaConfiguration.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/SpringCloudAlibabaConfiguration.java index 7669121831c3c5944705a52e9fca8e56739e0ce4..82c87000b41b1ba3d1a2be4a53c7f1847cbb79ce 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/SpringCloudAlibabaConfiguration.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/SpringCloudAlibabaConfiguration.java @@ -44,7 +44,7 @@ public class SpringCloudAlibabaConfiguration implements ApplicationContextAware * @return the application id */ public String getApplicationId() { - if (null == applicationId) { + if (applicationId == null) { applicationId = applicationContext.getEnvironment().getProperty(SPRING_APPLICATION_NAME_KEY); } return applicationId; @@ -56,9 +56,9 @@ public class SpringCloudAlibabaConfiguration implements ApplicationContextAware * @return the tx service group */ public String getTxServiceGroup() { - if (null == txServiceGroup) { + if (txServiceGroup == null) { String applicationId = getApplicationId(); - if (null == applicationId) { + if (applicationId == null) { LOGGER.warn("{} is null, please set its value", SPRING_APPLICATION_NAME_KEY); } txServiceGroup = applicationId + DEFAULT_SPRING_CLOUD_SERVICE_GROUP_POSTFIX; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/LockProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/LockProperties.java similarity index 97% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/LockProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/LockProperties.java index 569870c9f5794f8f587b6052d57713012e7de56f..483568653320ae018fbc3e2afcc501027d5e2bf2 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/LockProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/LockProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.file; +package io.seata.spring.boot.autoconfigure.properties.client; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/LogProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/LogProperties.java similarity index 95% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/LogProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/LogProperties.java index 597545426fafc6c4da14e8fb25900a341e2bb2f9..38f840aa39548349e7deabf31efce3a187d4d5aa 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/LogProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/LogProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.file; +package io.seata.spring.boot.autoconfigure.properties.client; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/RmProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/RmProperties.java similarity index 98% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/RmProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/RmProperties.java index f62d838d06a6c972d629c4dce95df9204d8bf005..f2df89e10a948f9d48fb6c83b9cb0ef9247673a2 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/RmProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/RmProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.file; +package io.seata.spring.boot.autoconfigure.properties.client; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/ServiceProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/ServiceProperties.java similarity index 97% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/ServiceProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/ServiceProperties.java index 405b434721b32eb1caa51f0d3d7699530b97bc54..9390765547263a4bc42f871979c4cebeb0288feb 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/ServiceProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/ServiceProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.file; +package io.seata.spring.boot.autoconfigure.properties.client; import java.util.HashMap; import java.util.Map; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/ShutdownProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/ShutdownProperties.java similarity index 95% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/ShutdownProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/ShutdownProperties.java index 2e39273f6c7958858a2dd74fdcfbd81da1872dc6..a057d6250f7e762276f4b51e0e368f3d160caa94 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/ShutdownProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/ShutdownProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.file; +package io.seata.spring.boot.autoconfigure.properties.client; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/ThreadFactoryProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/ThreadFactoryProperties.java similarity index 98% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/ThreadFactoryProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/ThreadFactoryProperties.java index 4923fb0fcb0fa25d6e431c0a0aa62bd93e12521f..3f9bde8f60d75dc947159da3c12408aeed38ea0f 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/ThreadFactoryProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/ThreadFactoryProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.file; +package io.seata.spring.boot.autoconfigure.properties.client; import io.seata.core.rpc.netty.NettyBaseConfig.WorkThreadMode; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/TmProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/TmProperties.java similarity index 58% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/TmProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/TmProperties.java index 90587ebc855a161f813065115a2a11d0070f43fd..ca801488fcd240f41693ba29494cec1c527e8a22 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/TmProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/TmProperties.java @@ -13,12 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.file; +package io.seata.spring.boot.autoconfigure.properties.client; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; + import static io.seata.core.constants.DefaultValues.DEFAULT_TM_COMMIT_RETRY_COUNT; +import static io.seata.core.constants.DefaultValues.DEFAULT_TM_DEGRADE_CHECK; +import static io.seata.core.constants.DefaultValues.DEFAULT_TM_DEGRADE_CHECK_ALLOW_TIMES; +import static io.seata.core.constants.DefaultValues.DEFAULT_TM_DEGRADE_CHECK_PERIOD; import static io.seata.core.constants.DefaultValues.DEFAULT_TM_ROLLBACK_RETRY_COUNT; import static io.seata.spring.boot.autoconfigure.StarterConstants.CLIENT_TM_PREFIX; @@ -30,6 +34,9 @@ import static io.seata.spring.boot.autoconfigure.StarterConstants.CLIENT_TM_PREF public class TmProperties { private int commitRetryCount = DEFAULT_TM_COMMIT_RETRY_COUNT; private int rollbackRetryCount = DEFAULT_TM_ROLLBACK_RETRY_COUNT; + private boolean degradeCheck = DEFAULT_TM_DEGRADE_CHECK; + private int degradeCheckAllowTimes = DEFAULT_TM_DEGRADE_CHECK_ALLOW_TIMES; + private int degradeCheckPeriod = DEFAULT_TM_DEGRADE_CHECK_PERIOD; public int getCommitRetryCount() { return commitRetryCount; @@ -48,4 +55,30 @@ public class TmProperties { this.rollbackRetryCount = rollbackRetryCount; return this; } + + public boolean isDegradeCheck() { + return degradeCheck; + } + + public TmProperties setDegradeCheck(boolean degradeCheck) { + this.degradeCheck = degradeCheck; + return this; + } + + public int getDegradeCheckPeriod() { + return degradeCheckPeriod; + } + + public TmProperties setDegradeCheckPeriod(int degradeCheckPeriod) { + this.degradeCheckPeriod = degradeCheckPeriod; + return this; + } + + public int getDegradeCheckAllowTimes() { + return degradeCheckAllowTimes; + } + + public void setDegradeCheckAllowTimes(int degradeCheckAllowTimes) { + this.degradeCheckAllowTimes = degradeCheckAllowTimes; + } } diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/TransportProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/TransportProperties.java similarity index 97% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/TransportProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/TransportProperties.java index 0f91b86d71d249423928a13d6119e00a486f6bce..c32ce9cbb4b1caf7c75afd5e3803d939f18f28c9 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/TransportProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/TransportProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.file; +package io.seata.spring.boot.autoconfigure.properties.client; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/UndoProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/UndoProperties.java similarity index 81% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/UndoProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/UndoProperties.java index 0bd8081124eb91c1ebbbeb042329000ef46390f1..e3ec9fb79b3ba5bcde535d2d5cafb17a51e6ad97 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/file/UndoProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/UndoProperties.java @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.file; +package io.seata.spring.boot.autoconfigure.properties.client; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; +import static io.seata.core.constants.DefaultValues.DEFAULT_ONLY_CARE_UPDATE_COLUMNS; import static io.seata.core.constants.DefaultValues.DEFAULT_TRANSACTION_UNDO_DATA_VALIDATION; import static io.seata.core.constants.DefaultValues.DEFAULT_TRANSACTION_UNDO_LOG_SERIALIZATION; import static io.seata.core.constants.DefaultValues.DEFAULT_TRANSACTION_UNDO_LOG_TABLE; @@ -32,6 +33,7 @@ public class UndoProperties { private boolean dataValidation = DEFAULT_TRANSACTION_UNDO_DATA_VALIDATION; private String logSerialization = DEFAULT_TRANSACTION_UNDO_LOG_SERIALIZATION; private String logTable = DEFAULT_TRANSACTION_UNDO_LOG_TABLE; + private boolean onlyCareUpdateColumns = DEFAULT_ONLY_CARE_UPDATE_COLUMNS; public boolean isDataValidation() { return dataValidation; @@ -59,4 +61,13 @@ public class UndoProperties { this.logTable = logTable; return this; } + + public boolean isOnlyCareUpdateColumns() { + return onlyCareUpdateColumns; + } + + public UndoProperties setOnlyCareUpdateColumns(boolean onlyCareUpdateColumns) { + this.onlyCareUpdateColumns = onlyCareUpdateColumns; + return this; + } } diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigApolloProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigApolloProperties.java similarity index 96% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigApolloProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigApolloProperties.java index 736d8e369f00112361d2a276488a2eefa16c3dbb..9e9f051a551324b78b7462c0246612f7c89e93bc 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigApolloProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigApolloProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.registry; +package io.seata.spring.boot.autoconfigure.properties.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigConsulProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigConsulProperties.java similarity index 95% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigConsulProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigConsulProperties.java index 50b8dc3b07fdce758187000d4958e0c056d4731c..4cd53bcd0ae88089f0013c8587eb3bdb785106cc 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigConsulProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigConsulProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.registry; +package io.seata.spring.boot.autoconfigure.properties.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigEtcd3Properties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigEtcd3Properties.java similarity index 95% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigEtcd3Properties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigEtcd3Properties.java index 5c72bbbfd90f846b572d1fe8a7c97d214100f27a..e2af9e45271d360e9e8f095c8d9030aa4a25be01 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigEtcd3Properties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigEtcd3Properties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.registry; +package io.seata.spring.boot.autoconfigure.properties.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigFileProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigFileProperties.java similarity index 94% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigFileProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigFileProperties.java index fd741a3e295632f635c1ed028e5b8afd88f993e6..0bc4177ad21ed67c9f147f24c83700a6655568f8 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigFileProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigFileProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.registry; +package io.seata.spring.boot.autoconfigure.properties.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigNacosProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigNacosProperties.java similarity index 97% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigNacosProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigNacosProperties.java index 2597c80f0610c7188ea094192a7adb949b598d4b..798c9e73dab9198cfb0d5bbc8f9257358a6483ec 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigNacosProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigNacosProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.registry; +package io.seata.spring.boot.autoconfigure.properties.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigProperties.java similarity index 95% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigProperties.java index 7c9f906198e0df80bb4564e514a256687d3df7ce..13a5df4806221240366941f0ed5ad0c9039e9cf5 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.registry; +package io.seata.spring.boot.autoconfigure.properties.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigZooKeeperProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigZooKeeperProperties.java similarity index 97% rename from seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigZooKeeperProperties.java rename to seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigZooKeeperProperties.java index 78be79d0d0683e5c6906e2eb4ada85a31c34b665..bae2fac3975aa7141b27db1a310b2db02ce6cc2c 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/ConfigZooKeeperProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/config/ConfigZooKeeperProperties.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.boot.autoconfigure.properties.registry; +package io.seata.spring.boot.autoconfigure.properties.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/RegistryNacosProperties.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/RegistryNacosProperties.java index c9e17e59add21459efed79ea7c83e44f2009d456..bcc8aa5ff4b610a74a3d6440acb7628da249376a 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/RegistryNacosProperties.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/properties/registry/RegistryNacosProperties.java @@ -28,6 +28,7 @@ import static io.seata.spring.boot.autoconfigure.StarterConstants.REGISTRY_NACOS public class RegistryNacosProperties { private String serverAddr = "localhost"; private String namespace = ""; + private String group = "SEATA_GROUP"; private String cluster = "default"; private String username = ""; private String password = ""; @@ -51,6 +52,14 @@ public class RegistryNacosProperties { return this; } + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + public String getCluster() { return cluster; } diff --git a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java index 0c735eaff781e3e64920f0f098e2a0a3706b500c..0b79cd42ad64e6e5b48ad88db863055aff44b839 100644 --- a/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java +++ b/seata-spring-boot-starter/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java @@ -20,7 +20,6 @@ import java.lang.reflect.Method; import java.util.Map; import java.util.Optional; import java.util.stream.Stream; - import io.seata.common.holder.ObjectHolder; import io.seata.config.Configuration; import io.seata.config.ExtConfigurationProvider; @@ -30,12 +29,13 @@ import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import org.springframework.context.ApplicationContext; + +import static io.seata.common.util.StringFormatUtils.DOT; import static io.seata.spring.boot.autoconfigure.StarterConstants.PROPERTY_MAP; import static io.seata.spring.boot.autoconfigure.StarterConstants.SEATA_PREFIX; import static io.seata.spring.boot.autoconfigure.StarterConstants.SERVICE_PREFIX; import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_GROUPLIST; import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_VGROUP_MAPPING; -import static io.seata.spring.boot.autoconfigure.util.StringFormatUtils.DOT; /** * @author xingfudeshi@gmail.com @@ -59,7 +59,7 @@ public class SpringBootConfigurationProvider implements ExtConfigurationProvider } else if (args.length == 3) { result = get(convertDataId(rawDataId), args[1], (Long) args[2]); } - if (null != result) { + if (result != null) { //If the return type is String,need to convert the object to string if (method.getReturnType().equals(String.class)) { return String.valueOf(result); @@ -80,7 +80,7 @@ public class SpringBootConfigurationProvider implements ExtConfigurationProvider private Object get(String dataId, Object defaultValue) throws IllegalAccessException { Object result = get(dataId); - if (null == result) { + if (result == null) { return defaultValue; } return result; @@ -89,7 +89,7 @@ public class SpringBootConfigurationProvider implements ExtConfigurationProvider private Object get(String dataId) throws IllegalAccessException { String propertySuffix = getPropertySuffix(dataId); Class propertyClass = getPropertyClass(getPropertyPrefix(dataId)); - if (null != propertyClass) { + if (propertyClass != null) { Object propertyObject = ObjectHolder.INSTANCE.getObject(ApplicationContext.class).getBean(propertyClass); Optional<Field> fieldOptional = Stream.of(propertyObject.getClass().getDeclaredFields()).filter( f -> f.getName().equalsIgnoreCase(propertySuffix)).findAny(); diff --git a/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/PropertiesTest.java b/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/PropertiesTest.java index cdd577dd9700f65d3aac96be72a42eb8f5b9c9cf..56ca556e82637bc612ecfc8766ca6e19e8975c4c 100644 --- a/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/PropertiesTest.java +++ b/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/PropertiesTest.java @@ -19,22 +19,22 @@ import java.util.Map; import io.seata.spring.boot.autoconfigure.properties.SeataProperties; import io.seata.spring.boot.autoconfigure.properties.SpringCloudAlibabaConfiguration; -import io.seata.spring.boot.autoconfigure.properties.file.LockProperties; -import io.seata.spring.boot.autoconfigure.properties.file.LogProperties; -import io.seata.spring.boot.autoconfigure.properties.file.RmProperties; -import io.seata.spring.boot.autoconfigure.properties.file.ServiceProperties; -import io.seata.spring.boot.autoconfigure.properties.file.ShutdownProperties; -import io.seata.spring.boot.autoconfigure.properties.file.ThreadFactoryProperties; -import io.seata.spring.boot.autoconfigure.properties.file.TmProperties; -import io.seata.spring.boot.autoconfigure.properties.file.TransportProperties; -import io.seata.spring.boot.autoconfigure.properties.file.UndoProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigApolloProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigConsulProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigEtcd3Properties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigFileProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigNacosProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigProperties; -import io.seata.spring.boot.autoconfigure.properties.registry.ConfigZooKeeperProperties; +import io.seata.spring.boot.autoconfigure.properties.client.LockProperties; +import io.seata.spring.boot.autoconfigure.properties.client.LogProperties; +import io.seata.spring.boot.autoconfigure.properties.client.RmProperties; +import io.seata.spring.boot.autoconfigure.properties.client.ServiceProperties; +import io.seata.spring.boot.autoconfigure.properties.client.ShutdownProperties; +import io.seata.spring.boot.autoconfigure.properties.client.ThreadFactoryProperties; +import io.seata.spring.boot.autoconfigure.properties.client.TmProperties; +import io.seata.spring.boot.autoconfigure.properties.client.TransportProperties; +import io.seata.spring.boot.autoconfigure.properties.client.UndoProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigApolloProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigConsulProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigEtcd3Properties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigFileProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigNacosProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigProperties; +import io.seata.spring.boot.autoconfigure.properties.config.ConfigZooKeeperProperties; import io.seata.spring.boot.autoconfigure.properties.registry.RegistryConsulProperties; import io.seata.spring.boot.autoconfigure.properties.registry.RegistryEtcd3Properties; import io.seata.spring.boot.autoconfigure.properties.registry.RegistryEurekaProperties; @@ -203,6 +203,7 @@ public class PropertiesTest { public void testRegistryNacosProperties() { assertEquals("localhost", context.getBean(RegistryNacosProperties.class).getServerAddr()); assertEquals("", context.getBean(RegistryNacosProperties.class).getNamespace()); + assertEquals("SEATA_GROUP", context.getBean(RegistryNacosProperties.class).getGroup()); assertEquals("default", context.getBean(RegistryNacosProperties.class).getCluster()); assertEquals("", context.getBean(RegistryNacosProperties.class).getUsername()); assertEquals("", context.getBean(RegistryNacosProperties.class).getPassword()); diff --git a/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java b/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java index 71962bc57b21e5a510f81cf4fdb44d5cbf8b1a2d..448e1da25313e27265dafed19eef71971052c347 100644 --- a/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java +++ b/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java @@ -52,7 +52,8 @@ public class RedisAutoInjectionTypeConvertTest { @Test public void testReadConfigurationItems() { FileConfiguration configuration = mock(FileConfiguration.class); - Configuration currentConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + Configuration currentConfiguration = + EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); assertEquals(1, currentConfiguration.getInt("registry.redis.db")); assertEquals("123456", currentConfiguration.getConfig("registry.redis.password")); assertEquals("localhost:123456", currentConfiguration.getConfig("registry.redis.serverAddr")); diff --git a/serializer/seata-serializer-seata/src/main/java/io/seata/serializer/seata/MessageCodecFactory.java b/serializer/seata-serializer-seata/src/main/java/io/seata/serializer/seata/MessageCodecFactory.java index a29fe2cb8d043e061536037d19f644748c7c35a9..30d703241fb54a210a9b852e8de53748077f9bec 100644 --- a/serializer/seata-serializer-seata/src/main/java/io/seata/serializer/seata/MessageCodecFactory.java +++ b/serializer/seata-serializer-seata/src/main/java/io/seata/serializer/seata/MessageCodecFactory.java @@ -137,7 +137,7 @@ public class MessageCodecFactory { break; } - if (null != msgCodec) { + if (msgCodec != null) { return msgCodec; } @@ -146,7 +146,7 @@ public class MessageCodecFactory { } catch (Exception exx) { } - if (null != msgCodec) { + if (msgCodec != null) { return msgCodec; } @@ -265,7 +265,7 @@ public class MessageCodecFactory { break; } - if (null != abstractMessage) { + if (abstractMessage != null) { return abstractMessage; } @@ -274,7 +274,7 @@ public class MessageCodecFactory { } catch (Exception exx) { } - if (null != abstractMessage) { + if (abstractMessage != null) { return abstractMessage; } diff --git a/server/pom.xml b/server/pom.xml index ec18d643943a2ce13086289a5018c3f7bc20ea7f..034cf217178a8eb2dd38fd0d6cc3be5fd610b144 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -26,7 +26,6 @@ <artifactId>seata-server</artifactId> <packaging>jar</packaging> <name>seata-server ${project.version}</name> - <dependencies> <dependency> @@ -70,6 +69,10 @@ <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> </dependency> + <dependency> + <groupId>com.zaxxer</groupId> + <artifactId>HikariCP</artifactId> + </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> @@ -99,10 +102,53 @@ <artifactId>logback-classic</artifactId> </dependency> + <!-- jedis --> + <dependency> + <groupId>redis.clients</groupId> + <artifactId>jedis</artifactId> + </dependency> + + <dependency> + <groupId>com.github.fppt</groupId> + <artifactId>jedis-mock</artifactId> + <scope>test</scope> + </dependency> + </dependencies> <build> <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>3.1.1</version> + <executions> + <execution> + <id>copy-mysql</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>${mysql.jdbc.version}</version> + </artifactItem> + <artifactItem> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>${mysql8.jdbc.version}</version> + </artifactItem> + </artifactItems> + <outputDirectory> + ${basedir}/target/lib/jdbc + </outputDirectory> + </configuration> + </execution> + </executions> + </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>appassembler-maven-plugin</artifactId> @@ -172,7 +218,7 @@ <plugin> <groupId>com.google.cloud.tools</groupId> <artifactId>jib-maven-plugin</artifactId> - <version>1.7.0</version> + <version>2.3.0</version> <configuration> <from> <image>${IMAGE_NAME}</image> @@ -223,6 +269,14 @@ </labels> <creationTime>USE_CURRENT_TIMESTAMP</creationTime> </container> + <extraDirectories> + <paths> + <path> + <from>target/lib/jdbc</from> + <into>/seata-server/libs/jdbc</into> + </path> + </paths> + </extraDirectories> <skip>${image.publish.skip}</skip> </configuration> <executions> diff --git a/server/src/main/java/io/seata/server/ParameterParser.java b/server/src/main/java/io/seata/server/ParameterParser.java index f5a03ea245a9fb1290c4041d7f77e21dfd2a711e..520645ce8eb37b77e748d01955651a1a9787bed6 100644 --- a/server/src/main/java/io/seata/server/ParameterParser.java +++ b/server/src/main/java/io/seata/server/ParameterParser.java @@ -18,20 +18,15 @@ package io.seata.server; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; -import io.seata.common.util.NumberUtils; +import io.seata.common.util.IdWorker; import io.seata.common.util.StringUtils; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.stream.Stream; +import io.seata.server.env.ContainerHelper; import static io.seata.config.ConfigurationFactory.ENV_PROPERTY_KEY; +import static io.seata.core.constants.DefaultValues.SERVER_DEFAULT_PORT; +import static io.seata.core.constants.DefaultValues.SERVER_DEFAULT_STORE_MODE; /** * The type Parameter parser. @@ -40,24 +35,9 @@ import static io.seata.config.ConfigurationFactory.ENV_PROPERTY_KEY; */ public class ParameterParser { - private static final Logger LOGGER = LoggerFactory.getLogger(ParameterParser.class); - private static final String PROGRAM_NAME = "sh seata-server.sh(for linux and mac) or cmd seata-server.bat(for windows)"; - private static final int SERVER_DEFAULT_PORT = 8091; - private static final String SERVER_DEFAULT_STORE_MODE = "file"; - private static final int SERVER_DEFAULT_NODE = 1; - - private static final String ENV_SYSTEM_KEY = "SEATA_ENV"; - private static final String ENV_SEATA_IP_KEY = "SEATA_IP"; - private static final String ENV_SERVER_NODE_KEY = "SERVER_NODE"; - private static final String ENV_SEATA_PORT_KEY = "SEATA_PORT"; - private static final String ENV_STORE_MODE_KEY = "STORE_MODE"; - private static final String C_GROUP_PATH = "/proc/1/cgroup"; - private static final String DOCKER_PATH = "/docker"; - private static final String KUBEPODS_PATH = "/kubepods"; - @Parameter(names = "--help", help = true) private boolean help; @Parameter(names = {"--host", "-h"}, description = "The ip to register to registry center.", order = 1) @@ -66,12 +46,11 @@ public class ParameterParser { private int port = SERVER_DEFAULT_PORT; @Parameter(names = {"--storeMode", "-m"}, description = "log store mode : file, db", order = 3) private String storeMode; - @Parameter(names = {"--serverNode", "-n"}, description = "server node id, such as 1, 2, 3. default is 1", order = 4) - private int serverNode = SERVER_DEFAULT_NODE; + @Parameter(names = {"--serverNode", "-n"}, description = "server node id, such as 1, 2, 3.it will be generated according to the snowflake by default", order = 4) + private Long serverNode; @Parameter(names = {"--seataEnv", "-e"}, description = "The name used for multi-configuration isolation.", order = 5) private String seataEnv; - /** * Instantiates a new Parameter parser. * @@ -83,18 +62,12 @@ public class ParameterParser { private void init(String[] args) { try { - boolean inContainer = this.isRunningInContainer(); - - if (inContainer) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("The server is running in container."); - } - - this.seataEnv = StringUtils.trimToNull(System.getenv(ENV_SYSTEM_KEY)); - this.host = StringUtils.trimToNull(System.getenv(ENV_SEATA_IP_KEY)); - this.serverNode = NumberUtils.toInt(System.getenv(ENV_SERVER_NODE_KEY), SERVER_DEFAULT_NODE); - this.port = NumberUtils.toInt(System.getenv(ENV_SEATA_PORT_KEY), SERVER_DEFAULT_PORT); - this.storeMode = StringUtils.trimToNull(System.getenv(ENV_STORE_MODE_KEY)); + if (ContainerHelper.isRunningInContainer()) { + this.seataEnv = ContainerHelper.getEnv(); + this.host = ContainerHelper.getHost(); + this.port = ContainerHelper.getPort(); + this.serverNode = ContainerHelper.getServerNode(); + this.storeMode = ContainerHelper.getStoreMode(); } else { JCommander jCommander = JCommander.newBuilder().addObject(this).build(); jCommander.parse(args); @@ -104,6 +77,9 @@ public class ParameterParser { System.exit(0); } } + if (this.serverNode == null) { + this.serverNode = IdWorker.initWorkerId(); + } if (StringUtils.isNotBlank(seataEnv)) { System.setProperty(ENV_PROPERTY_KEY, seataEnv); } @@ -124,23 +100,6 @@ public class ParameterParser { System.exit(0); } - /** - * Judge if application is run in container. - * - * @return If application is run in container - */ - private Boolean isRunningInContainer() { - Path path = Paths.get(C_GROUP_PATH); - if (Files.exists(path)) { - try (Stream<String> stream = Files.lines(path)) { - return stream.anyMatch(line -> line.contains(DOCKER_PATH) || line.contains(KUBEPODS_PATH)); - } catch (IOException e) { - LOGGER.error("Judge if running in container failed:{}", e.getMessage(), e); - } - } - return false; - } - /** * Gets host. * @@ -182,7 +141,7 @@ public class ParameterParser { * * @return the server node */ - public int getServerNode() { + public Long getServerNode() { return serverNode; } @@ -194,4 +153,5 @@ public class ParameterParser { public String getSeataEnv() { return seataEnv; } + } diff --git a/server/src/main/java/io/seata/server/Server.java b/server/src/main/java/io/seata/server/Server.java index 881bb0162cfaafd08df41827e8c247791c33c1c5..b3baf98f3e7a3c5f0f50f279766918578dbd4378 100644 --- a/server/src/main/java/io/seata/server/Server.java +++ b/server/src/main/java/io/seata/server/Server.java @@ -15,23 +15,24 @@ */ package io.seata.server; +import java.io.IOException; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import io.seata.common.XID; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.NetUtil; import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.rpc.netty.RpcServer; -import io.seata.core.rpc.netty.ShutdownHook; +import io.seata.core.rpc.ShutdownHook; +import io.seata.core.rpc.netty.NettyRemotingServer; import io.seata.server.coordinator.DefaultCoordinator; +import io.seata.server.env.ContainerHelper; +import io.seata.server.env.PortHelper; import io.seata.server.metrics.MetricsManager; import io.seata.server.session.SessionHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** * The type Server. * @@ -39,8 +40,6 @@ import java.util.concurrent.TimeUnit; */ public class Server { - private static final Logger LOGGER = LoggerFactory.getLogger(Server.class); - private static final int MIN_SERVER_POOL_SIZE = 50; private static final int MAX_SERVER_POOL_SIZE = 500; private static final int MAX_TASK_QUEUE_SIZE = 20000; @@ -57,6 +56,16 @@ public class Server { * @throws IOException the io exception */ public static void main(String[] args) throws IOException { + // get port first, use to logback.xml + int port = PortHelper.getPort(args); + System.setProperty(ConfigurationKeys.SERVER_PORT, Integer.toString(port)); + + // create logger + final Logger logger = LoggerFactory.getLogger(Server.class); + if (ContainerHelper.isRunningInContainer()) { + logger.info("The server is running in container."); + } + //initialize the parameter parser //Note that the parameter parser should always be the first line to execute. //Because, here we need to parse the parameters needed for startup. @@ -67,19 +76,19 @@ public class Server { System.setProperty(ConfigurationKeys.STORE_MODE, parameterParser.getStoreMode()); - RpcServer rpcServer = new RpcServer(WORKING_THREADS); + NettyRemotingServer nettyRemotingServer = new NettyRemotingServer(WORKING_THREADS); //server port - rpcServer.setListenPort(parameterParser.getPort()); + nettyRemotingServer.setListenPort(parameterParser.getPort()); UUIDGenerator.init(parameterParser.getServerNode()); - //log store mode : file, db + //log store mode : file, db, redis SessionHolder.init(parameterParser.getStoreMode()); - DefaultCoordinator coordinator = new DefaultCoordinator(rpcServer); + DefaultCoordinator coordinator = new DefaultCoordinator(nettyRemotingServer); coordinator.init(); - rpcServer.setHandler(coordinator); + nettyRemotingServer.setHandler(coordinator); // register ShutdownHook ShutdownHook.getInstance().addDisposable(coordinator); - ShutdownHook.getInstance().addDisposable(rpcServer); + ShutdownHook.getInstance().addDisposable(nettyRemotingServer); //127.0.0.1 and 0.0.0.0 are not valid here. if (NetUtil.isValidIp(parameterParser.getHost(), false)) { @@ -87,12 +96,12 @@ public class Server { } else { XID.setIpAddress(NetUtil.getLocalIp()); } - XID.setPort(rpcServer.getListenPort()); + XID.setPort(nettyRemotingServer.getListenPort()); try { - rpcServer.init(); + nettyRemotingServer.init(); } catch (Throwable e) { - LOGGER.error("rpcServer init error:{}", e.getMessage(), e); + logger.error("nettyServer init error:{}", e.getMessage(), e); System.exit(-1); } diff --git a/server/src/main/java/io/seata/server/UUIDGenerator.java b/server/src/main/java/io/seata/server/UUIDGenerator.java index 5746f24bcda6590984ded0e11fcf85256ce3ca2b..422d65860b89b1c1253d26083c28cb956d358225 100644 --- a/server/src/main/java/io/seata/server/UUIDGenerator.java +++ b/server/src/main/java/io/seata/server/UUIDGenerator.java @@ -15,15 +15,7 @@ */ package io.seata.server; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.time.LocalDate; -import java.time.temporal.TemporalAdjusters; -import java.util.Calendar; -import java.util.Date; -import java.util.concurrent.atomic.AtomicLong; - -import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.util.IdWorker; /** * The type Uuid generator. @@ -32,89 +24,22 @@ import io.seata.common.exception.ShouldNeverHappenException; */ public class UUIDGenerator { - private static final AtomicLong UUID = new AtomicLong(1000); - private static int serverNodeId = 1; - private static final long UUID_INTERNAL = 2000000000; - private static long initUUID = 0; - /** * Generate uuid long. * * @return the long */ public static long generateUUID() { - long id = UUID.incrementAndGet(); - if (id >= getMaxUUID()) { - synchronized (UUID) { - if (UUID.get() >= id) { - id -= UUID_INTERNAL; - UUID.set(id); - } - } - } - return id; - } - - /** - * Gets current uuid. - * - * @return the current uuid - */ - public static long getCurrentUUID() { - return UUID.get(); - } - - /** - * Sets uuid. - * - * @param expect the expect - * @param update the update - * @return the uuid - */ - public static boolean setUUID(long expect, long update) { - return UUID.compareAndSet(expect, update); - - } - - /** - * Gets max uuid. - * - * @return the max uuid - */ - public static long getMaxUUID() { - return UUID_INTERNAL * (serverNodeId + 1); - } - - /** - * Gets init uuid. - * - * @return the init uuid - */ - public static long getInitUUID() { - return initUUID; + return IdWorker.getInstance().nextId(); } /** * Init. * - * @param serverNodeId the server node id + * @param serverNode the server node id */ - public static void init(int serverNodeId) { - try { - UUIDGenerator.serverNodeId = serverNodeId; - UUID.set(UUID_INTERNAL * serverNodeId); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); - Calendar cal = Calendar.getInstance(); - String firstDayOfYear = LocalDate.now() - .with(TemporalAdjusters.firstDayOfYear()).toString(); - Date date = format.parse(firstDayOfYear); - cal.setTime(date); - long base = cal.getTimeInMillis(); - long current = System.currentTimeMillis(); - UUID.addAndGet((current - base) / 1000); - initUUID = getCurrentUUID(); - } catch (ParseException e) { - throw new ShouldNeverHappenException(e); - } + public static void init(Long serverNode) { + IdWorker.init(serverNode); } + } diff --git a/server/src/main/java/io/seata/server/auth/AbstractCheckAuthHandler.java b/server/src/main/java/io/seata/server/auth/AbstractCheckAuthHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..a0f0e8ce643407cc6b3becafd15e196d1b6ccfe3 --- /dev/null +++ b/server/src/main/java/io/seata/server/auth/AbstractCheckAuthHandler.java @@ -0,0 +1,54 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.auth; + +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.protocol.RegisterRMRequest; +import io.seata.core.protocol.RegisterTMRequest; +import io.seata.core.rpc.RegisterCheckAuthHandler; + +import static io.seata.core.constants.DefaultValues.DEFAULT_SERVER_ENABLE_CHECK_AUTH; + +/** + * @author slievrly + */ +public abstract class AbstractCheckAuthHandler implements RegisterCheckAuthHandler { + + private static final Boolean ENABLE_CHECK_AUTH = ConfigurationFactory.getInstance().getBoolean( + ConfigurationKeys.SERVER_ENABLE_CHECK_AUTH, DEFAULT_SERVER_ENABLE_CHECK_AUTH); + + @Override + public boolean regTransactionManagerCheckAuth(RegisterTMRequest request) { + if (!ENABLE_CHECK_AUTH) { + return true; + } + return doRegTransactionManagerCheck(request); + } + + public abstract boolean doRegTransactionManagerCheck(RegisterTMRequest request); + + @Override + public boolean regResourceManagerCheckAuth(RegisterRMRequest request) { + if (!ENABLE_CHECK_AUTH) { + return true; + } + return doRegResourceManagerCheck(request); + } + + public abstract boolean doRegResourceManagerCheck(RegisterRMRequest request); +} diff --git a/server/src/main/java/io/seata/server/auth/DefaultCheckAuthHandler.java b/server/src/main/java/io/seata/server/auth/DefaultCheckAuthHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..aeffc0e2504dc6ef8da700a241713c7a39cec26b --- /dev/null +++ b/server/src/main/java/io/seata/server/auth/DefaultCheckAuthHandler.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.auth; + +import io.seata.common.loader.LoadLevel; +import io.seata.core.protocol.RegisterRMRequest; +import io.seata.core.protocol.RegisterTMRequest; + +/** + * @author slievrly + */ +@LoadLevel(name = "defaultCheckAuthHandler", order = 100) +public class DefaultCheckAuthHandler extends AbstractCheckAuthHandler { + + @Override + public boolean doRegTransactionManagerCheck(RegisterTMRequest request) { + return true; + } + + @Override + public boolean doRegResourceManagerCheck(RegisterRMRequest request) { + return true; + } +} diff --git a/server/src/main/java/io/seata/server/coordinator/AbstractCore.java b/server/src/main/java/io/seata/server/coordinator/AbstractCore.java index a4b337f167d0dada9d78b6b82046f6af0b54b8bd..0e9de3c384a1cac94891605505241ca6604ed7b9 100644 --- a/server/src/main/java/io/seata/server/coordinator/AbstractCore.java +++ b/server/src/main/java/io/seata/server/coordinator/AbstractCore.java @@ -29,7 +29,7 @@ import io.seata.core.protocol.transaction.BranchCommitRequest; import io.seata.core.protocol.transaction.BranchCommitResponse; import io.seata.core.protocol.transaction.BranchRollbackRequest; import io.seata.core.protocol.transaction.BranchRollbackResponse; -import io.seata.core.rpc.ServerMessageSender; +import io.seata.core.rpc.RemotingServer; import io.seata.server.lock.LockManager; import io.seata.server.lock.LockerManagerFactory; import io.seata.server.session.BranchSession; @@ -57,10 +57,10 @@ public abstract class AbstractCore implements Core { protected LockManager lockManager = LockerManagerFactory.getLockManager(); - protected ServerMessageSender messageSender; + protected RemotingServer remotingServer; - public AbstractCore(ServerMessageSender messageSender) { - this.messageSender = messageSender; + public AbstractCore(RemotingServer remotingServer) { + this.remotingServer = remotingServer; } public abstract BranchType getHandleBranchType(); @@ -165,7 +165,7 @@ public abstract class AbstractCore implements Core { protected BranchStatus branchCommitSend(BranchCommitRequest request, GlobalSession globalSession, BranchSession branchSession) throws IOException, TimeoutException { - BranchCommitResponse response = (BranchCommitResponse) messageSender.sendSyncRequest( + BranchCommitResponse response = (BranchCommitResponse) remotingServer.sendSyncRequest( branchSession.getResourceId(), branchSession.getClientId(), request); return response.getBranchStatus(); } @@ -189,7 +189,7 @@ public abstract class AbstractCore implements Core { protected BranchStatus branchRollbackSend(BranchRollbackRequest request, GlobalSession globalSession, BranchSession branchSession) throws IOException, TimeoutException { - BranchRollbackResponse response = (BranchRollbackResponse) messageSender.sendSyncRequest( + BranchRollbackResponse response = (BranchRollbackResponse) remotingServer.sendSyncRequest( branchSession.getResourceId(), branchSession.getClientId(), request); return response.getBranchStatus(); } diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java index 7e9ca0b6a11788b471468214aee400699b1bdc03..f15734f104b1e0368909b57c4a7d9cce5954dc80 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java @@ -15,12 +15,6 @@ */ package io.seata.server.coordinator; -import java.time.Duration; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - import io.netty.channel.Channel; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.CollectionUtils; @@ -52,12 +46,12 @@ import io.seata.core.protocol.transaction.GlobalRollbackResponse; import io.seata.core.protocol.transaction.GlobalStatusRequest; import io.seata.core.protocol.transaction.GlobalStatusResponse; import io.seata.core.protocol.transaction.UndoLogDeleteRequest; -import io.seata.core.rpc.ChannelManager; +import io.seata.core.rpc.netty.ChannelManager; import io.seata.core.rpc.Disposable; +import io.seata.core.rpc.RemotingServer; import io.seata.core.rpc.RpcContext; -import io.seata.core.rpc.ServerMessageSender; import io.seata.core.rpc.TransactionMessageHandler; -import io.seata.core.rpc.netty.RpcServer; +import io.seata.core.rpc.netty.NettyRemotingServer; import io.seata.server.AbstractTCInboundHandler; import io.seata.server.event.EventBusManager; import io.seata.server.session.GlobalSession; @@ -65,6 +59,12 @@ import io.seata.server.session.SessionHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + /** * The type Default coordinator. */ @@ -134,7 +134,7 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran private ScheduledThreadPoolExecutor undoLogDelete = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("UndoLogDelete", 1)); - private ServerMessageSender messageSender; + private RemotingServer remotingServer; private DefaultCore core; @@ -143,11 +143,11 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran /** * Instantiates a new Default coordinator. * - * @param messageSender the message sender + * @param remotingServer the remoting server */ - public DefaultCoordinator(ServerMessageSender messageSender) { - this.messageSender = messageSender; - this.core = new DefaultCore(messageSender); + public DefaultCoordinator(RemotingServer remotingServer) { + this.remotingServer = remotingServer; + this.core = new DefaultCore(remotingServer); } @Override @@ -364,7 +364,7 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran deleteRequest.setResourceId(resourceId); deleteRequest.setSaveDays(saveDays > 0 ? saveDays : UndoLogDeleteRequest.DEFAULT_SAVE_DAYS); try { - messageSender.sendASyncRequest(channelEntry.getValue(), deleteRequest); + remotingServer.sendAsyncRequest(channelEntry.getValue(), deleteRequest); } catch (Exception e) { LOGGER.error("Failed to async delete undo log resourceId = {}, exception: {}", resourceId, e.getMessage()); } @@ -451,8 +451,8 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran } // 2. second close netty flow - if (messageSender instanceof RpcServer) { - ((RpcServer) messageSender).destroy(); + if (remotingServer instanceof NettyRemotingServer) { + ((NettyRemotingServer) remotingServer).destroy(); } // 3. last destroy SessionHolder SessionHolder.destroy(); diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCore.java b/server/src/main/java/io/seata/server/coordinator/DefaultCore.java index 6880227a110f1c66af3d1bc4bf5dc23b3162935a..2b5853892d4cb1da44016fffc08d278f571d3690 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCore.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCore.java @@ -32,7 +32,7 @@ import io.seata.core.logger.StackTraceLogger; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; import io.seata.core.model.GlobalStatus; -import io.seata.core.rpc.ServerMessageSender; +import io.seata.core.rpc.RemotingServer; import io.seata.server.event.EventBusManager; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; @@ -55,11 +55,11 @@ public class DefaultCore implements Core { /** * get the Default core. * - * @param messageSender the message sender + * @param remotingServer the remoting server */ - public DefaultCore(ServerMessageSender messageSender) { + public DefaultCore(RemotingServer remotingServer) { List<AbstractCore> allCore = EnhancedServiceLoader.loadAll(AbstractCore.class, - new Class[] {ServerMessageSender.class}, new Object[] {messageSender}); + new Class[]{RemotingServer.class}, new Object[]{remotingServer}); if (CollectionUtils.isNotEmpty(allCore)) { for (AbstractCore core : allCore) { coreMap.put(core.getHandleBranchType(), core); @@ -85,7 +85,7 @@ public class DefaultCore implements Core { * only for mock * * @param branchType the branchType - * @param core the core + * @param core the core */ public void mockCore(BranchType branchType, AbstractCore core) { coreMap.put(branchType, core); @@ -95,7 +95,7 @@ public class DefaultCore implements Core { public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String applicationData, String lockKeys) throws TransactionException { return getCore(branchType).branchRegister(branchType, resourceId, clientId, xid, - applicationData, lockKeys); + applicationData, lockKeys); } @Override @@ -106,7 +106,7 @@ public class DefaultCore implements Core { @Override public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys) - throws TransactionException { + throws TransactionException { return getCore(branchType).lockQuery(branchType, resourceId, xid, lockKeys); } @@ -122,16 +122,16 @@ public class DefaultCore implements Core { @Override public String begin(String applicationId, String transactionServiceGroup, String name, int timeout) - throws TransactionException { + throws TransactionException { GlobalSession session = GlobalSession.createGlobalSession(applicationId, transactionServiceGroup, name, - timeout); + timeout); session.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); session.begin(); // transaction start event eventBus.post(new GlobalTransactionEvent(session.getTransactionId(), GlobalTransactionEvent.ROLE_TC, - session.getTransactionName(), session.getBeginTime(), null, session.getStatus())); + session.getTransactionName(), session.getBeginTime(), null, session.getStatus())); return session.getXid(); } @@ -172,7 +172,7 @@ public class DefaultCore implements Core { boolean success = true; // start committing event eventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, - globalSession.getTransactionName(), globalSession.getBeginTime(), null, globalSession.getStatus())); + globalSession.getTransactionName(), globalSession.getBeginTime(), null, globalSession.getStatus())); if (globalSession.isSaga()) { success = getCore(BranchType.SAGA).doGlobalCommit(globalSession, retrying); @@ -234,8 +234,8 @@ public class DefaultCore implements Core { // committed event eventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, - globalSession.getTransactionName(), globalSession.getBeginTime(), System.currentTimeMillis(), - globalSession.getStatus())); + globalSession.getTransactionName(), globalSession.getBeginTime(), System.currentTimeMillis(), + globalSession.getStatus())); LOGGER.info("Committing global transaction is successfully done, xid = {}.", globalSession.getXid()); } @@ -271,7 +271,7 @@ public class DefaultCore implements Core { boolean success = true; // start rollback event eventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, - globalSession.getTransactionName(), globalSession.getBeginTime(), null, globalSession.getStatus())); + globalSession.getTransactionName(), globalSession.getBeginTime(), null, globalSession.getStatus())); if (globalSession.isSaga()) { success = getCore(BranchType.SAGA).doGlobalRollback(globalSession, retrying); @@ -287,7 +287,7 @@ public class DefaultCore implements Core { switch (branchStatus) { case PhaseTwo_Rollbacked: globalSession.removeBranch(branchSession); - LOGGER.info("Rollback branch transaction successfully, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId()); + LOGGER.info("Rollback branch transaction successfully, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId()); continue; case PhaseTwo_RollbackFailed_Unretryable: SessionHelper.endRollbackFailed(globalSession); @@ -328,8 +328,8 @@ public class DefaultCore implements Core { // rollbacked event eventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, - globalSession.getTransactionName(), globalSession.getBeginTime(), System.currentTimeMillis(), - globalSession.getStatus())); + globalSession.getTransactionName(), globalSession.getBeginTime(), System.currentTimeMillis(), + globalSession.getStatus())); LOGGER.info("Rollback global transaction successfully, xid = {}.", globalSession.getXid()); } @@ -339,7 +339,7 @@ public class DefaultCore implements Core { @Override public GlobalStatus getStatus(String xid) throws TransactionException { GlobalSession globalSession = SessionHolder.findGlobalSession(xid, false); - if (null == globalSession) { + if (globalSession == null) { return GlobalStatus.Finished; } else { return globalSession.getStatus(); diff --git a/server/src/main/java/io/seata/server/env/ContainerHelper.java b/server/src/main/java/io/seata/server/env/ContainerHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..d006dc9b314cdab44f22b3a5f0b12934a5d3ca25 --- /dev/null +++ b/server/src/main/java/io/seata/server/env/ContainerHelper.java @@ -0,0 +1,106 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.env; + +import io.seata.common.util.NumberUtils; +import io.seata.common.util.StringUtils; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.stream.Stream; + +import static io.seata.core.constants.DefaultValues.SERVER_DEFAULT_PORT; + +/** + * @author wang.liang + */ +public class ContainerHelper { + + private static final String C_GROUP_PATH = "/proc/1/cgroup"; + private static final String DOCKER_PATH = "/docker"; + private static final String KUBEPODS_PATH = "/kubepods"; + + private static final String ENV_SYSTEM_KEY = "SEATA_ENV"; + private static final String ENV_SEATA_IP_KEY = "SEATA_IP"; + private static final String ENV_SERVER_NODE_KEY = "SERVER_NODE"; + private static final String ENV_SEATA_PORT_KEY = "SEATA_PORT"; + private static final String ENV_STORE_MODE_KEY = "STORE_MODE"; + + /** + * Judge if application is run in container. + * + * @return If application is run in container + */ + public static boolean isRunningInContainer() { + Path path = Paths.get(C_GROUP_PATH); + if (Files.exists(path)) { + try (Stream<String> stream = Files.lines(path)) { + return stream.anyMatch(line -> line.contains(DOCKER_PATH) || line.contains(KUBEPODS_PATH)); + } catch (IOException e) { + System.err.println("Judge if running in container failed: " + e.getMessage()); + e.printStackTrace(); + } + } + return false; + } + + /** + * Gets env from container. + * + * @return the env + */ + public static String getEnv() { + return StringUtils.trimToNull(System.getenv(ENV_SYSTEM_KEY)); + } + + /** + * Gets host from container. + * + * @return the env + */ + public static String getHost() { + return StringUtils.trimToNull(System.getenv(ENV_SEATA_IP_KEY)); + } + + /** + * Gets port from container. + * + * @return the env + */ + public static int getPort() { + return NumberUtils.toInt(System.getenv(ENV_SEATA_PORT_KEY), SERVER_DEFAULT_PORT); + } + + /** + * Gets server node from container. + * + * @return the env + */ + public static Long getServerNode() { + return NumberUtils.toLong(System.getenv(ENV_SERVER_NODE_KEY)); + } + + /** + * Gets store mode from container. + * + * @return the env + */ + public static String getStoreMode() { + return StringUtils.trimToNull(System.getenv(ENV_STORE_MODE_KEY)); + } +} diff --git a/server/src/main/java/io/seata/server/env/PortHelper.java b/server/src/main/java/io/seata/server/env/PortHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..d496c685adf40fd17d83da30595fbb03358adad3 --- /dev/null +++ b/server/src/main/java/io/seata/server/env/PortHelper.java @@ -0,0 +1,41 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.env; + +import io.seata.common.util.NumberUtils; + +import static io.seata.core.constants.DefaultValues.SERVER_DEFAULT_PORT; + +/** + * @author wang.liang + */ +public class PortHelper { + + public static int getPort(String[] args) { + if (ContainerHelper.isRunningInContainer()) { + return ContainerHelper.getPort(); + } else if (args != null && args.length >= 2) { + for (int i = 0; i < args.length; ++i) { + if ("-p".equalsIgnoreCase(args[i]) && i < args.length - 1) { + return NumberUtils.toInt(args[i + 1], SERVER_DEFAULT_PORT); + } + } + } + + return SERVER_DEFAULT_PORT; + } + +} diff --git a/server/src/main/java/io/seata/server/logging/listener/SystemPropertyLoggerContextListener.java b/server/src/main/java/io/seata/server/logging/listener/SystemPropertyLoggerContextListener.java new file mode 100644 index 0000000000000000000000000000000000000000..5881a7615880cacd56fd42dd11aa589e35945bbe --- /dev/null +++ b/server/src/main/java/io/seata/server/logging/listener/SystemPropertyLoggerContextListener.java @@ -0,0 +1,75 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.logging.listener; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.LoggerContextListener; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.LifeCycle; +import io.seata.core.constants.ConfigurationKeys; + +/** + * @author wang.liang + */ +public class SystemPropertyLoggerContextListener extends ContextAwareBase implements LoggerContextListener, LifeCycle { + + private boolean started = false; + + @Override + public void start() { + if (started) { + return; + } + + Context context = getContext(); + context.putProperty("PORT", System.getProperty(ConfigurationKeys.SERVER_PORT)); + + started = true; + } + + @Override + public void stop() { + } + + @Override + public boolean isStarted() { + return started; + } + + @Override + public boolean isResetResistant() { + return true; + } + + @Override + public void onStart(LoggerContext context) { + } + + @Override + public void onReset(LoggerContext context) { + } + + @Override + public void onStop(LoggerContext context) { + } + + @Override + public void onLevelChange(Logger logger, Level level) { + } +} \ No newline at end of file diff --git a/server/src/main/java/io/seata/server/logging/logback/ColorConverter.java b/server/src/main/java/io/seata/server/logging/logback/ColorConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..a798cb4619688b768d867842d6af3774bbd64347 --- /dev/null +++ b/server/src/main/java/io/seata/server/logging/logback/ColorConverter.java @@ -0,0 +1,78 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.logging.logback; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.pattern.CompositeConverter; +import io.seata.server.logging.logback.ansi.AnsiColor; +import io.seata.server.logging.logback.ansi.AnsiElement; +import io.seata.server.logging.logback.ansi.AnsiOutput; +import io.seata.server.logging.logback.ansi.AnsiStyle; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Logback {@link CompositeConverter} colors output using the {@link AnsiOutput} class. A + * single 'color' option can be provided to the converter, or if not specified color will + * be picked based on the logging level. + * + * @author Phillip Webb + * @origin Copied from spring-boot.jar by wang.liang + */ +public class ColorConverter extends CompositeConverter<ILoggingEvent> { + + private static final Map<String, AnsiElement> ELEMENTS; + + static { + Map<String, AnsiElement> ansiElements = new HashMap<String, AnsiElement>(); + ansiElements.put("faint", AnsiStyle.FAINT); + ansiElements.put("red", AnsiColor.RED); + ansiElements.put("green", AnsiColor.GREEN); + ansiElements.put("yellow", AnsiColor.YELLOW); + ansiElements.put("blue", AnsiColor.BLUE); + ansiElements.put("magenta", AnsiColor.MAGENTA); + ansiElements.put("cyan", AnsiColor.CYAN); + ELEMENTS = Collections.unmodifiableMap(ansiElements); + } + + private static final Map<Integer, AnsiElement> LEVELS; + + static { + Map<Integer, AnsiElement> ansiLevels = new HashMap<Integer, AnsiElement>(); + ansiLevels.put(Level.ERROR_INTEGER, AnsiColor.RED); + ansiLevels.put(Level.WARN_INTEGER, AnsiColor.YELLOW); + LEVELS = Collections.unmodifiableMap(ansiLevels); + } + + @Override + protected String transform(ILoggingEvent event, String in) { + AnsiElement element = ELEMENTS.get(getFirstOption()); + if (element == null) { + // Assume highlighting + element = LEVELS.get(event.getLevel().toInteger()); + element = (element != null) ? element : AnsiColor.GREEN; + } + return toAnsiString(in, element); + } + + protected String toAnsiString(String in, AnsiElement element) { + return AnsiOutput.toString(element, in); + } + +} diff --git a/server/src/main/java/io/seata/server/logging/logback/ExtendedWhitespaceThrowableProxyConverter.java b/server/src/main/java/io/seata/server/logging/logback/ExtendedWhitespaceThrowableProxyConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..70ac7aaafcf3c738ebe4757ddb29e54feedc9b92 --- /dev/null +++ b/server/src/main/java/io/seata/server/logging/logback/ExtendedWhitespaceThrowableProxyConverter.java @@ -0,0 +1,36 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.logging.logback; + +import ch.qos.logback.classic.pattern.ExtendedThrowableProxyConverter; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.core.CoreConstants; + +/** + * {@link ExtendedThrowableProxyConverter} that adds some additional whitespace around the + * stack trace. + * + * @author Phillip Webb + * @origin Copied from spring-boot.jar by wang.liang + */ +public class ExtendedWhitespaceThrowableProxyConverter extends ExtendedThrowableProxyConverter { + + @Override + protected String throwableProxyToString(IThrowableProxy tp) { + return "==>" + CoreConstants.LINE_SEPARATOR + super.throwableProxyToString(tp) + + "<==" + CoreConstants.LINE_SEPARATOR + CoreConstants.LINE_SEPARATOR; + } +} diff --git a/server/src/main/java/io/seata/server/logging/logback/WhitespaceThrowableProxyConverter.java b/server/src/main/java/io/seata/server/logging/logback/WhitespaceThrowableProxyConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..4a84860889a6513d551b9d0bdb893c1190cd8f30 --- /dev/null +++ b/server/src/main/java/io/seata/server/logging/logback/WhitespaceThrowableProxyConverter.java @@ -0,0 +1,35 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.logging.logback; + +import ch.qos.logback.classic.pattern.ThrowableProxyConverter; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.core.CoreConstants; + +/** + * {@link ThrowableProxyConverter} that adds some additional whitespace around the stacktrace. + * + * @author Phillip Webb + * @origin Copied from spring-boot.jar by wang.liang + */ +public class WhitespaceThrowableProxyConverter extends ThrowableProxyConverter { + + @Override + protected String throwableProxyToString(IThrowableProxy tp) { + return "==>" + CoreConstants.LINE_SEPARATOR + super.throwableProxyToString(tp) + + "<==" + CoreConstants.LINE_SEPARATOR + CoreConstants.LINE_SEPARATOR; + } +} diff --git a/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiColor.java b/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiColor.java new file mode 100644 index 0000000000000000000000000000000000000000..9e31d946a037bc11e8f1a0bd3c9fd41ca9fd128b --- /dev/null +++ b/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiColor.java @@ -0,0 +1,126 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.logging.logback.ansi; + +/** + * {@link AnsiElement Ansi} colors. + * + * @author Phillip Webb + * @author Geoffrey Chandler + * @origin Copied from spring-boot.jar by wang.liang + */ +public enum AnsiColor implements AnsiElement { + + /** + * default is light-grey + */ + DEFAULT("39"), + + /** + * black + */ + BLACK("30"), + + /** + * red + */ + RED("31"), + + /** + * green + */ + GREEN("32"), + + /** + * yellow + */ + YELLOW("33"), + + /** + * blue + */ + BLUE("34"), + + /** + * magenta + */ + MAGENTA("35"), + + /** + * cyan + */ + CYAN("36"), + + /** + * white + */ + WHITE("37"), + + /** + * bright black + */ + BRIGHT_BLACK("90"), + + /** + * bright red + */ + BRIGHT_RED("91"), + + /** + * bright green + */ + BRIGHT_GREEN("92"), + + /** + * bright yellow + */ + BRIGHT_YELLOW("93"), + + /** + * bright blue + */ + BRIGHT_BLUE("94"), + + /** + * bright magenta + */ + BRIGHT_MAGENTA("95"), + + /** + * bright cyan + */ + BRIGHT_CYAN("96"), + + /** + * bright white + */ + BRIGHT_WHITE("97"); + + /** + * code of color + */ + private final String code; + + AnsiColor(String code) { + this.code = code; + } + + @Override + public String toString() { + return this.code; + } + +} diff --git a/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiElement.java b/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiElement.java new file mode 100644 index 0000000000000000000000000000000000000000..93af31bb3319aec53efa6700bc972d5344f6b02b --- /dev/null +++ b/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiElement.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.logging.logback.ansi; + +/** + * An ANSI encodable element. + * + * @author Phillip Webb + * @origin Copied from spring-boot.jar by wang.liang + */ +public interface AnsiElement { + + /** + * @return the ANSI escape code + */ + @Override + String toString(); + +} diff --git a/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiOutput.java b/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiOutput.java new file mode 100644 index 0000000000000000000000000000000000000000..9d3804b29747e840422a58e4d7e68c86a58e4333 --- /dev/null +++ b/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiOutput.java @@ -0,0 +1,185 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.logging.logback.ansi; + +import com.alipay.lookout.common.Assert; + +import java.util.Locale; + +/** + * Generates ANSI encoded output, automatically attempting to detect if the terminal + * supports ANSI. + * + * @author Phillip Webb + * @origin Copied from spring-boot.jar by wang.liang + */ +public class AnsiOutput { + + private static final String ENCODE_JOIN = ";"; + + private static Enabled enabled = Enabled.ALWAYS; + + private static Boolean consoleAvailable; + + private static Boolean ansiCapable; + + private static final String OPERATING_SYSTEM_NAME = System.getProperty("os.name") + .toLowerCase(Locale.ENGLISH); + + private static final String ENCODE_START = "\033["; + + private static final String ENCODE_END = "m"; + + private static final String RESET = "0;" + AnsiColor.DEFAULT; + + /** + * Sets if ANSI output is enabled. + * @param enabled if ANSI is enabled, disabled or detected + */ + public static void setEnabled(Enabled enabled) { + Assert.notNull(enabled, "Enabled must not be null"); + AnsiOutput.enabled = enabled; + } + + /** + * Sets if the System.console() is known to be available. + * @param consoleAvailable if the console is known to be available or {@code null} to + * use standard detection logic. + */ + public static void setConsoleAvailable(Boolean consoleAvailable) { + AnsiOutput.consoleAvailable = consoleAvailable; + } + + static Enabled getEnabled() { + return AnsiOutput.enabled; + } + + /** + * Encode a single {@link AnsiElement} if output is enabled. + * @param element the element to encode + * @return the encoded element or an empty string + */ + public static String encode(AnsiElement element) { + if (isEnabled()) { + return ENCODE_START + element + ENCODE_END; + } + return ""; + } + + /** + * Create a new ANSI string from the specified elements. Any {@link AnsiElement}s will + * be encoded as required. + * @param elements the elements to encode + * @return a string of the encoded elements + */ + public static String toString(Object... elements) { + StringBuilder sb = new StringBuilder(); + if (isEnabled()) { + buildEnabled(sb, elements); + } + else { + buildDisabled(sb, elements); + } + return sb.toString(); + } + + private static void buildEnabled(StringBuilder sb, Object[] elements) { + boolean writingAnsi = false; + boolean containsEncoding = false; + for (Object element : elements) { + if (element instanceof AnsiElement) { + containsEncoding = true; + if (!writingAnsi) { + sb.append(ENCODE_START); + writingAnsi = true; + } + else { + sb.append(ENCODE_JOIN); + } + } + else { + if (writingAnsi) { + sb.append(ENCODE_END); + writingAnsi = false; + } + } + sb.append(element); + } + if (containsEncoding) { + sb.append(writingAnsi ? ENCODE_JOIN : ENCODE_START); + sb.append(RESET); + sb.append(ENCODE_END); + } + } + + private static void buildDisabled(StringBuilder sb, Object[] elements) { + for (Object element : elements) { + if (!(element instanceof AnsiElement) && element != null) { + sb.append(element); + } + } + } + + private static boolean isEnabled() { + if (enabled == Enabled.DETECT) { + if (ansiCapable == null) { + ansiCapable = detectIfAnsiCapable(); + } + return ansiCapable; + } + return enabled == Enabled.ALWAYS; + } + + private static boolean detectIfAnsiCapable() { + try { + if (Boolean.FALSE.equals(consoleAvailable)) { + return false; + } + if ((consoleAvailable == null) && (System.console() == null)) { + return false; + } + return !(OPERATING_SYSTEM_NAME.indexOf("win") >= 0); + } + catch (Throwable ex) { + return false; + } + } + + /** + * Possible values to pass to {@link AnsiOutput#setEnabled}. Determines when to output + * ANSI escape sequences for coloring application output. + */ + public enum Enabled { + + /** + * Try to detect whether ANSI coloring capabilities are available. The default + * value for {@link AnsiOutput}. + */ + DETECT, + + /** + * Enable ANSI-colored output. + */ + ALWAYS, + + /** + * Disable ANSI-colored output. + */ + NEVER + + } + +} diff --git a/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiStyle.java b/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiStyle.java new file mode 100644 index 0000000000000000000000000000000000000000..cf4ae257839f096741230c971e5cf1224ef2dce9 --- /dev/null +++ b/server/src/main/java/io/seata/server/logging/logback/ansi/AnsiStyle.java @@ -0,0 +1,65 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.logging.logback.ansi; + +/** + * {@link AnsiElement Ansi} styles. + * + * @author Phillip Webb + * @origin Copied from spring-boot.jar by wang.liang + */ +public enum AnsiStyle implements AnsiElement { + + /** + * normal + */ + NORMAL("0"), + + /** + * bold + */ + BOLD("1"), + + /** + * faint + */ + FAINT("2"), + + /** + * italic + */ + ITALIC("3"), + + /** + * underline + */ + UNDERLINE("4"); + + /** + * code of style + */ + private final String code; + + AnsiStyle(String code) { + this.code = code; + } + + @Override + public String toString() { + return this.code; + } + +} diff --git a/server/src/main/java/io/seata/server/session/BranchSession.java b/server/src/main/java/io/seata/server/session/BranchSession.java index e4e26d6463cea712e9db70386c49146dccfc9295..959fa619a3495603788c2430ffb85be63982eb7f 100644 --- a/server/src/main/java/io/seata/server/session/BranchSession.java +++ b/server/src/main/java/io/seata/server/session/BranchSession.java @@ -330,28 +330,28 @@ public class BranchSession implements Lockable, Comparable<BranchSession>, Sessi byteBuffer.putLong(transactionId); byteBuffer.putLong(branchId); - if (null != resourceIdBytes) { + if (resourceIdBytes != null) { byteBuffer.putInt(resourceIdBytes.length); byteBuffer.put(resourceIdBytes); } else { byteBuffer.putInt(0); } - if (null != lockKeyBytes) { + if (lockKeyBytes != null) { byteBuffer.putInt(lockKeyBytes.length); byteBuffer.put(lockKeyBytes); } else { byteBuffer.putInt(0); } - if (null != clientIdBytes) { + if (clientIdBytes != null) { byteBuffer.putShort((short)clientIdBytes.length); byteBuffer.put(clientIdBytes); } else { byteBuffer.putShort((short)0); } - if (null != applicationDataBytes) { + if (applicationDataBytes != null) { byteBuffer.putInt(applicationDataBytes.length); byteBuffer.put(applicationDataBytes); } else { diff --git a/server/src/main/java/io/seata/server/session/GlobalSession.java b/server/src/main/java/io/seata/server/session/GlobalSession.java index bead6cc8813fea95cb6a5c8334cfaea399f13003..28f41c0e689965d4006aa52cab429c053e90012e 100644 --- a/server/src/main/java/io/seata/server/session/GlobalSession.java +++ b/server/src/main/java/io/seata/server/session/GlobalSession.java @@ -492,19 +492,19 @@ public class GlobalSession implements SessionLifecycle, SessionStorable { byteBuffer.putLong(transactionId); byteBuffer.putInt(timeout); - if (null != byApplicationIdBytes) { + if (byApplicationIdBytes != null) { byteBuffer.putShort((short)byApplicationIdBytes.length); byteBuffer.put(byApplicationIdBytes); } else { byteBuffer.putShort((short)0); } - if (null != byServiceGroupBytes) { + if (byServiceGroupBytes != null) { byteBuffer.putShort((short)byServiceGroupBytes.length); byteBuffer.put(byServiceGroupBytes); } else { byteBuffer.putShort((short)0); } - if (null != byTxNameBytes) { + if (byTxNameBytes != null) { byteBuffer.putShort((short)byTxNameBytes.length); byteBuffer.put(byTxNameBytes); } else { diff --git a/server/src/main/java/io/seata/server/session/SessionHolder.java b/server/src/main/java/io/seata/server/session/SessionHolder.java index b16e0549a07ede4b188ae69d98ac0562cb9a5366..fd2af233ad17098ea3360895f7e2fbfb77eda5de 100644 --- a/server/src/main/java/io/seata/server/session/SessionHolder.java +++ b/server/src/main/java/io/seata/server/session/SessionHolder.java @@ -105,7 +105,16 @@ public class SessionHolder { new Class[] {String.class, String.class}, new Object[] {RETRY_COMMITTING_SESSION_MANAGER_NAME, null}); RETRY_ROLLBACKING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.FILE.getName(), new Class[] {String.class, String.class}, new Object[] {RETRY_ROLLBACKING_SESSION_MANAGER_NAME, null}); + } else if (StoreMode.REDIS.equals(storeMode)) { + ROOT_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.REDIS.getName()); + ASYNC_COMMITTING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, + StoreMode.REDIS.getName(), new Object[] {ASYNC_COMMITTING_SESSION_MANAGER_NAME}); + RETRY_COMMITTING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, + StoreMode.REDIS.getName(), new Object[] {RETRY_COMMITTING_SESSION_MANAGER_NAME}); + RETRY_ROLLBACKING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, + StoreMode.REDIS.getName(), new Object[] {RETRY_ROLLBACKING_SESSION_MANAGER_NAME}); } else { + // unknown store throw new IllegalArgumentException("unknown store mode:" + mode); } reload(); diff --git a/server/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java b/server/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java index 6a2c7bb11ffa46faafe14f418b3666486207ce97..2e4e583db3025da1d7aeef641e27d52371eb3dff 100644 --- a/server/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java +++ b/server/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java @@ -27,7 +27,7 @@ import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.exception.TransactionException; import io.seata.core.lock.Locker; -import io.seata.core.store.db.DataSourceGenerator; +import io.seata.core.store.db.DataSourceProvider; import io.seata.server.lock.AbstractLockManager; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; @@ -49,9 +49,8 @@ public class DataBaseLockManager extends AbstractLockManager implements Initiali public void init() { // init dataSource String datasourceType = ConfigurationFactory.getInstance().getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); - DataSourceGenerator dataSourceGenerator = EnhancedServiceLoader.load(DataSourceGenerator.class, datasourceType); - DataSource logStoreDataSource = dataSourceGenerator.generateDataSource(); - locker = new DataBaseLocker(logStoreDataSource); + DataSource lockStoreDataSource = EnhancedServiceLoader.load(DataSourceProvider.class, datasourceType).provide(); + locker = new DataBaseLocker(lockStoreDataSource); } @Override diff --git a/server/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java b/server/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java index 3d1c15e0222514b82c6dbf87db18cdbe3867035e..c14980e1c9cd3fd29b1d842ed28173b0c9bd756e 100644 --- a/server/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java +++ b/server/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java @@ -25,7 +25,6 @@ import io.seata.common.util.StringUtils; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.GlobalStatus; -import io.seata.server.UUIDGenerator; import io.seata.server.session.AbstractSessionManager; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; @@ -200,9 +199,5 @@ public class DataBaseSessionManager extends AbstractSessionManager @Override public void reload() { - long maxSessionId = transactionStoreManager.getCurrentMaxSessionId(); - if (maxSessionId > UUIDGenerator.getCurrentUUID()) { - UUIDGenerator.setUUID(UUIDGenerator.getCurrentUUID(), maxSessionId); - } } } diff --git a/server/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java b/server/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java index 456979dcbb0032ce13543c0b62ad71488a3656d9..b301f896e12ebc30cbbb187556788639bd769b1a 100644 --- a/server/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java +++ b/server/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java @@ -35,8 +35,7 @@ import io.seata.core.model.GlobalStatus; import io.seata.core.store.BranchTransactionDO; import io.seata.core.store.GlobalTransactionDO; import io.seata.core.store.LogStore; -import io.seata.core.store.db.DataSourceGenerator; -import io.seata.server.UUIDGenerator; +import io.seata.core.store.db.DataSourceProvider; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; import io.seata.server.session.SessionCondition; @@ -78,9 +77,9 @@ public class DataBaseTransactionStoreManager extends AbstractTransactionStoreMan * Get the instance. */ public static DataBaseTransactionStoreManager getInstance() { - if (null == instance) { + if (instance == null) { synchronized (DataBaseTransactionStoreManager.class) { - if (null == instance) { + if (instance == null) { instance = new DataBaseTransactionStoreManager(); } } @@ -95,8 +94,7 @@ public class DataBaseTransactionStoreManager extends AbstractTransactionStoreMan logQueryLimit = CONFIG.getInt(ConfigurationKeys.STORE_DB_LOG_QUERY_LIMIT, DEFAULT_LOG_QUERY_LIMIT); String datasourceType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); //init dataSource - DataSourceGenerator dataSourceGenerator = EnhancedServiceLoader.load(DataSourceGenerator.class, datasourceType); - DataSource logStoreDataSource = dataSourceGenerator.generateDataSource(); + DataSource logStoreDataSource = EnhancedServiceLoader.load(DataSourceProvider.class, datasourceType).provide(); logStore = new LogStoreDataBaseDAO(logStoreDataSource); } @@ -218,12 +216,6 @@ public class DataBaseTransactionStoreManager extends AbstractTransactionStoreMan return null; } - @Override - public long getCurrentMaxSessionId() { - //check max transId or branchId - return logStore.getCurrentMaxSessionId(UUIDGenerator.getMaxUUID(), UUIDGenerator.getInitUUID()); - } - private GlobalSession getGlobalSession(GlobalTransactionDO globalTransactionDO, List<BranchTransactionDO> branchTransactionDOs) { GlobalSession globalSession = convertGlobalSession(globalTransactionDO); diff --git a/server/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java b/server/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java index 978fbc55b4527b7aee46485851ca520c0dc1150e..6c24c803f8910dd347df36a9a1c1f83ad1af5baf 100644 --- a/server/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java +++ b/server/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java @@ -22,7 +22,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import java.util.StringJoiner; import javax.sql.DataSource; import io.seata.common.exception.DataAccessException; @@ -77,9 +76,9 @@ public class LogStoreDataBaseDAO implements LogStore { protected String globalTable; /** - * The Brach table. + * The Branch table. */ - protected String brachTable; + protected String branchTable; private String dbType; @@ -94,7 +93,7 @@ public class LogStoreDataBaseDAO implements LogStore { this.logStoreDataSource = logStoreDataSource; globalTable = CONFIG.getConfig(ConfigurationKeys.STORE_DB_GLOBAL_TABLE, DEFAULT_STORE_DB_GLOBAL_TABLE); - brachTable = CONFIG.getConfig(ConfigurationKeys.STORE_DB_BRANCH_TABLE, + branchTable = CONFIG.getConfig(ConfigurationKeys.STORE_DB_BRANCH_TABLE, DEFAULT_STORE_DB_BRANCH_TABLE); dbType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE); if (StringUtils.isBlank(dbType)) { @@ -165,15 +164,9 @@ public class LogStoreDataBaseDAO implements LogStore { conn = logStoreDataSource.getConnection(); conn.setAutoCommit(true); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < statuses.length; i++) { - sb.append("?"); - if (i != (statuses.length - 1)) { - sb.append(", "); - } - } + String paramsPlaceHolder = org.apache.commons.lang.StringUtils.repeat("?", ",", statuses.length); - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryGlobalTransactionSQLByStatus(globalTable, sb.toString()); + String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryGlobalTransactionSQLByStatus(globalTable, paramsPlaceHolder); ps = conn.prepareStatement(sql); for (int i = 0; i < statuses.length; i++) { int status = statuses[i]; @@ -262,7 +255,7 @@ public class LogStoreDataBaseDAO implements LogStore { @Override public List<BranchTransactionDO> queryBranchTransactionDO(String xid) { List<BranchTransactionDO> rets = new ArrayList<>(); - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryBranchTransaction(brachTable); + String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryBranchTransaction(branchTable); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; @@ -288,11 +281,9 @@ public class LogStoreDataBaseDAO implements LogStore { @Override public List<BranchTransactionDO> queryBranchTransactionDO(List<String> xids) { int length = xids.size(); - int retsSize = length * 3; - List<BranchTransactionDO> rets = new ArrayList<>(retsSize); - StringJoiner sj = new StringJoiner(","); - xids.stream().forEach(xid -> sj.add("?")); - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryBranchTransaction(brachTable, sj.toString()); + List<BranchTransactionDO> rets = new ArrayList<>(length * 3); + String paramsPlaceHolder = org.apache.commons.lang.StringUtils.repeat("?", ",", length); + String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryBranchTransaction(branchTable, paramsPlaceHolder); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; @@ -317,7 +308,7 @@ public class LogStoreDataBaseDAO implements LogStore { @Override public boolean insertBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getInsertBranchTransactionSQL(brachTable); + String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getInsertBranchTransactionSQL(branchTable); Connection conn = null; PreparedStatement ps = null; try { @@ -343,7 +334,7 @@ public class LogStoreDataBaseDAO implements LogStore { @Override public boolean updateBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getUpdateBranchTransactionStatusSQL(brachTable); + String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getUpdateBranchTransactionStatusSQL(branchTable); Connection conn = null; PreparedStatement ps = null; try { @@ -363,7 +354,7 @@ public class LogStoreDataBaseDAO implements LogStore { @Override public boolean deleteBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getDeleteBranchTransactionByBranchIdSQL(brachTable); + String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getDeleteBranchTransactionByBranchIdSQL(branchTable); Connection conn = null; PreparedStatement ps = null; try { @@ -384,7 +375,7 @@ public class LogStoreDataBaseDAO implements LogStore { @Override public long getCurrentMaxSessionId(long high, long low) { String transMaxSql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryGlobalMax(globalTable); - String branchMaxSql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryBranchMax(brachTable); + String branchMaxSql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getQueryBranchMax(branchTable); long maxTransId = getCurrentMaxSessionId(transMaxSql, high, low); long maxBranchId = getCurrentMaxSessionId(branchMaxSql, high, low); return maxBranchId > maxTransId ? maxBranchId : maxTransId; @@ -524,12 +515,12 @@ public class LogStoreDataBaseDAO implements LogStore { } /** - * Sets brach table. + * Sets branch table. * - * @param brachTable the brach table + * @param branchTable the branch table */ - public void setBrachTable(String brachTable) { - this.brachTable = brachTable; + public void setBranchTable(String branchTable) { + this.branchTable = branchTable; } /** diff --git a/server/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java b/server/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java index 9c075090caf23ef1f6e748eba2796841e077c08b..491aa1ab96d4e1c0f3420cf95ac48b1861ced6d4 100644 --- a/server/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java +++ b/server/src/main/java/io/seata/server/storage/file/session/FileSessionManager.java @@ -24,7 +24,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; - import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.loader.LoadLevel; import io.seata.common.util.StringUtils; @@ -32,7 +31,6 @@ import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.exception.TransactionException; import io.seata.core.model.GlobalStatus; -import io.seata.server.UUIDGenerator; import io.seata.server.session.AbstractSessionManager; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; @@ -80,22 +78,6 @@ public class FileSessionManager extends AbstractSessionManager implements Reload public boolean writeSession(LogOperation logOperation, SessionStorable session) { return true; } - - @Override - public long getCurrentMaxSessionId() { - long maxSessionId = 0L; - for (Map.Entry<String, GlobalSession> entry : sessionMap.entrySet()) { - GlobalSession globalSession = entry.getValue(); - if (globalSession.hasBranch()) { - long maxBranchId = globalSession.getSortedBranches().get(globalSession.getSortedBranches().size() - 1) - .getBranchId(); - if (maxBranchId > maxSessionId) { - maxSessionId = maxBranchId; - } - } - } - return maxSessionId; - } }; } } @@ -223,11 +205,9 @@ public class FileSessionManager extends AbstractSessionManager implements Reload } private void restore(List<TransactionWriteStore> stores, Map<Long, BranchSession> unhandledBranchSessions) { - long maxRecoverId = UUIDGenerator.getCurrentUUID(); for (TransactionWriteStore store : stores) { TransactionStoreManager.LogOperation logOperation = store.getOperate(); SessionStorable sessionStorable = store.getSessionRequest(); - maxRecoverId = getMaxId(maxRecoverId, sessionStorable); switch (logOperation) { case GLOBAL_ADD: case GLOBAL_UPDATE: { @@ -318,32 +298,7 @@ public class FileSessionManager extends AbstractSessionManager implements Reload } } - setMaxId(maxRecoverId); - - } - - private long getMaxId(long maxRecoverId, SessionStorable sessionStorable) { - long currentId = 0; - if (sessionStorable instanceof GlobalSession) { - currentId = ((GlobalSession)sessionStorable).getTransactionId(); - } else if (sessionStorable instanceof BranchSession) { - currentId = ((BranchSession)sessionStorable).getBranchId(); - } - - return maxRecoverId > currentId ? maxRecoverId : currentId; - } - - private void setMaxId(long maxRecoverId) { - long currentId; - // will be recover multi-thread later - while ((currentId = UUIDGenerator.getCurrentUUID()) < maxRecoverId) { - if (UUIDGenerator.setUUID(currentId, maxRecoverId)) { - break; - } - } - } - private void restore(TransactionWriteStore store) { } @Override diff --git a/server/src/main/java/io/seata/server/storage/file/store/FileTransactionStoreManager.java b/server/src/main/java/io/seata/server/storage/file/store/FileTransactionStoreManager.java index e2cc27990dcc27c17f9fb707029ec743b95f5c7a..aa62dfddb5c49f5df88de7747e1e0e596d8f6902 100644 --- a/server/src/main/java/io/seata/server/storage/file/store/FileTransactionStoreManager.java +++ b/server/src/main/java/io/seata/server/storage/file/store/FileTransactionStoreManager.java @@ -32,7 +32,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.ReentrantLock; -import io.seata.common.exception.NotSupportYetException; import io.seata.common.exception.StoreException; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.CollectionUtils; @@ -282,7 +281,7 @@ public class FileTransactionStoreManager extends AbstractTransactionStoreManager return false; } List<BranchSession> branchSessIonsOverMaXTimeout = globalSession.getSortedBranches(); - if (null != branchSessIonsOverMaXTimeout) { + if (branchSessIonsOverMaXTimeout != null) { for (BranchSession branchSession : branchSessIonsOverMaXTimeout) { TransactionWriteStore branchWriteStore = new TransactionWriteStore(branchSession, LogOperation.BRANCH_ADD); @@ -312,7 +311,7 @@ public class FileTransactionStoreManager extends AbstractTransactionStoreManager @Override public void shutdown() { - if (null != fileWriteExecutor) { + if (fileWriteExecutor != null) { fileWriteExecutor.shutdown(); stopping = true; int retry = 0; @@ -335,11 +334,6 @@ public class FileTransactionStoreManager extends AbstractTransactionStoreManager closeFile(currRaf); } - @Override - public long getCurrentMaxSessionId() { - throw new NotSupportYetException("not support getCurrentMaxSessionId"); - } - @Override public List<TransactionWriteStore> readWriteStore(int readSize, boolean isHistory) { File file = null; @@ -423,7 +417,7 @@ public class FileTransactionStoreManager extends AbstractTransactionStoreManager return null; } finally { try { - if (null != fileChannel) { + if (fileChannel != null) { if (isHistory) { recoverHisOffset = fileChannel.position(); } else { @@ -439,7 +433,7 @@ public class FileTransactionStoreManager extends AbstractTransactionStoreManager private void closeFile(RandomAccessFile raf) { try { - if (null != raf) { + if (raf != null) { raf.close(); raf = null; } diff --git a/server/src/main/java/io/seata/server/storage/redis/JedisPooledFactory.java b/server/src/main/java/io/seata/server/storage/redis/JedisPooledFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..acfc2e02089d3b3ba7b750dc2cba433ee5b0b587 --- /dev/null +++ b/server/src/main/java/io/seata/server/storage/redis/JedisPooledFactory.java @@ -0,0 +1,94 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.storage.redis; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.seata.common.util.StringUtils; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +/** + * @author funkye + */ +public class JedisPooledFactory { + /** + * The constant LOGGER. + */ + protected static final Logger LOGGER = LoggerFactory.getLogger(JedisPooledFactory.class); + + private static volatile JedisPool jedisPool = null; + + private static final String HOST = "127.0.0.1"; + + private static final int PORT = 6379; + + private static final int MINCONN = 1; + + private static final int MAXCONN = 10; + + private static final int DATABASE = 0; + + private static final Configuration CONFIGURATION = ConfigurationFactory.getInstance(); + + /** + * get the RedisPool instance (singleton) + * + * @return redisPool + */ + public static JedisPool getJedisPoolInstance(JedisPool... jedisPools) { + if (jedisPool == null) { + synchronized (JedisPooledFactory.class) { + if (jedisPool == null) { + if (jedisPools != null && jedisPools.length > 0) { + jedisPool = jedisPools[0]; + } else { + String password = CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_PASSWORD); + if (StringUtils.isBlank(password)) { + password = null; + } + JedisPoolConfig poolConfig = new JedisPoolConfig(); + poolConfig.setMinIdle(CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_MIN_CONN, MINCONN)); + poolConfig.setMaxIdle(CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_MAX_CONN, MAXCONN)); + jedisPool = + new JedisPool(poolConfig, CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_HOST, HOST), + CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_PORT, PORT), 60000, password, + CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_DATABASE, DATABASE)); + } + if (LOGGER.isInfoEnabled()) { + LOGGER.info("initialization of the build redis connection pool is complete"); + } + } + } + } + return jedisPool; + } + + /** + * get an instance of Jedis (connection) from the connection pool + * + * @return jedis + */ + public static Jedis getJedisInstance() { + return getJedisPoolInstance().getResource(); + } + +} diff --git a/server/src/main/java/io/seata/server/storage/redis/lock/RedisLockManager.java b/server/src/main/java/io/seata/server/storage/redis/lock/RedisLockManager.java new file mode 100644 index 0000000000000000000000000000000000000000..ddf6b0e0e3dc785024aa6c98ea0b3d443ac91195 --- /dev/null +++ b/server/src/main/java/io/seata/server/storage/redis/lock/RedisLockManager.java @@ -0,0 +1,76 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.storage.redis.lock; + +import java.util.List; +import java.util.stream.Collectors; + +import io.seata.common.executor.Initialize; +import io.seata.common.loader.LoadLevel; +import io.seata.common.util.CollectionUtils; +import io.seata.core.exception.TransactionException; +import io.seata.core.lock.Locker; +import io.seata.server.lock.AbstractLockManager; +import io.seata.server.session.BranchSession; +import io.seata.server.session.GlobalSession; + +/** + * @author funkye + */ +@LoadLevel(name = "redis") +public class RedisLockManager extends AbstractLockManager implements Initialize { + + /** + * The locker. + */ + private Locker locker; + + @Override + public void init() { + locker = new RedisLocker(); + } + + @Override + public Locker getLocker(BranchSession branchSession) { + return locker; + } + + @Override + public boolean releaseLock(BranchSession branchSession) throws TransactionException { + try { + return getLocker().releaseLock(branchSession.getXid(), branchSession.getBranchId()); + } catch (Exception t) { + LOGGER.error("unLock error, xid {}, branchId:{}", branchSession.getXid(), branchSession.getBranchId(), t); + return false; + } + } + + @Override + public boolean releaseGlobalSessionLock(GlobalSession globalSession) throws TransactionException { + List<BranchSession> branchSessions = globalSession.getBranchSessions(); + if (CollectionUtils.isEmpty(branchSessions)) { + return true; + } + List<Long> branchIds = branchSessions.stream().map(BranchSession::getBranchId).collect(Collectors.toList()); + try { + return getLocker().releaseLock(globalSession.getXid(), branchIds); + } catch (Exception t) { + LOGGER.error("unLock globalSession error, xid:{} branchIds:{}", globalSession.getXid(), + CollectionUtils.toString(branchIds), t); + return false; + } + } +} \ No newline at end of file diff --git a/server/src/main/java/io/seata/server/storage/redis/lock/RedisLocker.java b/server/src/main/java/io/seata/server/storage/redis/lock/RedisLocker.java new file mode 100644 index 0000000000000000000000000000000000000000..d97972102ea400fb4deef25c0d349ad8be960e8a --- /dev/null +++ b/server/src/main/java/io/seata/server/storage/redis/lock/RedisLocker.java @@ -0,0 +1,224 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.storage.redis.lock; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import com.alibaba.fastjson.JSON; +import io.seata.common.util.CollectionUtils; +import io.seata.common.util.LambdaUtils; +import io.seata.common.util.StringUtils; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.lock.AbstractLocker; +import io.seata.core.lock.RowLock; +import io.seata.core.store.LockDO; +import io.seata.server.storage.redis.JedisPooledFactory; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.Pipeline; + +/** + * @author funkye + */ +public class RedisLocker extends AbstractLocker { + + private static final Integer DEFAULT_QUERY_LIMIT = 100; + + private static final String DEFAULT_REDIS_SEATA_LOCK_PREFIX = "SEATA_LOCK_"; + + private static final String DEFAULT_REDIS_SEATA_LOCK_XID_PREFIX = "SEATA_LOCK_XID_"; + + /** + * The query limit. + */ + private int logQueryLimit; + + /** + * Instantiates a new Redis locker. + * + */ + public RedisLocker() { + logQueryLimit = + ConfigurationFactory.getInstance().getInt(ConfigurationKeys.STORE_REDIS_QUERY_LIMIT, DEFAULT_QUERY_LIMIT); + } + + @Override + public boolean acquireLock(List<RowLock> rowLocks) { + if (CollectionUtils.isEmpty(rowLocks)) { + // no lock + return true; + } + Set<String> successList = new HashSet<>(); + long status = 1; + try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { + List<LockDO> locks = convertToLockDO(rowLocks); + if (locks.size() > 1) { + locks = + locks.stream().filter(LambdaUtils.distinctByKey(LockDO::getRowKey)).collect(Collectors.toList()); + } + Pipeline pipeline = jedis.pipelined(); + List<String> readyKeys = new ArrayList<>(); + for (LockDO lock : locks) { + String key = getLockKey(lock.getRowKey()); + pipeline.setnx(key, JSON.toJSONString(lock)); + readyKeys.add(key); + } + List<Object> results = pipeline.syncAndReturnAll(); + for (int i = 0; i < results.size(); i++) { + Long result = (long)results.get(i); + String key = readyKeys.get(i); + if (result != 1) { + status = result; + } else { + successList.add(key); + } + } + if (status != 1) { + String[] rms = successList.toArray(new String[0]); + if (rms.length > 0) { + jedis.del(rms); + } + return false; + } else { + try { + String xidLockKey = getXidLockKey(locks.get(0).getXid()); + jedis.lpush(xidLockKey, readyKeys.toArray(new String[0])); + } catch (Exception e) { + return false; + } + return true; + } + } + } + + @Override + public boolean releaseLock(List<RowLock> rowLocks) { + if (CollectionUtils.isEmpty(rowLocks)) { + // no lock + return true; + } + String[] keys = new String[rowLocks.size()]; + List<LockDO> locks = convertToLockDO(rowLocks); + for (int i = 0; i < locks.size(); i++) { + String key = getLockKey(locks.get(i).getRowKey()); + keys[i] = key; + } + try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { + String xidLockKey = getXidLockKey(locks.get(0).getXid()); + Pipeline pipeline = jedis.pipelined(); + pipeline.del(keys); + Arrays.stream(keys).forEach(key -> pipeline.lrem(xidLockKey, 0, key)); + pipeline.sync(); + return true; + } + } + + @Override + public boolean releaseLock(String xid, List<Long> branchIds) { + if (CollectionUtils.isEmpty(branchIds)) { + // no lock + return true; + } + try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { + String lockListKey = getXidLockKey(xid); + Set<String> keys = lRange(jedis, lockListKey); + if (CollectionUtils.isNotEmpty(keys)) { + Pipeline pipeline = null; + Iterator<String> it = keys.iterator(); + while (it.hasNext()) { + String key = it.next(); + LockDO lock = JSON.parseObject(jedis.get(key), LockDO.class); + for (int i = 0; i < branchIds.size(); i++) { + if (lock != null && Objects.equals(lock.getBranchId(), branchIds.get(i))) { + if (pipeline == null) { + pipeline = jedis.pipelined(); + } + pipeline.del(key); + pipeline.lrem(lockListKey, 0, key); + it.remove(); + } + } + } + if (pipeline != null) { + pipeline.sync(); + } + } + return true; + } + } + + @Override + public boolean releaseLock(String xid, Long branchId) { + List<Long> branchIds = new ArrayList<>(); + branchIds.add(branchId); + return releaseLock(xid, branchIds); + } + + @Override + public boolean isLockable(List<RowLock> rowLocks) { + if (CollectionUtils.isEmpty(rowLocks)) { + // no lock + return true; + } + try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { + List<LockDO> locks = convertToLockDO(rowLocks); + Set<String> lockKeys = new HashSet<>(); + for (LockDO rowlock : locks) { + lockKeys.add(getLockKey(rowlock.getRowKey())); + } + List<String> rowlockJsons = jedis.mget(lockKeys.toArray(new String[0])); + String xid = rowLocks.get(0).getXid(); + for (String rowlockJson : rowlockJsons) { + if (!StringUtils.isEmpty(rowlockJson)) { + LockDO lock = JSON.parseObject(rowlockJson, LockDO.class); + if (lock != null && !Objects.equals(lock.getXid(), xid)) { + return false; + } + } + } + } + return true; + } + + private Set<String> lRange(Jedis jedis, String key) { + Set<String> keys = new HashSet<>(); + List<String> redisLockJson; + int start = 0; + int stop = logQueryLimit; + do { + redisLockJson = jedis.lrange(key, start, stop); + keys.addAll(redisLockJson); + start = keys.size(); + stop = start + logQueryLimit; + } while (CollectionUtils.isNotEmpty(redisLockJson)); + return keys; + } + + private String getXidLockKey(String xid) { + return DEFAULT_REDIS_SEATA_LOCK_XID_PREFIX + xid; + } + + private String getLockKey(String rowKey) { + return DEFAULT_REDIS_SEATA_LOCK_PREFIX + rowKey; + } + +} diff --git a/server/src/main/java/io/seata/server/storage/redis/session/RedisSessionManager.java b/server/src/main/java/io/seata/server/storage/redis/session/RedisSessionManager.java new file mode 100644 index 0000000000000000000000000000000000000000..6b944dce51d01e495b50891c57f959f4fbf62432 --- /dev/null +++ b/server/src/main/java/io/seata/server/storage/redis/session/RedisSessionManager.java @@ -0,0 +1,200 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.storage.redis.session; + +import java.util.Collection; +import java.util.List; +import io.seata.common.exception.StoreException; +import io.seata.common.executor.Initialize; +import io.seata.common.loader.LoadLevel; +import io.seata.common.loader.Scope; +import io.seata.common.util.StringUtils; +import io.seata.core.exception.TransactionException; +import io.seata.core.model.BranchStatus; +import io.seata.core.model.GlobalStatus; +import io.seata.server.session.AbstractSessionManager; +import io.seata.server.session.BranchSession; +import io.seata.server.session.GlobalSession; +import io.seata.server.session.Reloadable; +import io.seata.server.session.SessionCondition; +import io.seata.server.session.SessionHolder; +import io.seata.server.session.SessionLifecycleListener; +import io.seata.server.session.SessionManager; +import io.seata.server.storage.redis.store.RedisTransactionStoreManager; +import io.seata.server.store.TransactionStoreManager.LogOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author funkye + */ +@LoadLevel(name = "redis", scope = Scope.PROTOTYPE) +public class RedisSessionManager extends AbstractSessionManager + implements SessionManager, SessionLifecycleListener, Initialize, Reloadable { + /** + * The constant LOGGER. + */ + protected static final Logger LOGGER = LoggerFactory.getLogger(RedisSessionManager.class); + + /** + * The Task name. + */ + protected String taskName; + + /** + * Instantiates a new Data base session manager. + */ + public RedisSessionManager() { + super(); + } + + /** + * Instantiates a new Data base session manager. + * + * @param name + * the name + */ + public RedisSessionManager(String name) { + super(); + this.taskName = name; + } + + @Override + public void init() { + transactionStoreManager = RedisTransactionStoreManager.getInstance(); + } + + @Override + public void addGlobalSession(GlobalSession session) throws TransactionException { + if (StringUtils.isBlank(taskName)) { + boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_ADD, session); + if (!ret) { + throw new StoreException("addGlobalSession failed."); + } + } else { + boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_UPDATE, session); + if (!ret) { + throw new StoreException("addGlobalSession failed."); + } + } + } + + @Override + public void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException { + if (!StringUtils.isEmpty(taskName)) { + return; + } + session.setStatus(status); + boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_UPDATE, session); + if (!ret) { + throw new StoreException("updateGlobalSessionStatus failed."); + } + } + + /** + * remove globalSession 1. rootSessionManager remove normal globalSession 2. retryCommitSessionManager and + * retryRollbackSessionManager remove retry expired globalSession + * + * @param session + * the session + * @throws TransactionException + */ + @Override + public void removeGlobalSession(GlobalSession session) throws TransactionException { + boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_REMOVE, session); + if (!ret) { + throw new StoreException("removeGlobalSession failed."); + } + } + + @Override + public void addBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException { + if (!StringUtils.isEmpty(taskName)) { + return; + } + boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_ADD, session); + if (!ret) { + throw new StoreException("addBranchSession failed."); + } + } + + @Override + public void updateBranchSessionStatus(BranchSession session, BranchStatus status) throws TransactionException { + if (!StringUtils.isEmpty(taskName)) { + return; + } + boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_UPDATE, session); + if (!ret) { + throw new StoreException("updateBranchSessionStatus failed."); + } + } + + @Override + public void removeBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException { + if (!StringUtils.isEmpty(taskName)) { + return; + } + boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_REMOVE, session); + if (!ret) { + throw new StoreException("removeBranchSession failed."); + } + } + + @Override + public GlobalSession findGlobalSession(String xid) { + return this.findGlobalSession(xid, true); + } + + @Override + public GlobalSession findGlobalSession(String xid, boolean withBranchSessions) { + return transactionStoreManager.readSession(xid, withBranchSessions); + } + + @Override + public Collection<GlobalSession> allSessions() { + // get by taskName + if (SessionHolder.ASYNC_COMMITTING_SESSION_MANAGER_NAME.equalsIgnoreCase(taskName)) { + return findGlobalSessions(new SessionCondition(GlobalStatus.AsyncCommitting)); + } else if (SessionHolder.RETRY_COMMITTING_SESSION_MANAGER_NAME.equalsIgnoreCase(taskName)) { + return findGlobalSessions(new SessionCondition(new GlobalStatus[] {GlobalStatus.CommitRetrying})); + } else if (SessionHolder.RETRY_ROLLBACKING_SESSION_MANAGER_NAME.equalsIgnoreCase(taskName)) { + return findGlobalSessions(new SessionCondition(new GlobalStatus[] {GlobalStatus.RollbackRetrying, + GlobalStatus.Rollbacking, GlobalStatus.TimeoutRollbacking, GlobalStatus.TimeoutRollbackRetrying})); + } else { + // all data + return findGlobalSessions(new SessionCondition(new GlobalStatus[] {GlobalStatus.UnKnown, GlobalStatus.Begin, + GlobalStatus.Committing, GlobalStatus.CommitRetrying, GlobalStatus.Rollbacking, + GlobalStatus.RollbackRetrying, GlobalStatus.TimeoutRollbacking, GlobalStatus.TimeoutRollbackRetrying, + GlobalStatus.AsyncCommitting})); + } + } + + @Override + public List<GlobalSession> findGlobalSessions(SessionCondition condition) { + // nothing need to do + return transactionStoreManager.readSession(condition); + } + + @Override + public <T> T lockAndExecute(GlobalSession globalSession, GlobalSession.LockCallable<T> lockCallable) + throws TransactionException { + return lockCallable.call(); + } + + @Override + public void reload() {} + +} diff --git a/server/src/main/java/io/seata/server/storage/redis/store/RedisTransactionStoreManager.java b/server/src/main/java/io/seata/server/storage/redis/store/RedisTransactionStoreManager.java new file mode 100644 index 0000000000000000000000000000000000000000..6479edc8f9130a7b730750a723047900d4622622 --- /dev/null +++ b/server/src/main/java/io/seata/server/storage/redis/store/RedisTransactionStoreManager.java @@ -0,0 +1,411 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.storage.redis.store; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import com.alibaba.fastjson.JSON; +import io.seata.common.exception.StoreException; +import io.seata.common.util.CollectionUtils; +import io.seata.common.util.StringUtils; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.model.BranchStatus; +import io.seata.core.model.BranchType; +import io.seata.core.model.GlobalStatus; +import io.seata.core.store.BranchTransactionDO; +import io.seata.core.store.GlobalTransactionDO; +import io.seata.server.session.BranchSession; +import io.seata.server.session.GlobalSession; +import io.seata.server.session.SessionCondition; +import io.seata.server.storage.redis.JedisPooledFactory; +import io.seata.server.store.AbstractTransactionStoreManager; +import io.seata.server.store.SessionStorable; +import io.seata.server.store.TransactionStoreManager; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.Pipeline; +import redis.clients.jedis.ScanParams; +import redis.clients.jedis.ScanResult; + +/** + * @author funkye + */ +public class RedisTransactionStoreManager extends AbstractTransactionStoreManager implements TransactionStoreManager { + + // global transaction prefix + private static final String DEFAULT_REDIS_SEATA_GLOBAL_PREFIX = "SEATA_GLOBAL_"; + + // the prefix of the branchs transaction + private static final String DEFAULT_REDIS_SEATA_XID_BRANCHS_PREFIX = "SEATA_XID_BRANCHS_"; + + // the prefix of the branch transaction + private static final String DEFAULT_REDIS_SEATA_BRANCH_PREFIX = "SEATA_BRANCH_"; + + // global transaction id PREFIX + private static final String DEFAULT_SEATA_TRANSACTION_ID_GLOBAL_PREFIX = "SEATA_TRANSACTION_ID_GLOBAL_"; + + private static volatile RedisTransactionStoreManager instance; + + private static final Integer DEFAULT_QUERY_LIMIT = 100; + + private static final String INITIAL_CURSOR = "0"; + /** + * The query limit. + */ + private int logQueryLimit = + ConfigurationFactory.getInstance().getInt(ConfigurationKeys.STORE_REDIS_QUERY_LIMIT, DEFAULT_QUERY_LIMIT);; + + /** + * Get the instance. + */ + public static RedisTransactionStoreManager getInstance() { + if (instance == null) { + synchronized (RedisTransactionStoreManager.class) { + if (instance == null) { + instance = new RedisTransactionStoreManager(); + } + } + } + return instance; + } + + @Override + public boolean writeSession(LogOperation logOperation, SessionStorable session) { + if (LogOperation.GLOBAL_ADD.equals(logOperation)) { + return insertOrUpdateGlobalTransactionDO(convertGlobalTransactionDO(session)); + } else if (LogOperation.GLOBAL_UPDATE.equals(logOperation)) { + return insertOrUpdateGlobalTransactionDO(convertGlobalTransactionDO(session)); + } else if (LogOperation.GLOBAL_REMOVE.equals(logOperation)) { + return deleteGlobalTransactionDO(convertGlobalTransactionDO(session)); + } else if (LogOperation.BRANCH_ADD.equals(logOperation)) { + return insertOrUpdateBranchTransactionDO(convertBranchTransactionDO(session)); + } else if (LogOperation.BRANCH_UPDATE.equals(logOperation)) { + return insertOrUpdateBranchTransactionDO(convertBranchTransactionDO(session)); + } else if (LogOperation.BRANCH_REMOVE.equals(logOperation)) { + return deleteBranchTransactionDO(convertBranchTransactionDO(session)); + } else { + throw new StoreException("Unknown LogOperation:" + logOperation.name()); + } + } + + private boolean deleteBranchTransactionDO(BranchTransactionDO branchTransactionDO) { + try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { + String key = getBranchKey(branchTransactionDO.getBranchId()); + jedis.del(key); + return true; + } + } + + private boolean insertOrUpdateBranchTransactionDO(BranchTransactionDO branchTransactionDO) { + try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { + String key = getBranchKey(branchTransactionDO.getBranchId()); + Pipeline pipeline = jedis.pipelined(); + if (jedis.get(key) == null) { + pipeline.lpush(getBranchListKeyByXid(branchTransactionDO.getXid()), key); + } + pipeline.set(key, JSON.toJSONString(branchTransactionDO)); + pipeline.sync(); + return true; + } + } + + private boolean deleteGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { + try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { + String[] keys = new String[3]; + keys[0] = getGlobalKeyByXid(globalTransactionDO.getXid()); + keys[1] = getGlobalKeyByTransactionId(globalTransactionDO.getTransactionId()); + keys[2] = getBranchListKeyByXid(globalTransactionDO.getXid()); + jedis.del(keys); + return true; + } + } + + private boolean insertOrUpdateGlobalTransactionDO(GlobalTransactionDO convertGlobalTransactionDO) { + try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { + String keys = getGlobalKeyByXid(convertGlobalTransactionDO.getXid()); + Pipeline pipeline = jedis.pipelined(); + String json = JSON.toJSONString(convertGlobalTransactionDO); + pipeline.set(keys, json); + keys = getGlobalKeyByTransactionId(convertGlobalTransactionDO.getTransactionId()); + pipeline.set(keys, json); + pipeline.sync(); + return true; + } + } + + /** + * Read session global session. + * + * @param xid + * the xid + * @param withBranchSessions + * the withBranchSessions + * @return the global session + */ + @Override + public GlobalSession readSession(String xid, boolean withBranchSessions) { + String globalSessionJson; + try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { + globalSessionJson = jedis.get(getGlobalKeyByXid(xid)); + if (StringUtils.isBlank(globalSessionJson)) { + return null; + } + // global transaction + GlobalTransactionDO globalTransactionDO = JSON.parseObject(globalSessionJson, GlobalTransactionDO.class); + if (globalTransactionDO == null) { + return null; + } + // branch transactions + List<BranchTransactionDO> branchTransactionDOs = null; + // reduce rpc with db when branchRegister and getGlobalStatus + if (withBranchSessions) { + Set<String> keys = lRange(jedis, getBranchListKeyByXid(globalTransactionDO.getXid())); + if (CollectionUtils.isNotEmpty(keys)) { + branchTransactionDOs = getBranchJsons(jedis, keys); + } + } + return getGlobalSession(globalTransactionDO, branchTransactionDOs); + } + } + + /** + * Read session global session. + * + * @param xid + * the xid + * @return the global session + */ + @Override + public GlobalSession readSession(String xid) { + return this.readSession(xid, true); + } + + /** + * Read session list. + * + * @param statuses + * the statuses + * @return the list + */ + public List<GlobalSession> readSession(GlobalStatus[] statuses) { + List<Integer> states = new ArrayList<>(); + for (int i = 0; i < statuses.length; i++) { + states.add(statuses[i].getCode()); + } + try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { + Set<String> keys = new HashSet<>(); + String cursor = INITIAL_CURSOR; + ScanParams params = new ScanParams(); + params.count(logQueryLimit); + params.match(getGlobalKeyByXid("*")); + ScanResult<String> scans; + do { + scans = jedis.scan(cursor, params); + keys.addAll(scans.getResult()); + cursor = scans.getCursor(); + } while (!INITIAL_CURSOR.equals(cursor)); + if (CollectionUtils.isNotEmpty(keys)) { + List<GlobalTransactionDO> globalTransactionDOs = new ArrayList<>(); + for (String globalKey : keys) { + GlobalTransactionDO globalTransactionDO = + JSON.parseObject(jedis.get(globalKey), GlobalTransactionDO.class); + if (globalTransactionDO != null && states.contains(globalTransactionDO.getStatus())) { + globalTransactionDOs.add(globalTransactionDO); + } + } + if (CollectionUtils.isNotEmpty(globalTransactionDOs)) { + List<String> xids = + globalTransactionDOs.stream().map(GlobalTransactionDO::getXid).collect(Collectors.toList()); + List<BranchTransactionDO> branchTransactionDOs = new ArrayList<>(); + for (String xid : xids) { + Set<String> branches = lRange(jedis, getBranchListKeyByXid(xid)); + if (CollectionUtils.isNotEmpty(branches)) { + branchTransactionDOs.addAll(getBranchJsons(jedis, branches)); + } + } + Map<String, List<BranchTransactionDO>> branchTransactionDOsMap = + branchTransactionDOs.stream().collect(Collectors.groupingBy(BranchTransactionDO::getXid, + LinkedHashMap::new, Collectors.toList())); + return globalTransactionDOs.stream() + .map(globalTransactionDO -> getGlobalSession(globalTransactionDO, + branchTransactionDOsMap.get(globalTransactionDO.getXid()))) + .collect(Collectors.toList()); + } + } + } + return null; + } + + @Override + public List<GlobalSession> readSession(SessionCondition sessionCondition) { + try (Jedis jedis = JedisPooledFactory.getJedisInstance()) { + if (!StringUtils.isEmpty(sessionCondition.getXid())) { + String globalSessionJson = jedis.get(getGlobalKeyByXid(sessionCondition.getXid())); + if (!StringUtils.isEmpty(globalSessionJson)) { + GlobalSession session = + convertGlobalSession(JSON.parseObject(globalSessionJson, GlobalTransactionDO.class)); + List<GlobalSession> globalSessions = new ArrayList<>(); + globalSessions.add(session); + return globalSessions; + } + } else if (sessionCondition.getTransactionId() != null) { + String global = jedis.get(getGlobalKeyByTransactionId(sessionCondition.getTransactionId())); + if (StringUtils.isEmpty(global)) { + return null; + } + GlobalTransactionDO globalTransactionDO = JSON.parseObject(global, GlobalTransactionDO.class); + String branchKey = getBranchListKeyByXid(globalTransactionDO.getXid()); + Set<String> keys = lRange(jedis, branchKey); + List<BranchTransactionDO> branchTransactionDOs = null; + if (CollectionUtils.isNotEmpty(keys)) { + branchTransactionDOs = getBranchJsons(jedis, keys); + } + GlobalSession globalSession = getGlobalSession(globalTransactionDO, branchTransactionDOs); + List<GlobalSession> globalSessions = new ArrayList<>(); + globalSessions.add(globalSession); + return globalSessions; + } else if (CollectionUtils.isNotEmpty(sessionCondition.getStatuses())) { + return readSession(sessionCondition.getStatuses()); + } + } + return null; + } + + private List<BranchTransactionDO> getBranchJsons(Jedis jedis, Set<String> keys) { + List<BranchTransactionDO> branchTransactionDOs = new ArrayList<>(); + List<String> branchJsons = jedis.mget(keys.toArray(new String[0])); + for (String branchJson : branchJsons) { + if (!StringUtils.isEmpty(branchJson)) { + branchTransactionDOs.add(JSON.parseObject(branchJson, BranchTransactionDO.class)); + } + } + return branchTransactionDOs; + } + + private GlobalTransactionDO convertGlobalTransactionDO(SessionStorable session) { + if (session == null || !(session instanceof GlobalSession)) { + throw new IllegalArgumentException( + "the parameter of SessionStorable is not available, SessionStorable:" + StringUtils.toString(session)); + } + GlobalSession globalSession = (GlobalSession)session; + + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid(globalSession.getXid()); + globalTransactionDO.setStatus(globalSession.getStatus().getCode()); + globalTransactionDO.setApplicationId(globalSession.getApplicationId()); + globalTransactionDO.setBeginTime(globalSession.getBeginTime()); + globalTransactionDO.setTimeout(globalSession.getTimeout()); + globalTransactionDO.setTransactionId(globalSession.getTransactionId()); + globalTransactionDO.setTransactionName(globalSession.getTransactionName()); + globalTransactionDO.setTransactionServiceGroup(globalSession.getTransactionServiceGroup()); + globalTransactionDO.setApplicationData(globalSession.getApplicationData()); + return globalTransactionDO; + } + + private BranchTransactionDO convertBranchTransactionDO(SessionStorable session) { + if (session == null || !(session instanceof BranchSession)) { + throw new IllegalArgumentException( + "the parameter of SessionStorable is not available, SessionStorable:" + StringUtils.toString(session)); + } + BranchSession branchSession = (BranchSession)session; + + BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); + branchTransactionDO.setXid(branchSession.getXid()); + branchTransactionDO.setBranchId(branchSession.getBranchId()); + branchTransactionDO.setBranchType(branchSession.getBranchType().name()); + branchTransactionDO.setClientId(branchSession.getClientId()); + branchTransactionDO.setResourceGroupId(branchSession.getResourceGroupId()); + branchTransactionDO.setTransactionId(branchSession.getTransactionId()); + branchTransactionDO.setApplicationData(branchSession.getApplicationData()); + branchTransactionDO.setResourceId(branchSession.getResourceId()); + branchTransactionDO.setStatus(branchSession.getStatus().getCode()); + return branchTransactionDO; + } + + private GlobalSession convertGlobalSession(GlobalTransactionDO globalTransactionDO) { + GlobalSession session = + new GlobalSession(globalTransactionDO.getApplicationId(), globalTransactionDO.getTransactionServiceGroup(), + globalTransactionDO.getTransactionName(), globalTransactionDO.getTimeout()); + session.setTransactionId(globalTransactionDO.getTransactionId()); + session.setXid(globalTransactionDO.getXid()); + session.setStatus(GlobalStatus.get(globalTransactionDO.getStatus())); + session.setApplicationData(globalTransactionDO.getApplicationData()); + session.setBeginTime(globalTransactionDO.getBeginTime()); + return session; + } + + private BranchSession convertBranchSession(BranchTransactionDO branchTransactionDO) { + BranchSession branchSession = new BranchSession(); + branchSession.setXid(branchTransactionDO.getXid()); + branchSession.setTransactionId(branchTransactionDO.getTransactionId()); + branchSession.setApplicationData(branchTransactionDO.getApplicationData()); + branchSession.setBranchId(branchTransactionDO.getBranchId()); + branchSession.setBranchType(BranchType.valueOf(branchTransactionDO.getBranchType())); + branchSession.setResourceId(branchTransactionDO.getResourceId()); + branchSession.setClientId(branchTransactionDO.getClientId()); + branchSession.setResourceGroupId(branchTransactionDO.getResourceGroupId()); + branchSession.setStatus(BranchStatus.get(branchTransactionDO.getStatus())); + return branchSession; + } + + private GlobalSession getGlobalSession(GlobalTransactionDO globalTransactionDO, + List<BranchTransactionDO> branchTransactionDOs) { + GlobalSession globalSession = convertGlobalSession(globalTransactionDO); + // branch transactions + if (CollectionUtils.isNotEmpty(branchTransactionDOs)) { + for (BranchTransactionDO branchTransactionDO : branchTransactionDOs) { + globalSession.add(convertBranchSession(branchTransactionDO)); + } + } + return globalSession; + } + + private Set<String> lRange(Jedis jedis, String key) { + Set<String> keys = new HashSet<>(); + List<String> redisBranchJson; + int start = 0; + int stop = logQueryLimit; + do { + redisBranchJson = jedis.lrange(key, start, stop); + keys.addAll(redisBranchJson); + start = keys.size(); + stop = start + logQueryLimit; + } while (CollectionUtils.isNotEmpty(redisBranchJson)); + return keys; + } + + private String getGlobalKeyByXid(String xid) { + return DEFAULT_REDIS_SEATA_GLOBAL_PREFIX + xid; + } + + private String getBranchListKeyByXid(String xid) { + return DEFAULT_REDIS_SEATA_XID_BRANCHS_PREFIX + xid; + } + + private String getGlobalKeyByTransactionId(Long transactionId) { + return DEFAULT_SEATA_TRANSACTION_ID_GLOBAL_PREFIX + transactionId; + } + + private String getBranchKey(Long branchId) { + return DEFAULT_REDIS_SEATA_BRANCH_PREFIX + branchId; + } + +} diff --git a/server/src/main/java/io/seata/server/store/DbcpDataSourceGenerator.java b/server/src/main/java/io/seata/server/store/DbcpDataSourceProvider.java similarity index 88% rename from server/src/main/java/io/seata/server/store/DbcpDataSourceGenerator.java rename to server/src/main/java/io/seata/server/store/DbcpDataSourceProvider.java index 494cccdfcc7972eae371d905aab4b9cc925c6222..8880943bf043cb4792715f600f5745cb36874555 100644 --- a/server/src/main/java/io/seata/server/store/DbcpDataSourceGenerator.java +++ b/server/src/main/java/io/seata/server/store/DbcpDataSourceProvider.java @@ -15,22 +15,23 @@ */ package io.seata.server.store; -import javax.sql.DataSource; - import io.seata.common.loader.LoadLevel; -import io.seata.core.store.db.AbstractDataSourceGenerator; +import io.seata.core.store.db.AbstractDataSourceProvider; import org.apache.commons.dbcp2.BasicDataSource; +import javax.sql.DataSource; + /** - * The type Dbcp data source generator. - * + * The dbcp datasource provider * @author zhangsen * @author ggndnn + * @author will */ @LoadLevel(name = "dbcp") -public class DbcpDataSourceGenerator extends AbstractDataSourceGenerator { +public class DbcpDataSourceProvider extends AbstractDataSourceProvider { + @Override - public DataSource generateDataSource() { + public DataSource generate() { BasicDataSource ds = new BasicDataSource(); ds.setDriverClassName(getDriverClassName()); // DriverClassLoader works if upgrade commons-dbcp to at least 1.3.1. @@ -38,6 +39,7 @@ public class DbcpDataSourceGenerator extends AbstractDataSourceGenerator { ds.setDriverClassLoader(getDriverClassLoader()); ds.setUrl(getUrl()); ds.setUsername(getUser()); + ds.setPassword(getPassword()); ds.setInitialSize(getMinConn()); ds.setMaxTotal(getMaxConn()); diff --git a/server/src/main/java/io/seata/server/store/DruidDataSourceGenerator.java b/server/src/main/java/io/seata/server/store/DruidDataSourceProvider.java similarity index 88% rename from server/src/main/java/io/seata/server/store/DruidDataSourceGenerator.java rename to server/src/main/java/io/seata/server/store/DruidDataSourceProvider.java index 5600cadb7ced55f29e2d0d6ac5ca6595c62d961e..4a33d946017b5da6100c4836455744025c4c94d3 100644 --- a/server/src/main/java/io/seata/server/store/DruidDataSourceGenerator.java +++ b/server/src/main/java/io/seata/server/store/DruidDataSourceProvider.java @@ -15,22 +15,23 @@ */ package io.seata.server.store; -import javax.sql.DataSource; - import com.alibaba.druid.pool.DruidDataSource; import io.seata.common.loader.LoadLevel; -import io.seata.core.store.db.AbstractDataSourceGenerator; +import io.seata.core.store.db.AbstractDataSourceProvider; + +import javax.sql.DataSource; /** - * The type Druid data source generator. - * + * The druid datasource provider * @author zhangsen * @author ggndnn + * @author will */ @LoadLevel(name = "druid") -public class DruidDataSourceGenerator extends AbstractDataSourceGenerator { +public class DruidDataSourceProvider extends AbstractDataSourceProvider { + @Override - public DataSource generateDataSource() { + public DataSource generate() { DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName(getDriverClassName()); ds.setDriverClassLoader(getDriverClassLoader()); diff --git a/server/src/main/java/io/seata/server/store/HikariDataSourceProvider.java b/server/src/main/java/io/seata/server/store/HikariDataSourceProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..8adb354f57481e7e9e7773bb0ab3dd6742ed5a03 --- /dev/null +++ b/server/src/main/java/io/seata/server/store/HikariDataSourceProvider.java @@ -0,0 +1,60 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.store; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import io.seata.common.loader.LoadLevel; +import io.seata.core.store.db.AbstractDataSourceProvider; + +import javax.sql.DataSource; +import java.util.Properties; + +/** + * The hikari datasource provider + * @author diguage + * @author will + */ +@LoadLevel(name = "hikari") +public class HikariDataSourceProvider extends AbstractDataSourceProvider { + + @Override + public DataSource generate() { + Properties properties = new Properties(); + properties.setProperty("dataSource.cachePrepStmts", "true"); + properties.setProperty("dataSource.prepStmtCacheSize", "250"); + properties.setProperty("dataSource.prepStmtCacheSqlLimit", "2048"); + properties.setProperty("dataSource.useServerPrepStmts", "true"); + properties.setProperty("dataSource.useLocalSessionState", "true"); + properties.setProperty("dataSource.rewriteBatchedStatements", "true"); + properties.setProperty("dataSource.cacheResultSetMetadata", "true"); + properties.setProperty("dataSource.cacheServerConfiguration", "true"); + properties.setProperty("dataSource.elideSetAutoCommits", "true"); + properties.setProperty("dataSource.maintainTimeStats", "false"); + + HikariConfig config = new HikariConfig(properties); + config.setDriverClassName(getDriverClassName()); + config.setJdbcUrl(getUrl()); + config.setUsername(getUser()); + config.setPassword(getPassword()); + config.setMaximumPoolSize(getMaxConn()); + config.setMinimumIdle(getMinConn()); + config.setAutoCommit(true); + config.setConnectionTimeout(getMaxWait()); + config.setInitializationFailTimeout(-1); + return new HikariDataSource(config); + } +} diff --git a/server/src/main/java/io/seata/server/store/TransactionStoreManager.java b/server/src/main/java/io/seata/server/store/TransactionStoreManager.java index fdebb3d84043b40d9491eedf820c161ae46a2d4d..f05ca772cd095d0aa4f3f7b2df43972cd6ce6e8d 100644 --- a/server/src/main/java/io/seata/server/store/TransactionStoreManager.java +++ b/server/src/main/java/io/seata/server/store/TransactionStoreManager.java @@ -67,13 +67,6 @@ public interface TransactionStoreManager { */ void shutdown(); - /** - * Gets current max session id. - * - * @return the current max session id - */ - long getCurrentMaxSessionId(); - /** * The enum Log operation. diff --git a/server/src/main/java/io/seata/server/transaction/at/ATCore.java b/server/src/main/java/io/seata/server/transaction/at/ATCore.java index b3e910fdbb15f3caf116be88a7ccdf53bdacb9d0..eb6860a62b4f81d14e32eb1a1e436ceb9c261871 100644 --- a/server/src/main/java/io/seata/server/transaction/at/ATCore.java +++ b/server/src/main/java/io/seata/server/transaction/at/ATCore.java @@ -18,7 +18,7 @@ package io.seata.server.transaction.at; import io.seata.core.exception.BranchTransactionException; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchType; -import io.seata.core.rpc.ServerMessageSender; +import io.seata.core.rpc.RemotingServer; import io.seata.server.coordinator.AbstractCore; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; @@ -32,8 +32,8 @@ import static io.seata.core.exception.TransactionExceptionCode.LockKeyConflict; */ public class ATCore extends AbstractCore { - public ATCore(ServerMessageSender messageSender) { - super(messageSender); + public ATCore(RemotingServer remotingServer) { + super(remotingServer); } @Override diff --git a/server/src/main/java/io/seata/server/transaction/saga/SagaCore.java b/server/src/main/java/io/seata/server/transaction/saga/SagaCore.java index 71d0f524605ff59a83827d4cef5412e322afdd29..31fe95557e8e8f5f69c8f8bc0da76f5e10c4027d 100644 --- a/server/src/main/java/io/seata/server/transaction/saga/SagaCore.java +++ b/server/src/main/java/io/seata/server/transaction/saga/SagaCore.java @@ -30,8 +30,8 @@ import io.seata.core.protocol.transaction.BranchCommitRequest; import io.seata.core.protocol.transaction.BranchCommitResponse; import io.seata.core.protocol.transaction.BranchRollbackRequest; import io.seata.core.protocol.transaction.BranchRollbackResponse; -import io.seata.core.rpc.ChannelManager; -import io.seata.core.rpc.ServerMessageSender; +import io.seata.core.rpc.netty.ChannelManager; +import io.seata.core.rpc.RemotingServer; import io.seata.server.coordinator.AbstractCore; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; @@ -45,8 +45,8 @@ import io.seata.server.session.SessionHolder; */ public class SagaCore extends AbstractCore { - public SagaCore(ServerMessageSender messageSender) { - super(messageSender); + public SagaCore(RemotingServer remotingServer) { + super(remotingServer); } @Override @@ -74,7 +74,7 @@ public class SagaCore extends AbstractCore { + ", cannot find channel by resourceId[" + sagaResourceId + "]"); return BranchStatus.PhaseTwo_CommitFailed_Retryable; } - BranchCommitResponse response = (BranchCommitResponse) messageSender.sendSyncRequest(sagaChannel, request); + BranchCommitResponse response = (BranchCommitResponse) remotingServer.sendSyncRequest(sagaChannel, request); return response.getBranchStatus(); } @@ -93,7 +93,7 @@ public class SagaCore extends AbstractCore { + ", cannot find channel by resourceId[" + sagaResourceId + "]"); return BranchStatus.PhaseTwo_RollbackFailed_Retryable; } - BranchRollbackResponse response = (BranchRollbackResponse) messageSender.sendSyncRequest(sagaChannel, request); + BranchRollbackResponse response = (BranchRollbackResponse) remotingServer.sendSyncRequest(sagaChannel, request); return response.getBranchStatus(); } diff --git a/server/src/main/java/io/seata/server/transaction/tcc/TccCore.java b/server/src/main/java/io/seata/server/transaction/tcc/TccCore.java index 489dcb62a7be7cb3a7f7b499e74c706e200b7f29..e0171aa571082d70b9dc4fad6091114ef1590895 100644 --- a/server/src/main/java/io/seata/server/transaction/tcc/TccCore.java +++ b/server/src/main/java/io/seata/server/transaction/tcc/TccCore.java @@ -16,7 +16,7 @@ package io.seata.server.transaction.tcc; import io.seata.core.model.BranchType; -import io.seata.core.rpc.ServerMessageSender; +import io.seata.core.rpc.RemotingServer; import io.seata.server.coordinator.AbstractCore; /** @@ -26,8 +26,8 @@ import io.seata.server.coordinator.AbstractCore; */ public class TccCore extends AbstractCore { - public TccCore(ServerMessageSender messageSender) { - super(messageSender); + public TccCore(RemotingServer remotingServer) { + super(remotingServer); } @Override diff --git a/server/src/main/java/io/seata/server/transaction/xa/XACore.java b/server/src/main/java/io/seata/server/transaction/xa/XACore.java index b840c1675397d3bf3f4aeb456d627c8ee04c8e25..de4620d42ad7de1d1d88691e63d0f9f9f4e6f424 100644 --- a/server/src/main/java/io/seata/server/transaction/xa/XACore.java +++ b/server/src/main/java/io/seata/server/transaction/xa/XACore.java @@ -18,7 +18,7 @@ package io.seata.server.transaction.xa; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; -import io.seata.core.rpc.ServerMessageSender; +import io.seata.core.rpc.RemotingServer; import io.seata.server.coordinator.AbstractCore; /** @@ -28,8 +28,8 @@ import io.seata.server.coordinator.AbstractCore; */ public class XACore extends AbstractCore { - public XACore(ServerMessageSender messageSender) { - super(messageSender); + public XACore(RemotingServer remotingServer) { + super(remotingServer); } @Override diff --git a/server/src/main/resources/META-INF/services/io.seata.core.rpc.RegisterCheckAuthHandler b/server/src/main/resources/META-INF/services/io.seata.core.rpc.RegisterCheckAuthHandler new file mode 100644 index 0000000000000000000000000000000000000000..1a54728bca5b24a390475c7270158b45c21cab92 --- /dev/null +++ b/server/src/main/resources/META-INF/services/io.seata.core.rpc.RegisterCheckAuthHandler @@ -0,0 +1 @@ +io.seata.server.auth.DefaultCheckAuthHandler \ No newline at end of file diff --git a/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceGenerator b/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceGenerator deleted file mode 100644 index a08f82b8aeacef8efaa781428867213d81f6df89..0000000000000000000000000000000000000000 --- a/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceGenerator +++ /dev/null @@ -1,2 +0,0 @@ -io.seata.server.store.DbcpDataSourceGenerator -io.seata.server.store.DruidDataSourceGenerator \ No newline at end of file diff --git a/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceProvider b/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceProvider new file mode 100644 index 0000000000000000000000000000000000000000..ac04a85e02d0e5b156186b7f936ab221fdc20080 --- /dev/null +++ b/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceProvider @@ -0,0 +1,3 @@ +io.seata.server.store.DbcpDataSourceProvider +io.seata.server.store.DruidDataSourceProvider +io.seata.server.store.HikariDataSourceProvider \ No newline at end of file diff --git a/server/src/main/resources/META-INF/services/io.seata.server.lock.LockManager b/server/src/main/resources/META-INF/services/io.seata.server.lock.LockManager index 54b629ed93db624f362c89d4a0ba27a1c80f9476..bca40c8591bcade897348c8886143e88a354cf98 100644 --- a/server/src/main/resources/META-INF/services/io.seata.server.lock.LockManager +++ b/server/src/main/resources/META-INF/services/io.seata.server.lock.LockManager @@ -1,2 +1,3 @@ io.seata.server.storage.db.lock.DataBaseLockManager -io.seata.server.storage.file.lock.FileLockManager \ No newline at end of file +io.seata.server.storage.file.lock.FileLockManager +io.seata.server.storage.redis.lock.RedisLockManager \ No newline at end of file diff --git a/server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager b/server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager index 62b1f8b8f70c9a124a43c69bec56f9fd92d0207b..f2e82316792e9779ed52c5926422f96ac68dadb8 100644 --- a/server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager +++ b/server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager @@ -1,2 +1,3 @@ io.seata.server.storage.file.session.FileSessionManager -io.seata.server.storage.db.session.DataBaseSessionManager \ No newline at end of file +io.seata.server.storage.db.session.DataBaseSessionManager +io.seata.server.storage.redis.session.RedisSessionManager \ No newline at end of file diff --git a/server/src/main/resources/file.conf b/server/src/main/resources/file.conf index 95483aecb7b182c5527fc23270889709d7b82669..cfb71b9cc3c6fbe152b6ca5989554eac72e5303d 100644 --- a/server/src/main/resources/file.conf +++ b/server/src/main/resources/file.conf @@ -1,7 +1,7 @@ ## transaction log store, only used in seata-server store { - ## store mode: file、db + ## store mode: file、db、redis mode = "file" ## file store property @@ -22,7 +22,7 @@ store { ## database store property db { - ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc. + ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc. datasource = "druid" ## mysql/oracle/postgresql/h2/oceanbase etc. dbType = "mysql" @@ -38,4 +38,16 @@ store { queryLimit = 100 maxWait = 5000 } + + ## redis store property + redis { + host = "127.0.0.1" + port = "6379" + password = "" + database = "0" + minConn = 1 + maxConn = 10 + queryLimit = 100 + } + } diff --git a/server/src/main/resources/file.conf.example b/server/src/main/resources/file.conf.example index 505cb42a49f229982933f272b4ed1fb2aacaa80f..36d80a1e02f885fb3723d1c3c099e9a235db9cfc 100644 --- a/server/src/main/resources/file.conf.example +++ b/server/src/main/resources/file.conf.example @@ -84,6 +84,8 @@ server { #schedule delete expired undo_log in milliseconds logDeletePeriod = 86400000 } + #check auth + enableCheckAuth = true #unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent maxCommitRetryTimeout = "-1" maxRollbackRetryTimeout = "-1" diff --git a/server/src/main/resources/logback.xml b/server/src/main/resources/logback.xml index 8dd43f1cd50523404567b721b1c6eb1239466f6b..a43bdb13a2a72b5ab407062b3ae61dc1a3047a33 100644 --- a/server/src/main/resources/logback.xml +++ b/server/src/main/resources/logback.xml @@ -16,39 +16,91 @@ --> <configuration scan="true" scanPeriod="60 seconds" debug="false"> + <!-- Context listeners --> + <contextListener class="io.seata.server.logging.listener.SystemPropertyLoggerContextListener" /> + + <!-- Copied from spring-boot.jar --> + <conversionRule conversionWord="clr" converterClass="io.seata.server.logging.logback.ColorConverter" /> + <conversionRule conversionWord="wex" converterClass="io.seata.server.logging.logback.WhitespaceThrowableProxyConverter" /> + <conversionRule conversionWord="wEx" converterClass="io.seata.server.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /> + <property name="CONSOLE_LOG_PATTERN" value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"/> + <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p --- [%t] %-40.40logger{39} : %m%n%wEx"/> + <property name="LOG_HOME" value="${user.home}/logs/seata"/> - <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> - <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> - <Pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n</Pattern> + <!--CONSOLE--> + <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <Pattern>${CONSOLE_LOG_PATTERN}</Pattern> + <charset>UTF-8</charset> + </encoder> + </appender> + + <!--ALL--> + <appender name="ALL" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${LOG_HOME}/txc.${PORT}.all.log</file> + <append>true</append> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${LOG_HOME}/history/txc.${PORT}.all.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> + <maxFileSize>2GB</maxFileSize> + <MaxHistory>7</MaxHistory> + <totalSizeCap>7GB</totalSizeCap> + <cleanHistoryOnStart>true</cleanHistoryOnStart> + </rollingPolicy> + <encoder> + <Pattern>${FILE_LOG_PATTERN}</Pattern> + <charset>UTF-8</charset> </encoder> </appender> - <appender name="seata-default" - class="ch.qos.logback.core.rolling.RollingFileAppender"> - <file>${LOG_HOME}/seata-server.log</file> + <!--WARN--> + <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>WARN</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + <file>${LOG_HOME}/txc.${PORT}.warn.log</file> <append>true</append> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> - <fileNamePattern>${LOG_HOME}/seata-server.log.%d{yyyy-MM-dd}.%i</fileNamePattern> + <fileNamePattern>${LOG_HOME}/history/txc.${PORT}.warn.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> <maxFileSize>2GB</maxFileSize> <MaxHistory>7</MaxHistory> <totalSizeCap>7GB</totalSizeCap> <cleanHistoryOnStart>true</cleanHistoryOnStart> </rollingPolicy> <encoder> - <Pattern>%date %level %msg%n%n</Pattern> + <Pattern>${FILE_LOG_PATTERN}</Pattern> <charset>UTF-8</charset> </encoder> </appender> - <logger name="io.seata.server.storage.file.store.FileTransactionStoreManager" additivity="false"> - <level value="INFO"/> - <appender-ref ref="seata-default"/> - </logger> + <!--ERROR--> + <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>ERROR</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + <file>${LOG_HOME}/txc.${PORT}.error.log</file> + <append>true</append> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${LOG_HOME}/history/txc.${PORT}.error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> + <maxFileSize>2GB</maxFileSize> + <MaxHistory>7</MaxHistory> + <totalSizeCap>7GB</totalSizeCap> + <cleanHistoryOnStart>true</cleanHistoryOnStart> + </rollingPolicy> + <encoder> + <Pattern>${FILE_LOG_PATTERN}</Pattern> + <charset>UTF-8</charset> + </encoder> + </appender> <root level="INFO"> - <appender-ref ref="seata-default"/> - <appender-ref ref="stdout"/> + <appender-ref ref="ALL"/> + <appender-ref ref="WARN"/> + <appender-ref ref="ERROR"/> + <appender-ref ref="CONSOLE"/> </root> </configuration> - diff --git a/server/src/main/resources/registry.conf b/server/src/main/resources/registry.conf index 5420c64ac55913e161755c681c8106ad3b12c9d6..71c42a432e2b02863643bb67106a105e25e1c842 100644 --- a/server/src/main/resources/registry.conf +++ b/server/src/main/resources/registry.conf @@ -4,7 +4,8 @@ registry { nacos { application = "seata-server" - serverAddr = "localhost" + serverAddr = "127.0.0.1:8848" + group = "SEATA_GROUP" namespace = "" cluster = "default" username = "" @@ -57,7 +58,7 @@ config { type = "file" nacos { - serverAddr = "localhost" + serverAddr = "127.0.0.1:8848" namespace = "" group = "SEATA_GROUP" username = "" diff --git a/server/src/test/java/ServerTest.java b/server/src/test/java/ServerTest.java index d957debcd0c965bd2004a0b3713370bf76a4509b..ba4e01a1687e8aca5b83256487a44f6a56eac580 100644 --- a/server/src/test/java/ServerTest.java +++ b/server/src/test/java/ServerTest.java @@ -15,7 +15,7 @@ */ import io.seata.common.XID; import io.seata.common.util.NetUtil; -import io.seata.core.rpc.netty.RpcServer; +import io.seata.core.rpc.netty.NettyRemotingServer; import io.seata.server.UUIDGenerator; import io.seata.server.coordinator.DefaultCoordinator; @@ -41,12 +41,12 @@ public class ServerTest { */ public static void main(String[] args) { - RpcServer rpcServer = new RpcServer(workingThreads); - rpcServer.setHandler(new DefaultCoordinator(rpcServer)); - UUIDGenerator.init(1); + NettyRemotingServer nettyServer = new NettyRemotingServer(workingThreads); + nettyServer.setHandler(new DefaultCoordinator(nettyServer)); + UUIDGenerator.init(1L); XID.setIpAddress(NetUtil.getLocalIp()); - XID.setPort(rpcServer.getListenPort()); - rpcServer.init(); + XID.setPort(nettyServer.getListenPort()); + nettyServer.init(); System.exit(0); } diff --git a/server/src/test/java/WriteStoreTest.java b/server/src/test/java/WriteStoreTest.java index aa765f9840db3a4f17faa21a6e86640532620bb9..dd3c355618bff58b18cc92cf6bfa16513bc15da2 100644 --- a/server/src/test/java/WriteStoreTest.java +++ b/server/src/test/java/WriteStoreTest.java @@ -235,7 +235,7 @@ public class WriteStoreTest { while (((ReloadableStore)transactionStoreManager).hasRemaining(true)) { List<TransactionWriteStore> transactionWriteStores = ((ReloadableStore)transactionStoreManager).readWriteStore(2000, true); - if (null != transactionWriteStores) { + if (transactionWriteStores != null) { for (TransactionWriteStore transactionWriteStore : transactionWriteStores) { printLog(transactionWriteStore); resultMap.put(transactionWriteStore.getSessionRequest(), transactionWriteStore.getOperate()); @@ -245,7 +245,7 @@ public class WriteStoreTest { while (((ReloadableStore)transactionStoreManager).hasRemaining(false)) { List<TransactionWriteStore> transactionWriteStores = ((ReloadableStore)transactionStoreManager).readWriteStore(2000, false); - if (null != transactionWriteStores) { + if (transactionWriteStores != null) { for (TransactionWriteStore transactionWriteStore : transactionWriteStores) { printLog(transactionWriteStore); resultMap.put(transactionWriteStore.getSessionRequest(), transactionWriteStore.getOperate()); diff --git a/server/src/test/java/io/seata/server/UUIDGeneratorOverflowTest.java b/server/src/test/java/io/seata/server/UUIDGeneratorOverflowTest.java index e437087f00f7f779e83f83df3b7f27507057d709..c6ac358403b178410cbdbd52e4e0df12afbfb75f 100644 --- a/server/src/test/java/io/seata/server/UUIDGeneratorOverflowTest.java +++ b/server/src/test/java/io/seata/server/UUIDGeneratorOverflowTest.java @@ -22,7 +22,7 @@ import org.junit.jupiter.api.Test; */ public class UUIDGeneratorOverflowTest { private static final int UUID_GENERATE_COUNT = 5; - private static final int SERVER_NODE_ID = 2; + private static final Long SERVER_NODE_ID = 1023L; /** * Test generate uuid. diff --git a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java index b2e3da97f380b886a6d2b05d1f11d9a166952808..8b349a9f7fb18569065e59526ec945034f0cb009 100644 --- a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java +++ b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java @@ -17,7 +17,6 @@ package io.seata.server.coordinator; import io.netty.channel.Channel; import io.seata.common.XID; -import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.util.DurationUtil; import io.seata.common.util.NetUtil; import io.seata.common.util.ReflectionUtil; @@ -32,7 +31,8 @@ import io.seata.core.protocol.transaction.BranchCommitRequest; import io.seata.core.protocol.transaction.BranchCommitResponse; import io.seata.core.protocol.transaction.BranchRollbackRequest; import io.seata.core.protocol.transaction.BranchRollbackResponse; -import io.seata.core.rpc.ServerMessageSender; +import io.seata.core.rpc.RemotingServer; +import io.seata.core.rpc.processor.RemotingProcessor; import io.seata.core.store.StoreMode; import io.seata.server.session.GlobalSession; import io.seata.server.session.SessionHolder; @@ -42,6 +42,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.time.Duration; import java.util.Collection; +import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.stream.Stream; @@ -64,7 +65,7 @@ import static io.seata.server.session.SessionHolder.DEFAULT_SESSION_STORE_FILE_D * @author leizhiyuan */ public class DefaultCoordinatorTest { - private static ServerMessageSender serverMessageSender; + private static RemotingServer remotingServer; private static DefaultCoordinator defaultCoordinator; private static final String applicationId = "demo-child-app"; @@ -95,9 +96,9 @@ public class DefaultCoordinatorTest { @BeforeAll public static void beforeClass() throws Exception { XID.setIpAddress(NetUtil.getLocalIp()); - serverMessageSender = new MockServerMessageSender(); - defaultCoordinator = new DefaultCoordinator(serverMessageSender); - core = new DefaultCore(serverMessageSender); + RemotingServer remotingServer = new MockServerMessageSender(); + defaultCoordinator = new DefaultCoordinator(remotingServer); + core = new DefaultCore(remotingServer); } @BeforeEach @@ -158,7 +159,7 @@ public class DefaultCoordinatorTest { @Test public void test_handleRetryRollbackingTimeOut() throws TransactionException, InterruptedException, NoSuchFieldException, IllegalAccessException { - defaultCoordinator = new DefaultCoordinator(serverMessageSender); + defaultCoordinator = new DefaultCoordinator(remotingServer); String xid = core.begin(applicationId, txServiceGroup, txName, 10); Long branchId = core.branchRegister(BranchType.AT, "abcd", clientId, xid, applicationData, lockKeys_2); @@ -185,7 +186,7 @@ public class DefaultCoordinatorTest { @Test public void test_handleRetryRollbackingTimeOut_unlock() throws TransactionException, InterruptedException, NoSuchFieldException, IllegalAccessException { - defaultCoordinator = new DefaultCoordinator(serverMessageSender); + defaultCoordinator = new DefaultCoordinator(remotingServer); String xid = core.begin(applicationId, txServiceGroup, txName, 10); Long branchId = core.branchRegister(BranchType.AT, "abcd", clientId, xid, applicationData, lockKeys_2); @@ -255,15 +256,10 @@ public class DefaultCoordinatorTest { } - public static class MockServerMessageSender implements ServerMessageSender { + public static class MockServerMessageSender implements RemotingServer { @Override - public void sendResponse(RpcMessage request, Channel channel, Object msg) { - - } - - @Override - public Object sendSyncRequest(String resourceId, String clientId, Object message, long timeout) throws IOException, TimeoutException { + public Object sendSyncRequest(String resourceId, String clientId, Object message) throws TimeoutException { if (message instanceof BranchCommitRequest) { final BranchCommitResponse branchCommitResponse = new BranchCommitResponse(); branchCommitResponse.setBranchStatus(BranchStatus.PhaseTwo_Committed); @@ -278,25 +274,23 @@ public class DefaultCoordinatorTest { } @Override - public Object sendSyncRequest(String resourceId, String clientId, Object message) throws IOException, TimeoutException { - - return sendSyncRequest(resourceId, clientId, message, 3000); - + public Object sendSyncRequest(Channel clientChannel, Object message) throws TimeoutException { + return null; } @Override - public Object sendASyncRequest(Channel channel, Object message) throws IOException, TimeoutException { - return null; + public void sendAsyncRequest(Channel channel, Object msg) { + } @Override - public Object sendSyncRequest(Channel clientChannel, Object message) throws TimeoutException { - return null; + public void sendAsyncResponse(RpcMessage request, Channel channel, Object msg) { + } @Override - public Object sendSyncRequest(Channel clientChannel, Object message, long timeout) throws TimeoutException { - return null; + public void registerProcessor(int messageType, RemotingProcessor processor, ExecutorService executor) { + } } } \ No newline at end of file diff --git a/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java b/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java index b854c40e4e29cd5f32decbbebefccfbcd3f31af3..7cfbef2bda9a742870267183763cb6460574e48f 100644 --- a/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java +++ b/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java @@ -22,7 +22,7 @@ import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; import io.seata.core.model.GlobalStatus; -import io.seata.core.rpc.ServerMessageSender; +import io.seata.core.rpc.RemotingServer; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; import io.seata.server.session.SessionHelper; @@ -45,7 +45,7 @@ import org.junit.jupiter.params.provider.MethodSource; public class DefaultCoreTest { private static DefaultCore core; - private static ServerMessageSender serverMessageSender; + private static RemotingServer remotingServer; private static final String applicationId = "demo-child-app"; @@ -75,8 +75,8 @@ public class DefaultCoreTest { @BeforeAll public static void initSessionManager() throws Exception { SessionHolder.init(null); - serverMessageSender = new DefaultCoordinatorTest.MockServerMessageSender(); - core = new DefaultCore(serverMessageSender); + remotingServer = new DefaultCoordinatorTest.MockServerMessageSender(); + core = new DefaultCore(remotingServer); } /** @@ -94,7 +94,7 @@ public class DefaultCoreTest { */ @AfterEach public void clean() throws TransactionException { - if (null != globalSession) { + if (globalSession != null) { globalSession.end(); globalSession = null; } diff --git a/server/src/test/java/io/seata/server/lock/redis/RedisLockManagerTest.java b/server/src/test/java/io/seata/server/lock/redis/RedisLockManagerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..95304b59d18731b9dcda6e04e005ac251b7f7173 --- /dev/null +++ b/server/src/test/java/io/seata/server/lock/redis/RedisLockManagerTest.java @@ -0,0 +1,113 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.lock.redis; + +import java.io.IOException; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import com.github.fppt.jedismock.RedisServer; + +import io.seata.core.exception.TransactionException; +import io.seata.core.lock.Locker; +import io.seata.server.lock.LockManager; +import io.seata.server.session.BranchSession; +import io.seata.server.storage.file.lock.FileLockManager; +import io.seata.server.storage.redis.JedisPooledFactory; +import io.seata.server.storage.redis.lock.RedisLocker; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +/** + * @author funkye + */ +public class RedisLockManagerTest { + static RedisServer server = null; + static LockManager lockManager = null; + + @BeforeAll + public static void start() throws IOException { + server = RedisServer.newRedisServer(6789); + server.start(); + JedisPoolConfig poolConfig = new JedisPoolConfig(); + poolConfig.setMinIdle(1); + poolConfig.setMaxIdle(10); + JedisPooledFactory.getJedisPoolInstance(new JedisPool(poolConfig, "127.0.0.1", 6789, 60000)); + lockManager = new RedisLockManagerForTest(); + } + + @Test + public void acquireLock() throws TransactionException { + BranchSession branchSession = new BranchSession(); + branchSession.setXid("abc-123:786756"); + branchSession.setTransactionId(123543465); + branchSession.setBranchId(5756678); + branchSession.setResourceId("abcss"); + branchSession.setLockKey("t1:13,14;t2:11,12"); + Assertions.assertTrue(lockManager.acquireLock(branchSession)); + } + + @Test + public void unLock() throws TransactionException { + BranchSession branchSession = new BranchSession(); + branchSession.setXid("abc-123:56867"); + branchSession.setTransactionId(1236765); + branchSession.setBranchId(204565); + branchSession.setResourceId("abcss"); + branchSession.setLockKey("t1:3,4;t2:4,5"); + Assertions.assertTrue(lockManager.acquireLock(branchSession)); + } + + @Test + public void isLockable() throws TransactionException { + BranchSession branchSession = new BranchSession(); + branchSession.setXid("abc-123:56877898"); + branchSession.setTransactionId(245686786); + branchSession.setBranchId(467568); + branchSession.setResourceId("abcss"); + branchSession.setLockKey("t1:8,7;t2:1,2"); + Assertions.assertTrue(lockManager.acquireLock(branchSession)); + BranchSession branchSession2 = new BranchSession(); + branchSession2.setXid("abc-123:56877898"); + branchSession2.setTransactionId(245686786); + branchSession2.setBranchId(1242354576); + branchSession2.setResourceId("abcss"); + branchSession2.setLockKey("t1:8"); + Assertions.assertTrue(lockManager.isLockable(branchSession2.getXid(), branchSession2.getResourceId(), + branchSession2.getLockKey())); + } + + @AfterAll + public static void after() { + server.stop(); + server = null; + } + + public static class RedisLockManagerForTest extends FileLockManager { + + public RedisLockManagerForTest() {} + + @Override + public Locker getLocker(BranchSession branchSession) { + + return new RedisLocker(); + } + } +} diff --git a/server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java b/server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java index b9fb6906634861a3b19b5be6cd1650857d11168b..4509e5642ad64a14e6324e1948a11f390cce8556 100644 --- a/server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java +++ b/server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java @@ -68,7 +68,7 @@ public class DataBaseSessionManagerTest { logStoreDataBaseDAO = new LogStoreDataBaseDAO(dataSource); logStoreDataBaseDAO.setDbType("h2"); logStoreDataBaseDAO.setGlobalTable("global_table"); - logStoreDataBaseDAO.setBrachTable("branch_table"); + logStoreDataBaseDAO.setBranchTable("branch_table"); transactionStoreManager.setLogQueryLimit(100); transactionStoreManager.setLogStore(logStoreDataBaseDAO); diff --git a/server/src/test/java/io/seata/server/session/redis/RedisSeesionManagerTest.java b/server/src/test/java/io/seata/server/session/redis/RedisSeesionManagerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..70520d218eba4923a5e4a6c222c991f4227792a1 --- /dev/null +++ b/server/src/test/java/io/seata/server/session/redis/RedisSeesionManagerTest.java @@ -0,0 +1,167 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.session.redis; + +import java.io.IOException; +import com.github.fppt.jedismock.RedisServer; +import io.seata.common.XID; +import io.seata.core.exception.TransactionException; +import io.seata.core.model.BranchStatus; +import io.seata.core.model.BranchType; +import io.seata.core.model.GlobalStatus; +import io.seata.server.UUIDGenerator; +import io.seata.server.session.BranchSession; +import io.seata.server.session.GlobalSession; +import io.seata.server.session.SessionManager; +import io.seata.server.storage.redis.JedisPooledFactory; +import io.seata.server.storage.redis.session.RedisSessionManager; +import io.seata.server.storage.redis.store.RedisTransactionStoreManager; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +/** + * @author funkye + */ +public class RedisSeesionManagerTest { + private static RedisServer server = null; + private static SessionManager sessionManager = null; + + @BeforeAll + public static void start() throws IOException { + server = RedisServer.newRedisServer(6789); + server.start(); + JedisPoolConfig poolConfig = new JedisPoolConfig(); + poolConfig.setMinIdle(1); + poolConfig.setMaxIdle(10); + JedisPooledFactory.getJedisPoolInstance(new JedisPool(poolConfig, "127.0.0.1", 6789, 60000)); + RedisTransactionStoreManager transactionStoreManager = RedisTransactionStoreManager.getInstance(); + RedisSessionManager redisSessionManager = new RedisSessionManager(); + redisSessionManager.setTransactionStoreManager(transactionStoreManager); + sessionManager = redisSessionManager; + } + + @Test + public void test_addGlobalSession() throws TransactionException { + GlobalSession session = GlobalSession.createGlobalSession("test", "test", "test123", 100); + String xid = XID.generateXID(session.getTransactionId()); + session.setXid(xid); + session.setTransactionId(146757978); + session.setBeginTime(System.currentTimeMillis()); + session.setApplicationData("abc=878s"); + session.setStatus(GlobalStatus.Begin); + sessionManager.addGlobalSession(session); + } + + @Test + public void test_updateGlobalSessionStatus() throws TransactionException { + GlobalSession session = GlobalSession.createGlobalSession("test", "test", "test123", 100); + String xid = XID.generateXID(session.getTransactionId()); + session.setXid(xid); + session.setTransactionId(146757978); + session.setBeginTime(System.currentTimeMillis()); + session.setApplicationData("abc=878s"); + session.setStatus(GlobalStatus.Begin); + sessionManager.addGlobalSession(session); + session.setStatus(GlobalStatus.Committing); + sessionManager.updateGlobalSessionStatus(session,GlobalStatus.Committing); + } + + @Test + public void test_removeGlobalSession() throws Exception { + GlobalSession session = GlobalSession.createGlobalSession("test", "test", "test123", 100); + String xid = XID.generateXID(session.getTransactionId()); + session.setXid(xid); + session.setTransactionId(146757978); + session.setBeginTime(System.currentTimeMillis()); + session.setApplicationData("abc=878s"); + session.setStatus(GlobalStatus.Begin); + sessionManager.addGlobalSession(session); + BranchSession branchSession = new BranchSession(); + branchSession.setBranchId(UUIDGenerator.generateUUID()); + branchSession.setXid(xid); + branchSession.setTransactionId(session.getTransactionId()); + branchSession.setBranchId(1L); + branchSession.setResourceGroupId("my_test_tx_group"); + branchSession.setResourceId("tb_1"); + branchSession.setLockKey("t_1"); + branchSession.setBranchType(BranchType.AT); + branchSession.setApplicationData("{\"data\":\"test\"}"); + sessionManager.addBranchSession(session, branchSession); + sessionManager.removeBranchSession(session, branchSession); + sessionManager.removeGlobalSession(session); + } + + @Test + public void test_addBranchSession() throws TransactionException { + GlobalSession globalSession = GlobalSession.createGlobalSession("test", "test", "test123", 100); + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.setTransactionId(146757978); + globalSession.setBeginTime(System.currentTimeMillis()); + globalSession.setApplicationData("abc=878s"); + globalSession.setStatus(GlobalStatus.Begin); + sessionManager.addGlobalSession(globalSession); + + BranchSession branchSession = new BranchSession(); + branchSession.setBranchId(UUIDGenerator.generateUUID()); + branchSession.setXid(xid); + branchSession.setTransactionId(globalSession.getTransactionId()); + branchSession.setBranchId(1L); + branchSession.setResourceGroupId("my_test_tx_group"); + branchSession.setResourceId("tb_1"); + branchSession.setLockKey("t_1"); + branchSession.setBranchType(BranchType.AT); + branchSession.setApplicationData("{\"data\":\"test\"}"); + sessionManager.addBranchSession(globalSession,branchSession); + } + + @Test + public void test_updateBranchSessionStatus() throws Exception { + GlobalSession globalSession = GlobalSession.createGlobalSession("test", "test", "test123", 100); + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.setTransactionId(146757978); + globalSession.setBeginTime(System.currentTimeMillis()); + globalSession.setApplicationData("abc=878s"); + globalSession.setStatus(GlobalStatus.Begin); + + BranchSession branchSession = new BranchSession(); + branchSession.setBranchId(UUIDGenerator.generateUUID()); + branchSession.setXid(xid); + branchSession.setTransactionId(globalSession.getTransactionId()); + branchSession.setBranchId(1L); + branchSession.setResourceGroupId("my_test_tx_group"); + branchSession.setResourceId("tb_1"); + branchSession.setLockKey("t_1"); + branchSession.setBranchType(BranchType.AT); + branchSession.setApplicationData("{\"data\":\"test\"}"); + branchSession.setStatus(BranchStatus.PhaseOne_Done); + sessionManager.addBranchSession(globalSession, branchSession); + branchSession.setStatus(BranchStatus.PhaseOne_Timeout); + sessionManager.updateBranchSessionStatus(branchSession, BranchStatus.PhaseOne_Timeout); + } + + @AfterAll + public static void after() { + server.stop(); + server = null; + } + +} diff --git a/server/src/test/java/io/seata/server/store/db/AbstractDataSourceProviderTest.java b/server/src/test/java/io/seata/server/store/db/AbstractDataSourceProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..15d320be6c3eb1c58ebc5c2d2833db61be10ce81 --- /dev/null +++ b/server/src/test/java/io/seata/server/store/db/AbstractDataSourceProviderTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.server.store.db; + +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.core.store.db.DataSourceProvider; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import javax.sql.DataSource; + +/** + * @author: will + */ +public class AbstractDataSourceProviderTest { + + private final String dbcpDatasourceType = "dbcp"; + + private final String druidDatasourceType = "druid"; + + private final String hikariDatasourceType = "hikari"; + + @Test + public void testDbcpDataSourceProvider() { + DataSource dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, dbcpDatasourceType).provide(); + Assertions.assertNotNull(dataSource); + } + + @Test + public void testDruidDataSourceProvider() { + DataSource dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, druidDatasourceType).provide(); + Assertions.assertNotNull(dataSource); + } + + @Test + public void testHikariDataSourceProvider() { + DataSource dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, hikariDatasourceType).provide(); + Assertions.assertNotNull(dataSource); + } +} diff --git a/server/src/test/java/io/seata/server/store/db/DataSourceGeneratorTest.java b/server/src/test/java/io/seata/server/store/db/DataSourceGeneratorTest.java deleted file mode 100644 index 918205c4e658d31395398b1006c6fac6137d76eb..0000000000000000000000000000000000000000 --- a/server/src/test/java/io/seata/server/store/db/DataSourceGeneratorTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache 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 - * - * http://www.apache.org/licenses/LICENSE-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 io.seata.server.store.db; - -import com.alibaba.druid.pool.DruidDataSource; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.core.store.db.DataSourceGenerator; -import org.apache.commons.dbcp2.BasicDataSource; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.sql.Connection; -import java.sql.Driver; -import java.sql.SQLException; - -public class DataSourceGeneratorTest { - @Test - public void testDbcpGenerateDataSource() { - DataSourceGenerator dataSourceGenerator = EnhancedServiceLoader.load(DataSourceGenerator.class, "dbcp"); - BasicDataSource dataSource = (BasicDataSource) dataSourceGenerator.generateDataSource(); - ClassLoader driverClassLoader = dataSource.getDriverClassLoader(); - Assertions.assertNotNull(driverClassLoader); - } - - @Test - public void testDruidGenerateDataSource() { - DataSourceGenerator dataSourceGenerator = EnhancedServiceLoader.load(DataSourceGenerator.class, "druid"); - DruidDataSource dataSource = (DruidDataSource) dataSourceGenerator.generateDataSource(); - ClassLoader driverClassLoader = dataSource.getDriverClassLoader(); - Assertions.assertNotNull(driverClassLoader); - try (Connection conn = dataSource.getConnection()) { - Assertions.assertNotNull(conn); - } catch (SQLException ignore) { - } finally { - Driver driver = dataSource.getDriver(); - Assertions.assertNotNull(driver); - Assertions.assertEquals(driverClassLoader, driver.getClass().getClassLoader()); - } - } -} diff --git a/server/src/test/java/io/seata/server/store/db/LogStoreDataBaseDAOTest.java b/server/src/test/java/io/seata/server/store/db/LogStoreDataBaseDAOTest.java index c3a5b46f0a8f973bad2b60c8b267286499bf60c5..42a7ee05fd190fc59fae7c4dd1d5cafe37430ded 100644 --- a/server/src/test/java/io/seata/server/store/db/LogStoreDataBaseDAOTest.java +++ b/server/src/test/java/io/seata/server/store/db/LogStoreDataBaseDAOTest.java @@ -55,7 +55,7 @@ public class LogStoreDataBaseDAOTest { logStoreDataBaseDAO = new LogStoreDataBaseDAO(dataSource); logStoreDataBaseDAO.setDbType("h2"); logStoreDataBaseDAO.setGlobalTable("global_table"); - logStoreDataBaseDAO.setBrachTable("branch_table"); + logStoreDataBaseDAO.setBranchTable("branch_table"); prepareTable(dataSource); } diff --git a/server/src/test/java/io/seata/server/store/file/FileTransactionStoreManagerTest.java b/server/src/test/java/io/seata/server/store/file/FileTransactionStoreManagerTest.java index d18148e006334cb0639bd69a6e85a88f4a7aabec..e3107dfedd14805b1450a3a4b1f79483e00118ec 100644 --- a/server/src/test/java/io/seata/server/store/file/FileTransactionStoreManagerTest.java +++ b/server/src/test/java/io/seata/server/store/file/FileTransactionStoreManagerTest.java @@ -67,7 +67,7 @@ public class FileTransactionStoreManagerTest { BranchSession loadedBranchSessionB = (BranchSession) list.get(1).getSessionRequest(); Assertions.assertEquals(branchSessionB.getApplicationData(), loadedBranchSessionB.getApplicationData()); } finally { - if (null != fileTransactionStoreManager) { + if (fileTransactionStoreManager != null) { fileTransactionStoreManager.shutdown(); } Assertions.assertTrue(seataFile.delete()); @@ -119,10 +119,10 @@ public class FileTransactionStoreManagerTest { }); } finally { findTimeoutAndSaveMethod.setAccessible(false); - if (null != fileTransactionStoreManager) { + if (fileTransactionStoreManager != null) { fileTransactionStoreManager.shutdown(); } - if (null != sessionManager) { + if (sessionManager != null) { sessionManager.destroy(); } Assertions.assertTrue(seataFile.delete()); diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalLock.java b/spring/src/main/java/io/seata/spring/annotation/GlobalLock.java index e4f80c674b2259deb07e43cceb04563a83eb31d0..0a84b6313fb4a197dead1ed2adfe1a6f6bb4bec3 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalLock.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalLock.java @@ -29,7 +29,7 @@ import java.lang.annotation.Target; * use this annotation instead of GlobalTransaction in the situation mentioned above will help performance. */ @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) +@Target({ElementType.METHOD,ElementType.TYPE}) @Inherited public @interface GlobalLock { } diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java index 1a0f209856219c35c66f10a35308742df880c913..1c8c0786b81f1307d259898e75dfba4ad3b9b454 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java @@ -18,15 +18,15 @@ package io.seata.spring.annotation; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; - import io.seata.common.util.CollectionUtils; import io.seata.common.util.StringUtils; import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; +import io.seata.config.ConfigurationCache; import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.rpc.netty.RmRpcClient; -import io.seata.core.rpc.netty.ShutdownHook; -import io.seata.core.rpc.netty.TmRpcClient; +import io.seata.core.rpc.netty.RmNettyRemotingClient; +import io.seata.core.rpc.ShutdownHook; +import io.seata.core.rpc.netty.TmNettyRemotingClient; import io.seata.rm.RMClient; import io.seata.spring.tcc.TccActionInterceptor; import io.seata.spring.util.SpringProxyUtils; @@ -48,6 +48,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; + import static io.seata.core.constants.DefaultValues.DEFAULT_DISABLE_GLOBAL_TRANSACTION; /** @@ -72,6 +73,7 @@ public class GlobalTransactionScanner extends AbstractAutoProxyCreator private static final Set<String> PROXYED_SET = new HashSet<>(); private MethodInterceptor interceptor; + private MethodInterceptor globalTransactionalInterceptor; private final String applicationId; private final String txServiceGroup; @@ -187,8 +189,8 @@ public class GlobalTransactionScanner extends AbstractAutoProxyCreator ((ConfigurableApplicationContext) applicationContext).registerShutdownHook(); ShutdownHook.removeRuntimeShutdownHook(); } - ShutdownHook.getInstance().addDisposable(TmRpcClient.getInstance(applicationId, txServiceGroup)); - ShutdownHook.getInstance().addDisposable(RmRpcClient.getInstance(applicationId, txServiceGroup)); + ShutdownHook.getInstance().addDisposable(TmNettyRemotingClient.getInstance(applicationId, txServiceGroup)); + ShutdownHook.getInstance().addDisposable(RmNettyRemotingClient.getInstance(applicationId, txServiceGroup)); } @Override @@ -216,8 +218,13 @@ public class GlobalTransactionScanner extends AbstractAutoProxyCreator } if (interceptor == null) { - interceptor = new GlobalTransactionalInterceptor(failureHandlerHook); - ConfigurationFactory.getInstance().addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, (ConfigurationChangeListener) interceptor); + if (globalTransactionalInterceptor == null) { + globalTransactionalInterceptor = new GlobalTransactionalInterceptor(failureHandlerHook); + ConfigurationCache.addConfigListener( + ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, + (ConfigurationChangeListener)globalTransactionalInterceptor); + } + interceptor = globalTransactionalInterceptor; } } @@ -245,9 +252,13 @@ public class GlobalTransactionScanner extends AbstractAutoProxyCreator if (clazz == null) { continue; } + GlobalTransactional trxAnno = clazz.getAnnotation(GlobalTransactional.class); + if (trxAnno != null) { + return true; + } Method[] methods = clazz.getMethods(); for (Method method : methods) { - GlobalTransactional trxAnno = method.getAnnotation(GlobalTransactional.class); + trxAnno = method.getAnnotation(GlobalTransactional.class); if (trxAnno != null) { return true; } diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactional.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactional.java index e0ea0a301fb55b08003529f3b4ca572ee089799a..8e534b4643198338cbdda4b4b31dde1df4d4bfe0 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactional.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactional.java @@ -15,20 +15,19 @@ */ package io.seata.spring.annotation; -import io.seata.tm.api.transaction.Propagation; -import io.seata.tm.api.transaction.TransactionInfo; - import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import io.seata.tm.api.transaction.Propagation; +import io.seata.tm.api.transaction.TransactionInfo; /** * The interface Global transactional. */ @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) +@Target({ElementType.METHOD,ElementType.TYPE}) @Inherited public @interface GlobalTransactional { @@ -72,6 +71,7 @@ public @interface GlobalTransactional { /** * the propagation of the global transaction + * * @return */ Propagation propagation() default Propagation.REQUIRED; diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java index d03163d46e69e817bf10c23e0a24d0d847ecc27e..b39c6166526f6fde0b333cedfcbb7ff01bbe10b4 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java @@ -18,15 +18,25 @@ package io.seata.spring.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.LinkedHashSet; +import java.util.Optional; import java.util.Set; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import com.google.common.eventbus.Subscribe; import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.StringUtils; +import io.seata.config.ConfigurationCache; import io.seata.config.ConfigurationChangeEvent; import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.event.EventBus; +import io.seata.core.event.GuavaEventBus; import io.seata.rm.GlobalLockTemplate; +import io.seata.spring.event.DegradeCheckEvent; +import io.seata.tm.TransactionManagerHolder; import io.seata.tm.api.DefaultFailureHandlerImpl; import io.seata.tm.api.FailureHandler; import io.seata.tm.api.TransactionalExecutor; @@ -42,7 +52,11 @@ import org.springframework.aop.support.AopUtils; import org.springframework.core.BridgeMethodResolver; import org.springframework.util.ClassUtils; + import static io.seata.core.constants.DefaultValues.DEFAULT_DISABLE_GLOBAL_TRANSACTION; +import static io.seata.core.constants.DefaultValues.DEFAULT_TM_DEGRADE_CHECK; +import static io.seata.core.constants.DefaultValues.DEFAULT_TM_DEGRADE_CHECK_ALLOW_TIMES; +import static io.seata.core.constants.DefaultValues.DEFAULT_TM_DEGRADE_CHECK_PERIOD; /** * The type Global transactional interceptor. @@ -58,34 +72,60 @@ public class GlobalTransactionalInterceptor implements ConfigurationChangeListen private final GlobalLockTemplate<Object> globalLockTemplate = new GlobalLockTemplate<>(); private final FailureHandler failureHandler; private volatile boolean disable; + private static int degradeCheckPeriod; + private static volatile boolean degradeCheck; + private static int degradeCheckAllowTimes; + private static volatile Integer degradeNum = 0; + private static volatile Integer reachNum = 0; + private static final EventBus EVENT_BUS = new GuavaEventBus("degradeCheckEventBus", true); + private static ScheduledThreadPoolExecutor executor = + new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("degradeCheckWorker", 1, true)); /** * Instantiates a new Global transactional interceptor. * - * @param failureHandler the failure handler + * @param failureHandler + * the failure handler */ public GlobalTransactionalInterceptor(FailureHandler failureHandler) { this.failureHandler = failureHandler == null ? DEFAULT_FAIL_HANDLER : failureHandler; this.disable = ConfigurationFactory.getInstance().getBoolean(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, DEFAULT_DISABLE_GLOBAL_TRANSACTION); + degradeCheck = ConfigurationFactory.getInstance().getBoolean(ConfigurationKeys.CLIENT_DEGRADE_CHECK, + DEFAULT_TM_DEGRADE_CHECK); + if (degradeCheck) { + ConfigurationCache.addConfigListener(ConfigurationKeys.CLIENT_DEGRADE_CHECK, this); + degradeCheckPeriod = ConfigurationFactory.getInstance().getInt( + ConfigurationKeys.CLIENT_DEGRADE_CHECK_PERIOD, DEFAULT_TM_DEGRADE_CHECK_PERIOD); + degradeCheckAllowTimes = ConfigurationFactory.getInstance().getInt( + ConfigurationKeys.CLIENT_DEGRADE_CHECK_ALLOW_TIMES, DEFAULT_TM_DEGRADE_CHECK_ALLOW_TIMES); + EVENT_BUS.register(this); + if (degradeCheckPeriod > 0 && degradeCheckAllowTimes > 0) { + startDegradeCheck(); + } + } } @Override public Object invoke(final MethodInvocation methodInvocation) throws Throwable { - Class<?> targetClass = methodInvocation.getThis() != null ? AopUtils.getTargetClass(methodInvocation.getThis()) - : null; + Class<?> targetClass = + methodInvocation.getThis() != null ? AopUtils.getTargetClass(methodInvocation.getThis()) : null; Method specificMethod = ClassUtils.getMostSpecificMethod(methodInvocation.getMethod(), targetClass); - final Method method = BridgeMethodResolver.findBridgedMethod(specificMethod); - - final GlobalTransactional globalTransactionalAnnotation = getAnnotation(method, GlobalTransactional.class); - final GlobalLock globalLockAnnotation = getAnnotation(method, GlobalLock.class); - if (!disable && globalTransactionalAnnotation != null) { - return handleGlobalTransaction(methodInvocation, globalTransactionalAnnotation); - } else if (!disable && globalLockAnnotation != null) { - return handleGlobalLock(methodInvocation); - } else { - return methodInvocation.proceed(); + if (specificMethod != null && !specificMethod.getDeclaringClass().equals(Object.class)) { + final Method method = BridgeMethodResolver.findBridgedMethod(specificMethod); + final GlobalTransactional globalTransactionalAnnotation = + getAnnotation(method, targetClass, GlobalTransactional.class); + final GlobalLock globalLockAnnotation = getAnnotation(method, targetClass, GlobalLock.class); + boolean localDisable = disable || (degradeCheck && degradeNum >= degradeCheckAllowTimes); + if (!localDisable) { + if (globalTransactionalAnnotation != null) { + return handleGlobalTransaction(methodInvocation, globalTransactionalAnnotation); + } else if (globalLockAnnotation != null) { + return handleGlobalLock(methodInvocation); + } + } } + return methodInvocation.proceed(); } private Object handleGlobalLock(final MethodInvocation methodInvocation) throws Exception { @@ -101,7 +141,8 @@ public class GlobalTransactionalInterceptor implements ConfigurationChangeListen } private Object handleGlobalTransaction(final MethodInvocation methodInvocation, - final GlobalTransactional globalTrxAnno) throws Throwable { + final GlobalTransactional globalTrxAnno) throws Throwable { + boolean succeed = true; try { return transactionalTemplate.execute(new TransactionalExecutor() { @Override @@ -146,26 +187,32 @@ public class GlobalTransactionalInterceptor implements ConfigurationChangeListen case RollbackDone: throw e.getOriginalException(); case BeginFailure: + succeed = false; failureHandler.onBeginFailure(e.getTransaction(), e.getCause()); throw e.getCause(); case CommitFailure: + succeed = false; failureHandler.onCommitFailure(e.getTransaction(), e.getCause()); throw e.getCause(); case RollbackFailure: - failureHandler.onRollbackFailure(e.getTransaction(), e.getCause()); - throw e.getCause(); + failureHandler.onRollbackFailure(e.getTransaction(), e.getOriginalException()); + throw e.getOriginalException(); case RollbackRetrying: - failureHandler.onRollbackRetrying(e.getTransaction(), e.getCause()); - throw e.getCause(); + failureHandler.onRollbackRetrying(e.getTransaction(), e.getOriginalException()); + throw e.getOriginalException(); default: throw new ShouldNeverHappenException(String.format("Unknown TransactionalExecutor.Code: %s", code)); - + } + } finally { + if (degradeCheck) { + EVENT_BUS.post(new DegradeCheckEvent(succeed)); } } } - private <T extends Annotation> T getAnnotation(Method method, Class<T> clazz) { - return method == null ? null : method.getAnnotation(clazz); + public <T extends Annotation> T getAnnotation(Method method, Class<?> targetClass, Class<T> annotationClass) { + return Optional.ofNullable(method).map(m -> m.getAnnotation(annotationClass)) + .orElse(Optional.ofNullable(targetClass).map(t -> t.getAnnotation(annotationClass)).orElse(null)); } private String formatMethod(Method method) { @@ -188,6 +235,57 @@ public class GlobalTransactionalInterceptor implements ConfigurationChangeListen LOGGER.info("{} config changed, old value:{}, new value:{}", ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, disable, event.getNewValue()); disable = Boolean.parseBoolean(event.getNewValue().trim()); + } else if (ConfigurationKeys.CLIENT_DEGRADE_CHECK.equals(event.getDataId())) { + degradeCheck = Boolean.parseBoolean(event.getNewValue()); + if (!degradeCheck) { + degradeNum = 0; + } + } + } + + /** + * auto upgrade service detection + */ + private static void startDegradeCheck() { + executor.scheduleAtFixedRate(() -> { + if (degradeCheck) { + try { + String xid = TransactionManagerHolder.get().begin(null, null, "degradeCheck", 60000); + TransactionManagerHolder.get().commit(xid); + EVENT_BUS.post(new DegradeCheckEvent(true)); + } catch (Exception e) { + EVENT_BUS.post(new DegradeCheckEvent(false)); + } + } + }, degradeCheckPeriod, degradeCheckPeriod, TimeUnit.MILLISECONDS); + } + + @Subscribe + public static void onDegradeCheck(DegradeCheckEvent event) { + if (event.isRequestSuccess()) { + if (degradeNum >= degradeCheckAllowTimes) { + reachNum++; + if (reachNum >= degradeCheckAllowTimes) { + reachNum = 0; + degradeNum = 0; + if (LOGGER.isInfoEnabled()) { + LOGGER.info("the current global transaction has been restored"); + } + } + } else if (degradeNum != 0) { + degradeNum = 0; + } + } else { + if (degradeNum < degradeCheckAllowTimes) { + degradeNum++; + if (degradeNum >= degradeCheckAllowTimes) { + if (LOGGER.isWarnEnabled()) { + LOGGER.warn("the current global transaction has been automatically downgraded"); + } + } + } else if (reachNum != 0) { + reachNum = 0; + } } } } diff --git a/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyAdvice.java b/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyAdvice.java index 3dcd9da42966341d6f4cecc27242092853d3b0c5..ed9ea41d36a729b64cf701d4f1014eae94eec82e 100644 --- a/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyAdvice.java +++ b/spring/src/main/java/io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyAdvice.java @@ -35,7 +35,7 @@ public class SeataAutoDataSourceProxyAdvice implements MethodInterceptor, Introd Method method = invocation.getMethod(); Object[] args = invocation.getArguments(); Method m = BeanUtils.findDeclaredMethod(DataSourceProxy.class, method.getName(), method.getParameterTypes()); - if (null != m) { + if (m != null) { return m.invoke(dataSourceProxy, args); } else { return invocation.proceed(); diff --git a/core/src/main/java/io/seata/core/rpc/netty/DefaultChannelPoolHandler.java b/spring/src/main/java/io/seata/spring/event/DegradeCheckEvent.java similarity index 57% rename from core/src/main/java/io/seata/core/rpc/netty/DefaultChannelPoolHandler.java rename to spring/src/main/java/io/seata/spring/event/DegradeCheckEvent.java index 07c57f84f788860f7205195b09b6ff50e7c5a1b4..57675c05e517fb3e4eb114ef7424033f0daa1549 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/DefaultChannelPoolHandler.java +++ b/spring/src/main/java/io/seata/spring/event/DegradeCheckEvent.java @@ -13,23 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.core.rpc.netty; -import io.netty.channel.Channel; -import io.netty.channel.pool.AbstractChannelPoolHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package io.seata.spring.event; + +import io.seata.core.event.Event; /** - * The type Default channel pool handler. - * * @author slievrly */ -public class DefaultChannelPoolHandler extends AbstractChannelPoolHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultChannelPoolHandler.class); +public class DegradeCheckEvent implements Event { + private boolean requestSuccess; - @Override - public void channelCreated(Channel ch) throws Exception { + public DegradeCheckEvent(boolean requestSuccess) { + this.requestSuccess = requestSuccess; + } + public boolean isRequestSuccess() { + return requestSuccess; } } diff --git a/spring/src/main/java/io/seata/spring/tcc/TccActionInterceptor.java b/spring/src/main/java/io/seata/spring/tcc/TccActionInterceptor.java index 598b29784355282c689c0e85d0ecba8b735b69fb..745503d8e31d68d9ec951abe041fe94c716028ee 100644 --- a/spring/src/main/java/io/seata/spring/tcc/TccActionInterceptor.java +++ b/spring/src/main/java/io/seata/spring/tcc/TccActionInterceptor.java @@ -16,6 +16,7 @@ package io.seata.spring.tcc; import io.seata.common.Constants; +import io.seata.common.util.StringUtils; import io.seata.core.context.RootContext; import io.seata.core.model.BranchType; import io.seata.rm.tcc.api.TwoPhaseBusinessAction; @@ -74,9 +75,9 @@ public class TccActionInterceptor implements MethodInterceptor { if (businessAction != null) { //save the xid String xid = RootContext.getXID(); - //clear the context - RootContext.unbind(); - RootContext.bindInterceptorType(xid, BranchType.TCC); + //save the previous branchType + String previousBranchType = RootContext.getBranchType(); + RootContext.bindBranchType(BranchType.TCC); try { Object[] methodArgs = invocation.getArguments(); //Handler the TCC Aspect @@ -84,10 +85,13 @@ public class TccActionInterceptor implements MethodInterceptor { invocation::proceed); //return the final result return ret.get(Constants.TCC_METHOD_RESULT); - } finally { - //recovery the context - RootContext.unbindInterceptorType(); - RootContext.bind(xid); + } + finally { + RootContext.unbindBranchType(); + //restore the TCC branchType if exists + if (StringUtils.equals(BranchType.TCC.name(), previousBranchType)) { + RootContext.bindBranchType(BranchType.TCC); + } } } return invocation.proceed(); @@ -100,8 +104,8 @@ public class TccActionInterceptor implements MethodInterceptor { * @return the action interface method */ protected Method getActionInterfaceMethod(MethodInvocation invocation) { + Class<?> interfaceType = null; try { - Class<?> interfaceType; if (remotingDesc == null) { interfaceType = getProxyInterface(invocation.getThis()); } else { @@ -116,6 +120,11 @@ public class TccActionInterceptor implements MethodInterceptor { } return interfaceType.getMethod(invocation.getMethod().getName(), invocation.getMethod().getParameterTypes()); + } catch (NoSuchMethodException e) { + if (interfaceType != null && !invocation.getMethod().getName().equals("toString")) { + LOGGER.warn("no such method '{}' from interface {}", invocation.getMethod().getName(), interfaceType.getName()); + } + return invocation.getMethod(); } catch (Exception e) { LOGGER.warn("get Method from interface failed", e); return invocation.getMethod(); diff --git a/spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java b/spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..5913539a6b3a5bcd821d81a815ae8ba427900255 --- /dev/null +++ b/spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java @@ -0,0 +1,132 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.spring.tcc; + +import io.seata.rm.tcc.api.TwoPhaseBusinessAction; +import io.seata.rm.tcc.remoting.RemotingDesc; +import io.seata.spring.util.TCCBeanParserUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.ReflectionUtils; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * An annotation adapter for TCC + * + * @author ppf + */ +public class TccAnnotationProcessor implements BeanPostProcessor { + private static final Logger LOGGER = LoggerFactory.getLogger(TccAnnotationProcessor.class); + + private static final List<Class<? extends Annotation>> ANNOTATIONS = new ArrayList<>(4); + private static final Set<String> PROXIED_SET = new HashSet<>(); + + static { + ANNOTATIONS.add(loadAnnotation("org.apache.dubbo.config.annotation.Reference")); + ANNOTATIONS.add(loadAnnotation("com.alipay.sofa.runtime.api.annotation.SofaReference")); + } + + private static Class<? extends Annotation> loadAnnotation(String annotation) { + try { + return (Class<? extends Annotation>) Class.forName(annotation); + } catch (ClassNotFoundException e) { + return null; + } + } + + + /** + * Process annotation + * + * @param bean + * @param beanName + * @param annotation + */ + protected void process(Object bean, String beanName, Class<? extends Annotation> annotation) { + if (Objects.isNull(annotation) || PROXIED_SET.contains(beanName)) { + return; + } + + ReflectionUtils.doWithFields(bean.getClass(), field -> { + Annotation reference = field.getAnnotation(annotation); + if (reference == null) { + return; + } + + addTccAdvise(bean, beanName, field, field.getType()); + + }, field -> !Modifier.isStatic(field.getModifiers()) + && (field.isAnnotationPresent(annotation))); + + PROXIED_SET.add(beanName); + } + + /** + * Add TCC interceptor for tcc proxy bean + * + * @param bean + * @param beanName + * @param field + * @param interfaceClass + * @return + * @throws IllegalAccessException + */ + public void addTccAdvise(Object bean, String beanName, Field field, Class interfaceClass) throws IllegalAccessException { + Object fieldValue = field.get(bean); + if (fieldValue == null) { + return; + } + for (Method method : field.getType().getMethods()) { + if (!Modifier.isStatic(method.getModifiers()) && (method.isAnnotationPresent(TwoPhaseBusinessAction.class))) { + RemotingDesc remotingDesc = new RemotingDesc(); + remotingDesc.setInterfaceClass(interfaceClass); + + TccActionInterceptor actionInterceptor = new TccActionInterceptor(remotingDesc); + Object proxyBean = TCCBeanParserUtils.createProxy(interfaceClass, fieldValue, actionInterceptor); + field.setAccessible(true); + field.set(bean, proxyBean); + LOGGER.info("Bean[" + bean.getClass().getName() + "] with name [" + field.getName() + "] would use proxy [" + actionInterceptor.getClass().getName() + "]"); + } + } + } + + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + for (Class<? extends Annotation> annotation : ANNOTATIONS) { + process(bean, beanName, annotation); + } + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + +} + diff --git a/spring/src/main/java/io/seata/spring/util/TCCBeanParserUtils.java b/spring/src/main/java/io/seata/spring/util/TCCBeanParserUtils.java index 4ebd321ad5e478d9730ae8b263bbed45710be528..c45c74b2578b40556032af0046e3dff0ba2f7f0e 100644 --- a/spring/src/main/java/io/seata/spring/util/TCCBeanParserUtils.java +++ b/spring/src/main/java/io/seata/spring/util/TCCBeanParserUtils.java @@ -15,15 +15,17 @@ */ package io.seata.spring.util; -import java.lang.reflect.Method; - import io.seata.rm.tcc.api.TwoPhaseBusinessAction; import io.seata.rm.tcc.remoting.Protocols; import io.seata.rm.tcc.remoting.RemotingDesc; import io.seata.rm.tcc.remoting.RemotingParser; import io.seata.rm.tcc.remoting.parser.DefaultRemotingParser; +import io.seata.spring.tcc.TccActionInterceptor; +import org.springframework.aop.framework.ProxyFactory; import org.springframework.context.ApplicationContext; +import java.lang.reflect.Method; + /** * parser TCC bean * @@ -103,7 +105,7 @@ public class TCCBeanParserUtils { * @param remotingDesc the remoting desc * @return boolean boolean */ - protected static boolean isTccProxyTargetBean(RemotingDesc remotingDesc) { + public static boolean isTccProxyTargetBean(RemotingDesc remotingDesc) { if (remotingDesc == null) { return false; } @@ -156,4 +158,21 @@ public class TCCBeanParserUtils { public static RemotingDesc getRemotingDesc(String beanName) { return DefaultRemotingParser.get().getRemotingBeanDesc(beanName); } + + /** + * Create a proxy bean for tcc service + * + * @param interfaceClass + * @param fieldValue + * @param actionInterceptor + * @return + */ + public static <T> T createProxy(Class<T> interfaceClass, Object fieldValue, TccActionInterceptor actionInterceptor) { + ProxyFactory factory = new ProxyFactory(); + factory.setTarget(fieldValue); + factory.setInterfaces(interfaceClass); + factory.addAdvice(actionInterceptor); + + return (T) factory.getProxy(); + } } diff --git a/spring/src/test/java/io/seata/spring/annotation/MethodDescTest.java b/spring/src/test/java/io/seata/spring/annotation/MethodDescTest.java index 0bee38d99577426f9ac9045d89e2dbea5b432828..afa407b6e834e74c89a2f51a09100d6ddb91a2b8 100644 --- a/spring/src/test/java/io/seata/spring/annotation/MethodDescTest.java +++ b/spring/src/test/java/io/seata/spring/annotation/MethodDescTest.java @@ -17,8 +17,14 @@ package io.seata.spring.annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; - +import io.seata.common.exception.FrameworkException; +import io.seata.core.context.RootContext; +import io.seata.tm.api.transaction.TransactionInfo; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.aop.framework.ProxyFactory; + import static org.assertj.core.api.Assertions.assertThat; @@ -30,6 +36,7 @@ public class MethodDescTest { private static final GlobalTransactionScanner GLOBAL_TRANSACTION_SCANNER = new GlobalTransactionScanner( "global-trans-scanner-test"); private static Method method = null; + private static Class<?> targetClass = null; private static GlobalTransactional transactional = null; public MethodDescTest() throws NoSuchMethodException { @@ -37,6 +44,52 @@ public class MethodDescTest { transactional = method.getAnnotation(GlobalTransactional.class); } + @Test + public void testGetAnnotation() throws NoSuchMethodException { + GlobalTransactionalInterceptor globalTransactionalInterceptor = new GlobalTransactionalInterceptor(null); + Method method = MockBusiness.class.getDeclaredMethod("doBiz", String.class); + targetClass = Mockito.mock(MockBusiness.class).getClass(); + transactional = globalTransactionalInterceptor.getAnnotation(method, targetClass, GlobalTransactional.class); + Assertions.assertEquals(transactional.timeoutMills(), 300000); + method = null; + transactional = globalTransactionalInterceptor.getAnnotation(method, targetClass, GlobalTransactional.class); + Assertions.assertEquals(transactional.timeoutMills(), TransactionInfo.DEFAULT_TIME_OUT * 2); + targetClass = null; + transactional = globalTransactionalInterceptor.getAnnotation(method, targetClass, GlobalTransactional.class); + Assertions.assertNull(transactional); + // only class has Annotation, method is not null + targetClass = Mockito.mock(MockMethodAnnotation.class).getClass(); + method = MockMethodAnnotation.class.getDeclaredMethod("doBiz", String.class); + transactional = globalTransactionalInterceptor.getAnnotation(method, targetClass, GlobalTransactional.class); + Assertions.assertEquals(transactional.name(), "doBiz"); + // only method has Annotation, class is not null + targetClass = Mockito.mock(MockClassAnnotation.class).getClass(); + method = MockClassAnnotation.class.getDeclaredMethod("doBiz", String.class); + transactional = globalTransactionalInterceptor.getAnnotation(method, targetClass, GlobalTransactional.class); + Assertions.assertEquals(transactional.name(), "MockClassAnnotation"); + } + + @Test + public void testGlobalTransactional() throws NoSuchMethodException { + MockClassAnnotation mockClassAnnotation = new MockClassAnnotation(); + ProxyFactory proxyFactory = new ProxyFactory(); + proxyFactory.setTarget(mockClassAnnotation); + proxyFactory.addAdvice(new GlobalTransactionalInterceptor(null)); + Object proxy = proxyFactory.getProxy(); + mockClassAnnotation = (MockClassAnnotation)proxy; + mockClassAnnotation.toString(); + Assertions.assertNull(RootContext.getXID()); + mockClassAnnotation.hashCode(); + Assertions.assertNull(RootContext.getXID()); + mockClassAnnotation.equals("test"); + Assertions.assertNull(RootContext.getXID()); + try { + mockClassAnnotation.doBiz("test"); + } catch (FrameworkException e) { + Assertions.assertEquals("No available service", e.getMessage()); + } + } + @Test public void testGetTransactionAnnotation() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { @@ -80,6 +133,7 @@ public class MethodDescTest { /** * the type mock business */ + @GlobalTransactional(timeoutMills = TransactionInfo.DEFAULT_TIME_OUT * 2) private static class MockBusiness { @GlobalTransactional(timeoutMills = 300000, name = "busi-doBiz") public String doBiz(String msg) { @@ -87,4 +141,24 @@ public class MethodDescTest { } } + /** + * the type mock class annotation + */ + @GlobalTransactional(name = "MockClassAnnotation") + private static class MockClassAnnotation { + public String doBiz(String msg) { + return "hello " + msg; + } + } + + /** + * the type mock method annotation + */ + private static class MockMethodAnnotation { + @GlobalTransactional(name = "doBiz") + public String doBiz(String msg) { + return "hello " + msg; + } + } + } diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/ParametersHolder.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/ParametersHolder.java index 323782980274830b59dfffe377dca9fd4365d5df..5c7f04d42a19ccbacfd761279d3914a9c8701601 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/ParametersHolder.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/ParametersHolder.java @@ -16,6 +16,7 @@ package io.seata.sqlparser; import java.util.ArrayList; +import java.util.Map; /** * The interface Parameters holder. @@ -29,5 +30,5 @@ public interface ParametersHolder { * * @return the array list [ ] */ - ArrayList<Object>[] getParameters(); + Map<Integer,ArrayList<Object>> getParameters(); } diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLInsertRecognizer.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLInsertRecognizer.java index 5262b73398ac9bde49f0adbe3ee07112357691e1..d85396d25bfcaec671d22164985e7f957c2e3518 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/SQLInsertRecognizer.java @@ -15,6 +15,7 @@ */ package io.seata.sqlparser; +import java.util.Collection; import java.util.List; /** @@ -24,6 +25,12 @@ import java.util.List; */ public interface SQLInsertRecognizer extends SQLRecognizer { + /** + * insert columns is empty. + * @return true: empty. false: not empty. + */ + boolean insertColumnsIsEmpty(); + /** * Gets insert columns. * @@ -34,7 +41,8 @@ public interface SQLInsertRecognizer extends SQLRecognizer { /** * Gets insert rows. * + * @param primaryKeyIndex insert sql primary key index. * @return the insert rows */ - List<List<Object>> getInsertRows(); + List<List<Object>> getInsertRows(Collection<Integer> primaryKeyIndex); } diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/Defaultable.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/Defaultable.java new file mode 100644 index 0000000000000000000000000000000000000000..883100046f7edecf53e64bccb50124ad1e4570d6 --- /dev/null +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/Defaultable.java @@ -0,0 +1,34 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.sqlparser.struct; + +import java.sql.SQLException; +import java.util.List; + +/** + * The default expr able. + * @author jsbxyyx + */ +public interface Defaultable { + + /** + * get primary key values by default keyword. + * @return + * @throws SQLException + */ + List<Object> getPkValuesByDefault() throws SQLException; + +} diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/NotPlaceholderExpr.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/NotPlaceholderExpr.java new file mode 100644 index 0000000000000000000000000000000000000000..a60cfbfa103bcda58c77bf4b34da926e6795f577 --- /dev/null +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/NotPlaceholderExpr.java @@ -0,0 +1,44 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.sqlparser.struct; + +/** + * The not placeholder expression. + * @author jsbxyyx + */ +public class NotPlaceholderExpr { + + private static NotPlaceholderExpr instance = new NotPlaceholderExpr(); + + /** + * Get NotPlaceholder. + * + * @return the NotPlaceholder + */ + public static NotPlaceholderExpr get() { + return instance; + } + + private NotPlaceholderExpr() { + } + + @Override + public String toString() { + return "NOT_PLACEHOLDER"; + } + +} diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/Sequenceable.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/Sequenceable.java new file mode 100644 index 0000000000000000000000000000000000000000..9c80ae49dfeff7801ddea3d2e0b13a4dc8389d08 --- /dev/null +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/Sequenceable.java @@ -0,0 +1,31 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.sqlparser.struct; + +/** + * The sequence able. + * @author jsbxyyx + */ +public interface Sequenceable { + + /** + * get sequence sql. + * @param expr + * @return + */ + String getSequenceSql(SqlSequenceExpr expr); + +} diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/SqlDefaultExpr.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/SqlDefaultExpr.java index e79a06a9b683ef08f2d2c8d40183e43f0e3aa20b..6775f65ea09d692d07311e38dfe6afa256e4b81a 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/SqlDefaultExpr.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/SqlDefaultExpr.java @@ -16,6 +16,7 @@ package io.seata.sqlparser.struct; /** + * sql default expression * @author jsbxyyx */ public class SqlDefaultExpr { diff --git a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/SqlMethodExpr.java b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/SqlMethodExpr.java index 7064a40c9d2266f2de024017cc739298a0b1e828..47877ead704a37137ba72f9dd8281aa63cfb5b48 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/SqlMethodExpr.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/io/seata/sqlparser/struct/SqlMethodExpr.java @@ -22,4 +22,23 @@ package io.seata.sqlparser.struct; */ public class SqlMethodExpr { + private static SqlMethodExpr instance = new SqlMethodExpr(); + + /** + * Get SqlMethodExpr. + * + * @return the SqlMethodExpr + */ + public static SqlMethodExpr get() { + return instance; + } + + private SqlMethodExpr() { + } + + @Override + public String toString() { + return "SQL_METHOD"; + } + } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/BaseMySQLRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/BaseMySQLRecognizer.java index 2bb127d336b029f3f745c8aa4774a0f7a3d790d0..77c7c8224bef64ac05c4eda7b83bc3a21066a14e 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/BaseMySQLRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/BaseMySQLRecognizer.java @@ -18,12 +18,10 @@ package io.seata.sqlparser.druid.mysql; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor; - import io.seata.common.util.StringUtils; import io.seata.sqlparser.ParametersHolder; import io.seata.sqlparser.druid.BaseRecognizer; import io.seata.sqlparser.struct.Null; - import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -50,7 +48,7 @@ public abstract class BaseMySQLRecognizer extends BaseRecognizer { @Override public boolean visit(SQLVariantRefExpr x) { if ("?".equals(x.getName())) { - ArrayList<Object> oneParamValues = parametersHolder.getParameters()[x.getIndex()]; + ArrayList<Object> oneParamValues = parametersHolder.getParameters().get(x.getIndex() + 1); if (paramAppenderList.isEmpty()) { oneParamValues.forEach(t -> paramAppenderList.add(new ArrayList<>())); } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLDeleteRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLDeleteRecognizer.java index 29834ada077a37854c098bc5b3ef21fcae7d6347..9cc124df9095bc315dbf9c33403a99a6c450fb90 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLDeleteRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLDeleteRecognizer.java @@ -55,7 +55,10 @@ public class MySQLDeleteRecognizer extends BaseMySQLRecognizer implements SQLDel @Override public String getTableAlias() { - return ast.getTableSource().getAlias(); + if (ast.getFrom() == null) { + return ast.getTableSource().getAlias(); + } + return ast.getFrom().getAlias(); } @Override @@ -69,7 +72,11 @@ public class MySQLDeleteRecognizer extends BaseMySQLRecognizer implements SQLDel return false; } }; - visitor.visit((SQLExprTableSource)ast.getTableSource()); + if (ast.getFrom() == null) { + visitor.visit((SQLExprTableSource) ast.getTableSource()); + } else { + visitor.visit((SQLExprTableSource) ast.getFrom()); + } return sb.toString(); } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLInsertRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLInsertRecognizer.java index d750a2aafee42facb0b02b44ff9e27bc04bf69bc..79c07abe5f57a39ac8a332614e48f2acb67bef09 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/mysql/MySQLInsertRecognizer.java @@ -27,13 +27,16 @@ import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor; +import io.seata.common.util.CollectionUtils; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.SQLParsingException; import io.seata.sqlparser.SQLType; +import io.seata.sqlparser.struct.NotPlaceholderExpr; import io.seata.sqlparser.struct.Null; import io.seata.sqlparser.struct.SqlMethodExpr; import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** @@ -81,6 +84,11 @@ public class MySQLInsertRecognizer extends BaseMySQLRecognizer implements SQLIns return sb.toString(); } + @Override + public boolean insertColumnsIsEmpty() { + return CollectionUtils.isEmpty(ast.getColumns()); + } + @Override public List<String> getInsertColumns() { List<SQLExpr> columnSQLExprs = ast.getColumns(); @@ -100,24 +108,28 @@ public class MySQLInsertRecognizer extends BaseMySQLRecognizer implements SQLIns } @Override - public List<List<Object>> getInsertRows() { + public List<List<Object>> getInsertRows(Collection<Integer> primaryKeyIndex) { List<SQLInsertStatement.ValuesClause> valuesClauses = ast.getValuesList(); List<List<Object>> rows = new ArrayList<>(valuesClauses.size()); for (SQLInsertStatement.ValuesClause valuesClause : valuesClauses) { List<SQLExpr> exprs = valuesClause.getValues(); List<Object> row = new ArrayList<>(exprs.size()); rows.add(row); - for (SQLExpr expr : valuesClause.getValues()) { + for (int i = 0, len = exprs.size(); i < len; i++) { + SQLExpr expr = exprs.get(i); if (expr instanceof SQLNullExpr) { row.add(Null.get()); } else if (expr instanceof SQLValuableExpr) { - row.add(((SQLValuableExpr)expr).getValue()); + row.add(((SQLValuableExpr) expr).getValue()); } else if (expr instanceof SQLVariantRefExpr) { - row.add(((SQLVariantRefExpr)expr).getName()); + row.add(((SQLVariantRefExpr) expr).getName()); } else if (expr instanceof SQLMethodInvokeExpr) { - row.add(new SqlMethodExpr()); + row.add(SqlMethodExpr.get()); } else { - throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr); + if (primaryKeyIndex.contains(i)) { + throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr); + } + row.add(NotPlaceholderExpr.get()); } } } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/BaseOracleRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/BaseOracleRecognizer.java index 5c75a110637a82d9be2aff1ca44f696bf5a14791..0be85bce0f96fc65a76a0dac446505862e250c34 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/BaseOracleRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/BaseOracleRecognizer.java @@ -15,18 +15,16 @@ */ package io.seata.sqlparser.druid.oracle; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; - import io.seata.common.util.StringUtils; import io.seata.sqlparser.ParametersHolder; import io.seata.sqlparser.druid.BaseRecognizer; import io.seata.sqlparser.struct.Null; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; /** * @author will @@ -50,7 +48,7 @@ public abstract class BaseOracleRecognizer extends BaseRecognizer { @Override public boolean visit(SQLVariantRefExpr x) { if ("?".equals(x.getName())) { - ArrayList<Object> oneParamValues = parametersHolder.getParameters()[x.getIndex()]; + ArrayList<Object> oneParamValues = parametersHolder.getParameters().get(x.getIndex() + 1); if (paramAppenderList.isEmpty()) { oneParamValues.forEach(t -> paramAppenderList.add(new ArrayList<>())); } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleInsertRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleInsertRecognizer.java index ab6d074a24764b5a881b000be8ad73f2fc5e7fe9..c913468b6310edb2ec85ae94fde8aeec7540d441 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/oracle/OracleInsertRecognizer.java @@ -16,6 +16,7 @@ package io.seata.sqlparser.druid.oracle; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; @@ -30,9 +31,11 @@ import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; +import io.seata.common.util.CollectionUtils; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.SQLParsingException; import io.seata.sqlparser.SQLType; +import io.seata.sqlparser.struct.NotPlaceholderExpr; import io.seata.sqlparser.struct.Null; import io.seata.sqlparser.struct.SqlMethodExpr; import io.seata.sqlparser.struct.SqlSequenceExpr; @@ -82,6 +85,11 @@ public class OracleInsertRecognizer extends BaseOracleRecognizer implements SQLI return sb.toString(); } + @Override + public boolean insertColumnsIsEmpty() { + return CollectionUtils.isEmpty(ast.getColumns()); + } + @Override public List<String> getInsertColumns() { List<SQLExpr> columnSQLExprs = ast.getColumns(); @@ -101,29 +109,33 @@ public class OracleInsertRecognizer extends BaseOracleRecognizer implements SQLI } @Override - public List<List<Object>> getInsertRows() { + public List<List<Object>> getInsertRows(Collection<Integer> primaryKeyIndex) { List<SQLInsertStatement.ValuesClause> valuesClauses = ast.getValuesList(); List<List<Object>> rows = new ArrayList<>(valuesClauses.size()); for (SQLInsertStatement.ValuesClause valuesClause : valuesClauses) { List<SQLExpr> exprs = valuesClause.getValues(); List<Object> row = new ArrayList<>(exprs.size()); rows.add(row); - for (SQLExpr expr : valuesClause.getValues()) { + for (int i = 0, len = exprs.size(); i < len; i++) { + SQLExpr expr = exprs.get(i); if (expr instanceof SQLNullExpr) { row.add(Null.get()); } else if (expr instanceof SQLValuableExpr) { - row.add(((SQLValuableExpr)expr).getValue()); + row.add(((SQLValuableExpr) expr).getValue()); } else if (expr instanceof SQLVariantRefExpr) { - row.add(((SQLVariantRefExpr)expr).getName()); + row.add(((SQLVariantRefExpr) expr).getName()); } else if (expr instanceof SQLMethodInvokeExpr) { - row.add(new SqlMethodExpr()); + row.add(SqlMethodExpr.get()); } else if (expr instanceof SQLSequenceExpr) { - SQLSequenceExpr sequenceExpr = (SQLSequenceExpr)expr; + SQLSequenceExpr sequenceExpr = (SQLSequenceExpr) expr; String sequence = sequenceExpr.getSequence().getSimpleName(); String function = sequenceExpr.getFunction().name; row.add(new SqlSequenceExpr(sequence, function)); } else { - throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr); + if (primaryKeyIndex.contains(i)) { + throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr); + } + row.add(NotPlaceholderExpr.get()); } } } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/BasePostgresqlRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/BasePostgresqlRecognizer.java index c6811bcc2b84bfdb58058d21ee1674e07860a58c..bc2f29faafeb719f7ea33cdc16fdb99c293dde88 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/BasePostgresqlRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/BasePostgresqlRecognizer.java @@ -47,7 +47,7 @@ public abstract class BasePostgresqlRecognizer extends BaseRecognizer { @Override public boolean visit(SQLVariantRefExpr x) { if ("?".equals(x.getName())) { - ArrayList<Object> oneParamValues = parametersHolder.getParameters()[x.getIndex()]; + ArrayList<Object> oneParamValues = parametersHolder.getParameters().get(x.getIndex() + 1); if (paramAppenderList.size() == 0) { oneParamValues.stream().forEach(t -> paramAppenderList.add(new ArrayList<>())); } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlInsertRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlInsertRecognizer.java index ce39d91a96d5593ed69433e03e7c173dc643f86b..c5ef47927b1fbe87bb94bcb013763de82a436fca 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/io/seata/sqlparser/druid/postgresql/PostgresqlInsertRecognizer.java @@ -28,15 +28,18 @@ import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor; +import io.seata.common.util.CollectionUtils; import io.seata.common.util.StringUtils; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.SQLParsingException; import io.seata.sqlparser.SQLType; +import io.seata.sqlparser.struct.NotPlaceholderExpr; import io.seata.sqlparser.struct.Null; import io.seata.sqlparser.struct.SqlDefaultExpr; import io.seata.sqlparser.struct.SqlMethodExpr; import io.seata.sqlparser.struct.SqlSequenceExpr; import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** @@ -82,6 +85,11 @@ public class PostgresqlInsertRecognizer extends BasePostgresqlRecognizer impleme return sb.toString(); } + @Override + public boolean insertColumnsIsEmpty() { + return CollectionUtils.isEmpty(ast.getColumns()); + } + @Override public List<String> getInsertColumns() { List<SQLExpr> columnSQLExprs = ast.getColumns(); @@ -101,14 +109,15 @@ public class PostgresqlInsertRecognizer extends BasePostgresqlRecognizer impleme } @Override - public List<List<Object>> getInsertRows() { + public List<List<Object>> getInsertRows(Collection<Integer> primaryKeyIndex) { List<SQLInsertStatement.ValuesClause> valuesClauses = ast.getValuesList(); List<List<Object>> rows = new ArrayList<>(valuesClauses.size()); for (SQLInsertStatement.ValuesClause valuesClause : valuesClauses) { List<SQLExpr> exprs = valuesClause.getValues(); List<Object> row = new ArrayList<>(exprs.size()); rows.add(row); - for (SQLExpr expr : valuesClause.getValues()) { + for (int i = 0, len = exprs.size(); i < len; i++) { + SQLExpr expr = exprs.get(i); if (expr instanceof SQLNullExpr) { row.add(Null.get()); } else if (expr instanceof SQLValuableExpr) { @@ -122,7 +131,7 @@ public class PostgresqlInsertRecognizer extends BasePostgresqlRecognizer impleme String sequence = sqlMethodInvokeExpr.getParameters().get(0).toString(); row.add(new SqlSequenceExpr(sequence, function)); } else { - row.add(new SqlMethodExpr()); + row.add(SqlMethodExpr.get()); } } else if (expr instanceof SQLSequenceExpr) { SQLSequenceExpr sequenceExpr = (SQLSequenceExpr) expr; @@ -132,7 +141,10 @@ public class PostgresqlInsertRecognizer extends BasePostgresqlRecognizer impleme } else if (expr instanceof SQLDefaultExpr) { row.add(SqlDefaultExpr.get()); } else { - throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr); + if (primaryKeyIndex.contains(i)) { + throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr); + } + row.add(NotPlaceholderExpr.get()); } } } diff --git a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/AbstractMySQLRecognizerTest.java b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/AbstractRecognizerTest.java similarity index 91% rename from sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/AbstractMySQLRecognizerTest.java rename to sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/AbstractRecognizerTest.java index 7db45cda69409b9ef25a92e75dfc2060cde60344..b6bfb3a275f24a40f0ab2846259c0d2962a28e47 100644 --- a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/AbstractMySQLRecognizerTest.java +++ b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/AbstractRecognizerTest.java @@ -25,7 +25,7 @@ import com.alibaba.druid.sql.ast.SQLStatement; * * @author hanwen created at 2019-01-25 */ -public class AbstractMySQLRecognizerTest { +public abstract class AbstractRecognizerTest { /** * Gets sql statement. @@ -34,8 +34,10 @@ public class AbstractMySQLRecognizerTest { * @return the sql statement */ public SQLStatement getSQLStatement(String sql) { - List<SQLStatement> stats = SQLUtils.parseStatements(sql, "mysql"); + List<SQLStatement> stats = SQLUtils.parseStatements(sql, getDbType()); return stats.get(0); } + public abstract String getDbType(); + } diff --git a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLDeleteRecognizerTest.java b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLDeleteRecognizerTest.java index fce38ac2737d36705e3afbd2891d2d168acf2cc6..9868e92f3ed086378c7d8a167f25936018e34d62 100644 --- a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLDeleteRecognizerTest.java +++ b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLDeleteRecognizerTest.java @@ -15,11 +15,6 @@ */ package io.seata.sqlparser.druid; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; @@ -28,6 +23,12 @@ import io.seata.sqlparser.ParametersHolder; import io.seata.sqlparser.SQLType; import io.seata.sqlparser.druid.mysql.MySQLDeleteRecognizer; import io.seata.sqlparser.util.JdbcConstants; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -36,7 +37,7 @@ import org.junit.jupiter.api.Test; * * @author hanwen created at 2019-01-25 */ -public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest { +public class MySQLDeleteRecognizerTest extends AbstractRecognizerTest { @Test public void testVMarker() { @@ -79,10 +80,12 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest { ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); String whereCondition = mySQLDeleteRecognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> idParam = new ArrayList<>(); idParam.add("id1"); - return new ArrayList[] {idParam}; + Map result = new HashMap<>(); + result.put(1,idParam); + return result; } }, paramAppenderList); @@ -109,12 +112,15 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest { ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); String whereCondition = mySQLDeleteRecognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> idParam = new ArrayList<>(); idParam.add("id1"); ArrayList<Object> id2Param = new ArrayList<>(); id2Param.add("id2"); - return new ArrayList[] {idParam, id2Param}; + Map result = new HashMap(); + result.put(1, idParam); + result.put(2, id2Param); + return result; } }, paramAppenderList); @@ -141,12 +147,15 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest { ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); String whereCondition = mySQLDeleteRecognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> idParam = new ArrayList<>(); idParam.add("id1"); ArrayList<Object> id2Param = new ArrayList<>(); id2Param.add("id2"); - return new ArrayList[] {idParam, id2Param}; + Map result = new HashMap(); + result.put(1, idParam); + result.put(2, id2Param); + return result; } }, paramAppenderList); @@ -180,7 +189,7 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest { MySQLDeleteRecognizer recognizer = new MySQLDeleteRecognizer(sql, asts.get(0)); String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { return null; } }, new ArrayList<>()); @@ -194,10 +203,12 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest { recognizer = new MySQLDeleteRecognizer(sql, asts.get(0)); whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> idParam = new ArrayList<>(); idParam.add(1); - return new ArrayList[] {idParam}; + Map result = new HashMap(); + result.put(1, idParam); + return result; } }, new ArrayList<>()); @@ -209,10 +220,12 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest { recognizer = new MySQLDeleteRecognizer(sql, asts.get(0)); whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> idParam = new ArrayList<>(); idParam.add(1); - return new ArrayList[] {idParam}; + Map result = new HashMap(); + result.put(1, idParam); + return result; } }, new ArrayList<>()); @@ -224,12 +237,15 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest { recognizer = new MySQLDeleteRecognizer(sql, asts.get(0)); whereCondition = recognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> idParam = new ArrayList<>(); idParam.add(1); ArrayList<Object> idParam2 = new ArrayList<>(); idParam.add(2); - return new ArrayList[] {idParam, idParam2}; + Map result = new HashMap(); + result.put(1, idParam); + result.put(2, idParam2); + return result; } }, new ArrayList<>()); //test for sql with in @@ -243,8 +259,8 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest { deleteAst.setWhere(new MySqlOrderingExpr()); new MySQLDeleteRecognizer(s, deleteAst).getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { - return new ArrayList[0]; + public Map<Integer,ArrayList<Object>> getParameters() { + return new HashMap(); } }, new ArrayList<>()); }); @@ -295,4 +311,9 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest { new MySQLDeleteRecognizer(s, deleteAst).getWhereCondition(); }); } + + @Override + public String getDbType() { + return JdbcConstants.MYSQL; + } } diff --git a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLInsertRecognizerTest.java b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLInsertRecognizerTest.java index d258278be56b4d5f3b6ebd55a2d290e25631a2f6..57987c868e47e0bf15ab631bbc7b3684fe9cc909 100644 --- a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLInsertRecognizerTest.java +++ b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLInsertRecognizerTest.java @@ -23,11 +23,11 @@ import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr; -import com.alibaba.druid.util.JdbcConstants; import io.seata.sqlparser.SQLParsingException; import io.seata.sqlparser.SQLType; import io.seata.sqlparser.druid.mysql.MySQLInsertRecognizer; +import io.seata.sqlparser.util.JdbcConstants; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -36,7 +36,9 @@ import org.junit.jupiter.api.Test; * * @author hanwen created at 2019-01-25 */ -public class MySQLInsertRecognizerTest extends AbstractMySQLRecognizerTest { +public class MySQLInsertRecognizerTest extends AbstractRecognizerTest { + + private final int pkIndex = 0; /** * Insert recognizer test 0. @@ -53,8 +55,8 @@ public class MySQLInsertRecognizerTest extends AbstractMySQLRecognizerTest { Assertions.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL()); Assertions.assertEquals("t1", mySQLInsertRecognizer.getTableName()); Assertions.assertEquals(Collections.singletonList("name"), mySQLInsertRecognizer.getInsertColumns()); - Assertions.assertEquals(1, mySQLInsertRecognizer.getInsertRows().size()); - Assertions.assertEquals(Collections.singletonList("name1"), mySQLInsertRecognizer.getInsertRows().get(0)); + Assertions.assertEquals(1, mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).size()); + Assertions.assertEquals(Collections.singletonList("name1"), mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).get(0)); } /** @@ -72,8 +74,8 @@ public class MySQLInsertRecognizerTest extends AbstractMySQLRecognizerTest { Assertions.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL()); Assertions.assertEquals("t1", mySQLInsertRecognizer.getTableName()); Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertColumns()); - Assertions.assertEquals(1, mySQLInsertRecognizer.getInsertRows().size()); - Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertRows().get(0)); + Assertions.assertEquals(1, mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).size()); + Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).get(0)); } /** @@ -91,10 +93,10 @@ public class MySQLInsertRecognizerTest extends AbstractMySQLRecognizerTest { Assertions.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL()); Assertions.assertEquals("t1", mySQLInsertRecognizer.getTableName()); Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertColumns()); - Assertions.assertEquals(3, mySQLInsertRecognizer.getInsertRows().size()); - Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertRows().get(0)); - Assertions.assertEquals(Arrays.asList("name3", "name4"), mySQLInsertRecognizer.getInsertRows().get(1)); - Assertions.assertEquals(Arrays.asList("name5", "name6"), mySQLInsertRecognizer.getInsertRows().get(2)); + Assertions.assertEquals(3, mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).size()); + Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).get(0)); + Assertions.assertEquals(Arrays.asList("name3", "name4"), mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).get(1)); + Assertions.assertEquals(Arrays.asList("name5", "name6"), mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).get(2)); } @Test @@ -153,7 +155,7 @@ public class MySQLInsertRecognizerTest extends AbstractMySQLRecognizerTest { List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); MySQLInsertRecognizer recognizer = new MySQLInsertRecognizer(sql, asts.get(0)); - List<List<Object>> insertRows = recognizer.getInsertRows(); + List<List<Object>> insertRows = recognizer.getInsertRows(Collections.singletonList(pkIndex)); Assertions.assertEquals(1, insertRows.size()); //test for exception @@ -161,11 +163,15 @@ public class MySQLInsertRecognizerTest extends AbstractMySQLRecognizerTest { String s = "insert into t(a) values (?)"; List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, JdbcConstants.MYSQL); SQLInsertStatement sqlInsertStatement = (SQLInsertStatement)sqlStatements.get(0); - sqlInsertStatement.getValuesList().get(0).getValues().add(new MySqlOrderingExpr()); + sqlInsertStatement.getValuesList().get(0).getValues().set(pkIndex, new MySqlOrderingExpr()); - MySQLInsertRecognizer oracleInsertRecognizer = new MySQLInsertRecognizer(s, sqlInsertStatement); - oracleInsertRecognizer.getInsertRows(); + MySQLInsertRecognizer mysqlInsertRecognizer = new MySQLInsertRecognizer(s, sqlInsertStatement); + mysqlInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)); }); } + @Override + public String getDbType() { + return JdbcConstants.MYSQL; + } } diff --git a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLSelectForUpdateRecognizerTest.java b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLSelectForUpdateRecognizerTest.java index c194e8636bc36f81b85273b4b012504b25bd6c42..0e7ff281d16db1a689a15f748e268901c1796192 100644 --- a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLSelectForUpdateRecognizerTest.java +++ b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLSelectForUpdateRecognizerTest.java @@ -15,11 +15,6 @@ */ package io.seata.sqlparser.druid; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; @@ -28,13 +23,19 @@ import io.seata.sqlparser.SQLParsingException; import io.seata.sqlparser.SQLType; import io.seata.sqlparser.druid.mysql.MySQLSelectForUpdateRecognizer; import io.seata.sqlparser.util.JdbcConstants; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * The type My sql select for update recognizer test. */ -public class MySQLSelectForUpdateRecognizerTest extends AbstractMySQLRecognizerTest { +public class MySQLSelectForUpdateRecognizerTest extends AbstractRecognizerTest { /** * Select for update recognizer test 0. @@ -71,10 +72,12 @@ public class MySQLSelectForUpdateRecognizerTest extends AbstractMySQLRecognizerT ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> idParam = new ArrayList<>(); idParam.add("id1"); - return new ArrayList[] {idParam}; + Map result = new HashMap(); + result.put(1, idParam); + return result; } }, paramAppenderList); @@ -101,10 +104,12 @@ public class MySQLSelectForUpdateRecognizerTest extends AbstractMySQLRecognizerT ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> id1Param = new ArrayList<>(); id1Param.add("id1"); - return new ArrayList[] {id1Param}; + Map result = new HashMap(); + result.put(1, id1Param); + return result; } }, paramAppenderList); @@ -131,12 +136,15 @@ public class MySQLSelectForUpdateRecognizerTest extends AbstractMySQLRecognizerT ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> id1Param = new ArrayList<>(); id1Param.add("id1"); ArrayList<Object> id2Param = new ArrayList<>(); id2Param.add("id2"); - return new ArrayList[] {id1Param, id2Param}; + Map result = new HashMap(); + result.put(1, id1Param); + result.put(2, id2Param); + return result; } }, paramAppenderList); @@ -163,12 +171,15 @@ public class MySQLSelectForUpdateRecognizerTest extends AbstractMySQLRecognizerT ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> id1Param = new ArrayList<>(); id1Param.add("id1"); ArrayList<Object> id2Param = new ArrayList<>(); id2Param.add("id2"); - return new ArrayList[] {id1Param, id2Param}; + Map result = new HashMap(); + result.put(1, id1Param); + result.put(2, id2Param); + return result; } }, paramAppenderList); @@ -222,4 +233,9 @@ public class MySQLSelectForUpdateRecognizerTest extends AbstractMySQLRecognizerT MySQLSelectForUpdateRecognizer recognizer = new MySQLSelectForUpdateRecognizer(sql, asts.get(0)); Assertions.assertNull(recognizer.getTableAlias()); } + + @Override + public String getDbType() { + return JdbcConstants.MYSQL; + } } diff --git a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java index 7ce61d8b9daab6b77bae0f89c379466d24fb1cb7..1aaecce66fb69633cb970cc65381ffe083f6d99d 100644 --- a/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java +++ b/sqlparser/seata-sqlparser-druid/src/test/java/io/seata/sqlparser/druid/MySQLUpdateRecognizerTest.java @@ -15,11 +15,6 @@ */ package io.seata.sqlparser.druid; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; @@ -31,13 +26,19 @@ import io.seata.sqlparser.SQLParsingException; import io.seata.sqlparser.SQLType; import io.seata.sqlparser.druid.mysql.MySQLUpdateRecognizer; import io.seata.sqlparser.util.JdbcConstants; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * The type My sql update recognizer test. */ -public class MySQLUpdateRecognizerTest extends AbstractMySQLRecognizerTest { +public class MySQLUpdateRecognizerTest extends AbstractRecognizerTest { /** * Update recognizer test 0. @@ -104,10 +105,12 @@ public class MySQLUpdateRecognizerTest extends AbstractMySQLRecognizerTest { ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> idParam = new ArrayList<>(); idParam.add("id1"); - return new ArrayList[]{idParam}; + Map result = new HashMap(); + result.put(1, idParam); + return result; } }, paramAppenderList); @@ -139,12 +142,15 @@ public class MySQLUpdateRecognizerTest extends AbstractMySQLRecognizerTest { ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> id1Param = new ArrayList<>(); id1Param.add("id1"); ArrayList<Object> id2Param = new ArrayList<>(); id2Param.add("id2"); - return new ArrayList[]{id1Param, id2Param}; + Map result = new HashMap(); + result.put(1, id1Param); + result.put(2, id2Param); + return result; } }, paramAppenderList); @@ -176,14 +182,18 @@ public class MySQLUpdateRecognizerTest extends AbstractMySQLRecognizerTest { ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> id1Param = new ArrayList<>(); id1Param.add("id1"); ArrayList<Object> id2Param = new ArrayList<>(); id2Param.add("id2"); ArrayList<Object> name1Param = new ArrayList<>(); name1Param.add("name"); - return new ArrayList[]{id1Param, id2Param, name1Param}; + Map result = new HashMap(); + result.put(1, id1Param); + result.put(2, id2Param); + result.put(3, name1Param); + return result; } }, paramAppenderList); @@ -215,12 +225,15 @@ public class MySQLUpdateRecognizerTest extends AbstractMySQLRecognizerTest { ArrayList<List<Object>> paramAppenderList = new ArrayList<>(); String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() { @Override - public ArrayList<Object>[] getParameters() { + public Map<Integer,ArrayList<Object>> getParameters() { ArrayList<Object> id1Param = new ArrayList<>(); id1Param.add("id1"); ArrayList<Object> id2Param = new ArrayList<>(); id2Param.add("id2"); - return new ArrayList[]{id1Param, id2Param}; + Map result = new HashMap(); + result.put(1, id1Param); + result.put(2, id2Param); + return result; } }, paramAppenderList); @@ -305,4 +318,9 @@ public class MySQLUpdateRecognizerTest extends AbstractMySQLRecognizerTest { MySQLUpdateRecognizer recognizer = new MySQLUpdateRecognizer(sql, asts.get(0)); Assertions.assertNull(recognizer.getTableAlias()); } + + @Override + public String getDbType() { + return JdbcConstants.MYSQL; + } } diff --git a/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java b/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java index e07cde5a23575b50ab29b50f438577f735919ef2..e149c5912d960fbd62e60fc692e8509560353063 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java +++ b/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java @@ -23,7 +23,6 @@ import java.util.concurrent.ConcurrentHashMap; import com.alibaba.fastjson.JSON; import io.seata.common.Constants; -import io.seata.common.exception.FrameworkException; import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.util.StringUtils; import io.seata.core.exception.TransactionException; @@ -92,24 +91,26 @@ public class TCCResourceManager extends AbstractResourceManager { throw new ShouldNeverHappenException(String.format("TCC resource is not available, resourceId: %s", resourceId)); } try { - boolean result = false; //BusinessActionContext BusinessActionContext businessActionContext = getBusinessActionContext(xid, branchId, resourceId, applicationData); Object ret = commitMethod.invoke(targetTCCBean, businessActionContext); LOGGER.info("TCC resource commit result : {}, xid: {}, branchId: {}, resourceId: {}", ret, xid, branchId, resourceId); + boolean result; if (ret != null) { if (ret instanceof TwoPhaseResult) { result = ((TwoPhaseResult)ret).isSuccess(); } else { result = (boolean)ret; } + } else { + result = true; } return result ? BranchStatus.PhaseTwo_Committed : BranchStatus.PhaseTwo_CommitFailed_Retryable; } catch (Throwable t) { String msg = String.format("commit TCC resource error, resourceId: %s, xid: %s.", resourceId, xid); LOGGER.error(msg, t); - throw new FrameworkException(t, msg); + return BranchStatus.PhaseTwo_CommitFailed_Retryable; } } @@ -137,24 +138,26 @@ public class TCCResourceManager extends AbstractResourceManager { throw new ShouldNeverHappenException(String.format("TCC resource is not available, resourceId: %s", resourceId)); } try { - boolean result = false; //BusinessActionContext BusinessActionContext businessActionContext = getBusinessActionContext(xid, branchId, resourceId, applicationData); Object ret = rollbackMethod.invoke(targetTCCBean, businessActionContext); LOGGER.info("TCC resource rollback result : {}, xid: {}, branchId: {}, resourceId: {}", ret, xid, branchId, resourceId); + boolean result; if (ret != null) { if (ret instanceof TwoPhaseResult) { result = ((TwoPhaseResult)ret).isSuccess(); } else { result = (boolean)ret; } + } else { + result = true; } return result ? BranchStatus.PhaseTwo_Rollbacked : BranchStatus.PhaseTwo_RollbackFailed_Retryable; } catch (Throwable t) { String msg = String.format("rollback TCC resource error, resourceId: %s, xid: %s.", resourceId, xid); LOGGER.error(msg, t); - throw new FrameworkException(t, msg); + return BranchStatus.PhaseTwo_RollbackFailed_Retryable; } } diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java b/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java index 15cdb3d7bf4a620d3f7af0220e39889a2a3618a4..2d4e038a85caa5c47cc5d0dfa58d4a54b02082ae 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java +++ b/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java @@ -61,7 +61,7 @@ public class ActionInterceptorHandler { String actionName = businessAction.name(); BusinessActionContext actionContext = new BusinessActionContext(); actionContext.setXid(xid); - //set action anme + //set action name actionContext.setActionName(actionName); //Creating Branch Record @@ -173,7 +173,7 @@ public class ActionInterceptorHandler { for (int j = 0; j < parameterAnnotations[i].length; j++) { if (parameterAnnotations[i][j] instanceof BusinessActionContextParameter) { BusinessActionContextParameter param = (BusinessActionContextParameter)parameterAnnotations[i][j]; - if (null == arguments[i]) { + if (arguments[i] == null) { throw new IllegalArgumentException("@BusinessActionContextParameter 's params can not null"); } Object paramObject = arguments[i]; diff --git a/test/src/test/java/io/seata/common/ApplicationKeeper.java b/test/src/test/java/io/seata/common/ApplicationKeeper.java index 77af0d9bdda7ecc98f38c3dfaab3af67be793699..63fc11beebb3b05e23e445fa624de5bcd7e0036f 100644 --- a/test/src/test/java/io/seata/common/ApplicationKeeper.java +++ b/test/src/test/java/io/seata/common/ApplicationKeeper.java @@ -68,13 +68,14 @@ public class ApplicationKeeper { * Keep. */ public void keep() { - synchronized (LOCK) { - try { - LOGGER.info("Application is keep running ... "); - LOCK.wait(); - } catch (InterruptedException e) { - LOGGER.error("interrupted error", e); - } + LOCK.lock(); + try { + LOGGER.info("Application is keep running ... "); + STOP.await(); + } catch (InterruptedException e) { + LOGGER.error("interrupted error ", e); + } finally { + LOCK.unlock(); } } } diff --git a/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java b/test/src/test/java/io/seata/core/rpc/netty/TmNettyClientTest.java similarity index 65% rename from test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java rename to test/src/test/java/io/seata/core/rpc/netty/TmNettyClientTest.java index 18c4f7bbcc163b423af4bc3b54b613be7f117c36..eeb84f575e0a9e8c48050dcd35dd8f6258ab5689 100644 --- a/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java +++ b/test/src/test/java/io/seata/core/rpc/netty/TmNettyClientTest.java @@ -20,13 +20,12 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import io.seata.server.UUIDGenerator; -import io.seata.server.coordinator.DefaultCoordinator; - import io.netty.channel.Channel; import io.seata.core.protocol.ResultCode; import io.seata.core.protocol.transaction.BranchRegisterRequest; import io.seata.core.protocol.transaction.BranchRegisterResponse; +import io.seata.server.UUIDGenerator; +import io.seata.server.coordinator.DefaultCoordinator; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -35,7 +34,7 @@ import org.junit.jupiter.api.Test; * @author slievrly */ @Disabled -public class TmRpcClientTest { +public class TmNettyClientTest { private static final ThreadPoolExecutor workingThreads = new ThreadPoolExecutor(100, 500, 500, TimeUnit.SECONDS, @@ -53,10 +52,10 @@ public class TmRpcClientTest { workingThreads.submit(new Runnable() { @Override public void run() { - RpcServer rpcServer = new RpcServer(workingThreads); - rpcServer.setHandler(new DefaultCoordinator(rpcServer)); - UUIDGenerator.init(1); - rpcServer.init(); + NettyRemotingServer nettyRemotingServer = new NettyRemotingServer(workingThreads); + nettyRemotingServer.setHandler(new DefaultCoordinator(nettyRemotingServer)); + UUIDGenerator.init(1L); + nettyRemotingServer.init(); } }); @@ -65,14 +64,14 @@ public class TmRpcClientTest { String applicationId = "app 1"; String transactionServiceGroup = "group A"; - TmRpcClient tmRpcClient = TmRpcClient.getInstance(applicationId, transactionServiceGroup); + TmNettyRemotingClient tmNettyRemotingClient = TmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup); - tmRpcClient.init(); + tmNettyRemotingClient.init(); - Method doConnectMethod = TmRpcClient.class.getDeclaredMethod("doConnect", String.class); + Method doConnectMethod = TmNettyRemotingClient.class.getDeclaredMethod("doConnect", String.class); doConnectMethod.setAccessible(true); String serverAddress = "0.0.0.0:8091"; - Channel channel = (Channel) doConnectMethod.invoke(tmRpcClient, serverAddress); + Channel channel = (Channel) doConnectMethod.invoke(tmNettyRemotingClient, serverAddress); Assertions.assertNotNull(channel); } @@ -88,10 +87,10 @@ public class TmRpcClientTest { workingThreads.submit(new Runnable() { @Override public void run() { - RpcServer rpcServer = new RpcServer(workingThreads); - rpcServer.setHandler(new DefaultCoordinator(rpcServer)); - UUIDGenerator.init(1); - rpcServer.init(); + NettyRemotingServer nettyRemotingServer = new NettyRemotingServer(workingThreads); + nettyRemotingServer.setHandler(new DefaultCoordinator(nettyRemotingServer)); + UUIDGenerator.init(1L); + nettyRemotingServer.init(); } }); @@ -100,13 +99,13 @@ public class TmRpcClientTest { String applicationId = "app 1"; String transactionServiceGroup = "my_test_tx_group"; - TmRpcClient tmRpcClient = TmRpcClient.getInstance(applicationId, transactionServiceGroup); + TmNettyRemotingClient tmNettyRemotingClient = TmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup); - tmRpcClient.init(); + tmNettyRemotingClient.init(); - Method doConnectMethod = TmRpcClient.class.getDeclaredMethod("reconnect"); + Method doConnectMethod = TmNettyRemotingClient.class.getDeclaredMethod("reconnect"); doConnectMethod.setAccessible(true); - doConnectMethod.invoke(tmRpcClient); + doConnectMethod.invoke(tmNettyRemotingClient); } @Test @@ -114,30 +113,30 @@ public class TmRpcClientTest { workingThreads.submit(new Runnable() { @Override public void run() { - RpcServer rpcServer = new RpcServer(workingThreads); - rpcServer.setHandler(new DefaultCoordinator(rpcServer)); - UUIDGenerator.init(1); - rpcServer.init(); + NettyRemotingServer nettyRemotingServer = new NettyRemotingServer(workingThreads); + nettyRemotingServer.setHandler(new DefaultCoordinator(nettyRemotingServer)); + UUIDGenerator.init(1L); + nettyRemotingServer.init(); } }); Thread.sleep(3000); String applicationId = "app 1"; String transactionServiceGroup = "my_test_tx_group"; - TmRpcClient tmRpcClient = TmRpcClient.getInstance(applicationId, transactionServiceGroup); - tmRpcClient.init(); + TmNettyRemotingClient tmNettyRemotingClient = TmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup); + tmNettyRemotingClient.init(); - Method doConnectMethod = TmRpcClient.class.getDeclaredMethod("doConnect", String.class); + Method doConnectMethod = TmNettyRemotingClient.class.getDeclaredMethod("doConnect", String.class); doConnectMethod.setAccessible(true); String serverAddress = "0.0.0.0:8091"; - Channel channel = (Channel) doConnectMethod.invoke(tmRpcClient, serverAddress); + Channel channel = (Channel) doConnectMethod.invoke(tmNettyRemotingClient, serverAddress); Assertions.assertNotNull(channel); BranchRegisterRequest request = new BranchRegisterRequest(); request.setXid("127.0.0.1:8091:1249853"); request.setLockKey("lock key testSendMsgWithResponse"); request.setResourceId("resoutceId1"); - BranchRegisterResponse branchRegisterResponse = (BranchRegisterResponse)tmRpcClient.sendMsgWithResponse(request); + BranchRegisterResponse branchRegisterResponse = (BranchRegisterResponse) tmNettyRemotingClient.sendSyncRequest(request); Assertions.assertNotNull(branchRegisterResponse); Assertions.assertEquals(ResultCode.Failed, branchRegisterResponse.getResultCode()); Assertions.assertEquals("RuntimeException[SessionManager is NOT init!]", diff --git a/test/src/test/java/io/seata/core/rpc/netty/v1/ProtocolV1Client.java b/test/src/test/java/io/seata/core/rpc/netty/v1/ProtocolV1Client.java index fef0a4484ce684d01eda5bcfd4df689ce9f88e0a..3b3c8c39894e6628ce715e6e3a1bab3fbe2be0ab 100644 --- a/test/src/test/java/io/seata/core/rpc/netty/v1/ProtocolV1Client.java +++ b/test/src/test/java/io/seata/core/rpc/netty/v1/ProtocolV1Client.java @@ -122,7 +122,7 @@ public class ProtocolV1Client { rpcMessage.setCompressor(ProtocolConstants.CONFIGURED_COMPRESSOR); rpcMessage.setHeadMap(head); rpcMessage.setBody(body); - rpcMessage.setMessageType(ProtocolConstants.MSGTYPE_RESQUEST); + rpcMessage.setMessageType(ProtocolConstants.MSGTYPE_RESQUEST_SYNC); if (channel != null) { DefaultPromise promise = new DefaultPromise(defaultEventExecutor); diff --git a/test/src/test/java/io/seata/saga/engine/StateMachineAsyncTests.java b/test/src/test/java/io/seata/saga/engine/StateMachineAsyncTests.java index 5ec0bb89bfd497c90f19e33e2f2cac5b40a2c269..ea71c40d5979dc959a20776e462413b73a5237b2 100644 --- a/test/src/test/java/io/seata/saga/engine/StateMachineAsyncTests.java +++ b/test/src/test/java/io/seata/saga/engine/StateMachineAsyncTests.java @@ -64,6 +64,51 @@ public class StateMachineAsyncTests { Assertions.assertTrue(ExecutionStatus.FA.equals(inst.getStatus())); } + @Test + public void testSimpleScriptTaskStateMachine() { + + long start = System.currentTimeMillis(); + + Map<String, Object> paramMap = new HashMap<>(1); + paramMap.put("a", 1); + + String stateMachineName = "simpleScriptTaskStateMachine"; + + StateMachineInstance inst = stateMachineEngine.start(stateMachineName, null, paramMap); + + waittingForFinish(inst); + + long cost = System.currentTimeMillis() - start; + System.out.println("====== cost :" + cost); + + Assertions.assertTrue(ExecutionStatus.SU.equals(inst.getStatus())); + Assertions.assertNotNull(inst.getEndParams().get("scriptStateResult")); + + + start = System.currentTimeMillis(); + + inst = stateMachineEngine.start(stateMachineName, null, paramMap); + + waittingForFinish(inst); + + cost = System.currentTimeMillis() - start; + System.out.println("====== cost :" + cost); + + Assertions.assertTrue(ExecutionStatus.SU.equals(inst.getStatus())); + + + start = System.currentTimeMillis(); + paramMap.put("scriptThrowException", true); + inst = stateMachineEngine.start(stateMachineName, null, paramMap); + + waittingForFinish(inst); + + cost = System.currentTimeMillis() - start; + System.out.println("====== cost :" + cost); + + Assertions.assertTrue(ExecutionStatus.FA.equals(inst.getStatus())); + } + @Test public void testSimpleRetryStateMachine() { diff --git a/test/src/test/java/io/seata/saga/engine/StateMachineTests.java b/test/src/test/java/io/seata/saga/engine/StateMachineTests.java index 42c64d126637f519578de7447560fa1403257e4d..95368d345fa5a430bcc5a185a4b1f11f154ded1f 100644 --- a/test/src/test/java/io/seata/saga/engine/StateMachineTests.java +++ b/test/src/test/java/io/seata/saga/engine/StateMachineTests.java @@ -141,6 +141,45 @@ public class StateMachineTests { Assertions.assertTrue(ExecutionStatus.FA.equals(inst.getStatus())); } + @Test + public void testSimpleScriptTaskStateMachine() { + + long start = System.currentTimeMillis(); + + Map<String, Object> paramMap = new HashMap<>(1); + paramMap.put("a", 1); + + String stateMachineName = "simpleScriptTaskStateMachine"; + + StateMachineInstance inst = stateMachineEngine.start(stateMachineName, null, paramMap); + + long cost = System.currentTimeMillis() - start; + System.out.println("====== cost :" + cost); + + Assertions.assertTrue(ExecutionStatus.SU.equals(inst.getStatus())); + Assertions.assertNotNull(inst.getEndParams().get("scriptStateResult")); + + + start = System.currentTimeMillis(); + + inst = stateMachineEngine.start(stateMachineName, null, paramMap); + + cost = System.currentTimeMillis() - start; + System.out.println("====== cost :" + cost); + + Assertions.assertTrue(ExecutionStatus.SU.equals(inst.getStatus())); + + + start = System.currentTimeMillis(); + paramMap.put("scriptThrowException", true); + inst = stateMachineEngine.start(stateMachineName, null, paramMap); + + cost = System.currentTimeMillis() - start; + System.out.println("====== cost :" + cost); + + Assertions.assertTrue(ExecutionStatus.FA.equals(inst.getStatus())); + } + @Test public void testSimpleRetryStateMachine() { diff --git a/test/src/test/java/io/seata/saga/engine/db/AbstractServerTest.java b/test/src/test/java/io/seata/saga/engine/db/AbstractServerTest.java index e88c8231d299898a62982d3dcf2f94e315d89406..31c7624662dd27453f0722d4b6b06566bcf75f71 100644 --- a/test/src/test/java/io/seata/saga/engine/db/AbstractServerTest.java +++ b/test/src/test/java/io/seata/saga/engine/db/AbstractServerTest.java @@ -18,8 +18,8 @@ package io.seata.saga.engine.db; import io.seata.common.XID; import io.seata.common.util.NetUtil; import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.rpc.netty.RpcServer; -import io.seata.core.rpc.netty.ShutdownHook; +import io.seata.core.rpc.ShutdownHook; +import io.seata.core.rpc.netty.NettyRemotingServer; import io.seata.server.ParameterParser; import io.seata.server.UUIDGenerator; import io.seata.server.coordinator.DefaultCoordinator; @@ -40,7 +40,7 @@ import java.util.concurrent.TimeUnit; public abstract class AbstractServerTest { - private static RpcServer rpcServer; + private static NettyRemotingServer nettyServer; private static final ThreadPoolExecutor workingThreads = new ThreadPoolExecutor(100, 500, 500, TimeUnit.SECONDS, new LinkedBlockingQueue(20000), new ThreadPoolExecutor.CallerRunsPolicy()); @@ -61,16 +61,16 @@ public abstract class AbstractServerTest { System.setProperty(ConfigurationKeys.STORE_MODE, parameterParser.getStoreMode()); - rpcServer = new RpcServer(workingThreads); + nettyServer = new NettyRemotingServer(workingThreads); //server port - rpcServer.setListenPort(parameterParser.getPort()); + nettyServer.setListenPort(parameterParser.getPort()); UUIDGenerator.init(parameterParser.getServerNode()); //log store mode : file、db SessionHolder.init(parameterParser.getStoreMode()); - DefaultCoordinator coordinator = new DefaultCoordinator(rpcServer); + DefaultCoordinator coordinator = new DefaultCoordinator(nettyServer); coordinator.init(); - rpcServer.setHandler(coordinator); + nettyServer.setHandler(coordinator); // register ShutdownHook ShutdownHook.getInstance().addDisposable(coordinator); @@ -80,9 +80,9 @@ public abstract class AbstractServerTest { } else { XID.setIpAddress(NetUtil.getLocalIp()); } - XID.setPort(rpcServer.getListenPort()); + XID.setPort(nettyServer.getListenPort()); - rpcServer.init(); + nettyServer.init(); } catch (IOException e) { throw new RuntimeException(e); } @@ -92,8 +92,8 @@ public abstract class AbstractServerTest { } protected static final void stopSeataServer() throws InterruptedException { - if(rpcServer != null){ - rpcServer.destroy(); + if(nettyServer != null){ + nettyServer.destroy(); Thread.sleep(5000); } } diff --git a/test/src/test/java/io/seata/saga/engine/db/StateMachineDBTests.java b/test/src/test/java/io/seata/saga/engine/db/StateMachineDBTests.java index ce6983f8d5aa76cf67b48d4a7cfccf927483534b..675660a04c3ba0bd8350f4ff519ed8500d86d925 100644 --- a/test/src/test/java/io/seata/saga/engine/db/StateMachineDBTests.java +++ b/test/src/test/java/io/seata/saga/engine/db/StateMachineDBTests.java @@ -378,10 +378,6 @@ public class StateMachineDBTests extends AbstractServerTest { Assertions.assertNotNull(inst.getException()); Assertions.assertTrue(ExecutionStatus.FA.equals(inst.getStatus())); - - GlobalTransaction globalTransaction = getGlobalTransaction(inst); - Assertions.assertNotNull(globalTransaction); - Assertions.assertTrue(GlobalStatus.Finished.equals(globalTransaction.getStatus())); } @Test @@ -460,6 +456,7 @@ public class StateMachineDBTests extends AbstractServerTest { } @Test + @Disabled("https://github.com/seata/seata/issues/2414#issuecomment-639546811") public void simpleChoiceTestStateMachineAsyncConcurrently() throws Exception { final CountDownLatch countDownLatch = new CountDownLatch(100); @@ -514,6 +511,7 @@ public class StateMachineDBTests extends AbstractServerTest { } @Test + @Disabled("https://github.com/seata/seata/issues/2414#issuecomment-651526068") public void testCompensationAndSubStateMachineAsync() throws Exception { long start = System.currentTimeMillis(); @@ -539,6 +537,7 @@ public class StateMachineDBTests extends AbstractServerTest { } @Test + @Disabled("https://github.com/seata/seata/issues/2414#issuecomment-640432396") public void testCompensationAndSubStateMachineAsyncWithLayout() throws Exception { long start = System.currentTimeMillis(); diff --git a/test/src/test/java/io/seata/saga/engine/db/mockserver/StateMachineDBMockServerTests.java b/test/src/test/java/io/seata/saga/engine/db/mockserver/StateMachineDBMockServerTests.java index 2cdf62feae8bdd05786f3c8c2f2c789e75574c76..cd6a458d4ef87b94bd6ddb46367185e540f46d02 100644 --- a/test/src/test/java/io/seata/saga/engine/db/mockserver/StateMachineDBMockServerTests.java +++ b/test/src/test/java/io/seata/saga/engine/db/mockserver/StateMachineDBMockServerTests.java @@ -21,6 +21,8 @@ import io.seata.saga.engine.mock.DemoService.People; import io.seata.saga.statelang.domain.DomainConstants; import io.seata.saga.statelang.domain.ExecutionStatus; import io.seata.saga.statelang.domain.StateMachineInstance; +import io.seata.saga.statelang.parser.JsonParser; +import io.seata.saga.statelang.parser.JsonParserFactory; import io.seata.saga.statelang.parser.utils.DesignerJsonTransformer; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -152,6 +154,45 @@ public class StateMachineDBMockServerTests { Assertions.assertTrue(ExecutionStatus.FA.equals(inst.getStatus())); } + @Test + public void testSimpleScriptTaskStateMachineWithLayout() { + + long start = System.currentTimeMillis(); + + Map<String, Object> paramMap = new HashMap<>(1); + paramMap.put("a", 1); + + String stateMachineName = "designerSimpleScriptTaskStateMachine"; + + StateMachineInstance inst = stateMachineEngine.start(stateMachineName, null, paramMap); + + long cost = System.currentTimeMillis() - start; + System.out.println("====== cost :" + cost); + + Assertions.assertTrue(ExecutionStatus.SU.equals(inst.getStatus())); + Assertions.assertNotNull(inst.getEndParams().get("scriptStateResult")); + + + start = System.currentTimeMillis(); + + inst = stateMachineEngine.start(stateMachineName, null, paramMap); + + cost = System.currentTimeMillis() - start; + System.out.println("====== cost :" + cost); + + Assertions.assertTrue(ExecutionStatus.SU.equals(inst.getStatus())); + + + start = System.currentTimeMillis(); + paramMap.put("scriptThrowException", true); + inst = stateMachineEngine.start(stateMachineName, null, paramMap); + + cost = System.currentTimeMillis() - start; + System.out.println("====== cost :" + cost); + + Assertions.assertTrue(ExecutionStatus.FA.equals(inst.getStatus())); + } + @Test public void testSimpleRetryStateMachine() { @@ -317,7 +358,8 @@ public class StateMachineDBMockServerTests { Assertions.assertTrue(ExecutionStatus.UN.equals(inst.getStatus())); - String graphJson = DesignerJsonTransformer.generateTracingGraphJson(inst); + JsonParser jsonParser = JsonParserFactory.getJsonParser("jackson"); + String graphJson = DesignerJsonTransformer.generateTracingGraphJson(inst, jsonParser); Assertions.assertNotNull(graphJson); System.out.println(graphJson); @@ -331,7 +373,7 @@ public class StateMachineDBMockServerTests { Assertions.assertTrue(ExecutionStatus.SU.equals(inst.getStatus())); - String graphJson2 = DesignerJsonTransformer.generateTracingGraphJson(inst); + String graphJson2 = DesignerJsonTransformer.generateTracingGraphJson(inst, jsonParser); Assertions.assertNotNull(graphJson2); System.out.println(graphJson2); } @@ -384,7 +426,8 @@ public class StateMachineDBMockServerTests { Assertions.assertTrue(ExecutionStatus.UN.equals(inst.getStatus())); - String graphJson = DesignerJsonTransformer.generateTracingGraphJson(inst); + JsonParser jsonParser = JsonParserFactory.getJsonParser("jackson"); + String graphJson = DesignerJsonTransformer.generateTracingGraphJson(inst, jsonParser); Assertions.assertNotNull(graphJson); System.out.println(graphJson); @@ -397,7 +440,7 @@ public class StateMachineDBMockServerTests { Assertions.assertTrue(ExecutionStatus.UN.equals(inst.getCompensationStatus())); - String graphJson2 = DesignerJsonTransformer.generateTracingGraphJson(inst); + String graphJson2 = DesignerJsonTransformer.generateTracingGraphJson(inst, jsonParser); Assertions.assertNotNull(graphJson2); System.out.println(graphJson2); } diff --git a/test/src/test/java/io/seata/saga/engine/mock/MockSagaTransactionTemplate.java b/test/src/test/java/io/seata/saga/engine/mock/MockSagaTransactionTemplate.java index 1cbe035610af5f47ba8282f53db8d41d158c8586..7a4a9866575bf34543238875bbd1bfabcdf90efe 100644 --- a/test/src/test/java/io/seata/saga/engine/mock/MockSagaTransactionTemplate.java +++ b/test/src/test/java/io/seata/saga/engine/mock/MockSagaTransactionTemplate.java @@ -30,10 +30,6 @@ import io.seata.tm.api.transaction.TransactionInfo; */ public class MockSagaTransactionTemplate implements SagaTransactionalTemplate { - static { - UUIDGenerator.init(0); - } - @Override public void commitTransaction(GlobalTransaction tx) throws ExecutionException { diff --git a/test/src/test/java/io/seata/saga/engine/mock/MockStateHandlerInterceptor.java b/test/src/test/java/io/seata/saga/engine/mock/MockStateHandlerInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..5fb9b149a5baa9871202420fa773ac359eccd8b9 --- /dev/null +++ b/test/src/test/java/io/seata/saga/engine/mock/MockStateHandlerInterceptor.java @@ -0,0 +1,47 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.engine.mock; + +import io.seata.saga.engine.exception.EngineExecutionException; +import io.seata.saga.engine.pcext.InterceptableStateHandler; +import io.seata.saga.engine.pcext.StateHandlerInterceptor; +import io.seata.saga.proctrl.ProcessContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author lorne.cl + */ +public class MockStateHandlerInterceptor implements StateHandlerInterceptor { + + private static final Logger LOGGER = LoggerFactory.getLogger(MockStateHandlerInterceptor.class); + + @Override + public void preProcess(ProcessContext context) throws EngineExecutionException { + LOGGER.info("test StateHandlerInterceptor preProcess"); + } + + @Override + public void postProcess(ProcessContext context, Exception e) throws EngineExecutionException { + LOGGER.info("test StateHandlerInterceptor postProcess"); + } + + @Override + public boolean match(Class<? extends InterceptableStateHandler> clazz) { + return true; + } +} \ No newline at end of file diff --git a/test/src/test/java/io/seata/saga/engine/mock/MockStateRouterInterceptor.java b/test/src/test/java/io/seata/saga/engine/mock/MockStateRouterInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..4e8ae23462d55c33ffc8f41f324508ddc480d181 --- /dev/null +++ b/test/src/test/java/io/seata/saga/engine/mock/MockStateRouterInterceptor.java @@ -0,0 +1,49 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache 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 + * + * http://www.apache.org/licenses/LICENSE-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 io.seata.saga.engine.mock; + +import io.seata.saga.engine.exception.EngineExecutionException; +import io.seata.saga.engine.pcext.InterceptableStateRouter; +import io.seata.saga.engine.pcext.StateRouterInterceptor; +import io.seata.saga.proctrl.Instruction; +import io.seata.saga.proctrl.ProcessContext; +import io.seata.saga.statelang.domain.State; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author lorne.cl + */ +public class MockStateRouterInterceptor implements StateRouterInterceptor { + + private static final Logger LOGGER = LoggerFactory.getLogger(MockStateRouterInterceptor.class); + + @Override + public void preRoute(ProcessContext context, State state) throws EngineExecutionException { + LOGGER.info("test StateRouterInterceptor preRoute"); + } + + @Override + public void postRoute(ProcessContext context, State state, Instruction instruction, Exception e) throws EngineExecutionException { + LOGGER.info("test StateRouterInterceptor postRoute"); + } + + @Override + public boolean match(Class<? extends InterceptableStateRouter> clazz) { + return true; + } +} \ No newline at end of file diff --git a/test/src/test/resources/META-INF/services/io.seata.saga.engine.pcext.StateHandlerInterceptor b/test/src/test/resources/META-INF/services/io.seata.saga.engine.pcext.StateHandlerInterceptor new file mode 100644 index 0000000000000000000000000000000000000000..2afce0bbcac7f4371a313cae3649ded003f942c9 --- /dev/null +++ b/test/src/test/resources/META-INF/services/io.seata.saga.engine.pcext.StateHandlerInterceptor @@ -0,0 +1 @@ +io.seata.saga.engine.mock.MockStateHandlerInterceptor \ No newline at end of file diff --git a/test/src/test/resources/META-INF/services/io.seata.saga.engine.pcext.StateRouterInterceptor b/test/src/test/resources/META-INF/services/io.seata.saga.engine.pcext.StateRouterInterceptor new file mode 100644 index 0000000000000000000000000000000000000000..80512fac6c456ff4ba6b655784fb14e75714c880 --- /dev/null +++ b/test/src/test/resources/META-INF/services/io.seata.saga.engine.pcext.StateRouterInterceptor @@ -0,0 +1 @@ +io.seata.saga.engine.mock.MockStateRouterInterceptor \ No newline at end of file diff --git a/test/src/test/resources/file.conf b/test/src/test/resources/file.conf index be56f56e607829f7c3c47aa3ad0100d288aeadc2..e9fb03b76016208df9a921e59352117beb6a4178 100644 --- a/test/src/test/resources/file.conf +++ b/test/src/test/resources/file.conf @@ -10,6 +10,7 @@ service { client { rm { reportSuccessEnable = false - sagaBranchRegisterEnable = false; + sagaBranchRegisterEnable = false + sagaJsonParser = jackson } } \ No newline at end of file diff --git a/test/src/test/resources/saga/spring/statemachine_engine_db_test.xml b/test/src/test/resources/saga/spring/statemachine_engine_db_test.xml index a35be0c468764d237911ace193aba3b3330eabf9..83bd60ae51bb5fd0402104067db16847a185f85b 100644 --- a/test/src/test/resources/saga/spring/statemachine_engine_db_test.xml +++ b/test/src/test/resources/saga/spring/statemachine_engine_db_test.xml @@ -51,6 +51,7 @@ <property name="applicationId" value="test_saga"></property> <property name="txServiceGroup" value="my_test_tx_group"></property> <property name="sagaBranchRegisterEnable" value="false"></property> + <property name="sagaJsonParser" value="jackson"></property> </bean> <bean id="threadExecutor" diff --git a/test/src/test/resources/saga/statelang/designer_simple_statelang_with_script.json b/test/src/test/resources/saga/statelang/designer_simple_statelang_with_script.json new file mode 100644 index 0000000000000000000000000000000000000000..c4f21d26cc4d150452e5f85ea1ecad23476a00f2 --- /dev/null +++ b/test/src/test/resources/saga/statelang/designer_simple_statelang_with_script.json @@ -0,0 +1,260 @@ +{ + "nodes": [ + { + "type": "node", + "size": "72*72", + "shape": "flow-circle", + "color": "#FA8C16", + "label": "Start", + "stateId": "Start1", + "stateType": "Start", + "stateProps": { + "StateMachine": { + "Name": "designerSimpleScriptTaskStateMachine", + "Comment": "带ScriptTask的测试状态机定义", + "Version": "0.0.1" + } + }, + "x": 318.875, + "y": 102, + "id": "9e56dbe7" + }, + { + "type": "node", + "size": "110*48", + "shape": "flow-rect", + "color": "#1890FF", + "label": "FirstState", + "stateId": "FirstState", + "stateType": "ServiceTask", + "stateProps": { + "ServiceName": "demoService", + "ServiceMethod": "foo", + "Input": [ + { + "fooInput": "$.[a]" + } + ], + "Output": { + "fooResult": "$.#root" + } + }, + "x": 318.875, + "y": 202, + "id": "d1d71346" + }, + { + "type": "node", + "size": "110*48", + "shape": "flow-rect", + "color": "#13C2C2", + "label": "ScriptState", + "stateId": "ScriptState", + "stateType": "ScriptTask", + "stateProps": { + "ScriptType": "groovy", + "ScriptContent": "if(throwException){ throw new RuntimeException(\"test\") } else { 'hello ' + inputA }", + "Input": [ + { + "inputA": "$.[a]", + "throwException": "$.[scriptThrowException]" + } + ], + "Output": { + "scriptStateResult": "$.#root" + } + }, + "x": 319.375, + "y": 290.5, + "id": "898649d3" + }, + { + "type": "node", + "size": "80*72", + "shape": "flow-rhombus", + "color": "#13C2C2", + "label": "Choice", + "stateId": "Choice1", + "stateType": "Choice", + "x": 318.875, + "y": 394.5, + "id": "39859d0b" + }, + { + "type": "node", + "size": "110*48", + "shape": "flow-rect", + "color": "#1890FF", + "label": "SecondState", + "stateId": "SecondState", + "stateType": "ServiceTask", + "stateProps": { + "ServiceName": "demoService", + "ServiceMethod": "bar", + "Input": [ + { + "barInput": "$.[fooResult]" + } + ], + "Output": { + "barResult": "$.#root" + } + }, + "x": 173.375, + "y": 493.49999999999994, + "id": "c65f1c20" + }, + { + "type": "node", + "size": "110*48", + "shape": "flow-rect", + "color": "#1890FF", + "label": "ThirdState", + "stateId": "ThirdState", + "stateType": "ServiceTask", + "stateProps": { + "ServiceName": "demoService", + "ServiceMethod": "foo", + "Input": [ + { + "fooInput": "$.[fooResult]" + } + ], + "Output": { + "fooResult": "$.#root" + } + }, + "x": 318.875, + "y": 492.99999999999994, + "id": "5857047e" + }, + { + "type": "node", + "size": "72*72", + "shape": "flow-circle", + "color": "#05A465", + "label": "Succeed", + "stateId": "Succeed1", + "stateType": "Succeed", + "x": 318.875, + "y": 592, + "id": "18bba9a0" + }, + { + "type": "node", + "size": "72*72", + "shape": "flow-circle", + "color": "red", + "label": "Fail", + "stateId": "Fail1", + "stateType": "Fail", + "stateProps": { + "ErrorCode": "", + "Message": "" + }, + "x": 474.57499999999993, + "y": 499.99999999999994, + "id": "95def921" + }, + { + "type": "node", + "size": "39*39", + "shape": "flow-circle", + "color": "red", + "label": "Catch", + "stateId": "Catch1", + "stateType": "Catch", + "x": 374.375, + "y": 315, + "id": "e264be2d" + } + ], + "edges": [ + { + "source": "9e56dbe7", + "sourceAnchor": 2, + "target": "d1d71346", + "targetAnchor": 0, + "id": "594d5078" + }, + { + "source": "d1d71346", + "sourceAnchor": 2, + "target": "898649d3", + "targetAnchor": 0, + "id": "e1f56d5c" + }, + { + "source": "898649d3", + "sourceAnchor": 2, + "target": "39859d0b", + "targetAnchor": 0, + "id": "d25b97b3" + }, + { + "source": "39859d0b", + "sourceAnchor": 3, + "target": "c65f1c20", + "targetAnchor": 0, + "id": "d957fcff", + "stateProps": { + "Expression": "[a] == 1", + "Default": false + }, + "label": "", + "shape": "flow-smooth" + }, + { + "source": "39859d0b", + "sourceAnchor": 2, + "target": "5857047e", + "targetAnchor": 0, + "id": "d7053595", + "stateProps": { + "Expression": "[a] == 2", + "Default": false + }, + "label": "", + "shape": "flow-smooth" + }, + { + "source": "e264be2d", + "sourceAnchor": 1, + "target": "95def921", + "targetAnchor": 0, + "id": "39925f4b", + "stateProps": { + "Exceptions": [ + "java.lang.Throwable" + ] + } + }, + { + "source": "39859d0b", + "sourceAnchor": 1, + "target": "95def921", + "targetAnchor": 0, + "id": "5500c8da", + "stateProps": { + "Expression": "", + "Default": true + }, + "label": "", + "shape": "flow-smooth" + }, + { + "source": "c65f1c20", + "sourceAnchor": 2, + "target": "18bba9a0", + "targetAnchor": 3, + "id": "33832e0d" + }, + { + "source": "5857047e", + "sourceAnchor": 2, + "target": "18bba9a0", + "targetAnchor": 0, + "id": "1191f8f0" + } + ] +} \ No newline at end of file diff --git a/test/src/test/resources/saga/statelang/simple_statelang_with_script.json b/test/src/test/resources/saga/statelang/simple_statelang_with_script.json new file mode 100644 index 0000000000000000000000000000000000000000..d1b225e0e59e60b570f72cc90f39d5505b21074b --- /dev/null +++ b/test/src/test/resources/saga/statelang/simple_statelang_with_script.json @@ -0,0 +1,104 @@ +{ + "Name": "simpleScriptTaskStateMachine", + "Comment": "带ScriptTask的测试状态机定义", + "StartState": "FirstState", + "Version": "0.0.1", + "States": { + "FirstState": { + "Type": "ServiceTask", + "ServiceName": "demoService", + "ServiceMethod": "foo", + "Next": "ScriptState", + "Input": [ + { + "fooInput": "$.[a]" + } + ], + "output": { + "fooResult": "$.#root" + } + }, + "ScriptState": { + "Type": "ScriptTask", + "ScriptType": "groovy", + "ScriptContent": "if(throwException){ throw new RuntimeException(\"test\") } else { 'hello ' + inputA }", + "Input": [ + { + "inputA": "$.[a]", + "throwException": "$.[scriptThrowException]" + } + ], + "Output": { + "scriptStateResult": "$.#root" + }, + "Catch": [ + { + "Exceptions": [ + "java.lang.Throwable" + ], + "Next": "Fail" + } + ], + "Next": "ChoiceState" + }, + "ChoiceState":{ + "Type": "Choice", + "Choices":[ + { + "Expression":"[a] == 1", + "Next":"SecondState" + }, + { + "Expression":"[a] == 2", + "Next":"ThirdState" + } + ], + "Default":"Fail" + }, + "SecondState": { + "Type": "ServiceTask", + "ServiceName": "demoService", + "ServiceMethod": "bar", + "Input": [ + { + "barInput": "$.[fooResult]", + "throwException": "$.[barThrowException]" + } + ], + "output": { + "barResult": "$.#root" + }, + "Catch": [ + { + "Exceptions": [ + "io.seata.saga.engine.mock.DemoException" + ], + "Next": "Fail" + } + ], + "Next": "Succeed" + }, + "ThirdState": { + "Type": "ServiceTask", + "ServiceName": "demoService", + "ServiceMethod": "foo", + "Input": [ + { + "fooInput": "$.[fooResult]" + } + ], + "output": { + "fooResult": "$.#root" + }, + "Next": "Succeed" + }, + "Succeed": { + "Type":"Succeed" + }, + "Fail": { + "Type":"Fail", + "ErrorCode": "NOT_FOUND", + "Message": "not found" + } + } +} \ No newline at end of file diff --git a/tm/src/main/java/io/seata/tm/DefaultTransactionManager.java b/tm/src/main/java/io/seata/tm/DefaultTransactionManager.java index 8bff469124674365ea85a9c4d460835b1756d9ac..879c626eaf45e554e91dd933f38ce2d26d9ca1c5 100644 --- a/tm/src/main/java/io/seata/tm/DefaultTransactionManager.java +++ b/tm/src/main/java/io/seata/tm/DefaultTransactionManager.java @@ -15,8 +15,6 @@ */ package io.seata.tm; -import java.util.concurrent.TimeoutException; - import io.seata.core.exception.TmTransactionException; import io.seata.core.exception.TransactionException; import io.seata.core.exception.TransactionExceptionCode; @@ -35,7 +33,9 @@ import io.seata.core.protocol.transaction.GlobalRollbackRequest; import io.seata.core.protocol.transaction.GlobalRollbackResponse; import io.seata.core.protocol.transaction.GlobalStatusRequest; import io.seata.core.protocol.transaction.GlobalStatusResponse; -import io.seata.core.rpc.netty.TmRpcClient; +import io.seata.core.rpc.netty.TmNettyRemotingClient; + +import java.util.concurrent.TimeoutException; /** * The type Default transaction manager. @@ -50,7 +50,7 @@ public class DefaultTransactionManager implements TransactionManager { GlobalBeginRequest request = new GlobalBeginRequest(); request.setTransactionName(name); request.setTimeout(timeout); - GlobalBeginResponse response = (GlobalBeginResponse)syncCall(request); + GlobalBeginResponse response = (GlobalBeginResponse) syncCall(request); if (response.getResultCode() == ResultCode.Failed) { throw new TmTransactionException(TransactionExceptionCode.BeginFailed, response.getMsg()); } @@ -61,7 +61,7 @@ public class DefaultTransactionManager implements TransactionManager { public GlobalStatus commit(String xid) throws TransactionException { GlobalCommitRequest globalCommit = new GlobalCommitRequest(); globalCommit.setXid(xid); - GlobalCommitResponse response = (GlobalCommitResponse)syncCall(globalCommit); + GlobalCommitResponse response = (GlobalCommitResponse) syncCall(globalCommit); return response.getGlobalStatus(); } @@ -69,7 +69,7 @@ public class DefaultTransactionManager implements TransactionManager { public GlobalStatus rollback(String xid) throws TransactionException { GlobalRollbackRequest globalRollback = new GlobalRollbackRequest(); globalRollback.setXid(xid); - GlobalRollbackResponse response = (GlobalRollbackResponse)syncCall(globalRollback); + GlobalRollbackResponse response = (GlobalRollbackResponse) syncCall(globalRollback); return response.getGlobalStatus(); } @@ -77,7 +77,7 @@ public class DefaultTransactionManager implements TransactionManager { public GlobalStatus getStatus(String xid) throws TransactionException { GlobalStatusRequest queryGlobalStatus = new GlobalStatusRequest(); queryGlobalStatus.setXid(xid); - GlobalStatusResponse response = (GlobalStatusResponse)syncCall(queryGlobalStatus); + GlobalStatusResponse response = (GlobalStatusResponse) syncCall(queryGlobalStatus); return response.getGlobalStatus(); } @@ -92,7 +92,7 @@ public class DefaultTransactionManager implements TransactionManager { private AbstractTransactionResponse syncCall(AbstractTransactionRequest request) throws TransactionException { try { - return (AbstractTransactionResponse)TmRpcClient.getInstance().sendMsgWithResponse(request); + return (AbstractTransactionResponse) TmNettyRemotingClient.getInstance().sendSyncRequest(request); } catch (TimeoutException toe) { throw new TmTransactionException(TransactionExceptionCode.IO, "RPC timeout", toe); } diff --git a/tm/src/main/java/io/seata/tm/TMClient.java b/tm/src/main/java/io/seata/tm/TMClient.java index bf7ad17ca6e8181e352256cc3174782a2baf5aef..96d8b2d266359a4c5f635978d0be5f945743efbe 100644 --- a/tm/src/main/java/io/seata/tm/TMClient.java +++ b/tm/src/main/java/io/seata/tm/TMClient.java @@ -15,7 +15,7 @@ */ package io.seata.tm; -import io.seata.core.rpc.netty.TmRpcClient; +import io.seata.core.rpc.netty.TmNettyRemotingClient; /** * The type Tm client. @@ -31,8 +31,8 @@ public class TMClient { * @param transactionServiceGroup the transaction service group */ public static void init(String applicationId, String transactionServiceGroup) { - TmRpcClient tmRpcClient = TmRpcClient.getInstance(applicationId, transactionServiceGroup); - tmRpcClient.init(); + TmNettyRemotingClient tmNettyRemotingClient = TmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup); + tmNettyRemotingClient.init(); } } diff --git a/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java b/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java index 923cfaaf6f16c8f8bb68bff416a5870fc4fda0f7..9e0bd304799436f381fe25d060cacfe758fd55a0 100644 --- a/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java +++ b/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java @@ -63,14 +63,14 @@ public class DefaultFailureHandlerImpl implements FailureHandler { } @Override - public void onRollbackFailure(GlobalTransaction tx, Throwable cause) { - LOGGER.warn("Failed to rollback transaction[" + tx.getXid() + "]", cause); + public void onRollbackFailure(GlobalTransaction tx, Throwable originalException) { + LOGGER.warn("Failed to rollback transaction[" + tx.getXid() + "]", originalException); timer.newTimeout(new CheckTimerTask(tx, GlobalStatus.Rollbacked), SCHEDULE_INTERVAL_SECONDS, TimeUnit.SECONDS); } @Override - public void onRollbackRetrying(GlobalTransaction tx, Throwable cause) { - StackTraceLogger.warn(LOGGER, cause, "Retrying to rollback transaction[{}]", new String[] {tx.getXid()}); + public void onRollbackRetrying(GlobalTransaction tx, Throwable originalException) { + StackTraceLogger.warn(LOGGER, originalException, "Retrying to rollback transaction[{}]", new String[] {tx.getXid()}); timer.newTimeout(new CheckTimerTask(tx, GlobalStatus.RollbackRetrying), SCHEDULE_INTERVAL_SECONDS, TimeUnit.SECONDS); } diff --git a/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java b/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java index 515153d98d03b816a247035ee301a3d961731c9c..492fd44186483ad347caaddc9059d9baaefc0e2d 100644 --- a/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java +++ b/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java @@ -120,7 +120,7 @@ public class DefaultGlobalTransaction implements GlobalTransaction { return; } assertXIDNotNull(); - int retry = COMMIT_RETRY_COUNT; + int retry = COMMIT_RETRY_COUNT <= 0 ? DEFAULT_TM_COMMIT_RETRY_COUNT : COMMIT_RETRY_COUNT; try { while (retry > 0) { try { @@ -156,7 +156,7 @@ public class DefaultGlobalTransaction implements GlobalTransaction { } assertXIDNotNull(); - int retry = ROLLBACK_RETRY_COUNT; + int retry = ROLLBACK_RETRY_COUNT <= 0 ? DEFAULT_TM_ROLLBACK_RETRY_COUNT : ROLLBACK_RETRY_COUNT; try { while (retry > 0) { try { diff --git a/tm/src/main/java/io/seata/tm/api/FailureHandler.java b/tm/src/main/java/io/seata/tm/api/FailureHandler.java index 0be1f16054697b774c6cd7aaf7bb101c58b70ca4..939a414cf58921ddcf755f72e38b16cb3912badb 100644 --- a/tm/src/main/java/io/seata/tm/api/FailureHandler.java +++ b/tm/src/main/java/io/seata/tm/api/FailureHandler.java @@ -41,16 +41,16 @@ public interface FailureHandler { /** * On rollback failure. * - * @param tx the tx - * @param cause the cause + * @param tx the tx + * @param originalException the originalException */ - void onRollbackFailure(GlobalTransaction tx, Throwable cause); + void onRollbackFailure(GlobalTransaction tx, Throwable originalException); /** * On rollback retrying * - * @param tx the tx - * @param cause the cause + * @param tx the tx + * @param originalException the originalException */ - void onRollbackRetrying(GlobalTransaction tx, Throwable cause); + void onRollbackRetrying(GlobalTransaction tx, Throwable originalException); } diff --git a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java index f1bef45595555c401078234a5e0e6085d4790251..b3d938cd709aa07eaa8985773e1109c8eb6e63ca 100644 --- a/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java +++ b/tm/src/main/java/io/seata/tm/api/TransactionalTemplate.java @@ -132,15 +132,15 @@ public class TransactionalTemplate { - private void completeTransactionAfterThrowing(TransactionInfo txInfo, GlobalTransaction tx, Throwable ex) throws TransactionalExecutor.ExecutionException { + private void completeTransactionAfterThrowing(TransactionInfo txInfo, GlobalTransaction tx, Throwable originalException) throws TransactionalExecutor.ExecutionException { //roll back - if (txInfo != null && txInfo.rollbackOn(ex)) { + if (txInfo != null && txInfo.rollbackOn(originalException)) { try { - rollbackTransaction(tx, ex); + rollbackTransaction(tx, originalException); } catch (TransactionException txe) { // Failed to rollback throw new TransactionalExecutor.ExecutionException(tx, txe, - TransactionalExecutor.Code.RollbackFailure, ex); + TransactionalExecutor.Code.RollbackFailure, originalException); } } else { // not roll back on this exception, so commit @@ -160,13 +160,13 @@ public class TransactionalTemplate { } } - private void rollbackTransaction(GlobalTransaction tx, Throwable ex) throws TransactionException, TransactionalExecutor.ExecutionException { + private void rollbackTransaction(GlobalTransaction tx, Throwable originalException) throws TransactionException, TransactionalExecutor.ExecutionException { triggerBeforeRollback(); tx.rollback(); triggerAfterRollback(); // 3.1 Successfully rolled back throw new TransactionalExecutor.ExecutionException(tx, GlobalStatus.RollbackRetrying.equals(tx.getLocalStatus()) - ? TransactionalExecutor.Code.RollbackRetrying : TransactionalExecutor.Code.RollbackDone, ex); + ? TransactionalExecutor.Code.RollbackRetrying : TransactionalExecutor.Code.RollbackDone, originalException); } private void beginTransaction(TransactionInfo txInfo, GlobalTransaction tx) throws TransactionalExecutor.ExecutionException { diff --git a/tm/src/test/java/io/seata/tm/api/APITest.java b/tm/src/test/java/io/seata/tm/api/APITest.java index e23e94aea58b5bf8210cb476525ab7387f297cc8..96c19d023f21c34c24d9cb0f5d3e90681a31b5c7 100644 --- a/tm/src/test/java/io/seata/tm/api/APITest.java +++ b/tm/src/test/java/io/seata/tm/api/APITest.java @@ -20,7 +20,6 @@ import io.seata.core.exception.TransactionException; import io.seata.core.model.GlobalStatus; import io.seata.core.model.TransactionManager; import io.seata.tm.TransactionManagerHolder; -import io.seata.tm.api.transaction.RollbackRule; import io.seata.tm.api.transaction.TransactionInfo; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions;