Extract license common structures (#36)
diff --git a/pom.xml b/pom.xml
index 5710de7..2e8d352 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<groupId>com.baidu.hugegraph</groupId>
<artifactId>hugegraph-common</artifactId>
- <version>1.6.13</version>
+ <version>1.6.14</version>
<name>hugegraph-common</name>
<url>https://github.com/hugegraph/hugegraph-common</url>
@@ -175,6 +175,12 @@
<artifactId>jersey-hk2</artifactId>
<version>${jersey.hk2.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>de.schlichtherle.truelicense</groupId>
+ <artifactId>truelicense-core</artifactId>
+ <version>1.33</version>
+ </dependency>
</dependencies>
<build>
@@ -212,7 +218,7 @@
<manifestEntries>
<!-- Must be on one line, otherwise the automatic
upgrade script cannot replace the version number -->
- <Implementation-Version>1.6.13.0</Implementation-Version>
+ <Implementation-Version>1.6.14.0</Implementation-Version>
</manifestEntries>
</archive>
</configuration>
diff --git a/src/main/java/com/baidu/hugegraph/license/CommonLicenseManager.java b/src/main/java/com/baidu/hugegraph/license/CommonLicenseManager.java
new file mode 100644
index 0000000..ede39d0
--- /dev/null
+++ b/src/main/java/com/baidu/hugegraph/license/CommonLicenseManager.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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 com.baidu.hugegraph.license;
+
+import java.beans.XMLDecoder;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.slf4j.Logger;
+
+import com.baidu.hugegraph.util.Log;
+
+import de.schlichtherle.license.LicenseContent;
+import de.schlichtherle.license.LicenseContentException;
+import de.schlichtherle.license.LicenseManager;
+import de.schlichtherle.license.LicenseNotary;
+import de.schlichtherle.license.LicenseParam;
+import de.schlichtherle.license.NoLicenseInstalledException;
+import de.schlichtherle.xml.GenericCertificate;
+
+public class CommonLicenseManager extends LicenseManager {
+
+ private static final Logger LOG = Log.logger(CommonLicenseManager.class);
+
+ private static final String CHARSET = "UTF-8";
+ private static final int BUF_SIZE = 8 * 1024;
+
+ public CommonLicenseManager(LicenseParam param) {
+ super(param);
+ }
+
+ @Override
+ protected synchronized byte[] create(LicenseContent content,
+ LicenseNotary notary)
+ throws Exception {
+ super.initialize(content);
+ this.validateCreate(content);
+ GenericCertificate certificate = notary.sign(content);
+ return super.getPrivacyGuard().cert2key(certificate);
+ }
+
+ @Override
+ protected synchronized LicenseContent install(byte[] key,
+ LicenseNotary notary)
+ throws Exception {
+ GenericCertificate certificate = super.getPrivacyGuard().key2cert(key);
+ notary.verify(certificate);
+ String encodedText = certificate.getEncoded();
+ LicenseContent content = (LicenseContent) this.load(encodedText);
+ this.validate(content);
+ super.setLicenseKey(key);
+ super.setCertificate(certificate);
+ return content;
+ }
+
+ @Override
+ protected synchronized LicenseContent verify(LicenseNotary notary)
+ throws Exception {
+ // Load license key from preferences
+ byte[] key = super.getLicenseKey();
+ if (key == null) {
+ String subject = super.getLicenseParam().getSubject();
+ throw new NoLicenseInstalledException(subject);
+ }
+
+ GenericCertificate certificate = super.getPrivacyGuard().key2cert(key);
+ notary.verify(certificate);
+ String encodedText = certificate.getEncoded();
+ LicenseContent content = (LicenseContent) this.load(encodedText);
+ this.validate(content);
+ super.setCertificate(certificate);
+ return content;
+ }
+
+ @Override
+ protected synchronized void validate(LicenseContent content)
+ throws LicenseContentException {
+ // Call super validate, expected to be overwritten
+ super.validate(content);
+ }
+
+ protected synchronized void validateCreate(LicenseContent content)
+ throws LicenseContentException {
+ // Just call super validate is ok
+ super.validate(content);
+ }
+
+ private Object load(String text) throws Exception {
+ InputStream bis = null;
+ XMLDecoder decoder = null;
+ try {
+ bis = new ByteArrayInputStream(text.getBytes(CHARSET));
+ decoder = new XMLDecoder(new BufferedInputStream(bis, BUF_SIZE));
+ return decoder.readObject();
+ } catch (UnsupportedEncodingException e) {
+ throw new LicenseContentException(String.format(
+ "Unsupported charset: %s", CHARSET));
+ } finally {
+ if (decoder != null) {
+ decoder.close();
+ }
+ try {
+ if (bis != null) {
+ bis.close();
+ }
+ } catch (Exception e) {
+ LOG.warn("Failed to close stream", e);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/baidu/hugegraph/license/ExtraParam.java b/src/main/java/com/baidu/hugegraph/license/ExtraParam.java
new file mode 100644
index 0000000..43f6d05
--- /dev/null
+++ b/src/main/java/com/baidu/hugegraph/license/ExtraParam.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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 com.baidu.hugegraph.license;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ExtraParam {
+
+ @JsonProperty("id")
+ private String id;
+
+ @JsonProperty("version")
+ private String version;
+
+ @JsonProperty("graphs")
+ private int graphs;
+
+ @JsonProperty("ip")
+ private String ip;
+
+ @JsonProperty("mac")
+ private String mac;
+
+ @JsonProperty("cpus")
+ private int cpus;
+
+ @JsonProperty("ram")
+ private int ram;
+
+ @JsonProperty("threads")
+ private int threads;
+
+ @JsonProperty("memory")
+ private int memory;
+
+ public String id() {
+ return this.id;
+ }
+
+ public String version() {
+ return this.version;
+ }
+
+ public int graphs() {
+ return this.graphs;
+ }
+
+ public String ip() {
+ return this.ip;
+ }
+
+ public String mac() {
+ return this.mac;
+ }
+
+ public int cpus() {
+ return this.cpus;
+ }
+
+ public int ram() {
+ return this.ram;
+ }
+
+ public int threads() {
+ return this.threads;
+ }
+
+ public int memory() {
+ return this.memory;
+ }
+}
diff --git a/src/main/java/com/baidu/hugegraph/license/FileKeyStoreParam.java b/src/main/java/com/baidu/hugegraph/license/FileKeyStoreParam.java
new file mode 100755
index 0000000..919cc23
--- /dev/null
+++ b/src/main/java/com/baidu/hugegraph/license/FileKeyStoreParam.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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 com.baidu.hugegraph.license;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import de.schlichtherle.license.AbstractKeyStoreParam;
+
+/**
+ * Custom KeyStoreParam to store public and private key storage files to
+ * other disk locations instead of projects
+ */
+public class FileKeyStoreParam extends AbstractKeyStoreParam {
+
+ private String storePath;
+ private String alias;
+ private String keyPwd;
+ private String storePwd;
+
+ public FileKeyStoreParam(Class clazz, String resource, String alias,
+ String storePwd, String keyPwd) {
+ super(clazz, resource);
+ this.storePath = resource;
+ this.alias = alias;
+ this.storePwd = storePwd;
+ this.keyPwd = keyPwd;
+ }
+
+ @Override
+ public String getAlias() {
+ return this.alias;
+ }
+
+ @Override
+ public String getStorePwd() {
+ return this.storePwd;
+ }
+
+ @Override
+ public String getKeyPwd() {
+ return this.keyPwd;
+ }
+
+ @Override
+ public InputStream getStream() throws IOException {
+ return new FileInputStream(new File(this.storePath));
+ }
+}
diff --git a/src/main/java/com/baidu/hugegraph/license/LicenseCreateParam.java b/src/main/java/com/baidu/hugegraph/license/LicenseCreateParam.java
new file mode 100644
index 0000000..00f0bdc
--- /dev/null
+++ b/src/main/java/com/baidu/hugegraph/license/LicenseCreateParam.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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 com.baidu.hugegraph.license;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang3.time.DateUtils;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class LicenseCreateParam {
+
+ @JsonProperty("subject")
+ private String subject;
+
+ @JsonProperty("private_alias")
+ private String privateAlias;
+
+ @JsonProperty("key_password")
+ private String keyPassword;
+
+ @JsonProperty("store_password")
+ private String storePassword;
+
+ @JsonProperty("privatekey_path")
+ private String privateKeyPath;
+
+ @JsonProperty("license_path")
+ private String licensePath;
+
+ @JsonProperty("issued_time")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private Date issuedTime = new Date();
+
+ @JsonProperty("not_before")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private Date notBefore = this.issuedTime;
+
+ @JsonProperty("not_after")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private Date notAfter = DateUtils.addDays(this.notBefore, 30);
+
+ @JsonProperty("consumer_type")
+ private String consumerType = "user";
+
+ @JsonProperty("consumer_amount")
+ private Integer consumerAmount = 1;
+
+ @JsonProperty("description")
+ private String description = "";
+
+ @JsonProperty("extra_params")
+ private List<ExtraParam> extraParams;
+
+ public String subject() {
+ return this.subject;
+ }
+
+ public String privateAlias() {
+ return this.privateAlias;
+ }
+
+ public String keyPassword() {
+ return this.keyPassword;
+ }
+
+ public String storePassword() {
+ return this.storePassword;
+ }
+
+ public String privateKeyPath() {
+ return this.privateKeyPath;
+ }
+
+ public String licensePath() {
+ return this.licensePath;
+ }
+
+ public Date issuedTime() {
+ return this.issuedTime;
+ }
+
+ public Date notBefore() {
+ return this.notBefore;
+ }
+
+ public Date notAfter() {
+ return this.notAfter;
+ }
+
+ public String consumerType() {
+ return this.consumerType;
+ }
+
+ public Integer consumerAmount() {
+ return this.consumerAmount;
+ }
+
+ public String description() {
+ return this.description;
+ }
+
+ public List<ExtraParam> extraParams() {
+ return this.extraParams;
+ }
+}
diff --git a/src/main/java/com/baidu/hugegraph/license/LicenseVerifyParam.java b/src/main/java/com/baidu/hugegraph/license/LicenseVerifyParam.java
new file mode 100644
index 0000000..f2359bf
--- /dev/null
+++ b/src/main/java/com/baidu/hugegraph/license/LicenseVerifyParam.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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 com.baidu.hugegraph.license;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class LicenseVerifyParam {
+
+ @JsonProperty("subject")
+ private String subject;
+
+ @JsonProperty("public_alias")
+ private String publicAlias;
+
+ @JsonProperty("store_password")
+ private String storePassword;
+
+ @JsonProperty("publickey_path")
+ private String publicKeyPath;
+
+ @JsonProperty("license_path")
+ private String licensePath;
+
+ public String subject() {
+ return this.subject;
+ }
+
+ public String publicAlias() {
+ return this.publicAlias;
+ }
+
+ public String storePassword() {
+ return this.storePassword;
+ }
+
+ public String licensePath() {
+ return this.licensePath;
+ }
+
+ public String publicKeyPath() {
+ return this.publicKeyPath;
+ }
+}
diff --git a/src/main/java/com/baidu/hugegraph/license/MachineInfo.java b/src/main/java/com/baidu/hugegraph/license/MachineInfo.java
new file mode 100755
index 0000000..eccc7bb
--- /dev/null
+++ b/src/main/java/com/baidu/hugegraph/license/MachineInfo.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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 com.baidu.hugegraph.license;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class MachineInfo {
+
+ private List<String> ipAddressList;
+ private List<String> macAddressList;
+
+ public MachineInfo() {
+ this.ipAddressList = null;
+ this.macAddressList = null;
+ }
+
+ public List<String> getIpAddress() {
+ if (this.ipAddressList != null) {
+ return this.ipAddressList;
+ }
+ this.ipAddressList = new ArrayList<>();
+ List<InetAddress> inetAddresses = this.getLocalAllInetAddress();
+ if (inetAddresses != null && !inetAddresses.isEmpty()) {
+ this.ipAddressList = inetAddresses.stream()
+ .map(InetAddress::getHostAddress)
+ .distinct()
+ .map(String::toLowerCase)
+ .collect(Collectors.toList());
+ }
+ return this.ipAddressList;
+ }
+
+ public List<String> getMacAddress() {
+ if (this.macAddressList != null) {
+ return this.macAddressList;
+ }
+ this.macAddressList = new ArrayList<>();
+ List<InetAddress> inetAddresses = this.getLocalAllInetAddress();
+ if (inetAddresses != null && !inetAddresses.isEmpty()) {
+ // Get the Mac address of all network interfaces
+ List<String> list = new ArrayList<>();
+ Set<String> uniqueValues = new HashSet<>();
+ for (InetAddress inetAddress : inetAddresses) {
+ String macByInetAddress = this.getMacByInetAddress(inetAddress);
+ if (uniqueValues.add(macByInetAddress)) {
+ list.add(macByInetAddress);
+ }
+ }
+ this.macAddressList = list;
+ }
+ return this.macAddressList;
+ }
+
+ public List<InetAddress> getLocalAllInetAddress() {
+ Enumeration interfaces;
+ try {
+ interfaces = NetworkInterface.getNetworkInterfaces();
+ } catch (SocketException e) {
+ throw new RuntimeException("Failed to get network interfaces");
+ }
+
+ List<InetAddress> result = new ArrayList<>();
+ while (interfaces.hasMoreElements()) {
+ NetworkInterface iface = (NetworkInterface) interfaces.nextElement();
+ for (Enumeration inetAddresses = iface.getInetAddresses();
+ inetAddresses.hasMoreElements(); ) {
+ InetAddress inetAddr = (InetAddress) inetAddresses.nextElement();
+ if (!inetAddr.isLoopbackAddress() &&
+ !inetAddr.isLinkLocalAddress() &&
+ !inetAddr.isMulticastAddress()) {
+ result.add(inetAddr);
+ }
+ }
+ }
+ return result;
+ }
+
+ public String getMacByInetAddress(InetAddress inetAddr) {
+ byte[] mac;
+ try {
+ mac = NetworkInterface.getByInetAddress(inetAddr)
+ .getHardwareAddress();
+ } catch (Exception e) {
+ throw new RuntimeException(String.format(
+ "Failed to get mac address for inet address '%s'",
+ inetAddr));
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < mac.length; i++) {
+ if (i != 0) {
+ sb.append("-");
+ }
+ String temp = Integer.toHexString(mac[i] & 0xff);
+ if (temp.length() == 1) {
+ sb.append("0").append(temp);
+ } else {
+ sb.append(temp);
+ }
+ }
+ return sb.toString().toUpperCase();
+ }
+}
diff --git a/src/main/java/com/baidu/hugegraph/version/CommonVersion.java b/src/main/java/com/baidu/hugegraph/version/CommonVersion.java
index d38af9c..92c5f27 100644
--- a/src/main/java/com/baidu/hugegraph/version/CommonVersion.java
+++ b/src/main/java/com/baidu/hugegraph/version/CommonVersion.java
@@ -27,5 +27,5 @@
// The second parameter of Version.of() is for all-in-one JAR
public static final Version VERSION = Version.of(CommonVersion.class,
- "1.6.13");
+ "1.6.14");
}
diff --git a/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java b/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java
index e5f65d7..6131b33 100644
--- a/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java
+++ b/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java
@@ -32,6 +32,11 @@
import com.baidu.hugegraph.unit.iterator.FlatMapperFilterIteratorTest;
import com.baidu.hugegraph.unit.iterator.FlatMapperIteratorTest;
import com.baidu.hugegraph.unit.iterator.MapperIteratorTest;
+import com.baidu.hugegraph.unit.license.ExtraParamTest;
+import com.baidu.hugegraph.unit.license.LicenseCreateParamTest;
+import com.baidu.hugegraph.unit.license.LicenseManagerTest;
+import com.baidu.hugegraph.unit.license.LicenseVerifyParamTest;
+import com.baidu.hugegraph.unit.license.MachineInfoTest;
import com.baidu.hugegraph.unit.perf.PerfUtilTest;
import com.baidu.hugegraph.unit.rest.RestClientTest;
import com.baidu.hugegraph.unit.rest.RestResultTest;
@@ -76,6 +81,12 @@
LongEncodingTest.class,
OrderLimitMapTest.class,
+ ExtraParamTest.class,
+ LicenseCreateParamTest.class,
+ LicenseVerifyParamTest.class,
+ MachineInfoTest.class,
+ LicenseManagerTest.class,
+
AssertTest.class,
WhiteboxTest.class
})
diff --git a/src/test/java/com/baidu/hugegraph/unit/license/ExtraParamTest.java b/src/test/java/com/baidu/hugegraph/unit/license/ExtraParamTest.java
new file mode 100644
index 0000000..0e0cc22
--- /dev/null
+++ b/src/test/java/com/baidu/hugegraph/unit/license/ExtraParamTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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 com.baidu.hugegraph.unit.license;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import com.baidu.hugegraph.license.ExtraParam;
+import com.baidu.hugegraph.testutil.Assert;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class ExtraParamTest {
+
+ @Test
+ public void testDeserializeExtraParam() throws IOException {
+ String json = "{"
+ + "\"id\":\"server-1\","
+ + "\"version\":\"0.10.2\","
+ + "\"graphs\":3,"
+ + "\"ip\":\"127.0.0.1\","
+ + "\"mac\":\"00-01-6C-06-A6-29\","
+ + "\"cpus\":32,"
+ + "\"ram\":65536,"
+ + "\"threads\":96,"
+ + "\"memory\":32768"
+ + "}";
+ ObjectMapper mapper = new ObjectMapper();
+ ExtraParam param = mapper.readValue(json, ExtraParam.class);
+ Assert.assertEquals("server-1", param.id());
+ Assert.assertEquals("0.10.2", param.version());
+ Assert.assertEquals(3, param.graphs());
+ Assert.assertEquals("127.0.0.1", param.ip());
+ Assert.assertEquals("00-01-6C-06-A6-29", param.mac());
+ Assert.assertEquals(32, param.cpus());
+ Assert.assertEquals(65536, param.ram());
+ Assert.assertEquals(96, param.threads());
+ Assert.assertEquals(32768, param.memory());
+ }
+}
diff --git a/src/test/java/com/baidu/hugegraph/unit/license/LicenseCreateParamTest.java b/src/test/java/com/baidu/hugegraph/unit/license/LicenseCreateParamTest.java
new file mode 100644
index 0000000..cc9ddaa
--- /dev/null
+++ b/src/test/java/com/baidu/hugegraph/unit/license/LicenseCreateParamTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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 com.baidu.hugegraph.unit.license;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.TimeZone;
+
+import org.junit.Test;
+
+import com.baidu.hugegraph.date.SafeDateFormat;
+import com.baidu.hugegraph.license.LicenseCreateParam;
+import com.baidu.hugegraph.testutil.Assert;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class LicenseCreateParamTest {
+
+ @Test
+ public void testDeserializeLicenseCreateParam()
+ throws IOException, ParseException {
+ String json = "{"
+ + "\"subject\":\"hugegraph-evaluation\","
+ + "\"private_alias\":\"privatekey\","
+ + "\"key_password\":\"123456\","
+ + "\"store_password\":\"123456\","
+ + "\"privatekey_path\":\"./privateKeys.store\","
+ + "\"license_path\":\"./hugegraph-evaluation.license\","
+ + "\"issued_time\":\"2019-08-10 00:00:00\","
+ + "\"not_before\":\"2019-08-10 00:00:00\","
+ + "\"not_after\":\"2020-08-10 00:00:00\","
+ + "\"consumer_type\":\"user\","
+ + "\"consumer_amount\":1,"
+ + "\"description\":\"hugegraph license\","
+ + "\"extra_params\":["
+ + "{"
+ + "\"id\":\"server-1\","
+ + "\"version\":\"0.9.2\","
+ + "\"graphs\":3,"
+ + "\"ip\":\"127.0.0.1\","
+ + "\"mac\":\"00-01-6C-06-A6-29\","
+ + "\"cpus\":32,"
+ + "\"ram\":65536,"
+ + "\"threads\":96,"
+ + "\"memory\":32768"
+ + "},"
+ + "{"
+ + "\"id\":\"server-2\","
+ + "\"version\":\"0.10.2\","
+ + "\"graphs\":3,"
+ + "\"ip\":\"127.0.0.1\","
+ + "\"mac\":\"00-02-6C-06-A6-29\","
+ + "\"cpus\":64,"
+ + "\"ram\":65536,"
+ + "\"threads\":96,"
+ + "\"memory\":65536"
+ + "}"
+ + "]"
+ + "}";
+ ObjectMapper mapper = new ObjectMapper();
+ LicenseCreateParam param = mapper.readValue(json,
+ LicenseCreateParam.class);
+ Assert.assertEquals("hugegraph-evaluation", param.subject());
+ Assert.assertEquals("privatekey", param.privateAlias());
+ Assert.assertEquals("123456", param.keyPassword());
+ Assert.assertEquals("123456", param.storePassword());
+ Assert.assertEquals("./privateKeys.store", param.privateKeyPath());
+ Assert.assertEquals("./hugegraph-evaluation.license",
+ param.licensePath());
+
+ DateFormat df = new SafeDateFormat("yyyy-MM-dd HH:mm:ss");
+ df.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
+ Assert.assertEquals(df.parse("2019-08-10 00:00:00"),
+ param.issuedTime());
+ Assert.assertEquals(df.parse("2019-08-10 00:00:00"),
+ param.notBefore());
+ Assert.assertEquals(df.parse("2020-08-10 00:00:00"),
+ param.notAfter());
+ Assert.assertEquals("user", param.consumerType());
+ Assert.assertEquals(1, param.consumerAmount());
+ Assert.assertEquals("hugegraph license", param.description());
+ Assert.assertEquals(2, param.extraParams().size());
+ }
+}
diff --git a/src/test/java/com/baidu/hugegraph/unit/license/LicenseManagerTest.java b/src/test/java/com/baidu/hugegraph/unit/license/LicenseManagerTest.java
new file mode 100644
index 0000000..65f6e03
--- /dev/null
+++ b/src/test/java/com/baidu/hugegraph/unit/license/LicenseManagerTest.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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 com.baidu.hugegraph.unit.license;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.prefs.Preferences;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.apache.commons.codec.Charsets;
+import org.apache.commons.io.FileUtils;
+import org.junit.Test;
+
+import com.baidu.hugegraph.license.CommonLicenseManager;
+import com.baidu.hugegraph.license.ExtraParam;
+import com.baidu.hugegraph.license.FileKeyStoreParam;
+import com.baidu.hugegraph.license.LicenseCreateParam;
+import com.baidu.hugegraph.license.LicenseVerifyParam;
+import com.baidu.hugegraph.testutil.Assert;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import de.schlichtherle.license.CipherParam;
+import de.schlichtherle.license.DefaultCipherParam;
+import de.schlichtherle.license.DefaultLicenseParam;
+import de.schlichtherle.license.KeyStoreParam;
+import de.schlichtherle.license.LicenseContent;
+import de.schlichtherle.license.LicenseContentException;
+import de.schlichtherle.license.LicenseManager;
+import de.schlichtherle.license.LicenseParam;
+import de.schlichtherle.license.NoLicenseInstalledException;
+
+public class LicenseManagerTest {
+
+ private static final Charset CHARSET = Charsets.UTF_8;
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ @Test
+ public void testCreateInstallVerifyLicense() throws IOException {
+ String createConfigPath = "src/test/resources/create-license.json";
+ LicenseCreator creator = LicenseCreator.build(createConfigPath);
+ creator.create();
+
+ String verifyConfigPath = "src/test/resources/verify-license.json";
+ LicenseVerifier verifier = LicenseVerifier.build(verifyConfigPath);
+ verifier.install();
+ verifier.verify();
+ }
+
+ @Test
+ public void testCreateVerifyLicenseWithoutInstall() throws IOException {
+ String createConfigPath = "src/test/resources/create-license.json";
+ LicenseCreator creator = LicenseCreator.build(createConfigPath);
+ creator.create();
+
+ String verifyConfigPath = "src/test/resources/verify-license.json";
+ LicenseVerifier verifier = LicenseVerifier.build(verifyConfigPath);
+ verifier.uninstall();
+ Assert.assertThrows(RuntimeException.class, () -> {
+ verifier.verify();
+ }, e -> {
+ Assert.assertEquals(NoLicenseInstalledException.class,
+ e.getCause().getClass());
+ });
+ }
+
+ private static class LicenseCreator {
+
+ private static final X500Principal DEFAULT_ISSUER = new X500Principal(
+ "CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN");
+
+ private final LicenseCreateParam param;
+
+ public LicenseCreator(LicenseCreateParam param) {
+ this.param = param;
+ }
+
+ public static LicenseCreator build(String path) throws IOException {
+ File file = FileUtils.getFile(path);
+ String json;
+ try {
+ json = FileUtils.readFileToString(file, CHARSET);
+ } catch (IOException e) {
+ throw new RuntimeException(String.format(
+ "Failed to read file '%s'", path));
+ }
+ LicenseCreateParam param = MAPPER.readValue(
+ json, LicenseCreateParam.class);
+ return new LicenseCreator(param);
+ }
+
+ public void create(){
+ try {
+ LicenseParam licenseParam = this.initLicenseParam();
+ LicenseManager manager = new LicenseCreateManager(licenseParam);
+ LicenseContent licenseContent = this.initLicenseContent();
+ File licenseFile = new File(this.param.licensePath());
+ manager.store(licenseContent, licenseFile);
+ } catch (Exception e){
+ throw new RuntimeException("Generate license failed", e);
+ }
+ }
+
+ private LicenseParam initLicenseParam(){
+ Preferences preferences = Preferences.userNodeForPackage(
+ LicenseCreator.class);
+ CipherParam cipherParam = new DefaultCipherParam(
+ this.param.storePassword());
+ KeyStoreParam keyStoreParam;
+ keyStoreParam = new FileKeyStoreParam(LicenseCreator.class,
+ this.param.privateKeyPath(),
+ this.param.privateAlias(),
+ this.param.storePassword(),
+ this.param.keyPassword());
+ return new DefaultLicenseParam(this.param.subject(), preferences,
+ keyStoreParam, cipherParam);
+ }
+
+ private LicenseContent initLicenseContent(){
+ LicenseContent content = new LicenseContent();
+ content.setHolder(DEFAULT_ISSUER);
+ content.setIssuer(DEFAULT_ISSUER);
+ content.setSubject(this.param.subject());
+ content.setIssued(this.param.issuedTime());
+ content.setNotBefore(this.param.notBefore());
+ content.setNotAfter(this.param.notAfter());
+ content.setConsumerType(this.param.consumerType());
+ content.setConsumerAmount(this.param.consumerAmount());
+ content.setInfo(this.param.description());
+ // Customized verification params
+ String json;
+ try {
+ json = MAPPER.writeValueAsString(this.param.extraParams());
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException("Failed to write extra params", e);
+ }
+ content.setExtra(json);
+ return content;
+ }
+ }
+
+ private static class LicenseCreateManager extends CommonLicenseManager {
+
+ public LicenseCreateManager(LicenseParam param) {
+ super(param);
+ }
+
+ @Override
+ protected synchronized void validateCreate(LicenseContent content)
+ throws LicenseContentException {
+ super.validateCreate(content);
+ }
+ }
+
+ private static class LicenseVerifier {
+
+ private final LicenseVerifyParam param;
+ private final LicenseVerifyManager manager;
+
+ public LicenseVerifier(LicenseVerifyParam param) {
+ this.param = param;
+ LicenseParam licenseParam = this.initLicenseParam(param);
+ this.manager = new LicenseVerifyManager(licenseParam);
+ }
+
+ public static LicenseVerifier build(String path) throws IOException {
+ File file = FileUtils.getFile(path);
+ String json;
+ try {
+ json = FileUtils.readFileToString(file, CHARSET);
+ } catch (IOException e) {
+ throw new RuntimeException(String.format(
+ "Failed to read file '%s'", path));
+ }
+ LicenseVerifyParam param = MAPPER.readValue(
+ json, LicenseVerifyParam.class);
+ return new LicenseVerifier(param);
+ }
+
+ public synchronized void install() {
+ try {
+ this.manager.uninstall();
+ File licenseFile = new File(this.param.licensePath());
+ this.manager.install(licenseFile);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to install license", e);
+ }
+ }
+
+ public synchronized void uninstall() {
+ try {
+ this.manager.uninstall();
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to uninstall license", e);
+ }
+ }
+
+ public void verify() {
+ try {
+ this.manager.verify();
+ } catch (Exception e) {
+ throw new RuntimeException("The license verify failed", e);
+ }
+ }
+
+ private LicenseParam initLicenseParam(LicenseVerifyParam param) {
+ Preferences preferences = Preferences.userNodeForPackage(
+ LicenseVerifier.class);
+ CipherParam cipherParam = new DefaultCipherParam(
+ param.storePassword());
+ KeyStoreParam keyStoreParam = new FileKeyStoreParam(
+ LicenseVerifier.class,
+ param.publicKeyPath(),
+ param.publicAlias(),
+ param.storePassword(),
+ null);
+ return new DefaultLicenseParam(param.subject(), preferences,
+ keyStoreParam, cipherParam);
+ }
+ }
+
+ private static class LicenseVerifyManager extends CommonLicenseManager {
+
+ private final String serverId = "server-1";
+
+ public LicenseVerifyManager(LicenseParam param) {
+ super(param);
+ }
+
+ @Override
+ protected synchronized void validate(LicenseContent content)
+ throws LicenseContentException {
+ // Call super validate firstly, will verify expired
+ super.validate(content);
+
+ // Verify the customized license parameters
+ String extra = (String) content.getExtra();
+ List<ExtraParam> extraParams;
+ try {
+ TypeReference type = new TypeReference<List<ExtraParam>>() {};
+ extraParams = MAPPER.readValue(extra, type);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to read extra params", e);
+ }
+ ExtraParam param = this.matchParam(this.serverId, extraParams);
+ if (param == null) {
+ throw newLicenseException("The current server's id '%s' " +
+ "is not authorized");
+ }
+ if (this.usingGraphs() > param.graphs()) {
+ throw newLicenseException("The using graphs exceeded '%s'" +
+ "authorized limit '%s'",
+ this.usingGraphs(), param.graphs());
+ }
+ }
+
+ private int usingGraphs() {
+ // Assume
+ return 2;
+ }
+
+ private ExtraParam matchParam(String id, List<ExtraParam> extraParams) {
+ for (ExtraParam param : extraParams) {
+ if (param.id().equals(id)) {
+ return param;
+ }
+ }
+ return null;
+ }
+
+ private LicenseContentException newLicenseException(String message,
+ Object... args) {
+ return new LicenseContentException(String.format(message, args));
+ }
+ }
+}
diff --git a/src/test/java/com/baidu/hugegraph/unit/license/LicenseVerifyParamTest.java b/src/test/java/com/baidu/hugegraph/unit/license/LicenseVerifyParamTest.java
new file mode 100644
index 0000000..f1126ce
--- /dev/null
+++ b/src/test/java/com/baidu/hugegraph/unit/license/LicenseVerifyParamTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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 com.baidu.hugegraph.unit.license;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import com.baidu.hugegraph.license.LicenseVerifyParam;
+import com.baidu.hugegraph.testutil.Assert;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class LicenseVerifyParamTest {
+
+ @Test
+ public void testDeserializeLicenseVerifyParam() throws IOException {
+ String json = "{"
+ + "\"subject\":\"hugegraph-evaluation\","
+ + "\"public_alias\":\"publiccert\","
+ + "\"store_password\":\"123456\","
+ + "\"publickey_path\":\"./publicCerts.store\","
+ + "\"license_path\":\"./hugegraph-evaluation.license\""
+ + "}";
+ ObjectMapper mapper = new ObjectMapper();
+ LicenseVerifyParam param = mapper.readValue(json,
+ LicenseVerifyParam.class);
+ Assert.assertEquals("hugegraph-evaluation", param.subject());
+ Assert.assertEquals("publiccert", param.publicAlias());
+ Assert.assertEquals("123456", param.storePassword());
+ Assert.assertEquals("./publicCerts.store", param.publicKeyPath());
+ Assert.assertEquals("./hugegraph-evaluation.license",
+ param.licensePath());
+ }
+}
diff --git a/src/test/java/com/baidu/hugegraph/unit/license/MachineInfoTest.java b/src/test/java/com/baidu/hugegraph/unit/license/MachineInfoTest.java
new file mode 100644
index 0000000..c436943
--- /dev/null
+++ b/src/test/java/com/baidu/hugegraph/unit/license/MachineInfoTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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 com.baidu.hugegraph.unit.license;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+
+import com.baidu.hugegraph.license.MachineInfo;
+import com.baidu.hugegraph.testutil.Assert;
+
+public class MachineInfoTest {
+
+ private static final Pattern IPV4_PATTERN = Pattern.compile(
+ "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}" +
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"
+ );
+ private static final Pattern IPV6_PATTERN = Pattern.compile(
+ "^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"
+ );
+
+ private static final Pattern MAC_PATTERN = Pattern.compile(
+ "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$"
+ );
+
+ private static final MachineInfo machineInfo = new MachineInfo();
+
+ @Test
+ public void testGetIpAddressList() {
+ List<String> ipAddressList = machineInfo.getIpAddress();
+ for (String ip : ipAddressList) {
+ Assert.assertTrue(IPV4_PATTERN.matcher(ip).matches() ||
+ IPV6_PATTERN.matcher(ip).matches());
+ }
+ Assert.assertEquals(ipAddressList, machineInfo.getIpAddress());
+ }
+
+ @Test
+ public void testGetMacAddressList() {
+ List<String> macAddressList = machineInfo.getMacAddress();
+ for (String mac : macAddressList) {
+ Assert.assertTrue(MAC_PATTERN.matcher(mac).matches());
+ }
+ Assert.assertEquals(macAddressList, machineInfo.getMacAddress());
+ }
+
+ @Test
+ public void testGetLocalAllInetAddress() {
+ List<InetAddress> addressList = machineInfo.getLocalAllInetAddress();
+ for (InetAddress address : addressList) {
+ String ip = address.getHostAddress();
+ Assert.assertTrue(IPV4_PATTERN.matcher(ip).matches() ||
+ IPV6_PATTERN.matcher(ip).matches());
+ }
+ }
+
+ @Test
+ public void testGetMacByInetAddress() throws UnknownHostException {
+ List<InetAddress> addressList = machineInfo.getLocalAllInetAddress();
+ for (InetAddress address : addressList) {
+ String mac = machineInfo.getMacByInetAddress(address);
+ Assert.assertTrue(MAC_PATTERN.matcher(mac).matches());
+ }
+ InetAddress address = InetAddress.getByAddress(new byte[]{0, 0, 0, 0});
+ Assert.assertThrows(RuntimeException.class, () -> {
+ machineInfo.getMacByInetAddress(address);
+ });
+ }
+}
diff --git a/src/test/resources/create-license.json b/src/test/resources/create-license.json
new file mode 100644
index 0000000..26b3bd5
--- /dev/null
+++ b/src/test/resources/create-license.json
@@ -0,0 +1,19 @@
+{
+ "subject": "hugegraph-evaluation",
+ "private_alias": "privatekey",
+ "key_password": "private_password123456",
+ "store_password": "public_password123456",
+ "privatekey_path": "src/test/resources/privateKeys.store",
+ "license_path": "src/test/resources/hugegraph-evaluation.license",
+ "issued_time": "2019-08-01 00:00:00",
+ "not_before": "2019-08-01 00:00:00",
+ "not_after": "2029-08-01 00:00:00",
+ "consumer_type": "user",
+ "consumer_amount": 1,
+ "extra_params": [
+ {
+ "id": "server-1",
+ "graphs": 3
+ }
+ ]
+}
diff --git a/src/test/resources/hugegraph-evaluation.license b/src/test/resources/hugegraph-evaluation.license
new file mode 100644
index 0000000..d09b0b9
--- /dev/null
+++ b/src/test/resources/hugegraph-evaluation.license
Binary files differ
diff --git a/src/test/resources/log4j2.xml b/src/test/resources/log4j2.xml
new file mode 100644
index 0000000..7ef111d
--- /dev/null
+++ b/src/test/resources/log4j2.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration status="error">
+ <appenders>
+ <Console name="console" target="SYSTEM_OUT">
+ <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
+ <PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} %-5r [%t] [%-5p] %c %x - %m%n"/>
+ </Console>
+
+ <RollingFile name="file" fileName="logs/hugegraph-common.log"
+ filePattern="logs/$${date:yyyy-MM}/hugegraph-common-%d{yyyy-MM-dd}-%i.log">
+ <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
+ <PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} %-5r [%t] [%-5p] %c %x - %m%n"/>
+ <SizeBasedTriggeringPolicy size="100MB"/>
+ </RollingFile>
+ </appenders>
+ <loggers>
+ <root level="INFO">
+ <appender-ref ref="console"/>
+ <appender-ref ref="file"/>
+ </root>
+ <logger name="com.baidu.hugegraph" level="INFO" additivity="false">
+ <appender-ref ref="console"/>
+ <appender-ref ref="file"/>
+ </logger>
+ </loggers>
+</configuration>
diff --git a/src/test/resources/privateKeys.store b/src/test/resources/privateKeys.store
new file mode 100644
index 0000000..836e413
--- /dev/null
+++ b/src/test/resources/privateKeys.store
Binary files differ
diff --git a/src/test/resources/publicCerts.store b/src/test/resources/publicCerts.store
new file mode 100644
index 0000000..7eee045
--- /dev/null
+++ b/src/test/resources/publicCerts.store
Binary files differ
diff --git a/src/test/resources/verify-license.json b/src/test/resources/verify-license.json
new file mode 100644
index 0000000..277e25d
--- /dev/null
+++ b/src/test/resources/verify-license.json
@@ -0,0 +1,7 @@
+{
+ "subject": "hugegraph-evaluation",
+ "public_alias": "publiccert",
+ "store_password": "public_password123456",
+ "publickey_path": "src/test/resources/publicCerts.store",
+ "license_path": "src/test/resources/hugegraph-evaluation.license"
+}