1 20 package fr.dyade.aaa.util; 21 22 import java.io.IOException ; 23 import java.io.OutputStream ; 24 import java.io.FileOutputStream ; 25 import java.io.InputStream ; 26 import java.util.Hashtable ; 27 import java.util.Properties ; 28 import java.util.StringTokenizer ; 29 import java.util.Vector ; 30 import org.apache.xml.serialize.OutputFormat; 31 import org.apache.xml.serialize.XMLSerializer; 32 import org.apache.xerces.dom.DocumentImpl; 33 import org.apache.xerces.parsers.DOMParser; 34 import org.w3c.dom.*; 35 import org.xml.sax.SAXException ; 36 import org.xml.sax.InputSource ; 37 38 40 public class AgentServerConfigGenerator{ 41 42 public static final String VAR_MARK = "$"; 43 public static final String CONFIG_TAG = "config"; 44 public static final String VAR_TAG = "var"; 45 public static final String SET_TAG = "serverSet"; 46 public static final String PROPERTY_TAG = "property"; 47 public static final String DOMAIN_TAG = "domain"; 48 public static final String NETWORK_TAG = "network"; 49 public static final String SERVER_TAG = "server"; 50 public static final String TRANSIENT_TAG = "transient"; 51 public static final String NAME = "name"; 52 public static final String ID = "id"; 53 public static final String PORT = "port"; 54 public static final String SERVER = "server"; 55 public static final String INFO = "info"; 56 public static final String VALUE = "value"; 57 public static final String TYPE = "type"; 58 public static final String A3_DTD = "a3config.dtd"; 59 60 private static final String DOMAINS_PREFIX = "D"; 61 private static final String ADMIN_SERVER_NAME = "s0"; 62 private static final String ADMIN_DOMAIN = "D0"; 63 private static final String GLOBALS = "GLOBALS"; 64 private int indent = 2; 65 private Element templateRoot; 66 private Hashtable defaultValues = new Hashtable (); 68 private Hashtable varsSet = new Hashtable (); 70 private String currentDomain = null; 71 private boolean merge = false; 72 73 76 public AgentServerConfigGenerator(String templateFile) 77 throws SAXException , IOException { 78 DOMParser parser = new DOMParser(); 79 parser.parse(templateFile); 80 init(parser); 81 } 82 83 public AgentServerConfigGenerator(InputStream template) 84 throws SAXException , IOException { 85 DOMParser parser = new DOMParser(); 86 parser.parse(new InputSource (template)); 87 init(parser); 88 } 89 90 private void init(DOMParser parser) throws SAXException , IOException { 91 Document doc = parser.getDocument(); 92 Element routerElement = doc.createElement(VAR_TAG); 95 routerElement.setAttribute(NAME, "domain.port"); 96 routerElement.setAttribute(TYPE, "java.lang.Integer"); 97 routerElement.setAttribute(INFO,"The port required on admin server to connect to new domain"); 98 templateRoot = doc.getDocumentElement(); 100 templateRoot.appendChild(routerElement); 101 } 102 103 106 public void setIndent(int indent){ 107 this.indent = indent; 108 } 109 110 113 public String [] getServerSetTypes(){ 114 NodeList childs = templateRoot.getChildNodes(); 115 Vector v = new Vector (); 116 for (int i=0; i<childs.getLength(); i++){ 117 Node currentNode = childs.item(i); 118 if (currentNode.getNodeType() == Node.ELEMENT_NODE && 119 currentNode.getNodeName().equals(SET_TAG)){ 120 v.addElement(currentNode.getAttributes().getNamedItem(NAME).getNodeValue()); 121 } 122 } 123 String [] res = new String [v.size()]; 124 v.copyInto(res); 125 return res; 126 } 127 128 129 130 148 160 public void merge(OutputStream totalConfig, OutputStream localConfig, 161 Properties p, InputStream previousConfig, 162 String instanceName) 163 throws IOException , A3configException, SAXException { 164 merge = true; 165 DOMParser parser = new DOMParser(); 167 parser.parse(new InputSource (previousConfig)); 168 Document previousDoc = parser.getDocument(); 169 Element previousRoot = previousDoc.getDocumentElement(); 170 currentDomain = instanceName; 173 DocumentImpl localDoc = new DocumentImpl(); 174 Element localRoot = localDoc.createElement(CONFIG_TAG); 178 localDoc.appendChild(localRoot); 179 buildSimpleElement(PROPERTY_TAG, localRoot, p); 180 buildSimpleElement(DOMAIN_TAG, localRoot, p); 181 short nextId = getNextId(previousRoot); 182 nextId = instantiateServers(nextId, localRoot, p); 183 previousRoot.setAttribute("nextServerId", "" + nextId); 184 updateConfs(localRoot, previousRoot, p); 186 write(previousDoc, totalConfig); 187 write(localDoc, localConfig); 188 } 189 190 private void updateImport(Element elem){ 195 NamedNodeMap attrs= elem.getAttributes(); 196 for (int i=0; i<attrs.getLength(); i++){ 197 attrs.item(i).getNodeName(); 198 attrs.item(i).getNodeValue(); 199 } 200 NodeList childs = elem.getChildNodes(); 201 for (int i=0; i<childs.getLength(); i++){ 202 if (childs.item(i).getNodeType() == Node.ELEMENT_NODE){ 204 updateImport((Element)childs.item(i)); 205 } 206 } 207 } 208 210 private void write(Document doc, OutputStream out) throws IOException { 211 OutputFormat format = new OutputFormat(doc); 212 format.setIndent(indent); 213 XMLSerializer serial = new XMLSerializer(out, format); 214 serial.asDOMSerializer(); 215 serial.serialize(doc); 216 out.flush(); 217 } 218 219 private static Element getChild(Element parent, String tagName, 220 String attrName, String attrValue) 221 throws A3configException{ 222 NodeList childs = parent.getChildNodes(); 223 Node required = null; 224 for (int i=0; i<childs.getLength(); i++){ 225 Node currentNode = childs.item(i); 226 if (currentNode.getNodeType() == Node.ELEMENT_NODE && 227 currentNode.getNodeName().equals(tagName)){ 228 Node attr = currentNode.getAttributes().getNamedItem(attrName); 229 if (attr != null && attr.getNodeValue().equals(attrValue)) 230 return (Element)currentNode; 231 } 232 } 233 throw new A3configException ("Unable to find " + tagName + 234 " element, with attr " + attrName + 235 " = " + attrValue); 236 } 237 238 241 public ConfigVariable[] getGlobalVariables() throws A3configException{ 242 varsSet.put(GLOBALS, GLOBALS); 243 return getVariables(templateRoot, true); 244 } 245 246 249 public ConfigVariable[] getServerSetVariables(String typeName) throws A3configException{ 250 varsSet.put(typeName, typeName); 251 Element elm = getChild(templateRoot, SET_TAG, NAME, typeName); 252 return getVariables(elm, true); 253 } 254 255 private short getNextId(Element elem){ 256 String lastId = elem.getAttribute("nextServerId"); 257 if (lastId == null || lastId.equals("")){ 258 return (short)1; 259 }else{ 260 return Short.parseShort(lastId); 261 } 262 268 } 284 285 301 private short instantiateServers(short nextId, Element root, Properties p) 302 throws A3configException{ 303 NodeList childs = templateRoot.getChildNodes(); 304 for (int i=0; i<childs.getLength(); i++){ 305 Node child = childs.item(i); 306 if (child.getNodeType() == Node.ELEMENT_NODE && 307 child.getNodeName().equals(SET_TAG)){ 308 String setName = 310 child.getAttributes().getNamedItem(NAME).getNodeValue(); 311 if (varsSet.get(setName) == null){ 313 getVariables(child, false); 314 } 315 String instances = p.getProperty(setName); 317 if (instances != null){ 318 StringTokenizer st = new StringTokenizer (instances, ","); 319 while(st.hasMoreElements()){ 320 String instanceName = ((String )st.nextElement()).trim(); 321 nextId = instantiateSet(instanceName, child, root, p, nextId); 322 } 323 } 324 } 325 } 326 if (nextId++ == Short.MAX_VALUE) 327 return (short)1; 328 return nextId; 329 } 330 331 332 private short instantiateSet(String instanceName, Node setNode, 333 Element root, Properties p, 334 short nextId) throws A3configException{ 335 NodeList childs = setNode.getChildNodes(); 336 int serversNb = countChilds(setNode, SERVER_TAG); 337 if (serversNb == 0) 339 throw new A3configException( 340 "A serverSet element must contain at least one server"); 341 int transientNb = countChilds(setNode, TRANSIENT_TAG); 342 int serverPrefixName = 1; 343 int transientPrefixName = 1; 344 Short firstServer = new Short (nextId); 345 Hashtable relativeIds = new Hashtable (); 346 for (int i=0; i<childs.getLength(); i++){ 348 Node sNode = childs.item(i); 349 if (sNode.getNodeType() == Node.ELEMENT_NODE && 350 sNode.getNodeName().equals(SERVER_TAG)){ 351 Element serverElt = instantiateElement(root.getOwnerDocument(), 352 instanceName, sNode, p); 353 String serverName = null; 355 if (serverElt.getAttributes().getNamedItem(NAME) != null){ 357 String definedName = 358 serverElt.getAttributes().getNamedItem(NAME).getNodeValue(); 359 if(! definedName.equals("")) 360 serverName = instanceName + "." + definedName; 361 } 362 if (serverName == null){ 363 serverName = instanceName; 364 if (serversNb > 1) 365 serverName += ("." + serverPrefixName ++); 366 } 367 serverElt.setAttribute(NAME, serverName); 381 Short id = new Short (nextId ++); 382 Node idNode = serverElt.getAttributes().getNamedItem(ID); 384 if (idNode != null){ 385 String relId = idNode.getNodeValue(); 386 if (relId != null && (! relId.equals(""))) 387 relativeIds.put(relId, id); 388 } 389 serverElt.setAttribute(ID, id.toString()); 390 NodeList serverChilds = sNode.getChildNodes(); 391 for (int j=0; j<serverChilds.getLength(); j++){ 392 if (serverChilds.item(j).getNodeType() == Node.ELEMENT_NODE) 393 serverElt.appendChild(instantiateElement(root.getOwnerDocument(), 394 instanceName, 395 serverChilds.item(j), 396 p)); 397 } 398 root.appendChild(serverElt); 399 } 400 } 401 for (int i=0; i<childs.getLength(); i++){ 402 Node tNode = childs.item(i); 403 if (tNode.getNodeType() == Node.ELEMENT_NODE && 404 tNode.getNodeName().equals(TRANSIENT_TAG)){ 405 Element transientElt = instantiateElement(root.getOwnerDocument(), 406 instanceName, tNode, p); 407 String transientName = 409 transientElt.getAttributes().getNamedItem(NAME).getNodeValue(); 410 if (transientName == null || transientName.equals("")){ 411 transientName = instanceName + ".transient"; 412 if (transientNb > 1) 413 transientName += ("." + transientPrefixName ++); 414 transientElt.setAttribute(NAME, transientName); 415 } 416 Short id = new Short (nextId ++); 418 transientElt.setAttribute(ID, id.toString()); 419 Node serverNode = transientElt.getAttributes().getNamedItem(SERVER); 421 String associatedServer = null; 422 Short serverId = null; 423 if (serverNode != null) 424 associatedServer = serverNode.getNodeValue(); 425 if (associatedServer == null || associatedServer.equals("")){ 426 serverId = firstServer; 428 }else{ 429 serverId = (Short )relativeIds.get(associatedServer); 430 } 431 if (serverId == null){ 432 throw new A3configException("transient " + transientName + 433 " has no associated server"); 434 } 435 transientElt.setAttribute(SERVER, serverId.toString()); 436 NodeList serverChilds = tNode.getChildNodes(); 437 for (int j=0; j<serverChilds.getLength(); j++){ 438 if (serverChilds.item(j).getNodeType() == Node.ELEMENT_NODE) 439 transientElt.appendChild( 440 instantiateElement(root.getOwnerDocument(), 441 instanceName, serverChilds.item(j), p)); 442 } 443 root.appendChild(transientElt); 444 } 445 } 446 return nextId; 447 } 448 449 450 private int countChilds(Node currentElt, String tagName){ 451 int nb = 0; 452 NodeList childs = currentElt.getChildNodes(); 453 for (int i=0; i<childs.getLength(); i++){ 454 Node currentNode = childs.item(i); 455 if (currentNode.getNodeType() == Node.ELEMENT_NODE && 456 currentNode.getNodeName().equals(tagName)) 457 nb++; 458 } 459 return nb; 460 } 461 462 private void buildSimpleElement(String tagName, Element root, Properties p) 463 throws A3configException{ 464 if (varsSet.get(GLOBALS) == null) 466 getVariables(templateRoot, false); 467 NodeList childs = templateRoot.getChildNodes(); 468 for (int i=0; i<childs.getLength(); i++){ 469 Node currentNode = childs.item(i); 470 if (currentNode.getNodeType() == Node.ELEMENT_NODE && 471 currentNode.getNodeName().equals(tagName)){ 472 root.appendChild(instantiateElement(root.getOwnerDocument(), 473 null, currentNode, p)); 474 } 475 } 476 } 477 478 479 private Element instantiateElement(Document doc, 481 String instance, 482 Node model, 483 Properties p) throws A3configException{ 484 Element instanceElt = (Element) doc.importNode(model, false); 485 NamedNodeMap attrs = model.getAttributes(); 486 for (int j=0; j<attrs.getLength(); j++){ 487 Node attrNode = attrs.item(j); 488 String attr = attrs.item(j).getNodeName(); 489 String attrValue = attrs.item(j).getNodeValue(); 490 if (attrNode.getNodeValue().startsWith(VAR_MARK)){ 491 String varName = attrValue.substring(1, attrValue.length()); 492 attrValue = null; 493 if (instance != null) 495 attrValue = p.getProperty(instance + "." + varName); 496 if (attrValue == null) 497 attrValue = p.getProperty(varName); 499 if (attrValue == null) 500 attrValue = (String )defaultValues.get(varName); 502 if (attrValue == null) 503 throw new A3configException("Variable " + 504 ((instance!=null) ? instance+"." : "") 505 + varName + 506 " not defined, no defaultValue"); 507 } 508 if (merge && (! attrValue.equals(TRANSIENT_TAG)) && 510 ((model.getNodeName().equals(NETWORK_TAG) 511 && attr.equals(DOMAIN_TAG)) || 512 (model.getNodeName().equals(DOMAIN_TAG) && attr.equals(NAME)))){ 513 attrValue = currentDomain + "." + attrValue; 514 } 515 instanceElt.setAttribute(attr, attrValue); 516 } 517 return instanceElt; 518 } 519 520 521 private ConfigVariable[] getVariables(Node node, boolean type) 522 throws A3configException{ 523 NodeList childs = node.getChildNodes(); 524 Vector v = new Vector (); 525 for (int i=0; i<childs.getLength(); i++){ 526 Node currentNode = childs.item(i); 527 if (currentNode.getNodeType() == Node.ELEMENT_NODE && 528 currentNode.getNodeName().equals(VAR_TAG)){ 529 NamedNodeMap attrs = currentNode.getAttributes(); 530 String name = attrs.getNamedItem(NAME).getNodeValue(); 531 Node valueNode = attrs.getNamedItem(VALUE); 532 String defaultValue = null; 533 if (valueNode != null){ 534 defaultValue = valueNode.getNodeValue(); 535 defaultValues.put(name, defaultValue); 536 } 537 if (!type) 538 continue; 539 Node infoNode = attrs.getNamedItem(INFO); 540 String info = null; 541 if (infoNode != null) 542 info = infoNode.getNodeValue(); 543 try{ 544 Class c = ConfigVariable.getClass( 545 attrs.getNamedItem(TYPE).getNodeValue()); 546 Object defaultObject = null; 547 if (defaultValue != null){ 548 defaultObject = ConfigVariable.getObject(c, defaultValue); 549 } 550 v.addElement(new ConfigVariable(name, c, defaultObject, info)); 551 }catch(Exception e){ 552 throw new A3configException("Error parsing variable type, variable " 553 + name + " has not a valid type"); 554 } 555 } 556 } 557 ConfigVariable[] res = new ConfigVariable[v.size()]; 558 v.copyInto(res); 559 return res; 560 } 561 562 563 564 private void updateConfs(Element localRoot,Element previousRoot, Properties p) 565 throws A3configException{ 566 NodeList childs = previousRoot.getChildNodes(); 568 for (int i=0; i<childs.getLength(); i++){ 569 Node currentNode = childs.item(i); 570 if (currentNode.getNodeType() == Node.ELEMENT_NODE && 571 currentNode.getNodeName().equals(PROPERTY_TAG)){ 572 try{ 573 Element oldPropr = getChild(localRoot, PROPERTY_TAG, NAME, 574 ((Element)currentNode).getAttribute(NAME)); 575 }catch(Exception e){ 576 updateImport((Element)currentNode); 578 localRoot.insertBefore( 579 localRoot.getOwnerDocument().importNode(currentNode, true), 580 localRoot.getFirstChild()); 581 } 582 } 583 } 584 Element D0Domain = getChild(previousRoot, DOMAIN_TAG, NAME, ADMIN_DOMAIN); 586 updateImport(D0Domain); 587 Element s0server = 589 getChild(previousRoot, SERVER_TAG, NAME, ADMIN_SERVER_NAME); 590 updateImport(s0server); 591 Element newDomain = null; 593 childs = localRoot.getChildNodes(); 594 for (int i=0; i<childs.getLength(); i++){ 595 Node currentNode = childs.item(i); 596 if (currentNode.getNodeType() == Node.ELEMENT_NODE && 597 currentNode.getNodeName().equals(DOMAIN_TAG)){ 598 newDomain = (Element)currentNode; 599 break; 600 } 601 } 602 if (newDomain == null) 603 throw new A3configException("No domain defined"); 604 String newDomainName = newDomain.getAttribute(NAME); 605 String routePort = p.getProperty("domain.port"); 607 if (routePort == null || Integer.parseInt(routePort)<1) 608 throw new A3configException( 609 "No port defined for admin server to route new application"); 610 checkRouterValid(previousRoot, routePort); 613 Element newDomainNetwork = 615 previousRoot.getOwnerDocument().createElement(NETWORK_TAG); 616 newDomainNetwork.setAttribute(DOMAIN_TAG, newDomainName); 617 newDomainNetwork.setAttribute(PORT, routePort); 618 s0server.insertBefore(newDomainNetwork, s0server.getFirstChild()); 619 Element firstNewServer = null; 621 for (int i=0; i<childs.getLength(); i++){ 622 Node currentNode = childs.item(i); 623 if (currentNode.getNodeType() == Node.ELEMENT_NODE && 624 currentNode.getNodeName().equals(SERVER_TAG) || 625 currentNode.getNodeName().equals(TRANSIENT_TAG)){ 626 if (firstNewServer == null) 627 firstNewServer = (Element)currentNode; 628 updateImport((Element)currentNode); 629 previousRoot.appendChild( 630 previousRoot.getOwnerDocument().importNode(currentNode, true)); 631 } 632 } 633 updateImport(newDomain); 635 previousRoot.insertBefore( 636 previousRoot.getOwnerDocument().importNode(newDomain, true), s0server); 637 updateImport(s0server); 639 Element localS0server = 640 (Element)(localRoot.getOwnerDocument().importNode(s0server, true)); 641 childs = localS0server.getChildNodes(); 642 for (int i=0; i<childs.getLength(); i++){ 643 Node currentNode = childs.item(i); 644 if (currentNode.getNodeType() == Node.ELEMENT_NODE && 645 currentNode.getNodeName().equals(NETWORK_TAG) && 646 ! currentNode.getAttributes().getNamedItem(DOMAIN_TAG). 647 getNodeValue().equals(ADMIN_DOMAIN) && 648 ! currentNode.getAttributes().getNamedItem(DOMAIN_TAG). 649 getNodeValue().equals(newDomainName)){ 650 localS0server.removeChild(currentNode); 651 } 652 } 653 localRoot.insertBefore(localS0server, firstNewServer); 654 updateImport(D0Domain); 655 localRoot.insertBefore( 656 localRoot.getOwnerDocument().importNode(D0Domain, true), localS0server); 657 } 658 659 private void checkRouterValid(Element previousRoot, String port) 660 throws A3configException{ 661 Element s0elt = getChild(previousRoot, "server", "id", "0"); 662 NodeList childs = s0elt.getChildNodes(); 663 for (int i=0; i<childs.getLength(); i++){ 664 Node currentNode = childs.item(i); 665 if (currentNode.getNodeType() == Node.ELEMENT_NODE && 666 currentNode.getNodeName().equals(NETWORK_TAG) && 667 currentNode.getAttributes().getNamedItem(PORT).getNodeValue(). 668 equals(port)) 669 throw new A3configException( 670 "The port " + port + " is already defined for domain " + 671 currentNode.getAttributes().getNamedItem(DOMAIN_TAG).getNodeValue()); 672 } 673 } 674 675 676 public static void deleteApplicationConfig(InputStream totalConfig, 677 InputStream localConfig, 678 String res) 679 throws Exception { 680 DOMParser parser = new DOMParser(); 681 parser.parse(new InputSource (totalConfig)); 682 Document resDoc = parser.getDocument(); 683 Element totalRoot = resDoc.getDocumentElement(); 684 parser.parse(new InputSource (localConfig)); 685 Element localRoot = parser.getDocument().getDocumentElement(); 686 Element s0server = getChild(totalRoot, SERVER, NAME, ADMIN_SERVER_NAME); 688 NodeList childs = localRoot.getChildNodes(); 690 for (int i=0; i<childs.getLength(); i++){ 691 Node child = childs.item(i); 692 if (child.getNodeType() == Node.ELEMENT_NODE){ 693 if (child.getNodeName().equals(DOMAIN_TAG)){ 694 String domainName = 695 child.getAttributes().getNamedItem(NAME).getNodeValue(); 696 if (! domainName.equals(ADMIN_DOMAIN)){ 697 removeChild(totalRoot, DOMAIN_TAG, NAME, domainName); 699 removeChild(s0server, NETWORK_TAG, DOMAIN_TAG, domainName); 701 } 702 }else if (child.getNodeName().equals(SERVER_TAG) 703 || child.getNodeName().equals(TRANSIENT_TAG)){ 704 String sid = child.getAttributes().getNamedItem(ID).getNodeValue(); 706 if (! sid.equals("0")) 707 removeChild(totalRoot, child.getNodeName(), ID, sid); 708 } 709 } 710 } 711 OutputFormat format = new OutputFormat(resDoc); 713 FileOutputStream fos = new FileOutputStream (res); 715 XMLSerializer serial = new XMLSerializer(fos, format); 716 serial.asDOMSerializer(); 717 serial.serialize(resDoc); 718 fos.flush(); 719 fos.close(); 720 } 721 722 private static void removeChild(Element parent, String tagName, 723 String attrName, String attrValue) 724 throws Exception { 725 NodeList childs = parent.getChildNodes(); 726 for (int i=0; i<childs.getLength(); i++){ 727 Node child = childs.item(i); 728 if (child.getNodeType() == Node.ELEMENT_NODE && 729 child.getNodeName().equals(tagName)){ 730 if (child.getAttributes().getNamedItem(attrName). 732 getNodeValue().equals(attrValue)){ 733 parent.removeChild(child); 734 return; 735 } 736 } 737 } 738 throw new Exception ("Unable to find tag " + tagName + " with attr " + 739 attrName + "=" + attrValue); 740 } 741 742 } 743 | Popular Tags |