View Javadoc

1   /**
2    * - Digitalis Internal Framework v2.0 - (C) 2007, Digitalis Informatica. Distribuicao e Gestao de Informatica, Lda.
3    * Estrada de Paco de Arcos num.9 - Piso -1 2780-666 Paco de Arcos Telefone: (351) 21 4408990 Fax: (351) 21 4408999
4    * http://www.digitalis.pt
5    */
6   package pt.digitalis.dif.dem.objects;
7   
8   import java.text.ParseException;
9   import java.util.Date;
10  
11  import pt.digitalis.dif.startup.DIFGeneralConfigurationParameters;
12  import pt.digitalis.dif.utils.logging.DIFLogger;
13  import pt.digitalis.utils.common.DateUtils;
14  import pt.digitalis.utils.common.StringUtils;
15  import pt.digitalis.utils.crypto.IEncryptor;
16  import pt.digitalis.utils.crypto.exeption.CryptoException;
17  import pt.digitalis.utils.crypto.impl.EncryptorBase64Impl;
18  
19  /**
20   * @author Pedro Viegas <a href="mailto:pviegas@digitalis.pt">pviegas@digitalis.pt</a><br/>
21   * @created Nov 1, 2007
22   */
23  /**
24   * This class will hold the information of a given registration. It allows the management of registrations including
25   * creation and deletion. TODO: Candidate for another project.
26   * 
27   * @author Pedro Viegas <a href="mailto:pviegas@digitalis.pt">pviegas@digitalis.pt</a>
28   * @created Sep 26, 2007
29   */
30  public class LicenseImpl implements ILicense {
31  
32      /** Active Encryptor implementation. */
33      private static IEncryptor encryptor = null;
34  
35      /**
36       * Full version date.
37       */
38      private static final String FULL_VERSION_DATE = "00000000";
39  
40      /** just a variable */
41      private static final char[] hideInPlainSight = {(char) 97, (char) 115, (char) 100, (char) 97, (char) 97,
42                          (char) 115, (char) 100, (char) 102, (char) 56, (char) 115, (char) 97, (char) 100, (char) 57,
43                          (char) 102, (char) 56, (char) 55, (char) 97, (char) 115};
44  
45      /**
46       * Registration key spliter.
47       */
48      private static final String SPLITER_REGISTRATION_KEY = "-&-";
49  
50      /** The variable to return */
51      private static final String variableToReturn = new String(hideInPlainSight);
52  
53      /** The License Edition */
54      private LicenseEditionType edition;
55  
56      /** The entity id */
57      private String entityId;
58  
59      /** The licence expiration date */
60      private Date expirationDate = null;
61  
62      /** The registration key */
63      private String key;
64  
65      /** Use to see if the key as ben check once */
66      private Boolean keyChecked = false;
67  
68      /** The name of the registration */
69      private String name;
70  
71      /** True if it is possible to register this element */
72      private boolean registrable = true;
73  
74      /** The result of key check */
75      private boolean validKey = false;
76  
77      /**
78       * Constructor for an unregistered element
79       */
80      public LicenseImpl()
81      {}
82  
83      /**
84       * Constructor for an unregistered element
85       * 
86       * @param name
87       *            the name of the element
88       */
89      public LicenseImpl(String name)
90      {
91          this.name = name;
92      }
93  
94      /**
95       * Constructor for a registered element
96       * 
97       * @param name
98       *            the name of the element
99       * @param key
100      *            the key of the registered element
101      */
102     public LicenseImpl(String name, String key)
103     {
104         this.name = name;
105         this.key = key;
106     }
107 
108     /**
109      * @return the key validation
110      */
111     private boolean checkKey()
112     {
113         String client = getClientName();
114         boolean keyOk = false;
115 
116         try
117         {
118 
119             if (client == null || "".equals(client))
120             {
121                 DIFLogger.getLogger().debug("The client name is not configured.");
122                 return false;
123             }
124             if (this.entityId == null)
125             {
126                 DIFLogger.getLogger().debug("The entityID cannot be null.");
127                 return false;
128             }
129 
130             String theClient = StringUtils.removeAccents(client);
131             String theEntity = StringUtils.removeAccents(this.entityId);
132 
133             // Verifies if the key is null or doesn't has the two phases separator
134             if (!simpleKeyCheck(this.key))
135             {
136                 return false;
137             }
138 
139             // The two Phases separator
140             String[] str = this.key.split(SPLITER_REGISTRATION_KEY);
141 
142             // Phase One
143 
144             // Inverts the second step of the first phase
145             String aux = getEncryptator().decrypt(str[0]);
146 
147             // Obtains the client which has register the application (first step of first phase)
148             String clientEnc = getEncryptator().decrypt(aux, theEntity);
149 
150             // Verifies the client's authenticity
151             keyOk = clientEnc.equals(theClient);
152 
153             // Second phase - If the first phase was wrong it will not be necessary process the second
154             if (keyOk)
155             {
156                 // Inverts the third step of second phase
157                 aux = getEncryptator().decrypt(str[1]);
158 
159                 // Inverts the second step of second phase
160                 aux = getEncryptator().decrypt(aux, theEntity);
161 
162                 // Obtains the registry key expiration date (first step of second phase)
163                 String dateEnc = getEncryptator().decrypt(aux, theClient);
164 
165                 // Verify if is a trial version
166                 if (!dateEnc.equals(FULL_VERSION_DATE))
167                 {
168                     try
169                     {
170                         this.expirationDate = DateUtils.stringToSimpleDate(dateEnc);
171                         keyOk = !this.hasExpired();
172                     }
173                     catch (ParseException pe)
174                     {
175                         DIFLogger.getLogger().debug(pe.getMessage());
176                         keyOk = false;
177                     }
178                 }
179             }
180             // Third phase - Determine the edition
181             this.edition = LicenseEditionType.STANDARD;
182             if (keyOk && str.length > 2)
183             {
184                 try
185                 {
186                     // Inverts the third step of second phase
187                     aux = getEncryptator().decrypt(str[2]);
188 
189                     // Inverts the second step of second phase
190                     aux = getEncryptator().decrypt(aux, theEntity);
191 
192                     // Obtains the registry key exparicy date (first stpe of second phase)
193                     String decryptEdition = getEncryptator().decrypt(aux, theClient);
194 
195                     if (LicenseEditionType.PREMIUM.name().equals(decryptEdition))
196                     {
197                         this.edition = LicenseEditionType.PREMIUM;
198                     }
199                 }
200                 catch (CryptoException ce)
201                 {
202                     keyOk = false;
203                 }
204             }
205             this.name = clientEnc;
206         }
207         catch (CryptoException ce)
208         {
209             DIFLogger.getLogger().debug(ce.getMessage());
210             keyOk = false;
211         }
212         return keyOk;
213     }
214 
215     /**
216      * @see pt.digitalis.dif.dem.objects.ILicense#generateKey(java.lang.String, java.lang.String, java.lang.String,
217      *      pt.digitalis.dif.dem.objects.LicenseEditionType)
218      */
219     public String generateKey(String client, String entity, String date, LicenseEditionType edition)
220     {
221         if (edition == null)
222         {
223             edition = LicenseEditionType.STANDARD;
224         }
225 
226         if (date == null || "".equals(date.trim()))
227         {
228             date = FULL_VERSION_DATE;
229         }
230         String theClient;
231         if (client == null || "".equals(client.trim()))
232         {
233             theClient = StringUtils.removeAccents(this.getClientName());
234         }
235         else
236         {
237             theClient = StringUtils.removeAccents(client);
238         }
239 
240         String theApp = StringUtils.removeAccents(entity);
241 
242         String result = null;
243         String phaseOne = null;
244         String phaseTwo = null;
245         String phaseThree = null;
246         try
247         {
248             // Phase One
249 
250             // encrypts the institution(client) with the given application as key(seed)
251             String aux = getEncryptator().encrypt(theClient, theApp);
252 
253             // encrypts the result with the internal seed
254             phaseOne = getEncryptator().encrypt(aux);
255 
256             // Phase Two
257 
258             // Encrypts the date using the institution(Client) as base
259             aux = getEncryptator().encrypt(date, theClient);
260             // Encrypt the last result with the application as key(seed)
261             aux = getEncryptator().encrypt(aux, theApp);
262             // encriptar o resultado anterior com a key interna.
263             phaseTwo = getEncryptator().encrypt(aux);
264 
265             // Encrypts the Edition using the institution(Client) as base
266             aux = getEncryptator().encrypt(edition.name(), theClient);
267             // Encrypt the last result with the application as key(seed)
268             aux = getEncryptator().encrypt(aux, theApp);
269             // encriptar o resultado anterior com a key interna.
270             phaseThree = getEncryptator().encrypt(aux);
271 
272             // Concatenates the thow phases result with the separator
273             result = phaseOne + SPLITER_REGISTRATION_KEY + phaseTwo + SPLITER_REGISTRATION_KEY + phaseThree;
274 
275             return result;
276         }
277         catch (CryptoException ce)
278         {
279             DIFLogger.getLogger().info(ce.getMessage());
280 
281             return null;
282         }
283     }
284 
285     /**
286      * Get the Client Name
287      * 
288      * @return the Client Name
289      */
290     protected String getClientName()
291     {
292         return DIFGeneralConfigurationParameters.getInstance().getClient();
293     }
294 
295     /**
296      * @see pt.digitalis.dif.dem.objects.ILicense#getEdition()
297      */
298     public LicenseEditionType getEdition()
299     {
300 
301         LicenseEditionType result = null;
302         if (isRegistered())
303         {
304             result = this.edition;
305         }
306         return result;
307     }
308 
309     /**
310      * Get the active encryptor instance.
311      * 
312      * @return the encryptor instance
313      */
314     private IEncryptor getEncryptator()
315     {
316         if (encryptor == null)
317         {
318             encryptor = new EncryptorBase64Impl();
319             encryptor.setSeed(getSeed());
320         }
321         return encryptor;
322     }
323 
324     /**
325      * @see pt.digitalis.dif.dem.objects.ILicense#getExpirationDate()
326      */
327     public Date getExpirationDate()
328     {
329         return this.expirationDate;
330     }
331 
332     /**
333      * @see pt.digitalis.dif.dem.objects.ILicense#getKey()
334      */
335     public String getKey()
336     {
337         return key;
338     }
339 
340     /**
341      * @see pt.digitalis.dif.dem.objects.ILicense#getName()
342      */
343     public String getName()
344     {
345         return name;
346     }
347 
348     /**
349      * The defined default Seed for DIF.
350      * 
351      * @return the seed
352      */
353     protected String getSeed()
354     {
355         return variableToReturn;
356     }
357 
358     /**
359      * @see pt.digitalis.dif.dem.objects.ILicense#hasExpirationDate()
360      */
361     public boolean hasExpirationDate()
362     {
363         return this.getExpirationDate() != null;
364     }
365 
366     /**
367      * @see pt.digitalis.dif.dem.objects.ILicense#hasExpired()
368      */
369     public boolean hasExpired()
370     {
371         if (this.expirationDate == null)
372             return false;
373 
374         Date dateCur = DateUtils.getTrimmedDate();
375         // If the trial version expired will set an invalid key
376         return (dateCur.after(this.expirationDate));
377     }
378 
379     /**
380      * @see pt.digitalis.dif.dem.objects.ILicense#isRegistered()
381      */
382     public boolean isRegistered()
383     {
384 
385         if (this.keyChecked)
386         {
387             if (this.hasExpirationDate())
388             {
389                 return !this.hasExpired();
390             }
391             return this.isValidKey();
392         }
393         else
394         {
395             this.setValidKey(this.checkKey());
396             this.keyChecked = isValidKey();
397         }
398         return isValidKey();
399     }
400 
401     /**
402      * @see pt.digitalis.dif.dem.objects.ILicense#isRegistrable()
403      */
404     public boolean isRegistrable()
405     {
406         return registrable;
407     }
408 
409     /**
410      * Inspector for the 'validKey' attribute.
411      * 
412      * @return the validKey value
413      */
414     private boolean isValidKey()
415     {
416         return validKey;
417     }
418 
419     /**
420      * @see pt.digitalis.dif.dem.objects.ILicense#register(java.lang.String, java.lang.String)
421      */
422     public boolean register(String key, String entityId)
423     {
424         if (isRegistrable())
425         {
426             this.key = key;
427             this.entityId = entityId;
428             this.keyChecked = false;
429             return isRegistered();
430         }
431         else
432             return true;
433 
434     }
435 
436     /**
437      * @see pt.digitalis.dif.dem.objects.ILicense#setName(java.lang.String)
438      */
439     public void setName(String name)
440     {
441         this.name = name;
442     }
443 
444     /**
445      * @see pt.digitalis.dif.dem.objects.ILicense#setRegistrable(boolean)
446      */
447     public void setRegistrable(boolean registrable)
448     {
449         this.registrable = registrable;
450     }
451 
452     /**
453      * Modifier for the 'validKey' attribute.
454      * 
455      * @param validKey
456      *            the new validKey value to set
457      */
458     private void setValidKey(boolean validKey)
459     {
460         this.validKey = validKey;
461     }
462 
463     /**
464      * Checks if the key has the correct format.
465      * 
466      * @param _regKeyToCheck
467      *            the key to check
468      * @return <code>true</code> if the key is not <code>null</code> and has the correct format
469      */
470     private boolean simpleKeyCheck(String _regKeyToCheck)
471     {
472         // Verifies if the key is null or doesn't has the two phases separator
473         if (_regKeyToCheck == null || _regKeyToCheck.indexOf(SPLITER_REGISTRATION_KEY) == -1)
474         {
475             return false;
476         }
477         return true;
478     }
479 
480     /**
481      * @see pt.digitalis.dif.dem.objects.ILicense#unregister()
482      */
483     public void unregister()
484     {
485         key = null;
486         validKey = false;
487         this.keyChecked = false;
488         this.expirationDate = null;
489     }
490 
491 }