KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sapia > util > license > LicenseRecord


1 package org.sapia.util.license;
2
3 import java.io.IOException JavaDoc;
4 import java.io.Serializable JavaDoc;
5 import java.security.PrivateKey JavaDoc;
6 import java.security.PublicKey JavaDoc;
7 import java.security.Signature JavaDoc;
8
9 /**
10  * An instance of this class holds a <code>License</code> object, a digital signature (kept as a byte array), and
11  * a public key. The digital signature was created upong signing the license's serialized bytes.
12  * <p>
13  * An instance of this class is normally given to a licensee (the beholder of a license, in legal terms). The public
14  * key held within an instance of this class is used on the licensee's side to ensure that the license is properly signed
15  * (more concretely: to ensure that a given license cannot be generated by another party than the licensing one).
16  * <p>
17  * A <code>License</code> record should be kept at the licensee (it is typically serialized in a file). Application code can then
18  * use the license object to ensure that the licensee has the proper rights (concretely: that in can use the application).
19  *
20  * @author Yanick Duchesne
21  *
22  * <dl>
23  * <dt><b>Copyright:</b><dd>Copyright &#169; 2002-2004 <a HREF="http://www.sapia-oss.org">Sapia Open Source Software</a>. All Rights Reserved.</dd></dt>
24  * <dt><b>License:</b><dd>Read the license.txt file of the jar or visit the
25  * <a HREF="http://www.sapia-oss.org/license.html">license page</a> at the Sapia OSS web site</dd></dt>
26  * </dl>
27  */

28 public class LicenseRecord implements Serializable JavaDoc{
29   
30   static final long serialVersionUID = 1L;
31   
32   private RecData _data;
33   private Object JavaDoc _vendorId;
34   private transient boolean _init, _valid;
35   private transient PublicKey JavaDoc _key;
36   private boolean _activated;
37   private long _id;
38     
39   LicenseRecord(Object JavaDoc vendorId, License license, byte[] sig, byte[] publicKey, long id){
40     _vendorId = vendorId;
41     _data = new RecData(sig, publicKey, license);
42     _id = id;
43   }
44   
45   /**
46    * This method internally checks that the digital signature of the license
47    * held by this instance corresponds to the internally kept public key, and
48    * that the <code>isValid()</code> method of the encapsulated <code>License</code>
49    * returns <code>true</code>.
50    * <p>
51    * If the digital signature does not match, or if the <code>License</code> is not
52    * valid, the this method returns <code>false</code>.
53
54    * @param context an arbitratry context <code>Object</code> that is
55    * eventually passed to the encapsulated <code>License</code> object.
56    * @param fac a <code>SecurityFactory</code>.
57    * @return <code>true</code> if the license held by this instance is valid.
58    * @throws IOException
59    * @throws Exception
60  
61    */

62   public boolean isValid(Object JavaDoc context, SecurityFactory fac) throws IOException JavaDoc, Exception JavaDoc{
63     if(!_init){
64       Signature JavaDoc algo = fac.newSignature("SHA/DSA");
65       _key = fac.generatePublic(_data._key);
66       algo.initVerify(_key);
67       byte[] toVerify = _data._license.getBytes();
68       algo.update(toVerify);
69       _valid = algo.verify(_data._sig);
70       _init = true;
71     }
72     if(!_valid){
73       return false;
74     }
75     return _valid = _data._license.isValid(context);
76     
77   }
78   
79   /**
80    * Activates the license that this instance encapsulates. This
81    * method should only be called once in this instance's lifecycle.
82    *
83    * @param context an arbitrary <code>Context</code> object.
84    */

85   public void activate(Object JavaDoc context){
86     if(!_activated){
87       _data._license.activate(context);
88       _activated = true;
89     }
90   }
91   
92   /**
93    * Updates this instance with the <code>License</code> that the
94    * passed in record contains.
95    * <p>
96    * This method can be used on the client side to insure that a license update
97    * is valid (a given license cannot be reused twice).
98    * <p>
99    * This method internally activates the license with which it is updated.
100    *
101    * @param newRecord a <code>LicenseRecord</code>.
102    * @param context an arbitrary context <code>Object</code>.
103    * @return <code>true</code> if the new data is accepted.
104    * @see License#activate(Object)
105    */

106   public synchronized boolean update(LicenseRecord newRecord, Object JavaDoc context){
107     if(_id >= newRecord._id){
108       return false;
109     }
110     if(newRecord._vendorId == null || !newRecord._vendorId.equals(_vendorId)){
111       return false;
112     }
113     _data = newRecord._data;
114     _id = newRecord._id;
115     _init = false;
116     _data._license.activate(context);
117     return true;
118   }
119   
120   /**
121    * This method creates an instance of this class, given the provided license and key pair.
122    * Internally, this method signs the bytes of the serialized license. The digital signature, as
123    * well as the public key present in the key pair, is kept within the returned <code>LicenseRecord</code>.
124    *
125    * @param license a <code>License</code>.
126    * @param pub the <code>PublicKey</code> corresponding to this instance.
127    * @param priv the <code>PrivateKey</code> corresponding to this instance.
128    * @param factory the <code>SecurityFactory</code> to use when internally creating
129    * @param idFactory the <code>LicenseIdFactory</code> to use to internally create license identifiers.
130    * @return a <code>LicenseRecord</code>
131    * @throws IOException if an IO problem occurs.
132    * @throws Exception if a low-level problem occurs.
133    */

134   public static LicenseRecord newInstance(Object JavaDoc vendorId,
135                                           License license,
136                                           PublicKey JavaDoc pub,
137                                           PrivateKey JavaDoc priv,
138                                           SecurityFactory factory,
139                                           LicenseIdFactory idFactory) throws IOException JavaDoc, Exception JavaDoc{
140     Signature JavaDoc algo = factory.newSignature("SHA/DSA");
141     algo.initSign(priv);
142     byte[] toSign = license.getBytes();
143     algo.update(toSign);
144     byte[] sig = algo.sign();
145     return new LicenseRecord(vendorId, license, sig, pub.getEncoded(), idFactory.newInstance());
146   }
147   
148   synchronized void registerNewLicense(Object JavaDoc vendorId,
149                                        License license,
150                                        PublicKey JavaDoc pub,
151                                        PrivateKey JavaDoc priv,
152                                        SecurityFactory factory,
153                                        LicenseIdFactory idFactory) throws IOException JavaDoc, Exception JavaDoc{
154     LicenseRecord rec = LicenseRecord.newInstance(vendorId, license, pub, priv, factory, idFactory);
155     if(_key == null){
156       _key = factory.generatePublic(_data._key);
157     }
158     if(!_key.equals(pub)){
159       throw new IllegalArgumentException JavaDoc("A license must be updated with existing public/private keys");
160     }
161     _data = rec._data;
162     _id = rec._id;
163     _init = false;
164   }
165   
166   static final class RecData implements Serializable JavaDoc{
167     
168     static final long serialVersionUID = 1L;
169     
170     private byte[] _sig;
171     private byte[] _key;
172     private License _license;
173     
174     public RecData(byte[] sig, byte[] key, License license){
175       _sig = sig;
176       _key = key;
177       _license = license;
178     }
179
180   }
181 }
182
183
Popular Tags