private License getArchiveInfoLicense(ArchiveInfo ai) { Archive a = ai.getNewArchive(); if (a != null) { Package p = a.getParentPackage(); if (p != null) { License lic = p.getLicense(); if (lic != null && lic.getLicenseRef() != null && !lic.getLicense().isEmpty() && lic.getLicense() != null && !lic.getLicense().isEmpty()) { return lic; } } } return null; }
private String getLicenseId(License lic) { return String.format( "%1$s-%2$08x", //$NON-NLS-1$ lic.getLicenseRef(), lic.getLicense().hashCode()); }
/** * Validates that all archive licenses are accepted. * * <p>There are 2 cases: <br> * - When {@code acceptLicenses} is given, the licenses specified are automatically accepted and * all those not specified are automatically rejected. <br> * - When {@code acceptLicenses} is empty or null, licenses are collected and there's an input * prompt on StdOut to ask a yes/no question. To output, this uses the current {@link #mSdkLog} * which should be configured to send {@link ILogger#info(String, Object...)} directly to {@link * System#out}. <br> * Finally only accepted licenses are kept in the archive list. * * @param archives The archives to validate. * @param acceptLicenseIds A comma-separated list of licenses ids already approved. * @param numRetries The number of times the command-line will ask to accept a given license when * the input doesn't match the expected y/n/yes/no answer. Use 0 for infinite. Useful for * unit-tests. Once the number of retries is reached, the license is assumed as rejected. * @return True if there are any archives left to install. */ @VisibleForTesting(visibility = Visibility.PRIVATE) boolean acceptLicense(List<ArchiveInfo> archives, String acceptLicenseIds, final int numRetries) { TreeSet<String> acceptedLids = new TreeSet<String>(); if (acceptLicenseIds != null) { acceptedLids.addAll(Arrays.asList(acceptLicenseIds.split(","))); // $NON-NLS-1$ } boolean automated = !acceptedLids.isEmpty(); TreeSet<String> rejectedLids = new TreeSet<String>(); TreeMap<String, License> lidToAccept = new TreeMap<String, License>(); TreeMap<String, List<String>> lidPkgNames = new TreeMap<String, List<String>>(); // Find the licenses needed. Include those already accepted. for (ArchiveInfo ai : archives) { License lic = getArchiveInfoLicense(ai); if (lic == null) { continue; } String lid = getLicenseId(lic); if (!acceptedLids.contains(lid)) { if (automated) { // Automatically reject those not already accepted rejectedLids.add(lid); } else { // Queue it to ask for it to be accepted lidToAccept.put(lid, lic); List<String> list = lidPkgNames.get(lid); if (list == null) { list = new ArrayList<String>(); lidPkgNames.put(lid, list); } list.add(ai.getShortDescription()); } } } // Ask for each license that needs to be asked manually for confirmation nextEntry: for (Map.Entry<String, License> entry : lidToAccept.entrySet()) { String lid = entry.getKey(); License lic = entry.getValue(); mSdkLog.info("-------------------------------\n"); mSdkLog.info("License id: %1$s\n", lid); mSdkLog.info( "Used by: \n - %1$s\n", Joiner.on("\n - ").skipNulls().join(lidPkgNames.get(lid))); mSdkLog.info("-------------------------------\n\n"); mSdkLog.info("%1$s\n", lic.getLicense()); int retries = numRetries; tryAgain: while (true) { try { mSdkLog.info("Do you accept the license '%1$s' [y/n]: ", lid); byte[] buffer = new byte[256]; if (mSdkLog instanceof IReaderLogger) { ((IReaderLogger) mSdkLog).readLine(buffer); } else { System.in.read(buffer); } mSdkLog.info("\n"); String reply = new String(buffer, Charsets.UTF_8); reply = reply.trim().toLowerCase(Locale.US); if ("y".equals(reply) || "yes".equals(reply)) { acceptedLids.add(lid); continue nextEntry; } else if ("n".equals(reply) || "no".equals(reply)) { break tryAgain; } else { mSdkLog.info("Unknown response '%1$s'.\n", reply); if (--retries == 0) { mSdkLog.info("Max number of retries exceeded. Rejecting '%1$s'\n", lid); break tryAgain; } continue tryAgain; } } catch (IOException e) { // Panic. Don't install anything. e.printStackTrace(); return false; } } rejectedLids.add(lid); } // Finally remove all archive which license is rejected or not accepted. for (Iterator<ArchiveInfo> it = archives.iterator(); it.hasNext(); ) { ArchiveInfo ai = it.next(); License lic = getArchiveInfoLicense(ai); if (lic == null) { continue; } String lid = getLicenseId(lic); if (rejectedLids.contains(lid) || !acceptedLids.contains(lid)) { mSdkLog.info( "Package %1$s not installed due to rejected license '%2$s'.\n", ai.getShortDescription(), lid); it.remove(); } } return !archives.isEmpty(); }