1 6 7 package com.quikj.server.framework; 8 9 import java.util.*; 10 import java.io.*; 11 import java.security.*; 12 13 import javax.xml.parsers.*; 15 import org.xml.sax.*; 16 import org.w3c.dom.*; 17 18 22 public class AceLicenseManager 23 { 24 private String errorMessage = ""; 25 private static AceLicenseManager instance = null; 26 private HashMap featureList = new HashMap(); 27 private String encryptionSecret = null; 28 private String absPath = null; 29 30 public static final String ROOT_NODE_NAME = "license"; 31 32 public static final String EL_CODE = "code"; 33 public static final String ATT_CODE = "value"; 34 35 public static final String EL_FEATURE = "feature"; 36 public static final String ATT_NAME = "name"; 37 public static final String ATT_EXPIRES = "expires"; 38 public static final String ATT_UNITS = "units"; 39 public static final String ATT_CHECKSUM = "checksum"; 40 public static final String ATT_INDEX = "index"; 41 42 43 public AceLicenseManager(String dir, String file) 44 throws FileNotFoundException, IOException, SAXException, 45 AceException, ParserConfigurationException 46 { 47 this(AceConfigTableFileParser.getAcePath(AceConfigTableFileParser.LOCAL_DATA, 48 dir, file)); 49 } 50 51 public AceLicenseManager(String path) 52 throws FileNotFoundException, IOException, SAXException, 53 AceException, ParserConfigurationException 54 { 55 absPath = path; 56 57 loadLicenseFile(); 58 59 instance = this; 60 } 61 62 public static AceLicenseManager getInstance() 63 { 64 return instance; 65 } 66 67 70 public java.lang.String getErrorMessage() 71 { 72 return errorMessage; 73 } 74 75 public AceFeatureLicenseElement findFeature(String feature) 76 { 77 return (AceFeatureLicenseElement)featureList.get(feature); 78 } 79 80 public HashMap getFeatureList() 81 { 82 return featureList; 83 } 84 85 public synchronized boolean consumeUnits(String feature, int units) 86 { 87 AceFeatureLicenseElement element = findFeature(feature); 88 if (element == null) 89 { 90 errorMessage = "The feature \"" + feature + "\" was not found"; 91 return false; 92 } 93 94 ArrayList list = element.getElementList(); 95 int size = list.size(); 96 int count = 0; 97 Date cur_time = new Date(); 98 99 for (int i = 0; i < size; i++) 100 { 101 AceLicenseElement fe = (AceLicenseElement)list.get(i); 102 103 Date expire_date = fe.getFeatureExpires(); 105 if (expire_date != null) { 107 if (cur_time.getTime() >= expire_date.getTime()) 108 { 109 continue; 110 } 111 } 112 int units_assigned = fe.getUnitsAssigned(); 114 if (units_assigned > 0) 115 { 116 count += units_assigned; 117 } 118 else 119 { 120 count = -1; 124 break; 125 } 126 } 128 if (count == 0) 129 { 130 errorMessage = "The feature \"" + feature + "\" has expired"; 133 return false; 134 } 135 else if (count == -1) 136 { 137 return true; 139 } 140 else 141 { 142 int units_consumed = element.getUnitsConsumed(); 144 if (units_consumed + units > count) 145 { 146 errorMessage = "The feature \"" + feature 147 + "\" has exceeded the licensed quota"; 148 return false; 149 } 150 151 element.incrementUnitsConsumed(units); 152 return true; 153 } 154 155 } 156 157 public synchronized void returnUnits(String feature, int units) 158 { 159 AceFeatureLicenseElement element = findFeature(feature); 160 if (element != null) 161 { 162 element.decrementUnitsConsumed(units); 163 } 164 } 165 166 public synchronized boolean licenseFeature(String feature) 167 { 168 return consumeUnits(feature, 0); 169 } 170 171 172 public void loadLicenseFile() 173 throws FileNotFoundException, IOException, SAXException, 174 AceException, ParserConfigurationException 175 176 { 177 featureList.clear(); 178 179 File file = new File(absPath); 180 FileInputStream fis = new FileInputStream(file); 181 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 182 183 dbf.setValidating(false); 185 dbf.setIgnoringComments(true); 186 dbf.setIgnoringElementContentWhitespace(true); 187 dbf.setCoalescing(true); 188 DocumentBuilder doc_builder = dbf.newDocumentBuilder(); 189 190 Document doc = doc_builder.parse(fis); 191 192 processDoc(doc); 193 194 fis.close(); 195 } 196 197 private void processDoc(Node doc) 198 throws AceException 199 { 200 if (doc.getNodeType() != Node.DOCUMENT_NODE) 201 { 202 204 throw new AceException("Document does not begin with an XML node"); 205 } 206 207 Node root_element; 208 boolean root_found = false; 209 for (root_element = doc.getFirstChild(); 210 root_element != null; 211 root_element = root_element.getNextSibling()) 212 { 213 if (root_element.getNodeType() == Node.ELEMENT_NODE) 214 { 215 if (root_element.getNodeName().equals(ROOT_NODE_NAME) == false) 216 { 217 throw new AceException("Root node name " 218 + root_element.getNodeName() 219 + " must be " 220 + ROOT_NODE_NAME); 221 } 222 root_found = true; 223 break; 224 225 } 226 } 228 229 if (root_found == false) 230 { 231 throw new AceException("Root node " 232 + ROOT_NODE_NAME 233 + " not found"); 234 } 235 236 HashMap index_map = new HashMap(); 238 Node ele_node; 239 for (ele_node = root_element.getFirstChild(); 240 ele_node != null; 241 ele_node = ele_node.getNextSibling()) 242 { 243 if (ele_node.getNodeType() == Node.ELEMENT_NODE) 244 { 245 String name = ele_node.getNodeName(); 246 if (name.equals(EL_CODE) == true) 247 { 248 processCode(ele_node); 249 } 250 else if (name.equals(EL_FEATURE) == true) 251 { 252 processFeature(ele_node, index_map); 253 } 254 } 256 } 258 259 String error = validateParams(); 260 if (error != null) 261 { 262 throw new AceException(error); 263 } 264 } 265 266 private void processCode(Node node) 267 throws AceException 268 { 269 String code_s = AceXMLHelper.getXMLAttribute(node, 270 ATT_CODE); 271 if (code_s == null) 272 { 273 throw new AceException("The syntax for " 274 + EL_CODE 275 + " is incorrect"); 276 } 277 278 try 279 { 280 Encryption decryptor = new Encryption(); 281 encryptionSecret = decryptor.decrypt(code_s, 282 SysParam.getAuth1(getClass())); 283 if (encryptionSecret == null) 284 { 285 throw new AceException("Invalid code specified"); 286 } 287 } 288 catch (Exception ex) 289 { 290 throw new AceException(ex.getClass().getName() + " occured : " 291 + ex.getMessage()); 292 } 293 } 294 295 private void processFeature(Node node, HashMap map) 296 throws AceException 297 { 298 if (encryptionSecret == null) 299 { 300 throw new AceException("The code element must be specified first"); 301 } 302 303 String [] attributes = 304 { ATT_NAME, ATT_INDEX, ATT_UNITS, ATT_EXPIRES, ATT_CHECKSUM }; 305 306 String [] attrib_values = AceXMLHelper.getXMLAttributes(node, attributes); 307 308 if ((attrib_values[0] == null) || (attrib_values[1] == null) || (attrib_values[4] == null)) 309 { 310 throw new AceException("Either " + ATT_NAME + "," + ATT_INDEX + 311 " and/or " 312 + ATT_CHECKSUM + " not specified"); 313 } 314 315 String name = attrib_values[0]; 316 317 int index = -1; 318 try 319 { 320 index = Integer.parseInt(attrib_values[1]); 321 } 322 catch (NumberFormatException ex) 323 { 324 throw new AceException("Feature " + name + " has invalid value for " 325 + ATT_INDEX); 326 } 327 328 if (map.get(new Integer (index)) != null) 329 { 330 throw new AceException("Feature " + name + " has a duplicate index"); 331 } 332 333 int units = -1; 334 if (attrib_values[2] != null) 335 { 336 try 337 { 338 units = Integer.parseInt(attrib_values[2]); 339 } 340 catch (NumberFormatException ex) 341 { 342 throw new AceException("Feature " + name + " has invalid value for " 343 + ATT_UNITS); 344 } 345 } 346 347 Date date = null; 348 if (attrib_values[3] != null) 349 { 350 date = processDate(attrib_values[3]); 351 if (date == null) 352 { 353 throw new AceException("Feature " + name 354 + " has invalid value for " 355 + ATT_EXPIRES); 356 } 357 } 358 359 if (computeChecksum(name, units, date, index).equals(attrib_values[4]) 362 == false) 363 { 364 throw new AceException("Feature " + name + " has invalid checksum"); 365 } 366 367 AceFeatureLicenseElement fle = (AceFeatureLicenseElement)featureList.get(name); 369 if (fle != null) { 371 AceLicenseElement ale = new AceLicenseElement(name, units, date); 372 fle.addElement(ale); 373 } 374 else { 376 fle = new AceFeatureLicenseElement(); 377 AceLicenseElement ale = new AceLicenseElement(name, units, date); 378 fle.addElement(ale); 379 featureList.put(name, fle); 380 } 381 382 map.put(new Integer (index), new Integer (index)); 384 } 385 386 private String validateParams() 387 { 388 if (encryptionSecret == null) 389 { 390 return "Code element not specified"; 391 } 392 return null; 393 } 394 395 public static Date processDate(String date) 396 { 397 StringTokenizer tokens = new StringTokenizer(date, "-"); 398 try 399 { 400 int num = tokens.countTokens(); 401 if (num != 3) 402 { 403 return null; 404 } 405 406 int month = Calendar.JANUARY 407 + (Integer.parseInt(tokens.nextToken()) - 1); 408 int day = Integer.parseInt(tokens.nextToken()); 409 int year = Integer.parseInt(tokens.nextToken()); 410 411 412 414 Calendar cal = Calendar.getInstance(); 415 cal.setLenient(false); 416 417 try 418 { 419 cal.set(year, month, day, 0, 0, 0); 420 } 421 catch (Exception ex) 422 { 423 return null; 424 } 425 426 return cal.getTime(); 427 428 } 429 catch (NumberFormatException ex) 430 { 431 return null; 432 } 433 } 434 435 public static String computeChecksum(String name, int units, Date date, 436 int index, 437 String secret) 438 throws AceException 439 { 440 String date_s = null; 441 if (date != null) 442 { 443 date_s = date.toString(); 444 } 445 else 446 { 447 date_s = "null"; 448 } 449 450 String str = secret + name + index + units + date_s + secret; 451 452 try 453 { 454 MessageDigest md = MessageDigest.getInstance("MD5"); 455 byte[] output = md.digest(str.getBytes()); 456 457 return Encryption.byteToString(output); 458 } 459 catch (NoSuchAlgorithmException ex) 460 { 461 throw new AceException("Checksum compute failed : " 462 + ex.getMessage()); 463 } 464 } 465 466 private String computeChecksum(String name, int units, Date date, int index) 467 throws AceException 468 { 469 return computeChecksum(name, units, date, index, encryptionSecret); 470 } 471 472 public static void main(String [] args) 473 { 474 try 475 { 476 AceLicenseManager a = new AceLicenseManager(args[0]); 477 } 478 catch (Exception ex) 479 { 480 System.err.println(ex.getClass().getName() + " : " + ex.getMessage()); 481 } 482 483 System.exit(0); 484 } 485 } 486 | Popular Tags |