001 /* 002 * SonarQube, open source software quality management tool. 003 * Copyright (C) 2008-2014 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * SonarQube is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * SonarQube is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public License 017 * along with this program; if not, write to the Free Software Foundation, 018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 */ 020 package org.sonar.api.config; 021 022 import com.google.common.annotations.VisibleForTesting; 023 import com.google.common.collect.Maps; 024 import org.apache.commons.codec.binary.Base64; 025 import org.apache.commons.io.IOUtils; 026 import org.apache.commons.lang.StringUtils; 027 import org.sonar.api.utils.DateUtils; 028 029 import javax.annotation.Nullable; 030 031 import java.io.IOException; 032 import java.io.StringReader; 033 import java.util.Calendar; 034 import java.util.Date; 035 import java.util.List; 036 import java.util.Map; 037 038 /** 039 * SonarSource license. This class aims to extract metadata but not to validate or - of course - 040 * to generate license 041 * 042 * @since 3.0 043 */ 044 public final class License { 045 private String product; 046 private String organization; 047 private String expirationDate; 048 private String type; 049 private String server; 050 private Map<String, String> additionalProperties; 051 052 private License(Map<String, String> properties) { 053 this.additionalProperties = Maps.newHashMap(properties); 054 product = StringUtils.defaultString(get("Product", properties), get("Plugin", properties)); 055 organization = StringUtils.defaultString(get("Organisation", properties), get("Name", properties)); 056 expirationDate = StringUtils.defaultString(get("Expiration", properties), get("Expires", properties)); 057 type = get("Type", properties); 058 server = get("Server", properties); 059 // SONAR-4340 Don't expose Digest and Obeo properties 060 additionalProperties.remove("Digest"); 061 additionalProperties.remove("Obeo"); 062 } 063 064 private String get(String key, Map<String, String> properties) { 065 additionalProperties.remove(key); 066 return properties.get(key); 067 } 068 069 /** 070 * Get additional properties available on this license (like threshold conditions) 071 * @since 3.6 072 */ 073 public Map<String, String> additionalProperties() { 074 return additionalProperties; 075 } 076 077 @Nullable 078 public String getProduct() { 079 return product; 080 } 081 082 @Nullable 083 public String getOrganization() { 084 return organization; 085 } 086 087 @Nullable 088 public String getExpirationDateAsString() { 089 return expirationDate; 090 } 091 092 @Nullable 093 public Date getExpirationDate() { 094 return DateUtils.parseDateQuietly(expirationDate); 095 } 096 097 public boolean isExpired() { 098 return isExpired(new Date()); 099 } 100 101 @VisibleForTesting 102 boolean isExpired(Date now) { 103 Date date = getExpirationDate(); 104 return date != null && !date.after(org.apache.commons.lang.time.DateUtils.truncate(now, Calendar.DATE)); 105 } 106 107 @Nullable 108 public String getType() { 109 return type; 110 } 111 112 @Nullable 113 public String getServer() { 114 return server; 115 } 116 117 public static License readBase64(String base64) { 118 return readPlainText(new String(Base64.decodeBase64(base64.getBytes()))); 119 } 120 121 @VisibleForTesting 122 static License readPlainText(String data) { 123 Map<String, String> props = Maps.newHashMap(); 124 StringReader reader = new StringReader(data); 125 try { 126 List<String> lines = IOUtils.readLines(reader); 127 for (String line : lines) { 128 if (StringUtils.isNotBlank(line) && line.indexOf(':') > 0) { 129 String key = StringUtils.substringBefore(line, ":"); 130 String value = StringUtils.substringAfter(line, ":"); 131 props.put(StringUtils.trimToEmpty(key), StringUtils.trimToEmpty(value)); 132 } 133 } 134 135 } catch (IOException e) { 136 // silently ignore 137 138 } finally { 139 IOUtils.closeQuietly(reader); 140 } 141 return new License(props); 142 } 143 }