-- adapted Spittoon to configure and connect to remote eXist instances
[Spittoon.git] / src / com / interrupt / spittoon / Spittoon.java
blob6f1c148fd79efc07458e62d0e9c107f2bc7ba10d
1 package com.interrupt.spittoon;
3 import java.io.ByteArrayInputStream;
4 import java.io.InputStream;
5 import java.io.UnsupportedEncodingException;
6 import java.util.Iterator;
7 import java.util.List;
8 import java.util.Properties;
9 import java.util.Set;
10 import java.util.StringTokenizer;
12 import javax.servlet.ServletException;
14 import org.xmldb.api.DatabaseManager;
15 import org.xmldb.api.base.Collection;
16 import org.xmldb.api.base.Database;
17 import org.xmldb.api.base.XMLDBException;
18 import org.xmldb.api.modules.CollectionManagementService;
19 import org.xmldb.api.modules.XMLResource;
20 import org.apache.log4j.Logger;
21 import org.exist.EXistException;
22 import org.exist.storage.BrokerPool;
23 import org.exist.util.Configuration;
24 import org.exist.util.DatabaseConfigurationException;
26 import com.interrupt.bob.base.Bob;
27 import com.interrupt.bob.base.IBob;
28 import com.interrupt.bob.util.Util;
31 public class Spittoon {
34 private String DRIVER = "org.exist.xmldb.DatabaseImpl";
35 private Properties props = new Properties();
36 private Properties mappings = new Properties();
38 private String rawDbUrl = null;
39 private String aauthDbUrl = null;
40 private String groupsDbUrl = null;
42 private String rootDir = null;
43 private String uname = null;
44 private String passwd = null;
46 private Logger logger = Logger.getLogger(Spittoon.class);
47 private Database databaseAauth = null;
48 private Database databaseGroups = null;
50 public String getAauthDbUrl() { return aauthDbUrl; }
51 public void setAauthDbUrl(String aauthDbUrl) { this.aauthDbUrl = aauthDbUrl; }
52 public String getGroupsDbUrl() { return groupsDbUrl; }
55 public void setGroupsDbUrl(String groupsDbUrl) {
56 this.groupsDbUrl = groupsDbUrl;
59 public void initialise() {
61 try {
63 //** load spittoon.properties
64 InputStream inStream = Spittoon.class.getResourceAsStream("/spittoon.properties");
65 props.load(inStream);
67 String einitDb = System.getProperty("exist.initdb");
68 if(einitDb == null || einitDb.trim().length() < 1)
69 einitDb = props.getProperty("exist.initdb");
71 String ehome = System.getProperty("exist.home");
72 if(ehome == null || ehome.trim().length() < 1)
73 ehome = props.getProperty("exist.home");
75 String eSaxValidation = System.getProperty("org.xml.sax.features.validation");
76 if(eSaxValidation == null || eSaxValidation.trim().length() < 1)
77 eSaxValidation = props.getProperty("org.xml.sax.features.validation");
79 String eEndorsedDirs = System.getProperty("java.endorsed.dirs");
80 if(eEndorsedDirs == null || eEndorsedDirs.trim().length() < 1)
81 eEndorsedDirs = props.getProperty("java.endorsed.dirs");
84 logger.debug("exist.initdb["+einitDb+"] / exist.home["+ehome+
85 "] / org.xml.sax.features.validation["+eSaxValidation+"] / java.endorsed.dirs["+eEndorsedDirs+"]");
87 String db1Config = props.getProperty("db-1-config");
88 String db1Id = props.getProperty("db-1-id").trim();
89 String db1Port = props.getProperty("db-1-port");
91 String db2Config = props.getProperty("db-2-config").trim();
92 String db2Id = props.getProperty("db-2-id");
93 String db2Port = props.getProperty("db-2-port");
94 logger.debug("Database / config-1["+ db1Config +"] / id-1["+ db1Id +"] / port-1["+db1Port+"]");
95 logger.debug("Database / config-2["+ db2Config +"] / id-2["+ db2Id +"] / port-2["+db2Port+"]");
99 //** initialize driver
100 Class cl = Class.forName(DRIVER);
102 databaseAauth = (Database)cl.newInstance();
103 databaseAauth.setProperty("create-database", einitDb);
104 databaseAauth.setProperty("configuration", db1Config);
105 databaseAauth.setProperty("database-id", db1Id);
106 DatabaseManager.registerDatabase(databaseAauth);
107 logger.debug("Database registered["+ databaseAauth.getName() +"]");
109 databaseGroups = (Database)cl.newInstance();
110 databaseGroups.setProperty("create-database", einitDb);
111 databaseGroups.setProperty("configuration", db2Config);
112 databaseGroups.setProperty("database-id", db2Id);
113 DatabaseManager.registerDatabase(databaseGroups);
114 logger.debug("Database registered["+ databaseGroups.getName() +"]");
117 System.setProperty("exist.initdb", einitDb);
118 System.setProperty("exist.home", ehome);
119 System.setProperty("org.xml.sax.features.validation", eSaxValidation);
120 System.setProperty("java.endorsed.dirs", eEndorsedDirs);
122 //** extract the mappings into a separate properties object
123 extractMappings();
126 //** eXist Broker Pool properties; initialize from properties
127 rawDbUrl = props.getProperty("db.url");
128 rootDir = props.getProperty("root.dir", "root.dir");
129 uname = props.getProperty("db.uname");
130 passwd = props.getProperty("db.passwd");
132 rawDbUrl = rawDbUrl.trim();
133 rootDir = rootDir.trim();
134 uname = uname.trim();
135 passwd = passwd.trim();
137 if(einitDb.equals("true")) {
138 aauthDbUrl = rawDbUrl.replaceFirst("exist", db1Id);
139 groupsDbUrl = rawDbUrl.replaceFirst("exist", db2Id);
141 else {
143 aauthDbUrl = rawDbUrl.replaceFirst("exist", db1Id);
144 groupsDbUrl = rawDbUrl.replaceFirst("exist", db2Id);
146 aauthDbUrl = aauthDbUrl.replaceFirst("8080", db1Port);
147 groupsDbUrl = groupsDbUrl.replaceFirst("8080", db2Port);
150 logger.debug("RawDBURL["+rawDbUrl+"] / ROOT["+rootDir+"] / UNAME["+uname+"] / PASSWD["+passwd+"]");
151 logger.debug("Aauth DBURL["+aauthDbUrl+"] / Groups DBURL["+groupsDbUrl+"]");
152 logger.debug("exist.initdb > " + System.getProperty("exist.initdb"));
154 Configuration configuration1 = new Configuration(db1Config);
155 Configuration configuration2 = new Configuration(db2Config);
156 BrokerPool.configure( 1, 5, configuration1 );
157 BrokerPool.configure( 1, 5, configuration2 );
159 //** set Bob properties
160 System.setProperty(Util.HOME, props.getProperty("bob.home"));
161 System.setProperty(Util.BASE, props.getProperty("bob.base"));
162 System.setProperty(Util.GEN, props.getProperty("bob.gen"));
163 System.setProperty(Util.END, props.getProperty("bob.end"));
164 System.setProperty(Util.DEF, props.getProperty("bob.def"));
167 catch(DatabaseConfigurationException e) {
168 e.printStackTrace();
170 catch(EXistException e) {
171 e.printStackTrace();
173 catch(Exception e) {
174 e.printStackTrace();
179 public void setupRoot() throws SpittoonException {
181 String db1Id = props.getProperty("db-1-id");
182 String db2Id = props.getProperty("db-2-id");
184 String aauthDbUrl = rawDbUrl.replaceAll("exist", db1Id);
185 String groupsDbUrl = rawDbUrl.replaceAll("exist", db2Id);
187 createCollection(aauthDbUrl, rootDir);
188 createCollection(groupsDbUrl, rootDir);
191 public void tearDownRoot() throws SpittoonException {
193 removeCollection(aauthDbUrl, rootDir);
194 removeCollection(groupsDbUrl, rootDir);
196 try {
198 DatabaseManager.deregisterDatabase(databaseAauth);
199 logger.debug("De-registered Database ["+ databaseAauth.getName() +"]");
201 DatabaseManager.deregisterDatabase(databaseGroups);
202 logger.debug("De-registered Database ["+ databaseGroups.getName() +"]");
205 catch(Exception e) {
206 e.printStackTrace();
209 private Collection getCollection(String dbdirectory) throws SpittoonException {
211 logger.debug("Retrieving collection for URL["+ dbdirectory +"]");
212 Collection dbCollection = null;
213 try {
215 dbCollection = DatabaseManager.getCollection(dbdirectory, uname, passwd);
216 logger.debug("Retrieved collection["+ dbCollection.getName() +"]");
218 catch(XMLDBException e) {
219 throw new SpittoonException(e);
222 return dbCollection;
224 private Collection createCollection(String dburl, String dirname) throws SpittoonException {
226 Collection dbCollection = null;
227 Collection col = null;
228 try {
230 logger.debug("createCollection for dburl["+ dburl +"]");
232 dbCollection = DatabaseManager.getCollection(dburl, uname, passwd);
233 CollectionManagementService mgtService = (CollectionManagementService)
234 dbCollection.getService("CollectionManagementService", "1.0");
235 col = mgtService.createCollection(dirname);
236 logger.debug("Created directory["+ col.getName() +"]");
238 catch(XMLDBException e) {
239 throw new SpittoonException(e);
242 return col;
244 private void removeCollection(String dburl, String dirname) throws SpittoonException {
246 Collection dbCollection = null;
247 try {
249 dbCollection = DatabaseManager.getCollection(dburl, uname, passwd);
250 CollectionManagementService mgtService = (CollectionManagementService)
251 dbCollection.getService("CollectionManagementService", "1.0");
252 mgtService.removeCollection(dirname);
253 logger.debug("Removed directory["+ dburl + dirname +"]");
255 catch(XMLDBException e) {
256 throw new SpittoonException(e);
262 private void extractMappings() {
265 * deal with a path that is not mapped
267 Set keys = props.keySet();
268 Iterator kiter = keys.iterator();
269 String nextKey = null;
270 while(kiter.hasNext()) {
272 nextKey = (String)kiter.next();
273 if(nextKey.startsWith("mapping")) {
274 mappings.setProperty(nextKey, props.getProperty(nextKey));
280 public boolean alive() throws SpittoonException {
283 users: {
285 /**
286 * generate root collection URL string
288 StringBuffer sbuffer = new StringBuffer();
289 sbuffer.append(aauthDbUrl);
290 if(!aauthDbUrl.endsWith("/")) {
291 sbuffer.append("/");
293 sbuffer.append(rootDir);
294 String rootCollection = sbuffer.toString();
296 /**
297 * see if we have the exist 'db' collection
299 Collection dbCollection = null;
300 try {
301 dbCollection = DatabaseManager.getCollection(aauthDbUrl, uname, passwd);
302 if(dbCollection == null) {
303 throw new SpittoonException("Cannot find groups 'db' directory");
306 catch(XMLDBException xe) {
307 throw new SpittoonException(xe.getMessage(), xe.getCause());
310 /**
311 * test to see if the root collection exists
313 Collection currentCollection = null;
314 try {
315 currentCollection = DatabaseManager.getCollection(rootCollection, uname, passwd);
316 if(currentCollection == null)
317 throw new SpittoonException("root collection for aauth DB is NULL");
319 catch(XMLDBException xe) {
320 throw new SpittoonException(xe.getMessage(), xe.getCause());
323 groups: {
326 /**
327 * generate root collection URL string
329 StringBuffer sbuffer = new StringBuffer();
330 sbuffer.append(groupsDbUrl);
331 if(!groupsDbUrl.endsWith("/")) {
332 sbuffer.append("/");
334 sbuffer.append(rootDir);
335 String rootCollection = sbuffer.toString();
338 /**
339 * see if we have the exist 'db' collection
341 Collection dbCollection = null;
342 try {
343 dbCollection = DatabaseManager.getCollection(groupsDbUrl, uname, passwd);
344 if(dbCollection == null) {
345 throw new SpittoonException("Cannot find groups 'db' directory");
348 catch(XMLDBException xe) {
349 throw new SpittoonException(xe.getMessage(), xe.getCause());
352 /**
353 * test to see if the root collection exists
355 Collection currentCollection = null;
356 try {
357 currentCollection = DatabaseManager.getCollection(rootCollection, uname, passwd);
358 if(currentCollection != null)
359 return true;
361 catch(XMLDBException xe) {
362 throw new SpittoonException(xe.getMessage(), xe.getCause());
365 return false;
370 public void create(String dbUrl, String xpath, String xml) throws SpittoonException {
373 logger.debug("Spittoon.create CALLED / dbUrl["+dbUrl+"] / xpath["+xpath+"] / xml["+xml+"]");
375 //** check if xpath is mapped
376 String bareXPath = stripXPath(xpath);
377 //if(!verifyXPathMapping(bareXPath)) {
378 // throw new SpittoonException("XPath mapping ["+ bareXPath +"] not registered");
381 //** load IBob from xml
382 IBob loadedBob = loadBobFromXML(xml);
383 String tagName = loadedBob.getTagName();
384 tagName = tagName.trim();
387 //** check if we're saving the right tag
388 String targetTag = bareXPath.substring( (bareXPath.lastIndexOf("/") + 1) );
389 targetTag = targetTag.trim();
390 logger.debug("Comparing tagName["+tagName+"] to targetTag["+targetTag+"]");
391 if(!tagName.equals(targetTag))
392 throw new SpittoonException("XML supplied does not match the target xpath");
395 //** find collection from xpath
396 Collection collection = getCollectionForXPath(dbUrl, bareXPath);
397 logger.debug("Retrieved collection["+ collection +"]");
398 if(collection == null) {
400 //** generate collection
401 logger.debug("Collection is NULL / generating collection...");
402 collection = generateCollectionFromXPath(dbUrl, xpath);
403 logger.debug("Generated collection ["+ collection +"]");
406 String resourceName = generateResourceName(loadedBob);
407 try {
409 //** check if document exists
410 logger.debug("Checking if resource["+resourceName+"] exists in collection["+collection.getName()+"]");
411 XMLResource document = (XMLResource)collection.getResource(resourceName);
412 if(document == null) {
414 document = (XMLResource)collection.createResource(resourceName, "XMLResource");
415 logger.debug("Resource does NOT exist / created resource["+document.getId()+"] in collection["+collection.getName()+"]");
417 document.setContent(loadedBob.toXML(false));
419 //** save document
420 logger.debug("testing 123 - loadedBob.toXML["+loadedBob.toXML(false)+"]");
421 logger.debug("Spittoon.create:: Storing document resource > " + document.getId() + " > content["+document.getContent()+"]");
422 collection.storeResource(document);
424 catch(XMLDBException e) {
425 throw new SpittoonException(e);
427 catch(ClassCastException e) {
428 throw new SpittoonException(e);
434 public void createR(String dbUrl, String xpath, String xml) throws SpittoonException {
437 logger.debug("Spittoon.createR CALLED / dbUrl["+ dbUrl +"] / xpath["+ xpath +"] / xml["+ xml +"]");
439 //** check if xpath is mapped
440 String bareXPath = stripXPath(xpath);
441 //if(!verifyXPathMapping(bareXPath)) {
442 // throw new SpittoonException("XPath mapping ["+ bareXPath +"] not registered");
446 //** load IBob from xml
447 IBob loadedBob = loadBobFromXML(xml);
448 String tagName = loadedBob.getTagName();
449 tagName = tagName.trim();
452 //** check if we're saving the right tag
453 String targetTag = bareXPath.substring( (bareXPath.lastIndexOf("/") + 1) );
454 targetTag = targetTag.trim();
455 logger.debug("Comparing tagName["+tagName+"] to targetTag["+targetTag+"]");
456 if(!tagName.equals(targetTag))
457 throw new SpittoonException("XML supplied does not match the target xpath");
459 //**
460 this.generateCollectionFromXPath(dbUrl, xpath);
462 //** recurse through tree and save
463 List results = loadedBob.find(xpath);
464 IBob targetBob = null;
465 if(!results.isEmpty()) { // is the XML the entire block from 'system'
466 targetBob = (IBob)results.get(0);
468 else {
470 targetBob = loadedBob;
471 //String xtraPath = generateCollectionNameR(xpath, bareXPath);
472 //dbUrl += xtraPath;
473 //logger.debug("targetBob = loadedBob / xtraPath["+xtraPath+"] / dbUrl["+dbUrl+"]");
476 logger.debug("Running SaveOrUpdateVisitor on target["+ targetBob.toXML(false) +"]");
478 SaveOrUpdateVisitor suVisitor = new SaveOrUpdateVisitor(this);
479 if(!results.isEmpty()) {
480 suVisitor.setParentXPath(
481 xpath.substring( 0,
482 (xpath.lastIndexOf("/") + 1) ));
484 suVisitor.setDbUrl(dbUrl);
486 targetBob.acceptFirst(suVisitor);
491 private Collection getCollectionForFullXPath(String dbUrl, String xpath) {
493 String bareXPath = stripXPath(xpath);
494 logger.debug("getCollectionForFullXPath:: xpath["+xpath+"] > bareXPath["+bareXPath+"]");
496 //** generate collection name
497 String colName = generateCollectionNameR(xpath, bareXPath);
498 logger.debug("getCollectionForFullXPath:: generated collection name["+ colName +"]");
500 //** get collection
501 String dbdirectory = dbUrl + rootDir +"/"+ colName;
502 Collection collection = this.getCollection(dbdirectory); // use full URL
503 logger.debug("getCollectionForFullXPath:: retrieved collection["+collection+"]");
505 return collection;
507 public IBob retrieve(String dbUrl, String xpath, boolean recurse) {
510 /******
511 * check if there's a child document
513 String bareXPath = stripXPath(xpath);
514 logger.debug("retrieve:: xpath["+xpath+"] > bareXPath["+bareXPath+"]");
516 //** generate collection name
517 String colName = generateCollectionNameR(xpath, bareXPath);
518 logger.debug("retrieve:: generated collection name["+ colName +"]");
520 //** get collection
521 String dbdirectory = dbUrl + rootDir +"/"+ colName;
522 Collection collection = this.getCollection(dbdirectory); // use full URL
525 /******
526 * check if there's a child document
528 logger.debug("Retrieving for > dbUrl["+ dbUrl +"] / xpath["+ xpath +"]");
529 Collection collection = getCollectionForFullXPath(dbUrl, xpath);
531 //** child resource will be named the same as the directory
532 IBob resultBob = null;
533 try {
535 String rname = collection.getName();
536 rname = rname.substring(rname.lastIndexOf("/") + 1);
537 XMLResource eachResource = (XMLResource)collection.getResource(rname);
538 logger.debug("Child resource ["+ eachResource +"] > forName["+rname+"] > inCollection["+collection.getName()+"]");
540 if(eachResource == null) {
541 throw new SpittoonException("NULL child resource in directory ["+ collection.getName()+"]");
544 /******
545 * if yes, then i) add to parent 'bob' ii) set as parent 'bob'
547 resultBob = this.loadBobFromXML((String)eachResource.getContent());
548 logger.debug("retrieve:: recurse > found child XML tag["+ resultBob.getTagName() +"] > ["+ resultBob.xpath(true) +"]");
550 /*if(parent != null) {
552 FindParentBob fpvisitor = new FindParentBob();
553 fpvisitor.setTagName(resultBob.getTagName());
554 fpvisitor.setAttributeValue(resultBob.getAttributeValue("id"));
555 fpvisitor.setReplacement(resultBob);
556 parent.acceptFirst(fpvisitor); //** i)
558 logger.debug("OK > new parent after replace... " + parent.toXML(false));
563 //** should we recurse
564 if(recurse) {
566 //** get child collections
567 String[] childCollections = collection.listChildCollections();
568 IBob eachBob = null;
569 for (String string : childCollections) {
571 //** for each child collection, recurse to it's children
572 String tname = string.substring(0, string.indexOf("."));
573 String idvalue = string.substring(string.indexOf(".") + 1);
575 StringBuffer sbuf = new StringBuffer(xpath);
576 sbuf.append("/");
577 sbuf.append(tname);
578 sbuf.append("[ ");
579 sbuf.append("@id='");
580 sbuf.append(idvalue);
581 sbuf.append("' ]");
583 //** next XML retrieved
584 String eachXPath = sbuf.toString();
585 logger.debug("retrieve:: recurse > XPath > " + eachXPath);
587 eachBob = retrieve(dbUrl, eachXPath, recurse); //** ii)
588 resultBob.remove(eachBob.getTagName(), "id", eachBob.getAttributeValue("id"));
589 resultBob.addChild(eachBob);
595 catch(XMLDBException e) {
596 throw new SpittoonException(e);
599 return resultBob;
602 public Collection getCollectionForXPath(String dbUrl, String bareXPath) throws SpittoonException {
605 //if(!verifyXPathMapping(bareXPath)) {
606 // throw new SpittoonException("XPath ["+ bareXPath +"] is not mapped");
609 String eurl = generateDbUrl((dbUrl + rootDir), bareXPath);
610 logger.debug("getCollectionForXPath:: Generated eurl["+ eurl +"]");
612 Collection collection = null;
613 try {
614 collection = DatabaseManager.getCollection(eurl, uname, passwd);
616 catch(XMLDBException e) {
617 throw new SpittoonException(e.getMessage(), e);
620 return collection;
623 public Collection generateCollectionFromXPath(String dbUrl, String xpath) throws SpittoonException {
625 logger.debug("Spittoon.generateCollectionFromXPath:: dbUrl["+ dbUrl +"] / xpath["+ xpath +"]");
626 String bareXPath = stripXPath(xpath);
628 //if(!verifyXPathMapping(bareXPath)) {
629 // throw new SpittoonException("XPath ["+ bareXPath +"] is not mapped");
632 String baseName = dbUrl + rootDir;
633 String eurl = dbUrl + rootDir;
634 logger.debug("generateCollectionFromXPath:: Generated rootUrl["+ eurl +"]");
637 StringTokenizer stokenizer = new StringTokenizer( bareXPath, "/" );
638 StringTokenizer xpathTokenizer = new StringTokenizer( xpath, "/" ); //** mirroring stokenizer in loop ** It's bad, I know, I knooowwww **
639 Collection nextCollection = null;
640 try {
642 //** this should be the root collection
643 nextCollection = DatabaseManager.getCollection(eurl, uname, passwd);
644 //logger.debug("1. Next collection["+ nextCollection +"]");
645 if(nextCollection == null)
646 throw new SpittoonException("There is no root collection["+ eurl +"]");
648 String nextToken = stokenizer.nextToken();
649 String nextXPath = xpathTokenizer.nextToken();
650 String previousUrl = null;
652 //logger.debug("1. nextToken ["+ nextToken +"] / nextXPath["+ nextXPath +"]");
654 boolean moreTokens = false;
655 if(nextToken != null)
656 moreTokens = true;
659 //String checkMappingS = "";
661 while((nextCollection != null) && moreTokens) {
663 previousUrl = eurl;
665 logger.debug("nextToken["+nextToken +"] / nextXPath["+ nextXPath +"]");
666 String colName = generateNextCollectionName(nextToken, nextXPath);
667 eurl += "/" + colName;
669 /** check if collection is mapped
670 checkMappingS += "/" + nextToken;
671 logger.debug("generateCollectionFromXPath:: verifying mapping > ["+ verifyXPathMapping(checkMappingS) +"] > ["+ checkMappingS +"]");
673 if(!verifyXPathMapping(checkMappingS)) {
675 //** if xpath is not mapped, do not create a collection
677 //** KLUDGE 1 - some control stuff
678 if(stokenizer.hasMoreTokens()) {
679 moreTokens = true;
680 nextToken = stokenizer.nextToken();
681 nextXPath = xpathTokenizer.nextToken();
683 else {
684 moreTokens = false;
686 continue;
690 mainbit: {
692 logger.debug("Looking for the next collection["+eurl+"]");
694 nextCollection = DatabaseManager.getCollection(eurl, uname, passwd);
695 if(nextCollection == null) {
697 logger.debug(">> didn't find the last collection / eurl["+eurl+"]... creating previousUrl["+previousUrl+"] / collection name["+colName+"]");
698 nextCollection = createCollection(previousUrl, colName);
699 logger.debug(">> Created the next collection["+ nextCollection +"] / url["+ previousUrl +"/"+ colName +"]");
704 //** KLUDGE 2
705 if(stokenizer.hasMoreTokens()) {
706 moreTokens = true;
707 nextToken = stokenizer.nextToken();
708 nextXPath = xpathTokenizer.nextToken();
709 //logger.debug("2. nextToken ["+ nextToken +"]");
711 else {
712 moreTokens = false;
716 catch(XMLDBException e) {
717 throw new SpittoonException(e.getMessage(), e);
720 return nextCollection;
723 private String generateCollectionNameR(String xpath, String bareXPath) {
726 StringTokenizer xtokenizer = new StringTokenizer(xpath, "/");
727 StringTokenizer btokenizer = new StringTokenizer(bareXPath, "/");
729 String eachx = null;
730 String eachb = null;
731 String eachPart = null;
732 StringBuffer sbuffer = new StringBuffer();
734 while(xtokenizer.hasMoreTokens()) {
736 eachx = xtokenizer.nextToken();
737 eachb = btokenizer.nextToken();
739 eachPart = generateNextCollectionName(eachb, eachx);
740 logger.info("generateCollectionNameR:: eachx["+ eachx +"] > eachb["+ eachb +"] > eachPart["+ eachPart +"]");
742 sbuffer.append(eachPart);
743 if(xtokenizer.hasMoreTokens())
744 sbuffer.append("/");
746 String resultName = sbuffer.toString();
747 logger.info("generateCollectionNameR:: result["+ resultName +"]");
749 return resultName;
751 private String generateNextCollectionName(String nextToken, String nextXPath) {
753 String yvalue = yankAttributeId(nextXPath);
754 logger.info("generating Collection name / nextXPath ["+ nextXPath +"] / yanked 'id' value ["+ yvalue +"] ...");
756 return nextToken + "." + yvalue;
758 private String yankAttributeId(String attributeString) {
760 logger.debug("yankAttributeId["+ attributeString +"]");
762 //** test yanking 'id' attribute
763 //** make sure there's an 'id' attribute
764 int ii = attributeString.indexOf("@id");
765 int jj = (ii + 3);
766 String id = null;
767 try {
768 attributeString.substring(ii, jj);
770 catch(StringIndexOutOfBoundsException e) {
771 throw new SpittoonException("No 'id' attribute specified for ["+ attributeString +"]", e);
774 //** find value for id attribute
775 String marker = attributeString.substring(jj);
776 //logger.info("yanking marker["+marker+"]");
778 int kk = marker.indexOf("\"");
780 String subs = null;
781 if(kk == -1) {
783 kk = marker.indexOf("'");
784 int ll = marker.indexOf("'", kk + 1);
785 subs = marker.substring(kk + 1, ll);
787 //logger.info("yanking >> ' > kk["+ kk +"] / ll["+ll+"] / marker["+marker+"] / subs["+subs+"]");
790 else {
792 int ll = marker.indexOf("\"", kk + 1);
793 subs = marker.substring(kk + 1, ll);
795 //logger.info("yanking >> \" > kk["+ kk +"] / ll["+ll+"] / marker["+marker+"] / subs["+subs+"]");
799 logger.info("yanked >> id["+id+"] / value["+subs+"]");
800 return subs;
802 private String generateDbUrl(String baseUrl, String xpath) {
804 return baseUrl + xpath;
806 public String generateResourceName(IBob bob) {
808 String tagName = bob.getTagName();
809 String id = bob.getAttributeValue("id");
811 return generateResourceName(tagName, id);
813 public String generateResourceName(String tagName, String idValue) {
815 StringBuffer sbuf = new StringBuffer(tagName);
816 sbuf.append(".");
817 sbuf.append(idValue);
819 String rname = sbuf.toString();
820 logger.info("Generated resource name["+rname+"]");
821 return rname;
824 public boolean verifyXPathMapping(String xpath) {
826 java.util.Collection values = mappings.values();
827 return values.contains(xpath);
831 * strips out any predicate(s)
833 public String stripXPath(String xpath) {
836 * this regular expression: \\[[^\\]]*\\]
837 * matches on all content between square brackets [ ], except a right square bracket.
838 * The last condition allows multiple [ abc ] patterns in a single string
840 String bareXPath = xpath.replaceAll("\\[[^\\]]*\\]", "");
841 if(bareXPath.indexOf("/") == bareXPath.length())
842 bareXPath = bareXPath.substring(0, bareXPath.lastIndexOf("/"));
844 return bareXPath;
848 public IBob loadBobFromXML(String xmlString) throws SpittoonException {
851 logger.debug("loadBobFromXML:: ["+ xmlString +"]");
853 //** load a Bob object
854 InputStream istream = null;
855 try {
856 istream = new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
858 catch(UnsupportedEncodingException e) {
859 throw new SpittoonException(e);
863 //System.getProperties().setProperty("bob.home", props.getProperty("bob.home"));
864 //System.getProperties().setProperty("bob.base", props.getProperty("bob.base"));
865 //System.getProperties().setProperty("bob.gen", props.getProperty("bob.gen"));
866 //System.getProperties().setProperty("bob.end", props.getProperty("bob.gen"));
867 System.getProperties().setProperty("bob.home", "/Users/timothyw/Projects/Spittoon");
868 System.getProperties().setProperty("bob.base", "/Users/timothyw/Projects/Spittoon");
869 System.getProperties().setProperty("bob.gen", "/Users/timothyw/Projects/Spittoon/src/main/gen");
870 System.getProperties().setProperty("bob.end", ".xml");
872 IBob bob = Bob.loadS(istream, System.getProperty(Util.DEF));
873 logger.debug("Loaded Bob from XML" + bob.toXML(false));
875 return bob;
880 public static void main(String args[]) {
882 System.getProperties().setProperty("bob.home", "/Users/timothyw/Projects/maven.trials/Spittoon");
883 System.getProperties().setProperty("bob.base", "/Users/timothyw/Projects/maven.trials/Spittoon");
884 System.getProperties().setProperty("bob.gen", "/Users/timothyw/Projects/maven.trials/Spittoon/src/main/gen");
885 System.getProperties().setProperty("bob.end", ".xml");
887 String testme = "<group xmlns=\"com/interrupt/bookkeeping/users\" id=\"webkell\" name=\"Webkell\" owner=\"root\">" +
888 "<user id=\"root\" username=\"\" password=\"\" logintimeout=\"\" accountLevel=\"\" defaultGroup=\"\" authenticated=\"\"/>" +
889 "</group>";
891 InputStream istream = null;
892 try {
893 istream = new ByteArrayInputStream(testme.getBytes("UTF-8"));
895 catch(UnsupportedEncodingException e) {
896 throw new SpittoonException(e);
899 IBob bob = Bob.loadS(istream, "src/main/resources/bookkeeping.system.xml");
900 System.out.println("Loaded Bob form XML" + bob.toXML(false));
904 private static void testStripXPath() {
906 //** testing stripXPath
907 /*String origXPath = "/system[ @id=\"thing\" ]/bookkeeping[ @attr=\"value\" ]/thing";
909 Spittoon spittoon = new Spittoon();
910 String bareXPath = spittoon.stripXPath(origXPath);
911 System.out.println(bareXPath);
914 //String testme = "/system[ @id=\"blahblah blah\" ]";
915 String testme = "/system[ @id='blahblah blah' ]";
916 System.out.println("Begin ["+ testme +"]");
918 /*String sstring[] = testme.split("\\[[^\\]]*\\]");
919 for (String string : sstring) {
920 System.out.println(string);
925 private static void testYanking() {
928 String testme = "/system[ @id='blahblah blah' ]";
930 //** test yanking 'id' attribute
931 //** make sure there's an 'id' attribute
932 int ii = testme.indexOf("@id");
933 int jj = (ii + 3);
934 String id = testme.substring(ii, jj);
936 //** find value for id attribute
937 String marker = testme.substring(jj);
938 System.out.println("marker["+marker+"]");
940 int kk = marker.indexOf("\"");
942 String subs = null;
943 if(kk == -1) {
945 kk = marker.indexOf("'");
946 int ll = marker.indexOf("'", kk + 1);
947 subs = marker.substring(kk + 1, ll);
949 System.out.println(">> ' > kk["+ kk +"] / ll["+ll+"] / marker["+marker+"] / subs["+subs+"]");
952 else {
954 int ll = marker.indexOf("\"", kk + 1);
955 subs = marker.substring(kk + 1, ll);
957 System.out.println(">> \" > kk["+ kk +"] / ll["+ll+"] / marker["+marker+"] / subs["+subs+"]");
961 System.out.println("id["+id+"] / value["+subs+"]");
965 class FindParentBob implements IVisitor {
967 private Logger logger = Logger.getLogger(FindParentBob.class);
968 private String tagName = null;
969 private String attributeValue = null;
970 private IBob replacement = null;
972 public String getTagName() { return tagName; }
973 public void setTagName(String tagName) { this.tagName = tagName; }
974 public String getAttributeValue() { return attributeValue; }
975 public void setAttributeValue(String attributeValue) { this.attributeValue = attributeValue; }
976 public IBob getReplacement() { return replacement; }
977 public void setReplacement(IBob replacement) { this.replacement = replacement; }
979 private boolean acceptControl = true;
980 public void visit(IBob bob) {
982 if(acceptControl) {
984 String tname = bob.getTagName();
985 String avalue = bob.getAttributeValue("id");
987 logger.debug("FindParentBob.visit > comparing tagName["+tagName+"] <=> tname["+tname+"] / attributeValue["+attributeValue+"] <=> avalue["+avalue+"]");
988 if((tagName.equals(tname)) && (attributeValue.equals(avalue))) {
990 logger.debug("FindParentBob.visit > replacing ["+bob.xpath(false)+"] with ["+replacement.toXML(false)+"]");
991 bob.replace(replacement);
992 acceptControl = false;