/* * Copyright 2000-2016 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.CvalChecker.LINE; import static com.vaadin.tools.CvalChecker.computeMajorVersion; import static com.vaadin.tools.CvalChecker.getErrorMessage; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; import com.vaadin.client.metadata.ConnectorBundleLoader.CValUiInfo; import com.vaadin.tools.CvalChecker.CvalInfo; import com.vaadin.tools.CvalChecker.CvalServer; import com.vaadin.tools.CvalChecker.InvalidCvalException; import com.vaadin.tools.CvalChecker.UnreachableCvalServerException; /** * This class is able to visit all MANIFEST.MF files present in the classpath, * filter by name, and check if the user has a valid license. * * Manifest files should have a few attributes indicating the license type of * the addon: * <ul> * <li>Implementation-Version: 4.x.x * <li>AdVaaName: addon_name * <li>AdVaaLicen: cval, agpl, empty * <li>AdVaaPkg: package of the widgets in this addon * </ul> * * The class also have a method to check just one product. * * @since 7.3 */ public final class CvalAddonsChecker { // Manifest attributes public static final String VAADIN_ADDON_LICENSE = "AdVaaLicen"; public static final String VAADIN_ADDON_NAME = "AdVaaName"; public static final String VAADIN_ADDON_WIDGETSET = "Vaadin-Widgetsets"; public static final String VAADIN_ADDON_VERSION = "Implementation-Version"; public static final String VAADIN_ADDON_TITLE = "Implementation-Title"; // License types public static final String VAADIN_AGPL = "agpl"; public static final String VAADIN_CVAL = "cval"; private CvalChecker cvalChecker = new CvalChecker(); private String filterPattern; /** * The constructor. */ public CvalAddonsChecker() { setLicenseProvider(new CvalServer()); setFilter(".*vaadin.*"); } /** * Visit all MANIFEST.MF files in the classpath validating licenses. * * Return a list of Cval licensed products in order to have enough info to * generate nag messages in the UI. */ public List<CValUiInfo> run() throws InvalidCvalException { List<CValUiInfo> ret = new ArrayList<>(); try { // Visit all MANIFEST in our classpath Enumeration<URL> manifests = Thread.currentThread() .getContextClassLoader() .getResources(JarFile.MANIFEST_NAME); while (manifests.hasMoreElements()) { try { URL url = manifests.nextElement(); // Discard manifests whose name does not match the filter // pattern if (!url.getPath().matches(filterPattern)) { continue; } InputStream is = url.openStream(); // Should never happen, but we don't want a NPE here if (is == null) { continue; } // Read manifest attributes Manifest manifest = new Manifest(is); Attributes attribs = manifest.getMainAttributes(); String license = attribs.getValue(VAADIN_ADDON_LICENSE); String name = attribs.getValue(VAADIN_ADDON_NAME); String vers = attribs.getValue(VAADIN_ADDON_VERSION) == null ? "" : attribs.getValue(VAADIN_ADDON_VERSION); String title = attribs.getValue(VAADIN_ADDON_TITLE) == null ? name : attribs.getValue(VAADIN_ADDON_TITLE); String widgetsets = attribs .getValue(VAADIN_ADDON_WIDGETSET) == null ? name : attribs.getValue(VAADIN_ADDON_WIDGETSET); if (name == null || license == null) { continue; } if (VAADIN_AGPL.equals(license)) { // For agpl version we print an info message printAgplLicense(title, vers); } else if (VAADIN_CVAL.equals(license)) { // We only check cval licensed products CvalInfo info; try { info = cvalChecker.validateProduct(name, vers, title); printValidLicense(info, title, vers); } catch (UnreachableCvalServerException e) { info = CvalChecker.parseJson( "{'product':{'name':'" + name + "'}}"); printServerUnreachable(title, vers); } for (String w : widgetsets.split("[, ]+")) { ret.add(new CValUiInfo(title, String.valueOf(computeMajorVersion(vers)), w, info.getType())); } } } catch (IOException ignored) { } } } catch (IOException ignored) { } return ret; } /** * Set the filter regexp of .jar names which we have to consider. * * default is '.*touchkit.*' */ public CvalAddonsChecker setFilter(String regexp) { filterPattern = regexp; return this; } /* * Change the license provider, only used in tests. */ protected CvalAddonsChecker setLicenseProvider(CvalServer p) { cvalChecker.setLicenseProvider(p); return this; } private void printAgplLicense(String name, String version) { System.out.println(LINE + "\n" + getErrorMessage("agpl", name, computeMajorVersion(version)) + "\n" + LINE); } private void printServerUnreachable(String name, String version) { System.out.println(LINE + "\n" + getErrorMessage("unreachable", name, computeMajorVersion(version)) + "\n" + LINE); } private void printValidLicense(CvalInfo info, String title, String version) { String msg = info.getMessage(); if (msg == null) { String key = "evaluation".equals(info.getType()) ? "evaluation" : "valid"; msg = getErrorMessage(key, title, computeMajorVersion(version), info.getLicensee()); } System.out.println("\n" + LINE + "\n" + msg + "\n" + LINE + "\n"); } }