diff options
author | Manolo Carrasco <manolo@vaadin.com> | 2014-04-30 13:26:32 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2014-06-26 08:30:46 +0000 |
commit | 9a84fb14f2b7fc3c405f1446a007d5b9cd796c97 (patch) | |
tree | 40f1a0420f22fa70b91f7d59d064fe9975c2c33f /client-compiler/tests | |
parent | 0ff4e15b96b91becdd6c8e38ad20d8272c5455b7 (diff) | |
download | vaadin-framework-9a84fb14f2b7fc3c405f1446a007d5b9cd796c97.tar.gz vaadin-framework-9a84fb14f2b7fc3c405f1446a007d5b9cd796c97.zip |
License Checker for vaadin cval products (#13696 #13474)
- This patch includes four elements:
1.- A class able to validate a licensed product against Vaadin
license server. It can be used in any vaadin product (thought
for non addons like TB) just adding vaadin dependency, or
copying the class.
2.- A class able to inspect all addons in the classpath and figure
out, based on the MANIFEST.MF info, whether we have to check
developer license.
3.- A modification to Vaadin connector generator to use the classes
above and to stop compilation in case.
4.- A modification to ConnectorBundleLoader, so as when a new connector
is instatiated, we check whether it is using an evaluation
license and show a notice. We only show the notice once.
- In addition to validating developer licenses, the checker caches the
server response for using it when there are connection problems.
- This stuff is in Vaadin core, so as we dont maintain license code in
each addon. For checking an addon license we just add the license type
to the manifest when packaging the artefact.
- It checks expiration time, product name and major version.
Fixes: #13696
In some-way related with: #13474
Change-Id: Ib61b1c2e9c3cacd463a1ce5db02c2cfbc06851c2
Diffstat (limited to 'client-compiler/tests')
3 files changed, 743 insertions, 0 deletions
diff --git a/client-compiler/tests/src/com/vaadin/tools/CvalAddonsCheckerTest.java b/client-compiler/tests/src/com/vaadin/tools/CvalAddonsCheckerTest.java new file mode 100644 index 0000000000..1fb9413ee4 --- /dev/null +++ b/client-compiler/tests/src/com/vaadin/tools/CvalAddonsCheckerTest.java @@ -0,0 +1,184 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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 com.vaadin.tools; + +import static com.vaadin.tools.CvalAddonsChecker.VAADIN_AGPL; +import static com.vaadin.tools.CvalAddonsChecker.VAADIN_CVAL; +import static com.vaadin.tools.CvalChecker.GRACE_DAYS_MSECS; +import static com.vaadin.tools.CvalChecker.computeLicenseName; +import static com.vaadin.tools.CvalChecker.deleteCache; +import static com.vaadin.tools.CvalCheckerTest.VALID_KEY; +import static com.vaadin.tools.CvalCheckerTest.addLicensedJarToClasspath; +import static com.vaadin.tools.CvalCheckerTest.cacheExists; +import static com.vaadin.tools.CvalCheckerTest.captureSystemOut; +import static com.vaadin.tools.CvalCheckerTest.productNameAgpl; +import static com.vaadin.tools.CvalCheckerTest.productNameApache; +import static com.vaadin.tools.CvalCheckerTest.productNameCval; +import static com.vaadin.tools.CvalCheckerTest.readSystemOut; +import static com.vaadin.tools.CvalCheckerTest.saveCache; +import static com.vaadin.tools.CvalCheckerTest.unreachableLicenseProvider; +import static com.vaadin.tools.CvalCheckerTest.validLicenseProvider; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.client.metadata.ConnectorBundleLoader.CValUiInfo; +import com.vaadin.tools.CvalChecker.InvalidCvalException; + +/** + * The CvalAddonsChecker test. + */ +public class CvalAddonsCheckerTest { + + CvalAddonsChecker addonChecker; + private String licenseName; + + @Before + public void setup() { + addonChecker = new CvalAddonsChecker().setLicenseProvider( + validLicenseProvider).setFilter(".*test.*"); + licenseName = computeLicenseName(productNameCval); + + deleteCache(productNameCval); + System.getProperties().remove(licenseName); + } + + @Test + public void testRunChecker() throws Exception { + // Create a product .jar with a cval license non required and add to our + // classpath + addLicensedJarToClasspath(productNameCval, VAADIN_CVAL); + // Remove other products in case other tests added them previously + addLicensedJarToClasspath(productNameAgpl, null); + addLicensedJarToClasspath(productNameApache, null); + + // No license + // -> Break compilation + System.getProperties().remove(licenseName); + addonChecker.setLicenseProvider(validLicenseProvider); + try { + addonChecker.run(); + Assert.fail(); + } catch (InvalidCvalException expected) { + } + Assert.assertFalse(cacheExists(productNameCval)); + + // We have a license that has never been validated from the server and + // we are offline + // -> Show a message on compile time (“Your license for TouchKit 4 has + // not been validated.”) + System.setProperty(licenseName, VALID_KEY); + addonChecker.setLicenseProvider(unreachableLicenseProvider); + captureSystemOut(); + addonChecker.run(); + Assert.assertTrue(readSystemOut().contains("has not been validated")); + Assert.assertFalse(cacheExists(productNameCval)); + + // Valid license has previously been validated from the server and we + // are offline + // -> Use the cached server response + System.setProperty(licenseName, VALID_KEY); + addonChecker.setLicenseProvider(validLicenseProvider); + captureSystemOut(); + addonChecker.run(); + Assert.assertTrue(cacheExists(productNameCval)); + addonChecker.setLicenseProvider(unreachableLicenseProvider); + addonChecker.run(); + + // Expired license and we are offline + // -> If it has expired less than 14 days ago, just work with no nag + // messages + System.setProperty(licenseName, VALID_KEY); + addonChecker.setLicenseProvider(unreachableLicenseProvider); + setCacheFileTs(System.currentTimeMillis() - (GRACE_DAYS_MSECS / 2), + "normal"); + captureSystemOut(); + addonChecker.run(); + + // Expired license and we are offline + // -> After 14 days, interpret it as expired license + setCacheFileTs(System.currentTimeMillis() - (GRACE_DAYS_MSECS * 2), + "normal"); + try { + addonChecker.run(); + Assert.fail(); + } catch (InvalidCvalException expected) { + } + + // Invalid evaluation license + // -> Fail compilation with a message + // "Your evaluation license for TouchKit 4 is not valid" + System.setProperty(licenseName, VALID_KEY); + addonChecker.setLicenseProvider(unreachableLicenseProvider); + setCacheFileTs(System.currentTimeMillis() - (GRACE_DAYS_MSECS / 2), + "evaluation"); + try { + addonChecker.run(); + Assert.fail(); + } catch (InvalidCvalException expected) { + Assert.assertTrue(expected.getMessage().contains("expired")); + } + + // Valid evaluation license + // -> The choice on whether to show the message is generated in + // widgetset + // compilation phase. No license checks are done in application runtime. + System.setProperty(licenseName, VALID_KEY); + addonChecker.setLicenseProvider(unreachableLicenseProvider); + setCacheFileTs(System.currentTimeMillis() + GRACE_DAYS_MSECS, + "evaluation"); + List<CValUiInfo> uiInfo = addonChecker.run(); + Assert.assertEquals(1, uiInfo.size()); + Assert.assertEquals("Test " + productNameCval, uiInfo.get(0).product); + Assert.assertEquals("evaluation", uiInfo.get(0).type); + + // Valid real license + // -> Work as expected + // -> Show info message “Using TouchKit 4 license + // 312-312321-321312-3-12-312-312 + // licensed to <licensee> (1 developer license)” + System.setProperty(licenseName, VALID_KEY); + addonChecker.setLicenseProvider(validLicenseProvider); + captureSystemOut(); + addonChecker.run(); + Assert.assertTrue(readSystemOut().contains("valid")); + } + + @Test + public void validateMultipleLicenses() throws Exception { + addLicensedJarToClasspath(productNameCval, VAADIN_CVAL); + addLicensedJarToClasspath(productNameAgpl, VAADIN_AGPL); + addLicensedJarToClasspath(productNameApache, "apache"); + + // We have a valid license for all products + System.setProperty(licenseName, VALID_KEY); + captureSystemOut(); + addonChecker.run(); + String out = readSystemOut(); + Assert.assertTrue(out.contains("valid")); + Assert.assertTrue(out.contains("AGPL")); + Assert.assertTrue(cacheExists(productNameCval)); + } + + private void setCacheFileTs(long expireTs, String type) { + saveCache(productNameCval, null, false, expireTs, type); + } + +} diff --git a/client-compiler/tests/src/com/vaadin/tools/CvalAddonstCheckerUseCasesTest.java b/client-compiler/tests/src/com/vaadin/tools/CvalAddonstCheckerUseCasesTest.java new file mode 100644 index 0000000000..89c8fc1f81 --- /dev/null +++ b/client-compiler/tests/src/com/vaadin/tools/CvalAddonstCheckerUseCasesTest.java @@ -0,0 +1,217 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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 com.vaadin.tools; + +import static com.vaadin.tools.CvalAddonsChecker.VAADIN_AGPL; +import static com.vaadin.tools.CvalAddonsChecker.VAADIN_CVAL; +import static com.vaadin.tools.CvalChecker.computeLicenseName; +import static com.vaadin.tools.CvalChecker.deleteCache; +import static com.vaadin.tools.CvalCheckerTest.INVALID_KEY; +import static com.vaadin.tools.CvalCheckerTest.VALID_KEY; +import static com.vaadin.tools.CvalCheckerTest.addLicensedJarToClasspath; +import static com.vaadin.tools.CvalCheckerTest.cachedPreferences; +import static com.vaadin.tools.CvalCheckerTest.captureSystemOut; +import static com.vaadin.tools.CvalCheckerTest.expiredLicenseProvider; +import static com.vaadin.tools.CvalCheckerTest.productNameAgpl; +import static com.vaadin.tools.CvalCheckerTest.productNameCval; +import static com.vaadin.tools.CvalCheckerTest.readSystemOut; +import static com.vaadin.tools.CvalCheckerTest.restoreSystemOut; +import static com.vaadin.tools.CvalCheckerTest.saveCache; +import static com.vaadin.tools.CvalCheckerTest.unreachableLicenseProvider; +import static com.vaadin.tools.CvalCheckerTest.validEvaluationLicenseProvider; +import static com.vaadin.tools.CvalCheckerTest.validLicenseProvider; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.tools.CvalChecker.CvalServer; + +/** + * Tests for Use Cases + */ +public class CvalAddonstCheckerUseCasesTest { + + enum License { + NONE, EVAL, INVALID, REAL, EVAL_EXPIRED, REAL_EXPIRED + }; + + enum Version { + AGPL, CVAL + }; + + enum Validated { + YES, NO, OLD_KEY + }; + + enum Network { + ON, OFF + }; + + enum Compile { + YES, NO + }; + + enum Cached { + YES, NO + }; + + enum Message { + AGPL("AGPL"), VALID(">.* valid"), INVALID("not valid"), NO_LICENSE( + "not found"), NO_VALIDATED("has not been validated"), EXPIRED( + "has expired"), EVALUATION("evaluation"); + + String msg; + + Message(String s) { + msg = s; + } + } + + @Test + public void testUseCases() throws Exception { + useCase(1, License.NONE, Version.AGPL, Validated.NO, Network.OFF, + Compile.YES, Cached.NO, Message.AGPL); + + useCase(2, License.NONE, Version.CVAL, Validated.NO, Network.ON, + Compile.NO, Cached.NO, Message.NO_LICENSE); + + useCase(3, License.NONE, Version.CVAL, Validated.NO, Network.OFF, + Compile.NO, Cached.NO, Message.NO_LICENSE); + + useCase(4, License.EVAL, Version.CVAL, Validated.NO, Network.ON, + Compile.YES, Cached.YES, Message.EVALUATION); + + useCase(5, License.INVALID, Version.CVAL, Validated.NO, Network.OFF, + Compile.YES, Cached.NO, Message.NO_VALIDATED); + + useCase(6, License.INVALID, Version.CVAL, Validated.NO, Network.ON, + Compile.NO, Cached.NO, Message.INVALID); + + useCase(7, License.REAL, Version.CVAL, Validated.NO, Network.ON, + Compile.YES, Cached.YES, Message.VALID); + + useCase(8, License.REAL, Version.CVAL, Validated.NO, Network.OFF, + Compile.YES, Cached.NO, Message.NO_VALIDATED); + + useCase(9, License.REAL, Version.CVAL, Validated.YES, Network.OFF, + Compile.YES, Cached.YES, Message.VALID); + + useCase(10, License.EVAL_EXPIRED, Version.CVAL, Validated.NO, + Network.ON, Compile.NO, Cached.YES, Message.EXPIRED); + + useCase(11, License.EVAL_EXPIRED, Version.CVAL, Validated.YES, + Network.OFF, Compile.NO, Cached.YES, Message.EXPIRED); + + useCase(12, License.REAL_EXPIRED, Version.CVAL, Validated.YES, + Network.OFF, Compile.NO, Cached.YES, Message.EXPIRED); + + useCase(13, License.REAL_EXPIRED, Version.CVAL, Validated.NO, + Network.ON, Compile.NO, Cached.YES, Message.EXPIRED); + + useCase(14, License.INVALID, Version.CVAL, Validated.OLD_KEY, + Network.OFF, Compile.YES, Cached.NO, Message.NO_VALIDATED); + } + + @Test + public void testMultipleLicenseUseCases() throws Exception { + addLicensedJarToClasspath("test.foo", VAADIN_CVAL); + System.setProperty(computeLicenseName("test.foo"), VALID_KEY); + + useCase(15, License.REAL, Version.CVAL, Validated.YES, Network.OFF, + Compile.YES, Cached.YES, Message.NO_VALIDATED); + + useCase(16, License.REAL, Version.CVAL, Validated.YES, Network.ON, + Compile.NO, Cached.YES, Message.INVALID); + } + + private void useCase(int number, License lic, Version ver, Validated val, + Network net, Compile res, Cached cached, Message msg) + throws Exception { + + if (ver == Version.AGPL) { + addLicensedJarToClasspath(productNameAgpl, VAADIN_AGPL); + addLicensedJarToClasspath(productNameCval, null); + } else { + addLicensedJarToClasspath(productNameAgpl, null); + addLicensedJarToClasspath(productNameCval, VAADIN_CVAL); + } + + String licenseName = computeLicenseName(productNameCval); + + if (lic == License.NONE) { + System.getProperties().remove(licenseName); + } else if (lic == License.INVALID) { + System.setProperty(licenseName, INVALID_KEY); + } else { + System.setProperty(licenseName, VALID_KEY); + } + + if (val == Validated.NO) { + deleteCache(productNameCval); + } else { + String type = lic == License.EVAL || lic == License.EVAL_EXPIRED ? "evaluation" + : null; + Boolean expired = lic == License.EVAL_EXPIRED + || lic == License.REAL_EXPIRED ? true : null; + String key = val == Validated.OLD_KEY ? "oldkey" : null; + saveCache(productNameCval, key, expired, null, type); + } + + CvalServer licenseProvider = validLicenseProvider; + if (net == Network.OFF) { + licenseProvider = unreachableLicenseProvider; + } else if (lic == License.EVAL_EXPIRED || lic == License.REAL_EXPIRED) { + licenseProvider = expiredLicenseProvider; + } else if (lic == License.EVAL) { + licenseProvider = validEvaluationLicenseProvider; + } + + CvalAddonsChecker addonChecker = new CvalAddonsChecker(); + addonChecker.setLicenseProvider(licenseProvider).setFilter(".*test.*"); + + captureSystemOut(); + + String testNumber = "Test #" + number + " "; + String message; + try { + addonChecker.run(); + message = readSystemOut(); + if (res == Compile.NO) { + Assert.fail(testNumber + "Exception not thrown:" + message); + } + } catch (Exception e) { + restoreSystemOut(); + message = e.getMessage(); + if (res == Compile.YES) { + Assert.fail(testNumber + "Unexpected Exception: " + + e.getMessage()); + } + } + + // System.err.println("\n> " + testNumber + " " + lic + " " + ver + " " + // + val + " " + net + " " + res + " " + cached + "\n" + message); + + Assert.assertTrue(testNumber + "Fail:\n" + message + + "\nDoes not match:" + msg.msg, + message.matches("(?s).*" + msg.msg + ".*")); + + String c = cachedPreferences(productNameCval); + Assert.assertTrue(testNumber + "Fail: cacheExists != " + + (cached == Cached.YES) + "\n " + c, + (c != null) == (cached == Cached.YES)); + } +} diff --git a/client-compiler/tests/src/com/vaadin/tools/CvalCheckerTest.java b/client-compiler/tests/src/com/vaadin/tools/CvalCheckerTest.java new file mode 100644 index 0000000000..51b12f4c7e --- /dev/null +++ b/client-compiler/tests/src/com/vaadin/tools/CvalCheckerTest.java @@ -0,0 +1,342 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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 com.vaadin.tools; + +import static com.vaadin.tools.CvalAddonsChecker.VAADIN_ADDON_LICENSE; +import static com.vaadin.tools.CvalAddonsChecker.VAADIN_ADDON_NAME; +import static com.vaadin.tools.CvalAddonsChecker.VAADIN_ADDON_TITLE; +import static com.vaadin.tools.CvalAddonsChecker.VAADIN_ADDON_VERSION; +import static com.vaadin.tools.CvalChecker.GRACE_DAYS_MSECS; +import static com.vaadin.tools.CvalChecker.cacheLicenseInfo; +import static com.vaadin.tools.CvalChecker.deleteCache; +import static com.vaadin.tools.CvalChecker.parseJson; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.prefs.Preferences; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.tools.CvalChecker.CvalInfo; +import com.vaadin.tools.CvalChecker.CvalServer; +import com.vaadin.tools.CvalChecker.InvalidCvalException; +import com.vaadin.tools.CvalChecker.UnreachableCvalServerException; + +/** + * The CvalChecker test. + */ +public class CvalCheckerTest { + + static final String productNameCval = "test.cval"; + static final String productTitleCval = "Vaadin Test"; + static final String productNameAgpl = "test.agpl"; + static final String productTitleAgpl = "Vaadin Test"; + static final String productNameApache = "test.apache"; + static final String VALID_KEY = "valid"; + static final String INVALID_KEY = "invalid"; + + static final String responseJson = "{'licenseKey':'" + VALID_KEY + "'," + + "'licensee':'Test User','type':'normal'," + + "'expiredEpoch':'1893511225000'," + "'product':{'name':'" + + productNameCval + "', 'version': 2}}"; + + private static ByteArrayOutputStream outContent; + + // A provider returning a valid license if productKey is valid or null if + // invalid + static final CvalServer validLicenseProvider = new CvalServer() { + @Override + String askServer(String productName, String productKey, int timeout) { + return VALID_KEY.equals(productKey) ? responseJson : null; + } + }; + // A provider returning a valid evaluation license + static final CvalServer validEvaluationLicenseProvider = new CvalServer() { + @Override + String askServer(String productName, String productKey, int timeout) { + return responseJson.replace("normal", "evaluation"); + } + }; + // A provider returning an expired license with a server message + static final CvalServer expiredLicenseProviderWithMessage = new CvalServer() { + @Override + String askServer(String productName, String productKey, int timeout) { + return responseJson + .replace("'expired", + "'message':'Custom\\\\nServer\\\\nMessage','expired':true,'expired"); + } + }; + // A provider returning an expired license with a server message + static final CvalServer expiredLicenseProvider = new CvalServer() { + @Override + String askServer(String productName, String productKey, int timeout) { + return responseJson.replace("'expired", "'expired':true,'expired"); + } + }; + // A provider returning an expired epoch license + static final CvalServer expiredEpochLicenseProvider = new CvalServer() { + @Override + String askServer(String productName, String productKey, int timeout) { + long ts = System.currentTimeMillis() - GRACE_DAYS_MSECS - 1000; + return responseJson.replace("1893511225000", "" + ts); + } + }; + // A provider returning an unlimited license + static final CvalServer unlimitedLicenseProvider = new CvalServer() { + @Override + String askServer(String productName, String productKey, int timeout) { + return responseJson.replaceFirst("1893511225000", ""); + } + }; + // An unreachable provider + static final CvalServer unreachableLicenseProvider = new CvalServer() { + @Override + String askServer(String productName, String productKey, int timeout) + throws IOException { + // Normally there is no route for this ip in public routers, so we + // should get a timeout. + licenseUrl = "http://localhost:9999/"; + return super.askServer(productName, productKey, 1000); + } + }; + + private CvalChecker licenseChecker; + private String licenseName; + + @Before + public void setup() { + licenseChecker = new CvalChecker() + .setLicenseProvider(validLicenseProvider); + licenseName = CvalChecker.computeLicenseName(productNameCval); + System.getProperties().remove(licenseName); + deleteCache(productNameCval); + } + + @Test + public void testValidateProduct() throws Exception { + deleteCache(productNameCval); + + // If the license key in our environment is null, throw an exception + try { + licenseChecker.validateProduct(productNameCval, "2.1", + productTitleCval); + Assert.fail(); + } catch (InvalidCvalException expected) { + Assert.assertEquals(productNameCval, expected.name); + } + Assert.assertFalse(cacheExists(productNameCval)); + + // If the license key is empty, throw an exception + System.setProperty(licenseName, ""); + try { + licenseChecker.validateProduct(productNameCval, "2.1", + productTitleCval); + Assert.fail(); + } catch (InvalidCvalException expected) { + Assert.assertEquals(productNameCval, expected.name); + } + Assert.assertFalse(cacheExists(productNameCval)); + + // If license key is invalid, throw an exception + System.setProperty(licenseName, "invalid"); + try { + licenseChecker.validateProduct(productNameCval, "2.1", + productTitleCval); + Assert.fail(); + } catch (InvalidCvalException expected) { + Assert.assertEquals(productNameCval, expected.name); + } + Assert.assertFalse(cacheExists(productNameCval)); + + // Fail if version is bigger + System.setProperty(licenseName, VALID_KEY); + try { + licenseChecker.validateProduct(productNameCval, "3.0", + productTitleCval); + Assert.fail(); + } catch (InvalidCvalException expected) { + Assert.assertEquals(productNameCval, expected.name); + } + Assert.assertFalse(cacheExists(productNameCval)); + + // Success if license key and version are valid + System.setProperty(licenseName, VALID_KEY); + licenseChecker + .validateProduct(productNameCval, "2.1", productTitleCval); + Assert.assertTrue(cacheExists(productNameCval)); + + // Success if license and cache file are valid, although the license + // server is offline + licenseChecker.setLicenseProvider(unreachableLicenseProvider); + licenseChecker + .validateProduct(productNameCval, "2.1", productTitleCval); + Assert.assertTrue(cacheExists(productNameCval)); + + // Fail if license key changes although cache file were validated + // previously and it is ok, we are offline + try { + System.setProperty(licenseName, INVALID_KEY); + licenseChecker.validateProduct(productNameCval, "2.1", + productTitleCval); + Assert.fail(); + } catch (InvalidCvalException expected) { + Assert.fail(); + } catch (UnreachableCvalServerException expected) { + Assert.assertEquals(productNameCval, expected.name); + } + Assert.assertFalse(cacheExists(productNameCval)); + + // Fail with unreachable exception if license has never verified and + // server is offline + try { + System.setProperty(licenseName, VALID_KEY); + licenseChecker.validateProduct(productNameCval, "2.1", + productTitleCval); + Assert.fail(); + } catch (InvalidCvalException expected) { + Assert.fail(); + } catch (UnreachableCvalServerException expected) { + Assert.assertEquals(productNameCval, expected.name); + } + Assert.assertFalse(cacheExists(productNameCval)); + + // Fail when expired flag comes in the server response, although the + // expired is valid. + deleteCache(productNameCval); + licenseChecker.setLicenseProvider(expiredLicenseProviderWithMessage); + try { + licenseChecker.validateProduct(productNameCval, "2.1", + productTitleCval); + Assert.fail(); + } catch (InvalidCvalException expected) { + Assert.assertEquals(productNameCval, expected.name); + // Check that we use server customized message if it comes + Assert.assertTrue(expected.getMessage().contains("Custom")); + } + Assert.assertTrue(cacheExists(productNameCval)); + + // Check an unlimited license + licenseChecker.setLicenseProvider(unlimitedLicenseProvider); + licenseChecker + .validateProduct(productNameCval, "2.1", productTitleCval); + Assert.assertTrue(cacheExists(productNameCval)); + + // Fail if expired flag does not come, but expired epoch is in the past + System.setProperty(licenseName, VALID_KEY); + deleteCache(productNameCval); + licenseChecker.setLicenseProvider(expiredEpochLicenseProvider); + try { + licenseChecker.validateProduct(productNameCval, "2.1", + productTitleCval); + Assert.fail(); + } catch (InvalidCvalException expected) { + Assert.assertEquals(productNameCval, expected.name); + } + Assert.assertTrue(cacheExists(productNameCval)); + } + + /* + * Creates a new .jar file with a MANIFEST.MF with all vaadin license info + * attributes set, and add the .jar to the classpath + */ + static void addLicensedJarToClasspath(String productName, String licenseType) + throws Exception { + // Create a manifest with Vaadin CVAL license + Manifest testManifest = new Manifest(); + testManifest.getMainAttributes().putValue("Manifest-Version", "1.0"); + testManifest.getMainAttributes().putValue(VAADIN_ADDON_LICENSE, + licenseType); + testManifest.getMainAttributes().putValue(VAADIN_ADDON_NAME, + productName); + testManifest.getMainAttributes().putValue(VAADIN_ADDON_TITLE, + "Test " + productName); + testManifest.getMainAttributes().putValue(VAADIN_ADDON_VERSION, "2"); + + // Create a temporary Jar + String tmpDir = System.getProperty("java.io.tmpdir"); + File testJarFile = new File(tmpDir + "vaadin." + productName + ".jar"); + testJarFile.deleteOnExit(); + JarOutputStream target = new JarOutputStream(new FileOutputStream( + testJarFile), testManifest); + target.close(); + + // Add the new jar to our classpath (use reflection) + URL url = new URL("file://" + testJarFile.getAbsolutePath()); + final Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", + new Class[] { URL.class }); + addURL.setAccessible(true); + final URLClassLoader urlClassLoader = (URLClassLoader) Thread + .currentThread().getContextClassLoader(); + addURL.invoke(urlClassLoader, new Object[] { url }); + } + + static boolean cacheExists(String productName) { + return cachedPreferences(productName) != null; + } + + static String cachedPreferences(String productName) { + // ~/Library/Preferences/com.apple.java.util.prefs.plist + // .java/.userPrefs/com/google/gwt/dev/shell/prefs.xml + // HKEY_CURRENT_USER\SOFTWARE\JavaSoft\Prefs + Preferences p = Preferences.userNodeForPackage(CvalInfo.class); + return p.get(productName, null); + } + + static void saveCache(String productName, String key, Boolean expired, + Long expireTs, String type) { + String json = responseJson.replace(productNameCval, productName); + if (expired != null && expired) { + expireTs = System.currentTimeMillis() - GRACE_DAYS_MSECS - 1000; + } + if (expireTs != null) { + json = json.replace("1893511225000", "" + expireTs); + } + if (key != null) { + json = json.replace(VALID_KEY, key); + } + if (type != null) { + json = json.replace("normal", type); + + } + cacheLicenseInfo(parseJson(json)); + } + + static void captureSystemOut() { + outContent = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outContent)); + } + + static String readSystemOut() { + restoreSystemOut(); + return outContent.toString(); + } + + static void restoreSystemOut() { + System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out))); + } +} |