View Javadoc
1   package com.atlassian.refapp.sal.license;
2   
3   import com.atlassian.extras.api.AtlassianLicense;
4   import com.atlassian.extras.api.LicenseException;
5   import com.atlassian.extras.api.LicenseManager;
6   import com.atlassian.extras.api.Product;
7   import com.atlassian.extras.core.AtlassianLicenseFactory;
8   import com.atlassian.extras.core.DefaultAtlassianLicenseFactory;
9   import com.atlassian.extras.core.DefaultLicenseManager;
10  import com.atlassian.extras.core.ProductLicenseFactory;
11  import com.atlassian.extras.decoder.api.LicenseDecoder;
12  import com.atlassian.extras.decoder.v2.Version2LicenseDecoder;
13  import com.atlassian.plugin.spring.scanner.annotation.export.ExportAsService;
14  import com.atlassian.sal.api.license.BaseLicenseDetails;
15  import com.atlassian.sal.api.license.LicenseHandler;
16  import com.atlassian.sal.api.license.MultiProductLicenseDetails;
17  import com.atlassian.sal.api.license.ProductLicense;
18  import com.atlassian.sal.api.license.SingleProductLicenseDetailsView;
19  import com.atlassian.sal.api.validate.ValidationResult;
20  import com.google.common.base.Function;
21  import com.google.common.collect.ImmutableList;
22  import com.google.common.collect.ImmutableMap;
23  import com.google.common.collect.ImmutableSet;
24  import org.apache.commons.lang.StringUtils;
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  import javax.annotation.Nonnull;
29  import javax.annotation.Nullable;
30  import javax.inject.Named;
31  import java.util.Collection;
32  import java.util.Date;
33  import java.util.Locale;
34  import java.util.Map;
35  import java.util.Set;
36  import java.util.SortedSet;
37  import java.util.TreeSet;
38  
39  import static com.google.common.collect.Collections2.transform;
40  
41  /**
42   * Simple implementation of license handler
43   */
44  @ExportAsService
45  @Named("licenseHandler")
46  public class RefimplLicenseHandler implements LicenseHandler {
47      private static final Log log = LogFactory.getLog(RefimplLicenseHandler.class);
48  
49      private final LicenseManager licenseManager;
50  
51      private String license;
52  
53      public RefimplLicenseHandler() {
54          final LicenseDecoder licenseDecoder = new Version2LicenseDecoder();
55          final ProductLicenseFactory productLicenseFactory = new RefappProduct.RefappProductLicenseFactory();
56          final Map<Product, ProductLicenseFactory> licenseMap = ImmutableMap.of(RefappProduct.REFAPP, productLicenseFactory);
57          final AtlassianLicenseFactory atlassianLicenseFactory = new DefaultAtlassianLicenseFactory(licenseMap);
58          licenseManager = new DefaultLicenseManager(licenseDecoder, atlassianLicenseFactory);
59      }
60  
61      /**
62       * Sets the license, going through the regular validation steps as if you used the web UI
63       *
64       * @param license The license string
65       */
66      @Override
67      @Deprecated
68      public void setLicense(final String license) {
69          addProductLicense(RefappProduct.REFAPP.getNamespace(), license);
70      }
71  
72  
73      @Override
74      public boolean hostAllowsMultipleLicenses() {
75          return false;
76      }
77  
78      @Override
79      public boolean hostAllowsCustomProducts() {
80          return false;
81      }
82  
83      @Override
84      public Set<String> getProductKeys() {
85          return ImmutableSet.of(RefappProduct.REFAPP.getNamespace());
86      }
87  
88      @Override
89      public void addProductLicense(@Nonnull final String productKey, @Nonnull final String license) {
90          final String refappProductId = RefappProduct.REFAPP.getNamespace();
91          if (!refappProductId.equals(productKey)) {
92              throw new IllegalArgumentException("Refapp only supports '" + refappProductId + "' licenses");
93          }
94  
95          log.info("Setting license " + license);
96          final ValidationResult validationResult = validateProductLicense(refappProductId, license, null);
97  
98          if (validationResult.isValid()) {
99              this.license = license;
100         } else {
101             final String message = StringUtils.join(validationResult.getErrorMessages().iterator(), ", ");
102             throw new IllegalArgumentException("Invalid License: " + message);
103         }
104     }
105 
106     @Override
107     public void removeProductLicense(@Nonnull final String productKey) {
108         if (RefappProduct.REFAPP.getNamespace().equals(productKey)) {
109             throw new IllegalStateException("Cannot remove last license from Refapp");
110         }
111         // else just do nothing - removing a license we don't have is a no-op
112     }
113 
114     @Override
115     @Nonnull
116     public ValidationResult validateProductLicense(
117             @Nonnull final String productKey,
118             @Nonnull final String license,
119             @Nullable final Locale locale) {
120         try {
121             if (!RefappProduct.REFAPP.getNamespace().equals(productKey)) {
122                 return ValidationResult.withErrorMessages(ImmutableList.of("Unknown product '" + productKey + "'"));
123             }
124 
125             final AtlassianLicense atlassianLicense = licenseManager.getLicense(license);
126             if (null == atlassianLicense) {
127                 return ValidationResult.withErrorMessages(ImmutableList.of("Failed to parse license '" + license + "'"));
128             }
129 
130             // It feels like we should check the license contains a Refapp license, but the default license in the CTK doesn't,
131             // and consequently Refapp fails the CTK if we check for this.
132             // if (null == atlassianLicense.getProductLicense(RefappProduct.REFAPP))
133             // {
134             //     return ValidationResult.withErrorMessages(ImmutableList.of("No License for '" + RefappProduct.REFAPP + "'"));
135             // }
136 
137             return ValidationResult.valid();
138         } catch (final LicenseException el) {
139             return ValidationResult.withErrorMessages(ImmutableList.of(el.getMessage()));
140         }
141     }
142 
143     /**
144      * Gets the server ID of the currently running application.
145      *
146      * @return the server ID.
147      */
148     @Override
149     @Nullable
150     public String getServerId() {
151         return "AREF-IMPL-SERV-ERID";
152     }
153 
154     /**
155      * Gets the Support Entitlement Number (SEN) for the currently running application.
156      *
157      * @return the Support Entitlement Number, or {@code null} if there is no current support entitlement.
158      */
159     @Override
160     @Nullable
161     @Deprecated
162     public String getSupportEntitlementNumber() {
163         return null;
164     }
165 
166     @Nonnull
167     @Override
168     public SortedSet<String> getAllSupportEntitlementNumbers() {
169         return new TreeSet<String>();
170     }
171 
172     @Override
173     @Nullable
174     public String getRawProductLicense(final String productKey) {
175         return (RefappProduct.REFAPP.getNamespace().equals(productKey)) ? license : null;
176     }
177 
178     @Override
179     @Nullable
180     public SingleProductLicenseDetailsView getProductLicenseDetails(@Nonnull final String productKey) {
181         final AtlassianLicense atlassianLicense = licenseManager.getLicense(license);
182         for (final com.atlassian.extras.api.ProductLicense productLicense : atlassianLicense.getProductLicenses()) {
183             if (productLicense.getProduct().getNamespace().equals(productKey)) {
184                 return new SingleProductLicenseDetailsViewImpl(productLicense);
185             }
186         }
187         return null;
188     }
189 
190     @Override
191     @Nonnull
192     public Collection<MultiProductLicenseDetails> getAllProductLicenses() {
193         return ImmutableList.of(decodeLicenseDetails(license));
194     }
195 
196     @Override
197     @Nonnull
198     public MultiProductLicenseDetails decodeLicenseDetails(@Nonnull final String licenseString) {
199         final AtlassianLicense atlassianLicense = licenseManager.getLicense(licenseString);
200         final com.atlassian.extras.api.ProductLicense refappLicense = atlassianLicense.getProductLicense(RefappProduct.REFAPP);
201         if (null == refappLicense) {
202             throw new IllegalArgumentException("Cannot decode license '" + licenseString + "'");
203         }
204 
205         return new MultiProductLicenseDetailsImpl(atlassianLicense, refappLicense);
206     }
207 
208     private static class BaseLicenseDetailsImpl implements BaseLicenseDetails {
209         private final com.atlassian.extras.api.ProductLicense extrasProductLicense;
210 
211         BaseLicenseDetailsImpl(final com.atlassian.extras.api.ProductLicense extrasProductLicense) {
212             this.extrasProductLicense = extrasProductLicense;
213         }
214 
215         public com.atlassian.extras.api.ProductLicense getExtrasProductLicense() {
216             return extrasProductLicense;
217         }
218 
219         @Override
220         public boolean isEvaluationLicense() {
221             return extrasProductLicense.isEvaluation();
222         }
223 
224         @Override
225         @Nonnull
226         public String getLicenseTypeName() {
227             return extrasProductLicense.getLicenseType().name();
228         }
229 
230         @Override
231         public String getOrganisationName() {
232             return extrasProductLicense.getOrganisation().getName();
233         }
234 
235         @Override
236         @Nullable
237         public String getSupportEntitlementNumber() {
238             return extrasProductLicense.getSupportEntitlementNumber();
239         }
240 
241         @Override
242         public String getDescription() {
243             return extrasProductLicense.getDescription();
244         }
245 
246         @Override
247         public String getServerId() {
248             return extrasProductLicense.getServerId();
249         }
250 
251         @Override
252         public boolean isPerpetualLicense() {
253             return (null == extrasProductLicense.getExpiryDate());
254         }
255 
256         @Override
257         @Nullable
258         public Date getLicenseExpiryDate() {
259             return extrasProductLicense.getExpiryDate();
260         }
261 
262         @Override
263         @Nullable
264         public Date getMaintenanceExpiryDate() {
265             return extrasProductLicense.getMaintenanceExpiryDate();
266         }
267 
268         @Override
269         public boolean isDataCenter() {
270             return extrasProductLicense.isClusteringEnabled();
271         }
272 
273         @Override
274         public boolean isEnterpriseLicensingAgreement() {
275             // No analogue in "extras" licenses
276             return false;
277         }
278 
279         @Override
280         @Nullable
281         public String getProperty(@Nonnull final String key) {
282             return extrasProductLicense.getProperty(key);
283         }
284     }
285 
286     private static class SingleProductLicenseDetailsViewImpl
287             extends BaseLicenseDetailsImpl
288             implements SingleProductLicenseDetailsView {
289         public SingleProductLicenseDetailsViewImpl(final com.atlassian.extras.api.ProductLicense extrasProductLicense) {
290             super(extrasProductLicense);
291         }
292 
293         @Override
294         @Nonnull
295         public String getProductKey() {
296             return getExtrasProductLicense().getProduct().getNamespace();
297         }
298 
299         @Override
300         public boolean isUnlimitedNumberOfUsers() {
301             return getExtrasProductLicense().isUnlimitedNumberOfUsers();
302         }
303 
304         @Override
305         public int getNumberOfUsers() {
306             return getExtrasProductLicense().getMaximumNumberOfUsers();
307         }
308 
309         @Override
310         @Nonnull
311         public String getProductDisplayName() {
312             return getExtrasProductLicense().getProduct().getName();
313         }
314     }
315 
316     private static class MultiProductLicenseDetailsImpl
317             extends BaseLicenseDetailsImpl
318             implements MultiProductLicenseDetails {
319         private final AtlassianLicense atlassianLicense;
320 
321         public MultiProductLicenseDetailsImpl(
322                 final AtlassianLicense atlassianLicense,
323                 final com.atlassian.extras.api.ProductLicense extrasProductLicense) {
324             super(extrasProductLicense);
325             this.atlassianLicense = atlassianLicense;
326         }
327 
328         @Nonnull
329         @Override
330         public Set<ProductLicense> getProductLicenses() {
331             return ImmutableSet.copyOf(
332                     transform(atlassianLicense.getProductLicenses(),
333                             new Function<com.atlassian.extras.api.ProductLicense, com.atlassian.sal.api.license.ProductLicense>() {
334                                 @Override
335                                 public com.atlassian.sal.api.license.ProductLicense
336                                 apply(@Nullable final com.atlassian.extras.api.ProductLicense extrasProductLicense) {
337                                     return (null == extrasProductLicense)
338                                             ? null
339                                             : new SingleProductLicenseDetailsViewImpl(extrasProductLicense);
340                                 }
341                             })
342             );
343         }
344 
345         @Nonnull
346         @Override
347         public Set<ProductLicense> getEmbeddedLicenses() {
348             return ImmutableSet.of();
349         }
350 
351         @Override
352         @Nullable
353         public com.atlassian.sal.api.license.ProductLicense getProductLicense(@Nonnull final String productKey) {
354             for (final com.atlassian.sal.api.license.ProductLicense salProductLicense : getProductLicenses()) {
355                 if (salProductLicense.getProductKey().equals(productKey)) {
356                     return salProductLicense;
357                 }
358             }
359 
360             return null;
361         }
362 
363     }
364 }