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
;
8 import java
.util
.Properties
;
10 import java
.util
.StringTokenizer
;
12 import org
.xmldb
.api
.DatabaseManager
;
13 import org
.xmldb
.api
.base
.Collection
;
14 import org
.xmldb
.api
.base
.Database
;
15 import org
.xmldb
.api
.base
.XMLDBException
;
16 import org
.xmldb
.api
.modules
.CollectionManagementService
;
17 import org
.xmldb
.api
.modules
.XMLResource
;
18 import org
.apache
.log4j
.Logger
;
19 import org
.exist
.EXistException
;
20 import org
.exist
.storage
.BrokerPool
;
21 import org
.exist
.util
.Configuration
;
22 import org
.exist
.util
.DatabaseConfigurationException
;
24 import com
.interrupt
.bob
.base
.Bob
;
25 import com
.interrupt
.bob
.base
.IBob
;
26 import com
.interrupt
.bob
.util
.Util
;
29 public class Spittoon
{
32 private String DRIVER
= "org.exist.xmldb.DatabaseImpl";
33 private Properties props
= new Properties();
34 private Properties mappings
= new Properties();
36 private String rawDbUrl
= null;
37 private String aauthDbUrl
= null;
38 private String groupsDbUrl
= null;
40 private String rootDir
= null;
41 private String uname
= null;
42 private String passwd
= null;
44 private Logger logger
= Logger
.getLogger(Spittoon
.class);
45 private Logger algorithm
= Logger
.getLogger("algorithm");
47 private Database databaseAauth
= null;
48 private Database databaseGroups
= null;
49 private Database database
= null;
51 private String einitDb
= null;
54 public String
getAauthDbUrl() { return aauthDbUrl
; }
55 public void setAauthDbUrl(String aauthDbUrl
) { this.aauthDbUrl
= aauthDbUrl
; }
56 public String
getGroupsDbUrl() { return groupsDbUrl
; }
59 public void setGroupsDbUrl(String groupsDbUrl
) {
60 this.groupsDbUrl
= groupsDbUrl
;
63 public void initialise() {
67 //** load spittoon.properties
68 InputStream inStream
= Spittoon
.class.getResourceAsStream("/spittoon.properties");
71 einitDb
= System
.getProperty("exist.initdb");
72 if(einitDb
== null || einitDb
.trim().length() < 1)
73 einitDb
= props
.getProperty("exist.initdb");
75 String ehome
= System
.getProperty("exist.home");
76 if(ehome
== null || ehome
.trim().length() < 1)
77 ehome
= props
.getProperty("exist.home");
79 String eSaxValidation
= System
.getProperty("org.xml.sax.features.validation");
80 if(eSaxValidation
== null || eSaxValidation
.trim().length() < 1)
81 eSaxValidation
= props
.getProperty("org.xml.sax.features.validation");
83 String eEndorsedDirs
= System
.getProperty("java.endorsed.dirs");
84 if(eEndorsedDirs
== null || eEndorsedDirs
.trim().length() < 1)
85 eEndorsedDirs
= props
.getProperty("java.endorsed.dirs");
88 logger
.debug("exist.initdb["+einitDb
+"] / exist.home["+ehome
+
89 "] / org.xml.sax.features.validation["+eSaxValidation
+"] / java.endorsed.dirs["+eEndorsedDirs
+"]");
91 String db1Config
= props
.getProperty("db-1-config");
92 String db1Id
= props
.getProperty("db-1-id").trim();
93 String db1Port
= props
.getProperty("db-1-port");
95 String db2Config
= props
.getProperty("db-2-config").trim();
96 String db2Id
= props
.getProperty("db-2-id");
97 String db2Port
= props
.getProperty("db-2-port");
99 String dbSplit
= props
.getProperty("db-split");
101 logger
.debug("Database / split["+ dbSplit
+"]");
102 logger
.debug("Database / config-1["+ db1Config
+"] / id-1["+ db1Id
+"] / port-1["+db1Port
+"]");
103 logger
.debug("Database / config-2["+ db2Config
+"] / id-2["+ db2Id
+"] / port-2["+db2Port
+"]");
107 //** initialize driver
108 Class cl
= Class
.forName(DRIVER
);
110 System
.setProperty("exist.initdb", einitDb
);
111 System
.setProperty("exist.home", ehome
);
112 System
.setProperty("org.xml.sax.features.validation", eSaxValidation
);
113 System
.setProperty("java.endorsed.dirs", eEndorsedDirs
);
115 //** extract the mappings into a separate properties object
119 //** eXist Broker Pool properties; initialize from properties
120 rawDbUrl
= props
.getProperty("db.url");
121 rootDir
= props
.getProperty("root.dir", "root.dir");
122 uname
= props
.getProperty("db.uname");
123 passwd
= props
.getProperty("db.passwd");
125 rawDbUrl
= rawDbUrl
.trim();
126 rootDir
= rootDir
.trim();
127 uname
= uname
.trim();
128 passwd
= passwd
.trim();
130 if(einitDb
.equals("true")) {
132 databaseAauth
= (Database
)cl
.newInstance();
133 databaseAauth
.setProperty("create-database", einitDb
);
134 databaseAauth
.setProperty("configuration", db1Config
);
135 databaseAauth
.setProperty("database-id", db1Id
);
136 DatabaseManager
.registerDatabase(databaseAauth
);
137 logger
.debug("EMBEDDED Database registered["+ databaseAauth
.getName() +"]");
139 databaseGroups
= (Database
)cl
.newInstance();
140 databaseGroups
.setProperty("create-database", einitDb
);
141 databaseGroups
.setProperty("configuration", db2Config
);
142 databaseGroups
.setProperty("database-id", db2Id
);
143 DatabaseManager
.registerDatabase(databaseGroups
);
144 logger
.debug("EMBEDDED Database registered["+ databaseGroups
.getName() +"]");
146 aauthDbUrl
= rawDbUrl
.replaceFirst("exist", db1Id
);
147 groupsDbUrl
= rawDbUrl
.replaceFirst("exist", db2Id
);
151 //aauthDbUrl = rawDbUrl.replaceFirst("exist", db1Id);
152 //groupsDbUrl = rawDbUrl.replaceFirst("exist", db2Id);
153 //aauthDbUrl = aauthDbUrl.replaceFirst("8080", db1Port);
154 //groupsDbUrl = groupsDbUrl.replaceFirst("8080", db2Port);
156 database
= (Database
)cl
.newInstance();
157 DatabaseManager
.registerDatabase(database
);
158 logger
.debug("REMOTE Database registered["+ database
.getName() +"]");
160 aauthDbUrl
= rawDbUrl
.replaceFirst("8080", db1Port
);
161 groupsDbUrl
= rawDbUrl
.replaceFirst("8080", db2Port
);
164 logger
.debug("RawDBURL["+rawDbUrl
+"] / ROOT["+rootDir
+"] / UNAME["+uname
+"] / PASSWD["+passwd
+"]");
165 logger
.debug("Aauth DBURL["+aauthDbUrl
+"] / Groups DBURL["+groupsDbUrl
+"]");
166 logger
.debug("exist.initdb > " + System
.getProperty("exist.initdb"));
168 Configuration configuration1
= null;
171 configuration1
= new Configuration(db1Config
);
173 catch(org
.exist
.util
.DatabaseConfigurationException e
) {
175 logger
.error("ERROR in configuration ["+e
.getMessage()+"] with file["+db1Config
+"]");
177 // On error, try Tomcat specific context
178 String catalinaBase
= System
.getProperty("catalina.base");
179 configuration1
= new Configuration( catalinaBase
+ "/webapps/webkell/" + db1Config
);
181 BrokerPool
.configure( 1, 5, configuration1
);
183 if(dbSplit
.equals("true")) {
184 Configuration configuration2
= new Configuration(db2Config
);
185 BrokerPool
.configure( 1, 5, configuration2
);
189 //** set Bob properties
190 System
.setProperty(Util
.HOME
, props
.getProperty("bob.home"));
191 System
.setProperty(Util
.BASE
, props
.getProperty("bob.base"));
192 System
.setProperty(Util
.GEN
, props
.getProperty("bob.gen"));
193 System
.setProperty(Util
.END
, props
.getProperty("bob.end"));
194 System
.setProperty(Util
.DEF
, props
.getProperty("bob.def"));
197 catch(DatabaseConfigurationException e
) {
200 catch(EXistException e
) {
209 public void setupRoot() throws SpittoonException
{
211 String db1Id
= props
.getProperty("db-1-id");
212 String db2Id
= props
.getProperty("db-2-id");
214 String aauthDbUrl
= rawDbUrl
.replaceAll("exist", db1Id
);
215 String groupsDbUrl
= rawDbUrl
.replaceAll("exist", db2Id
);
217 createCollection(aauthDbUrl
, rootDir
);
218 createCollection(groupsDbUrl
, rootDir
);
221 public void tearDownRoot() throws SpittoonException
{
223 removeCollection(aauthDbUrl
, rootDir
);
224 removeCollection(groupsDbUrl
, rootDir
);
228 if(einitDb
.equals("true")) {
230 DatabaseManager
.deregisterDatabase(databaseAauth
);
231 logger
.debug("De-registered EMBEDED Database ["+ databaseAauth
.getName() +"]");
233 DatabaseManager
.deregisterDatabase(databaseGroups
);
234 logger
.debug("De-registered EMBEDED atabase ["+ databaseGroups
.getName() +"]");
238 DatabaseManager
.deregisterDatabase(database
);
239 logger
.debug("De-registered REMOTE Database ["+ database
.getName() +"]");
246 private Collection
getCollection(String dbdirectory
) throws SpittoonException
{
248 logger
.debug("Retrieving collection for URL["+ dbdirectory
+"]");
249 Collection dbCollection
= null;
252 dbCollection
= DatabaseManager
.getCollection(dbdirectory
, uname
, passwd
);
253 logger
.debug("Retrieved collection["+ dbCollection
.getName() +"]");
255 catch(XMLDBException e
) {
256 throw new SpittoonException(e
);
261 private Collection
createCollection(String dburl
, String dirname
) throws SpittoonException
{
263 Collection dbCollection
= null;
264 Collection col
= null;
267 logger
.debug("createCollection for dburl["+ dburl
+"]");
269 dbCollection
= DatabaseManager
.getCollection(dburl
, uname
, passwd
);
270 CollectionManagementService mgtService
= (CollectionManagementService
)
271 dbCollection
.getService("CollectionManagementService", "1.0");
272 col
= mgtService
.createCollection(dirname
);
273 logger
.debug("Created directory["+ col
.getName() +"]");
275 catch(XMLDBException e
) {
276 throw new SpittoonException(e
);
281 private void removeCollection(String dburl
, String dirname
) throws SpittoonException
{
283 Collection dbCollection
= null;
286 dbCollection
= DatabaseManager
.getCollection(dburl
, uname
, passwd
);
287 CollectionManagementService mgtService
= (CollectionManagementService
)
288 dbCollection
.getService("CollectionManagementService", "1.0");
289 mgtService
.removeCollection(dirname
);
290 logger
.debug("Removed directory["+ dburl
+ dirname
+"]");
292 catch(XMLDBException e
) {
293 throw new SpittoonException(e
);
299 private void extractMappings() {
302 * deal with a path that is not mapped
304 Set keys
= props
.keySet();
305 Iterator kiter
= keys
.iterator();
306 String nextKey
= null;
307 while(kiter
.hasNext()) {
309 nextKey
= (String
)kiter
.next();
310 if(nextKey
.startsWith("mapping")) {
311 mappings
.setProperty(nextKey
, props
.getProperty(nextKey
));
317 public boolean alive() throws SpittoonException
{
323 * generate root collection URL string
325 StringBuffer sbuffer
= new StringBuffer();
326 sbuffer
.append(aauthDbUrl
);
327 if(!aauthDbUrl
.endsWith("/")) {
330 sbuffer
.append(rootDir
);
331 String rootCollection
= sbuffer
.toString();
334 * see if we have the exist 'db' collection
336 Collection dbCollection
= null;
338 dbCollection
= DatabaseManager
.getCollection(aauthDbUrl
, uname
, passwd
);
339 if(dbCollection
== null) {
340 throw new SpittoonException("Cannot find groups 'db' directory");
343 catch(XMLDBException xe
) {
344 throw new SpittoonException(xe
.getMessage(), xe
.getCause());
348 * test to see if the root collection exists
350 Collection currentCollection
= null;
352 currentCollection
= DatabaseManager
.getCollection(rootCollection
, uname
, passwd
);
353 if(currentCollection
== null)
354 throw new SpittoonException("root collection for aauth DB is NULL");
356 catch(XMLDBException xe
) {
357 throw new SpittoonException(xe
.getMessage(), xe
.getCause());
364 * generate root collection URL string
366 StringBuffer sbuffer
= new StringBuffer();
367 sbuffer
.append(groupsDbUrl
);
368 if(!groupsDbUrl
.endsWith("/")) {
371 sbuffer
.append(rootDir
);
372 String rootCollection
= sbuffer
.toString();
376 * see if we have the exist 'db' collection
378 Collection dbCollection
= null;
380 dbCollection
= DatabaseManager
.getCollection(groupsDbUrl
, uname
, passwd
);
381 if(dbCollection
== null) {
382 throw new SpittoonException("Cannot find groups 'db' directory");
385 catch(XMLDBException xe
) {
386 throw new SpittoonException(xe
.getMessage(), xe
.getCause());
390 * test to see if the root collection exists
392 Collection currentCollection
= null;
394 currentCollection
= DatabaseManager
.getCollection(rootCollection
, uname
, passwd
);
395 if(currentCollection
!= null)
398 catch(XMLDBException xe
) {
399 throw new SpittoonException(xe
.getMessage(), xe
.getCause());
407 public void create(String dbUrl
, String xpath
, String xml
) throws SpittoonException
{
410 logger
.debug("Spittoon.create CALLED / dbUrl["+dbUrl
+"] / xpath["+xpath
+"] / xml["+xml
+"]");
412 //** check if xpath is mapped
413 String bareXPath
= stripXPath(xpath
);
414 //if(!verifyXPathMapping(bareXPath)) {
415 // throw new SpittoonException("XPath mapping ["+ bareXPath +"] not registered");
418 //** load IBob from xml
419 IBob loadedBob
= loadBobFromXML(xml
);
420 String tagName
= loadedBob
.getTagName();
421 tagName
= tagName
.trim();
424 //** check if we're saving the right tag
425 String targetTag
= bareXPath
.substring( (bareXPath
.lastIndexOf("/") + 1) );
426 targetTag
= targetTag
.trim();
427 logger
.debug("Comparing tagName["+tagName
+"] to targetTag["+targetTag
+"]");
428 if(!tagName
.equals(targetTag
))
429 throw new SpittoonException("XML supplied does not match the target xpath");
432 //** find collection from xpath
433 Collection collection
= getCollectionForXPath(dbUrl
, bareXPath
);
434 logger
.debug("Retrieved collection["+ collection
+"]");
435 if(collection
== null) {
437 //** generate collection
438 logger
.debug("Collection is NULL / generating collection...");
439 collection
= generateCollectionFromXPath(dbUrl
, xpath
);
440 logger
.debug("Generated collection ["+ collection
+"]");
443 String resourceName
= generateResourceName(loadedBob
);
446 //** check if document exists
447 logger
.debug("Checking if resource["+resourceName
+"] exists in collection["+collection
.getName()+"]");
448 XMLResource document
= (XMLResource
)collection
.getResource(resourceName
);
449 if(document
== null) {
451 document
= (XMLResource
)collection
.createResource(resourceName
, "XMLResource");
452 logger
.debug("Resource does NOT exist / created resource["+document
.getId()+"] in collection["+collection
.getName()+"]");
454 document
.setContent(loadedBob
.toXML(false));
457 logger
.debug("testing 123 - loadedBob.toXML["+loadedBob
.toXML(false)+"]");
458 logger
.debug("Spittoon.create:: Storing document resource > " + document
.getId() + " > content["+document
.getContent()+"]");
459 collection
.storeResource(document
);
461 catch(XMLDBException e
) {
462 throw new SpittoonException(e
);
464 catch(ClassCastException e
) {
465 throw new SpittoonException(e
);
471 public void createR(String dbUrl
, String xpath
, String xml
) throws SpittoonException
{
474 logger
.debug("Spittoon.createR CALLED / dbUrl["+ dbUrl
+"] / xpath["+ xpath
+"] / xml["+ xml
+"]");
476 //** check if xpath is mapped
477 String bareXPath
= stripXPath(xpath
);
478 //if(!verifyXPathMapping(bareXPath)) {
479 // throw new SpittoonException("XPath mapping ["+ bareXPath +"] not registered");
483 //** load IBob from xml
484 IBob loadedBob
= loadBobFromXML(xml
);
485 String tagName
= loadedBob
.getTagName();
486 tagName
= tagName
.trim();
489 //** check if we're saving the right tag
490 String targetTag
= bareXPath
.substring( (bareXPath
.lastIndexOf("/") + 1) );
491 targetTag
= targetTag
.trim();
492 logger
.debug("Comparing tagName["+tagName
+"] to targetTag["+targetTag
+"]");
493 if(!tagName
.equals(targetTag
))
494 throw new SpittoonException("XML supplied does not match the target xpath");
497 this.generateCollectionFromXPath(dbUrl
, xpath
);
499 //** recurse through tree and save
500 List results
= loadedBob
.find(xpath
);
501 IBob targetBob
= null;
502 if(!results
.isEmpty()) { // is the XML the entire block from 'system'
503 targetBob
= (IBob
)results
.get(0);
507 targetBob
= loadedBob
;
508 //String xtraPath = generateCollectionNameR(xpath, bareXPath);
510 //logger.debug("targetBob = loadedBob / xtraPath["+xtraPath+"] / dbUrl["+dbUrl+"]");
513 logger
.debug("Running SaveOrUpdateVisitor on target["+ targetBob
.toXML(false) +"]");
515 SaveOrUpdateVisitor suVisitor
= new SaveOrUpdateVisitor(this);
516 //if(!results.isEmpty()) {
517 suVisitor
.setParentXPath(
519 (xpath
.lastIndexOf("/") + 1) ));
521 suVisitor
.setDbUrl(dbUrl
);
523 targetBob
.acceptFirst(suVisitor
);
528 private Collection
getCollectionForFullXPath(String dbUrl
, String xpath
) {
530 String bareXPath
= stripXPath(xpath
);
531 logger
.debug("getCollectionForFullXPath:: xpath["+xpath
+"] > bareXPath["+bareXPath
+"]");
533 //** generate collection name
534 String colName
= generateCollectionNameR(xpath
, bareXPath
);
535 logger
.debug("getCollectionForFullXPath:: generated collection name["+ colName
+"]");
538 String dbdirectory
= dbUrl
+ rootDir
+"/"+ colName
;
539 Collection collection
= this.getCollection(dbdirectory
); // use full URL
540 logger
.debug("getCollectionForFullXPath:: retrieved collection["+collection
+"]");
544 public IBob
retrieve(String dbUrl
, String xpath
, boolean recurse
) {
546 algorithm
.debug(""); algorithm
.debug("");
547 algorithm
.debug("retrieve CALLED > params("+dbUrl
+","+xpath
+","+recurse
+")");
550 * check if there's a child document
552 String bareXPath = stripXPath(xpath);
553 logger.debug("retrieve:: xpath["+xpath+"] > bareXPath["+bareXPath+"]");
555 //** generate collection name
556 String colName = generateCollectionNameR(xpath, bareXPath);
557 logger.debug("retrieve:: generated collection name["+ colName +"]");
560 String dbdirectory = dbUrl + rootDir +"/"+ colName;
561 Collection collection = this.getCollection(dbdirectory); // use full URL
565 * check if there's a child document
567 logger
.debug("Retrieving for > dbUrl["+ dbUrl
+"] / xpath["+ xpath
+"]");
568 Collection collection
= getCollectionForFullXPath(dbUrl
, xpath
);
570 //** child resource will be named the same as the directory
571 IBob resultBob
= null;
574 String rname
= collection
.getName();
575 rname
= rname
.substring(rname
.lastIndexOf("/") + 1);
576 XMLResource eachResource
= (XMLResource
)collection
.getResource(rname
);
577 algorithm
.debug("retrieve > Child resource ["+ eachResource
.getContent() +"] > forName["+rname
+"] > inCollection["+collection
.getName()+"]");
579 if(eachResource
== null) {
580 throw new SpittoonException("NULL child resource in directory ["+ collection
.getName()+"]");
584 * if yes, then i) add to parent 'bob' ii) set as parent 'bob'
586 resultBob
= this.loadBobFromXML((String
)eachResource
.getContent());
587 algorithm
.debug("retrieve > LOADED Child resource ["+ resultBob
+"] > xpath["+ resultBob
.xpath(true) +"]");
589 /*if(parent != null) {
591 FindParentBob fpvisitor = new FindParentBob();
592 fpvisitor.setTagName(resultBob.getTagName());
593 fpvisitor.setAttributeValue(resultBob.getAttributeValue("id"));
594 fpvisitor.setReplacement(resultBob);
595 parent.acceptFirst(fpvisitor); //** i)
597 logger.debug("OK > new parent after replace... " + parent.toXML(false));
602 //** should we recurse
605 algorithm
.debug("retrieve > IN recurse block");
607 //** get child collections
608 String
[] childCollections
= collection
.listChildCollections();
610 for (String string
: childCollections
) {
612 algorithm
.debug("retrieve > EACH ");
614 //** for each child collection, recurse to it's children
615 String tname
= string
.substring(0, string
.indexOf("."));
616 String idvalue
= string
.substring(string
.indexOf(".") + 1);
618 StringBuffer sbuf
= new StringBuffer(xpath
);
622 sbuf
.append("@id='");
623 sbuf
.append(idvalue
);
626 //** next XML retrieved
627 String eachXPath
= sbuf
.toString();
628 algorithm
.debug("retrieve > EACH childCollection string["+string
+"] > created XPath["+eachXPath
+"]");
630 algorithm
.debug("IN recurse");
631 eachBob
= retrieve(dbUrl
, eachXPath
, recurse
); //** ii)
632 algorithm
.debug("OUT recurse");
634 boolean removed
= resultBob
.remove(eachBob
.getTagName(), "id", eachBob
.getAttributeValue("id"));
635 algorithm
.debug("["+removed
+"] removed '"+eachBob
.getTagName()+"[@id='"+eachBob
.getAttributeValue("id")+"']");
637 resultBob
.addChild(eachBob
);
643 catch(XMLDBException e
) {
644 throw new SpittoonException(e
);
650 public Collection
getCollectionForXPath(String dbUrl
, String bareXPath
) throws SpittoonException
{
653 //if(!verifyXPathMapping(bareXPath)) {
654 // throw new SpittoonException("XPath ["+ bareXPath +"] is not mapped");
657 String eurl
= generateDbUrl((dbUrl
+ rootDir
), bareXPath
);
658 logger
.debug("getCollectionForXPath:: Generated eurl["+ eurl
+"]");
660 Collection collection
= null;
662 collection
= DatabaseManager
.getCollection(eurl
, uname
, passwd
);
664 catch(XMLDBException e
) {
665 throw new SpittoonException(e
.getMessage(), e
);
671 public Collection
generateCollectionFromXPath(String dbUrl
, String xpath
) throws SpittoonException
{
673 logger
.debug("Spittoon.generateCollectionFromXPath:: dbUrl["+ dbUrl
+"] / xpath["+ xpath
+"]");
674 String bareXPath
= stripXPath(xpath
);
676 //if(!verifyXPathMapping(bareXPath)) {
677 // throw new SpittoonException("XPath ["+ bareXPath +"] is not mapped");
680 String baseName
= dbUrl
+ rootDir
;
681 String eurl
= dbUrl
+ rootDir
;
682 logger
.debug("generateCollectionFromXPath:: Generated rootUrl["+ eurl
+"]");
685 StringTokenizer stokenizer
= new StringTokenizer( bareXPath
, "/" );
686 StringTokenizer xpathTokenizer
= new StringTokenizer( xpath
, "/" ); //** mirroring stokenizer in loop ** It's bad, I know, I knooowwww **
687 Collection nextCollection
= null;
690 //** this should be the root collection
691 nextCollection
= DatabaseManager
.getCollection(eurl
, uname
, passwd
);
692 //logger.debug("1. Next collection["+ nextCollection +"]");
693 if(nextCollection
== null)
694 throw new SpittoonException("There is no root collection["+ eurl
+"]");
696 String nextToken
= stokenizer
.nextToken();
697 String nextXPath
= xpathTokenizer
.nextToken();
698 String previousUrl
= null;
700 //logger.debug("1. nextToken ["+ nextToken +"] / nextXPath["+ nextXPath +"]");
702 boolean moreTokens
= false;
703 if(nextToken
!= null)
707 //String checkMappingS = "";
709 while((nextCollection
!= null) && moreTokens
) {
713 logger
.debug("nextToken["+nextToken
+"] / nextXPath["+ nextXPath
+"]");
714 String colName
= generateNextCollectionName(nextToken
, nextXPath
);
715 eurl
+= "/" + colName
;
717 /** check if collection is mapped
718 checkMappingS += "/" + nextToken;
719 logger.debug("generateCollectionFromXPath:: verifying mapping > ["+ verifyXPathMapping(checkMappingS) +"] > ["+ checkMappingS +"]");
721 if(!verifyXPathMapping(checkMappingS)) {
723 //** if xpath is not mapped, do not create a collection
725 //** KLUDGE 1 - some control stuff
726 if(stokenizer.hasMoreTokens()) {
728 nextToken = stokenizer.nextToken();
729 nextXPath = xpathTokenizer.nextToken();
740 logger
.debug("Looking for the next collection["+eurl
+"]");
742 nextCollection
= DatabaseManager
.getCollection(eurl
, uname
, passwd
);
743 if(nextCollection
== null) {
745 logger
.debug(">> didn't find the last collection / eurl["+eurl
+"]... creating previousUrl["+previousUrl
+"] / collection name["+colName
+"]");
746 nextCollection
= createCollection(previousUrl
, colName
);
747 logger
.debug(">> Created the next collection["+ nextCollection
+"] / url["+ previousUrl
+"/"+ colName
+"]");
753 if(stokenizer
.hasMoreTokens()) {
755 nextToken
= stokenizer
.nextToken();
756 nextXPath
= xpathTokenizer
.nextToken();
757 //logger.debug("2. nextToken ["+ nextToken +"]");
764 catch(XMLDBException e
) {
765 throw new SpittoonException(e
.getMessage(), e
);
768 return nextCollection
;
771 private String
generateCollectionNameR(String xpath
, String bareXPath
) {
774 StringTokenizer xtokenizer
= new StringTokenizer(xpath
, "/");
775 StringTokenizer btokenizer
= new StringTokenizer(bareXPath
, "/");
779 String eachPart
= null;
780 StringBuffer sbuffer
= new StringBuffer();
782 while(xtokenizer
.hasMoreTokens()) {
784 eachx
= xtokenizer
.nextToken();
785 eachb
= btokenizer
.nextToken();
787 eachPart
= generateNextCollectionName(eachb
, eachx
);
788 logger
.info("generateCollectionNameR:: eachx["+ eachx
+"] > eachb["+ eachb
+"] > eachPart["+ eachPart
+"]");
790 sbuffer
.append(eachPart
);
791 if(xtokenizer
.hasMoreTokens())
794 String resultName
= sbuffer
.toString();
795 logger
.info("generateCollectionNameR:: result["+ resultName
+"]");
799 private String
generateNextCollectionName(String nextToken
, String nextXPath
) {
801 String yvalue
= yankAttributeId(nextXPath
);
802 logger
.info("generating Collection name / nextXPath ["+ nextXPath
+"] / yanked 'id' value ["+ yvalue
+"] ...");
804 return nextToken
+ "." + yvalue
;
806 private String
yankAttributeId(String attributeString
) {
808 logger
.debug("yankAttributeId["+ attributeString
+"]");
810 //** test yanking 'id' attribute
811 //** make sure there's an 'id' attribute
812 int ii
= attributeString
.indexOf("@id");
816 attributeString
.substring(ii
, jj
);
818 catch(StringIndexOutOfBoundsException e
) {
819 throw new SpittoonException("No 'id' attribute specified for ["+ attributeString
+"]", e
);
822 //** find value for id attribute
823 String marker
= attributeString
.substring(jj
);
824 //logger.info("yanking marker["+marker+"]");
826 int kk
= marker
.indexOf("\"");
831 kk
= marker
.indexOf("'");
832 int ll
= marker
.indexOf("'", kk
+ 1);
833 subs
= marker
.substring(kk
+ 1, ll
);
835 //logger.info("yanking >> ' > kk["+ kk +"] / ll["+ll+"] / marker["+marker+"] / subs["+subs+"]");
840 int ll
= marker
.indexOf("\"", kk
+ 1);
841 subs
= marker
.substring(kk
+ 1, ll
);
843 //logger.info("yanking >> \" > kk["+ kk +"] / ll["+ll+"] / marker["+marker+"] / subs["+subs+"]");
847 logger
.info("yanked >> id["+id
+"] / value["+subs
+"]");
850 private String
generateDbUrl(String baseUrl
, String xpath
) {
852 return baseUrl
+ xpath
;
854 public String
generateResourceName(IBob bob
) {
856 String tagName
= bob
.getTagName();
857 String id
= bob
.getAttributeValue("id");
859 return generateResourceName(tagName
, id
);
861 public String
generateResourceName(String tagName
, String idValue
) {
863 StringBuffer sbuf
= new StringBuffer(tagName
);
865 sbuf
.append(idValue
);
867 String rname
= sbuf
.toString();
868 logger
.info("Generated resource name["+rname
+"]");
872 public boolean verifyXPathMapping(String xpath
) {
874 java
.util
.Collection values
= mappings
.values();
875 return values
.contains(xpath
);
879 * strips out any predicate(s)
881 public String
stripXPath(String xpath
) {
884 * this regular expression: \\[[^\\]]*\\]
885 * matches on all content between square brackets [ ], except a right square bracket.
886 * The last condition allows multiple [ abc ] patterns in a single string
888 String bareXPath
= xpath
.replaceAll("\\[[^\\]]*\\]", "");
889 if(bareXPath
.indexOf("/") == bareXPath
.length())
890 bareXPath
= bareXPath
.substring(0, bareXPath
.lastIndexOf("/"));
896 public IBob
loadBobFromXML(String xmlString
) throws SpittoonException
{
899 logger
.debug("loadBobFromXML:: ["+ xmlString
+"]");
901 //** load a Bob object
902 InputStream istream
= null;
904 istream
= new ByteArrayInputStream(xmlString
.getBytes("UTF-8"));
906 catch(UnsupportedEncodingException e
) {
907 throw new SpittoonException(e
);
911 //System.getProperties().setProperty("bob.home", props.getProperty("bob.home"));
912 //System.getProperties().setProperty("bob.base", props.getProperty("bob.base"));
913 //System.getProperties().setProperty("bob.gen", props.getProperty("bob.gen"));
914 //System.getProperties().setProperty("bob.end", props.getProperty("bob.gen"));
915 System
.getProperties().setProperty("bob.home", "/Users/timothyw/Projects/Spittoon");
916 System
.getProperties().setProperty("bob.base", "/Users/timothyw/Projects/Spittoon");
917 System
.getProperties().setProperty("bob.gen", "/Users/timothyw/Projects/Spittoon/src/main/gen");
918 System
.getProperties().setProperty("bob.end", ".xml");
920 IBob bob
= Bob
.loadS(istream
, System
.getProperty(Util
.DEF
));
921 logger
.debug("Loaded Bob from XML" + bob
.toXML(false));
928 public static void main(String args
[]) {
930 System
.getProperties().setProperty("bob.home", "/Users/timothyw/Projects/maven.trials/Spittoon");
931 System
.getProperties().setProperty("bob.base", "/Users/timothyw/Projects/maven.trials/Spittoon");
932 System
.getProperties().setProperty("bob.gen", "/Users/timothyw/Projects/maven.trials/Spittoon/src/main/gen");
933 System
.getProperties().setProperty("bob.end", ".xml");
935 String testme
= "<group xmlns=\"com/interrupt/bookkeeping/users\" id=\"webkell\" name=\"Webkell\" owner=\"root\">" +
936 "<user id=\"root\" username=\"\" password=\"\" logintimeout=\"\" accountLevel=\"\" defaultGroup=\"\" authenticated=\"\"/>" +
939 InputStream istream
= null;
941 istream
= new ByteArrayInputStream(testme
.getBytes("UTF-8"));
943 catch(UnsupportedEncodingException e
) {
944 throw new SpittoonException(e
);
947 IBob bob
= Bob
.loadS(istream
, "src/main/resources/bookkeeping.system.xml");
948 System
.out
.println("Loaded Bob form XML" + bob
.toXML(false));
952 private static void testStripXPath() {
954 //** testing stripXPath
955 /*String origXPath = "/system[ @id=\"thing\" ]/bookkeeping[ @attr=\"value\" ]/thing";
957 Spittoon spittoon = new Spittoon();
958 String bareXPath = spittoon.stripXPath(origXPath);
959 System.out.println(bareXPath);
962 //String testme = "/system[ @id=\"blahblah blah\" ]";
963 String testme
= "/system[ @id='blahblah blah' ]";
964 System
.out
.println("Begin ["+ testme
+"]");
966 /*String sstring[] = testme.split("\\[[^\\]]*\\]");
967 for (String string : sstring) {
968 System.out.println(string);
973 private static void testYanking() {
976 String testme
= "/system[ @id='blahblah blah' ]";
978 //** test yanking 'id' attribute
979 //** make sure there's an 'id' attribute
980 int ii
= testme
.indexOf("@id");
982 String id
= testme
.substring(ii
, jj
);
984 //** find value for id attribute
985 String marker
= testme
.substring(jj
);
986 System
.out
.println("marker["+marker
+"]");
988 int kk
= marker
.indexOf("\"");
993 kk
= marker
.indexOf("'");
994 int ll
= marker
.indexOf("'", kk
+ 1);
995 subs
= marker
.substring(kk
+ 1, ll
);
997 System
.out
.println(">> ' > kk["+ kk
+"] / ll["+ll
+"] / marker["+marker
+"] / subs["+subs
+"]");
1002 int ll
= marker
.indexOf("\"", kk
+ 1);
1003 subs
= marker
.substring(kk
+ 1, ll
);
1005 System
.out
.println(">> \" > kk["+ kk
+"] / ll["+ll
+"] / marker["+marker
+"] / subs["+subs
+"]");
1009 System
.out
.println("id["+id
+"] / value["+subs
+"]");
1013 class FindParentBob implements IVisitor {
1015 private Logger logger = Logger.getLogger(FindParentBob.class);
1016 private String tagName = null;
1017 private String attributeValue = null;
1018 private IBob replacement = null;
1020 public String getTagName() { return tagName; }
1021 public void setTagName(String tagName) { this.tagName = tagName; }
1022 public String getAttributeValue() { return attributeValue; }
1023 public void setAttributeValue(String attributeValue) { this.attributeValue = attributeValue; }
1024 public IBob getReplacement() { return replacement; }
1025 public void setReplacement(IBob replacement) { this.replacement = replacement; }
1027 private boolean acceptControl = true;
1028 public void visit(IBob bob) {
1032 String tname = bob.getTagName();
1033 String avalue = bob.getAttributeValue("id");
1035 logger.debug("FindParentBob.visit > comparing tagName["+tagName+"] <=> tname["+tname+"] / attributeValue["+attributeValue+"] <=> avalue["+avalue+"]");
1036 if((tagName.equals(tname)) && (attributeValue.equals(avalue))) {
1038 logger.debug("FindParentBob.visit > replacing ["+bob.xpath(false)+"] with ["+replacement.toXML(false)+"]");
1039 bob.replace(replacement);
1040 acceptControl = false;