commit b80fa05ed1b6d62a0e24b29d6c4c4963805c5806 Author: Eric J. Bowersox Date: Tue May 20 03:25:31 2003 +0000 *** empty log message *** diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..40caffa --- /dev/null +++ b/.cvsignore @@ -0,0 +1,28 @@ +# CVS default ignores begin +tags +TAGS +.make.state +.nse_depinfo +*~ +#* +.#* +,* +_$* +*$ +*.old +*.bak +*.BAK +*.orig +*.rej +.del-* +*.a +*.olb +*.o +*.obj +*.so +*.exe +*.Z +*.elc +*.ln +core +# CVS default ignores end diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..956db13 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +assembly +build.properties +jars +javadocs +OLD +workingarea diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..969b331 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Eric J. Bowersox diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..823a123 --- /dev/null +++ b/INSTALL @@ -0,0 +1,52 @@ +INSTALLATION INSTRUCTIONS +========================= + +THE JDK INSTALLATION +-------------------- +This version of Venice runs under JDK 1.4.1. The following extensions should +be installed to the $JAVA_HOME/jre/lib/ext directory: +- JavaMail 1.3 +- JavaBeans Activation Framework 1.0.2 +- Java Advanced Imaging 1.1.1, plus the JAI ImageIO extensions + +In addition, the Xalan 2.4.1 and Xerces 2.2.1 XML tools should be installed +as "endorsed standards overrides" in the $JAVA_HOME/jre/lib/endorsed directory. + +APACHE TOMCAT +------------- +A recent version of Apache Tomcat, such as version 4.1.24, must be installed. + +JAKARTA ANT +----------- +A recent version of Jakarta Ant, such as 1.5.1, must be installed to build +Venice. + +PACKAGES REQUIRED FOR VENICE +---------------------------- +The following packages must be referenced from within build.properties: +- Java Servlet API 2.3 (use the servlet.jar file from Tomcat) +- Jakarta Bean Scripting Framework 2.3 +- Jakarta Commons Collections Library, 2.1 +- Jakarta Commons Lang Library, 1.0.1 +- Mozilla.org Rhino, 1.5R3 +- Jakarta Log4J, 1.2.7 +- Jakarta Velocity, 1.3.1 + +Optionally: +- SourceID-SSO 1.0 + +DATABASE DRIVERS REQUIRED FOR VENICE +------------------------------------ +Currently, the only database supported with Venice is MySQL. The MySQL +Connector 3.0.7 should be copied to the drivers/ subdirectory. + +BUILDING AND DEPLOYING +---------------------- +When built, the complete installation of Venice will be copied to the +subdirectory "assembly/venice". This directory may be deployed into Tomcat +directly by editing $CATALINA_HOME/conf/server.xml. + +INITIALIZING THE DATABASE +------------------------- +The script "conf/venice-db-init-mysql.sql" can be used to initialize the +database. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7714141 --- /dev/null +++ b/LICENSE @@ -0,0 +1,470 @@ + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..00fcde6 --- /dev/null +++ b/README @@ -0,0 +1,2 @@ +This branch of the code is not really usable yet. New instructions will +be posted when it is. diff --git a/build.properties.sample b/build.properties.sample new file mode 100644 index 0000000..8ed6685 --- /dev/null +++ b/build.properties.sample @@ -0,0 +1,60 @@ +# The contents of this file are subject to the Mozilla Public License Version 1.1 +# (the "License"); you may not use this file except in compliance with the License. +# You may obtain a copy of the License at . +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +######################################################################################### + +# [Compilation control flags] +# compile.debug=on +# compile.deprecation=off +# compile.optimize=on +# build.compiler=modern + +# [Location of Servlet API 2.3] +servlet.base=/usr/local/jakarta/jakarta-tomcat-4.1.24-LE-jdk14 +servlet.lib=${servlet.base}/common/lib +# servlet.jarfile=servlet.jar + +# [Location of Bean Scripting Framework 2.3] +bsf.base=/usr/local/jakarta/bsf-2.3.0 +# bsf.lib=${bsf.base}/lib +# bsf.jarfile=bsf.jar + +# [Location of Commons Collections Library 2.1] +collections.base=/usr/local/jakarta/commons-collections-2.1 +# collections.lib=${collections.base} +# collections.jarfile=commons-collections.jar + +# [Location of Commons Lang Library 1.0.1] +commlang.base=/usr/local/jakarta/commons-lang-1.0.1 +# commlang.lib=${commlang.base} +commlang.jarfile=commons-lang-1.0.1.jar + +# [Location of Rhino 1.5R3] +rhino.base=/usr/local/java/rhino1_5R3 +# rhino.lib=${rhino.base} +# rhino.jarfile=js.jar + +# [Location of Log4J 1.2.7] +log4j.base=/usr/local/jakarta/jakarta-log4j-1.2.7 +# log4j.lib=${log4j.base}/dist/lib +log4j.jarfile=log4j-1.2.7.jar + +# [Location of Velocity 1.3.1] +velocity.base=/usr/local/jakarta/velocity-1.3.1 +# velocity.lib=${velocity.base} +velocity.jarfile=velocity-1.3.1.jar + +# [Location of SourceID SSO 1.0b7/1.0 (optional)] +# sourceid.base=${user.home}/sso diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..e4196d4 --- /dev/null +++ b/build.xml @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf-sso/extra-db-mysql.sql b/conf-sso/extra-db-mysql.sql new file mode 100644 index 0000000..831f84f --- /dev/null +++ b/conf-sso/extra-db-mysql.sql @@ -0,0 +1,33 @@ +# The contents of this file are subject to the Mozilla Public License Version 1.1 +# (the "License"); you may not use this file except in compliance with the License. +# You may obtain a copy of the License at . +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +# + +USE venice; + +############################################################################## +# Table Creation +############################################################################## + +# The table which stores federations for a user ID. Each user ID may federate to one or more providers. +CREATE TABLE sso_federate ( + uid INT NOT NULL, + provider VARCHAR(249) NOT NULL, + local_name VARCHAR(249) NOT NULL, + remote_name VARCHAR(249) NOT NULL, + PRIMARY KEY (uid, provider), + UNIQUE INDEX by_local (provider, local_name), + UNIQUE INDEX by_remote (provider, remote_name) +); diff --git a/conf-sso/sp/dynamo.xml b/conf-sso/sp/dynamo.xml new file mode 100644 index 0000000..ea723bb --- /dev/null +++ b/conf-sso/sp/dynamo.xml @@ -0,0 +1,182 @@ + + + + + + + + ${code.path} + + ${url} + ${context.path}/${url} + ${context.path}/images/${url} + ${context.path}/imagedata/${url} + ${context.path}/frame/${url} + + + + + + mysql + + com.mysql.jdbc.Driver + jdbc:mysql://localhost/venice + veniceuser + XYZZY0099 + + + + + + + + + + + ${code.path}/modules + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top.js.vs + verify_email.js.vs?tgt=${tgt} + + + + + /velocity + + + + + + + + /xmlrpc/siteinfo-metadata.xml + + + + + + /xmlrpc/session-metadata.xml + + + + + /dialogs + + + + + + + + + + /mailmessages + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf-sso/sp/logging.xml b/conf-sso/sp/logging.xml new file mode 100644 index 0000000..df3b1bb --- /dev/null +++ b/conf-sso/sp/logging.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf-sso/sp/sourceid-sso-providers.xml b/conf-sso/sp/sourceid-sso-providers.xml new file mode 100644 index 0000000..fe4f8fa --- /dev/null +++ b/conf-sso/sp/sourceid-sso-providers.xml @@ -0,0 +1,59 @@ + + + + + + SourceID-Sample-IDP + + + + + MIICSjCCAbMCBD4coSAwDQYJKoZIhvcNAQEEBQAwbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjAeFw0wMzAxMDgyMjA3MjhaFw0wMzA0MDgyMjA3MjhaMGwxEDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vua25vd24xEDAOBgNVBAoTB1Vua25vd24xEDAOBgNVBAsTB1Vua25vd24xEDAOBgNVBAMTB1Vua25vd24wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMJhokczPBJlZe48d5oKZiX6vo7DBU5b54t9JjSHLOEZd0XK5w81BY4iX8QADMc7GyTrqDDrehfh4S5eQO89Fll50D4f6HpSI2QGtionDrj3kuET9nW9n98IzWc3eiLLH+5q3VGm04rylo4PTnJCeMYmDRqYJkWR1xQbNsrv9HHJAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAI16O969XJkYRJaTiPXMcJg8XRM9oHKqc4L6YEDXGvnQ8NfTPDuJEzKIcU8QWNnprcY+MOue+O2YvP7u9NQuKK4zDA14CcIRb8G+VMLFa2A+BYiD66yIBWsb89YNFYnvH379wGp+ankQBTdljpgFo6Bt+fXmZxB6mToBdXy0h5b8= + + + + + + http://localhost:8080/sso-sample-idp/sso/soap/endpoint + http://localhost:8080/sso-sample-idp/sso/logout + http://localhost:8080/sso-sample-idp/sso/logout + http://localhost:8080/sso-sample-idp/sso/fedterm + http://localhost:8080/sso-sample-idp/sso/fedterm + http://localhost:8080/sso-sample-idp/sso/authn + + + http://projectliberty.org/profiles/rni-sp-soap + http://projectliberty.org/profiles/fedterm-sp-soap + http://projectliberty.org/profiles/fedterm-sp-http + http://projectliberty.org/profiles/slo-sp-soap + http://projectliberty.org/profiles/slo-sp-http + http://projectliberty.org/profiles/brws-art + http://projectliberty.org/profiles/brws-post + http://projectliberty.org/profiles/wml-post + http://projectliberty.org/profiles/lecp + + + diff --git a/conf-sso/sp/sourceid-sso.xml b/conf-sso/sp/sourceid-sso.xml new file mode 100644 index 0000000..0937d86 --- /dev/null +++ b/conf-sso/sp/sourceid-sso.xml @@ -0,0 +1,68 @@ + + + + + + Venice-SSO-SP + + + sp + /WEB-INF/sourceid-sso-providers.xml + + + /sourceid/errorHandler.js.vs + + + + /WEB-INF/venice-sp.keystore + numenor + mykey + mithrandir + + + + /idp/logon.jsp + 1800 + /idp/idpLogoutRender.jsp + /idp/checkmark.png + /idp/idpPost.jsp + + + dynamo.session + + + 60 + 300 + + + com.silverwrist.venice.sourceid.VeniceAccountHandler + + org.sourceid.sso.handlers.ArtifactHandlerInMemoryImpl + + + diff --git a/conf-sso/sp/sp-descriptor.xml b/conf-sso/sp/sp-descriptor.xml new file mode 100644 index 0000000..a9bedcd --- /dev/null +++ b/conf-sso/sp/sp-descriptor.xml @@ -0,0 +1,37 @@ + + + + + + Venice-SSO-SP + + + + MIICbjCCAdcCBD7AlmwwDQYJKoZIhvcNAQEEBQAwfjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNPMQ8wDQYDVQQHEwZEZW52ZXIxIzAhBgNVBAoTGlNpbHZlcndyaXN0IERlc2lnbiBTdHVkaW9zMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEWMBQGA1UEAxMNRXJpYyBCb3dlcnNveDAeFw0wMzA1MTMwNjUzMzJaFw0wMzA4MTEwNjUzMzJaMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMSMwIQYDVQQKExpTaWx2ZXJ3cmlzdCBEZXNpZ24gU3R1ZGlvczEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxFjAUBgNVBAMTDUVyaWMgQm93ZXJzb3gwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALvjYZPJwt16vTVIKleltTVDyvswVr2vCd9aHg7rKPhNKN+iVS2XY+Y5IopgcVtshQx/SbWnPNldtpGtFewaSQzCud/Lhja1xoGO/nTbjRr7MrPlR3yub8KO90tgslZ9yjEPZDWDEr3Y59ieDpMtAnYjS2GQ2LFRHq63kzd4AXg1AgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAVhJqkLZd59BiTjvRF0ZtBKXe+kxnvyclc0MeIzkzGFmnpMuSpSyZ3LlYp0uvFn5OADM6KkXj7DgXIqb1bqIvXmlwDds+oO3KL+WdHBO9KHW0KjR2jpIujpmJ8Eaf/cefcOxxA00CMrwBeL8EXyAaynpcT78nrT5iN3FZwMkBi9o= + + + + http://localhost:8080/venice-sp/sso/authnRequest + http://localhost:8080/venice-sp/sso/soap/endpoint + http://localhost:8080/venice-sp/sso/logout + http://localhost:8080/venice-sp/sso/logout + http://localhost:8080/venice-sp/sso/fedterm + http://localhost:8080/venice-sp/sso/fedterm + + http://projectliberty.org/profiles/fedterm-idp-soap + http://projectliberty.org/profiles/fedterm-idp-http + http://projectliberty.org/profiles/slo-idp-soap + http://projectliberty.org/profiles/slo-idp-http + http://projectliberty.org/profiles/slo-idp-http-get + http://projectliberty.org/profiles/rni-idp-soap + http://localhost:9080/sourceid-sso/sso/rni + http://localhost:9080/sourceid-sso/sso/rni + http://projectliberty.org/profiles/rni-idp-http + false + + + + diff --git a/conf-sso/sp/venice-sp.keystore b/conf-sso/sp/venice-sp.keystore new file mode 100644 index 0000000..929b650 Binary files /dev/null and b/conf-sso/sp/venice-sp.keystore differ diff --git a/conf-sso/sp/web.xml b/conf-sso/sp/web.xml new file mode 100644 index 0000000..5483072 --- /dev/null +++ b/conf-sso/sp/web.xml @@ -0,0 +1,335 @@ + + + + + Venice Web Communities System + + Venice Web Communities System (TODO: fill out description) + Contains SourceID-SSO, configured as Service Provider + + + + + + logging.config + WEB-INF/logging.xml + + The path and file name of the Log4J logger configuration file, relative to the application root. + + + + + dynamo.config + WEB-INF/dynamo.xml + + The path and file name of the base Dynamo configuration file, relative to the application root. + The default, if not specified, is "WEB-INF/dynamo.xml". + + + + + SSO.config.attrs + object=sso + + + + + + ScriptExec + Executes a scripting file as a servlet. + com.silverwrist.dynamo.servlet.ScriptExecServlet + + remove.extension + vs + + The extension which is used in the servlet mapping to distinguish scripts to execute. This + extension is removed from the servlet path to create the script name. + + + + script.prefix + /scripts + + The resource prefix to use for scripts. This is prepended to the servlet path to create the + script name which is executed. + + + 1 + + + + XmlRpc + Executes XML-RPC requests. + com.silverwrist.dynamo.xmlrpc.XmlRpcServlet + + subsystem.object + xmlrpc + + The object name of the XML-RPC subsystem object. Must match the name configured for the + com.silverwrist.dynamo.xmlrpc.XmlRpcSubSystem object in dynamo.xml. + + + + + + Remapper + Remaps URLs to other URLs programmatically. + com.silverwrist.dynamo.servlet.RemapperServlet + + data.object + remapper + + The object name of the remapper data object. Must match the name configured for the + com.silverwrist.dynamo.servlet.RemapperData object in dynamo.xml. + + + + + + Image + Serves up images from the ImageStore. + com.silverwrist.dynamo.servlet.ImageServlet + + image.store + images + + The object name of the image store object. Must match the name configured for the + com.silverwrist.dynamo.db.ImageStoreObject object in dynamo.xml. + + + + + + StyleSheet + Serves up CSS stylesheets for use by the frame. + com.silverwrist.venice.frame.StyleSheetServlet + + + + Frame + Frames static pages within the outer Venice frame. + com.silverwrist.venice.servlet.FrameServlet + + content.prefix + static + + The prefix to apply to the static content path before retrieving it. Interpreted + relative to the Web application root (i.e. where Web content normally gets linked from). + + + + cache.hard.limit + 5 + + Maximum number of documents that will be hard-cached by this servlet. Must be at least 1. + + + + cache.soft.limit + 10 + + Maximum number of documents that will be soft-cached by this servlet. Will always be at least + twice the number of hard-cached documents. + + + + + + PasswordRecovery + Used to access the password recovery feature; changes user passwords. + com.silverwrist.venice.session.PasswordRecoveryServlet + + + + User + Displays user profiles. + com.silverwrist.venice.servlet.UserServlet + + + + + + + SourceID-SSO-Manager + Loads configuration at boot time, and provides instrumentation and admin control + org.sourceid.sso.servlets.Manager + 15 + + + + + SourceID-SSO-Authenticator + Provides Identity Provider (IDP) Authentication Services + org.sourceid.sso.servlets.Authenticator + + + + + SourceID-SSO-AuthnRequestor + Provides Service Provider (SP) Authentication Request Services + org.sourceid.sso.servlets.AuthnRequestor + + + + + SourceID-SSO-FederationTerminator + Provides Federation Termination Services + org.sourceid.sso.servlets.FederationTerminator + + + + + SourceID-SSO-Logout + Provides Single Logout Services + org.sourceid.sso.servlets.Logout + + + + + SourceID-SSO-NameRegistrar + Provides Single Logout Services + org.sourceid.sso.servlets.NameRegistrar + + + + + AxisServlet + Apache-Axis Servlet + org.apache.axis.transport.http.AxisServlet + + + AdminServlet + Axis Admin Servlet + org.apache.axis.transport.http.AdminServlet + 100 + + + SOAPMonitorService + SOAPMonitorService + org.apache.axis.monitor.SOAPMonitorService + + SOAPMonitorPort + 5001 + + 100 + + + + + + + + ScriptExec + *.vs + + + + XmlRpc + /RPC2 + + + + Remapper + /verifyemail + + + + Image + /imagedata/* + + + + StyleSheet + /stylesheet-base.css + + + + StyleSheet + /stylesheet-advanced.css + + + + Frame + /frame/* + + + + PasswordRecovery + /passrecovery/* + + + + User + /user/* + + + + + + + SourceID-SSO-Authenticator + /sso/authn + + + + + SourceID-SSO-AuthnRequestor + /sso/authnRequest + + + + + SourceID-SSO-FederationTerminator + /sso/fedterm + + + + + SourceID-SSO-Logout + /sso/logout + + + + + SourceID-SSO-NameRegistrar + /sso/rni + + + + + AxisServlet + /sso/soap/* + + + + + + + 60 + + + + + default.jsp + index.html + + + diff --git a/conf/db-init-mysql.sql b/conf/db-init-mysql.sql new file mode 100644 index 0000000..2181ba1 --- /dev/null +++ b/conf/db-init-mysql.sql @@ -0,0 +1,236 @@ +# The contents of this file are subject to the Mozilla Public License Version 1.1 +# (the "License"); you may not use this file except in compliance with the License. +# You may obtain a copy of the License at . +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +# + +############################################################################## +# Database Creation +############################################################################## + +DROP DATABASE IF EXISTS dbname; +CREATE DATABASE dbname; +USE dbname; + +############################################################################## +# Table Creation +############################################################################## + +# The "namespace cache" table, used to map string namespaces (used in the code) to integer IDs +# (used in the database). +CREATE TABLE namespaces ( + nsid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + namespace VARCHAR(255) BINARY NOT NULL, + UNIQUE INDEX on_namespace (namespace) +); + +# The global properties table. +CREATE TABLE globalprop ( + nsid INT NOT NULL, + prop_name VARCHAR(255) BINARY NOT NULL, + prop_value VARCHAR(255), + PRIMARY KEY (nsid, prop_name) +); + +# The global "blocks" table, used to store fragments of text/HTML for later use. +CREATE TABLE globalblock ( + nsid INT NOT NULL, + block_name VARCHAR(255) BINARY NOT NULL, + block TEXT, + PRIMARY KEY (nsid, block_name) +); + +# The main user information table. +CREATE TABLE users ( + uid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(64) NOT NULL, + email VARCHAR(255) NOT NULL, + is_anon TINYINT DEFAULT 0, + locked TINYINT DEFAULT 0, + nospam TINYINT DEFAULT 0, + created DATETIME NOT NULL, + last_accessed DATETIME, + UNIQUE INDEX on_username (username) +); + +# The user authentication data table. We identify authentication methods by namespace ID +# and name, and provide "source data" to allow multiple sources for the same type of +# authentication (such as browser cookies for multiple browsers). +CREATE TABLE userauth ( + uid INT NOT NULL, + nsid INT NOT NULL, + method VARCHAR(255) BINARY NOT NULL, + source_data VARCHAR(255), + auth_data VARCHAR(255), + PRIMARY KEY (uid, nsid, method) +); + +# The user properties table. +CREATE TABLE userprop ( + uid INT NOT NULL, + nsid INT NOT NULL, + prop_name VARCHAR(255) BINARY NOT NULL, + prop_value VARCHAR(255), + PRIMARY KEY (uid, nsid, prop_name) +); + +# The groups table. +CREATE TABLE groups ( + gid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + groupname VARCHAR(64) NOT NULL, + gaclid INT NOT NULL DEFAULT -1, + UNIQUE INDEX on_groupname (groupname) +); + +# The group membership table. +CREATE TABLE groupmembers ( + gid INT NOT NULL, + uid INT NOT NULL, + PRIMARY KEY (gid, uid), + UNIQUE INDEX reverse_index (uid, gid) +); + +# The group properties table. +CREATE TABLE groupprop ( + gid INT NOT NULL, + nsid INT NOT NULL, + prop_name VARCHAR(255) BINARY NOT NULL, + prop_value VARCHAR(255), + PRIMARY KEY (gid, nsid, prop_name) +); + +# The main ACL table. Each ACL has a numeric ID, a name, an unordered collection of owners (which may +# be groups or users), and an ordered collection of entries (ACEs). +CREATE TABLE acl ( + aclid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + aclname VARCHAR(255) NOT NULL, + INDEX on_name (aclname) +); + +# The table of owners for ACLs. Each ACL has one or more owners. +# Flags Bit 0: 0=user, 1=group +CREATE TABLE aclowner ( + aclid INT NOT NULL, + ownerid INT NOT NULL, + flags TINYINT NOT NULL, + INDEX on_acl (aclid) +); + +# The table mapping ACLs to ACEs. Each ACL has zero or more ACEs. +CREATE TABLE acldata ( + aclid INT NOT NULL, + seq INT NOT NULL, + aceid INT NOT NULL, + PRIMARY KEY (aclid, seq) +); + +# The main ACE table. Each ACE has a numeric ID, a principal reference (which may be a user or +# group ID), a "negative" flag, and an unordered collection of permissions. +# Flags Bit 0: 0=user, 1=group +# Flags Bit 4: 0=positive ACE, 1=negative ACE +CREATE TABLE ace ( + aceid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + pri INT, + flags TINYINT NOT NULL DEFAULT 0 +); + +# The table mapping permissions into ACEs. Permissions are identified by namespace and name. +CREATE TABLE acedata ( + aceid INT NOT NULL, + perm_nsid INT NOT NULL, + perm_name VARCHAR(255) BINARY NOT NULL, + INDEX on_ace (aceid) +); + +# Global security data table. +CREATE TABLE globalsec ( + admin_uid INT NOT NULL, + admin_gid INT NOT NULL, + global_aclid INT NOT NULL, + alluser_gid INT NOT NULL, + verified_gid INT NOT NULL +); + +# The audit information table. Each audit "event" can have up to 8 properties defined with it, +# which are serialized as other "properties." +CREATE TABLE audit ( + record BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, + on_date DATETIME NOT NULL, + event INT NOT NULL, + uid INT NOT NULL, + subid INT NOT NULL DEFAULT 0, + ip VARCHAR(48), + prop0 VARCHAR(255), + prop1 VARCHAR(255), + prop2 VARCHAR(255), + prop3 VARCHAR(255), + prop4 VARCHAR(255), + prop5 VARCHAR(255), + prop6 VARCHAR(255), + prop7 VARCHAR(255), + INDEX by_date (on_date), + INDEX sub_view (subid, on_date) +); + +# The table where events are assigned "event IDs" in the master audit record, +# to cut down on space usage in the audit table. Event IDs can be predefined +# at database create time, or defined dynamically, or both. +CREATE TABLE auditevent ( + eventid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + event_nsid INT NOT NULL, + event_name VARCHAR(255) BINARY NOT NULL, + descr TINYTEXT, + UNIQUE INDEX by_event (event_nsid, event_name) +); + +# The image store table. This is used to store relatively small images like +# user photos and logos. +CREATE TABLE imagestore ( + imageid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + typecode INT NOT NULL, + ownerid INT NOT NULL, + ownerflag TINYINT NOT NULL DEFAULT 0, + mimetype VARCHAR(128), + length INT, + data MEDIUMBLOB +); + +# The image type table, used to differentiate between images stored in the table. +CREATE TABLE imagetype ( + typecode INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + nsid INT NOT NULL, + name VARCHAR(255) BINARY NOT NULL +); + +############################################################################## +# Set table access rights +############################################################################## + +# this is a test only - remove when we go to production +GRANT ALL PRIVILEGES ON dbname.* + TO erbo@localhost IDENTIFIED BY 'meesatest' + WITH GRANT OPTION; +GRANT ALL PRIVILEGES ON dbname.* + TO erbo@'10.29.99.%' IDENTIFIED BY 'meesatest' + WITH GRANT OPTION; + +GRANT INSERT, DELETE, UPDATE, SELECT ON dbname.* + TO testuser@localhost IDENTIFIED BY 'TestPassword'; + +############################################################################## +# Initialization data +############################################################################## + +INSERT INTO users (uid, username, email, is_anon, nospam, created) + VALUES (1, 'Anonymous_Honyak', 'nobody@localhost', 1, 1, '2002-12-15 12:00:00'); diff --git a/conf/dynamo-test.xml b/conf/dynamo-test.xml new file mode 100644 index 0000000..850eae0 --- /dev/null +++ b/conf/dynamo-test.xml @@ -0,0 +1,70 @@ + + + + + + + ${code.path} + + ${url} + ${context.path}/${url} + + + + + mysql + + com.mysql.jdbc.Driver + jdbc:mysql://localhost/dbname + testuser + TestPassword + + + + + ${code.path}/modules + + + + /velocity + + + + + + + + janelane + Venice Mail System + nobody@delenn.silverwrist.internal + Venice AutoMail System + /mailmessages + +The Venice Project is not responsible for the contents of this message +Report abuses to: + ]]> + X-Venice-User-Info + + + + + + diff --git a/conf/dynamo-venice.xml b/conf/dynamo-venice.xml new file mode 100644 index 0000000..3be3c0f --- /dev/null +++ b/conf/dynamo-venice.xml @@ -0,0 +1,175 @@ + + + + + + + + ${code.path} + + ${url} + ${context.path}/${url} + ${context.path}/images/${url} + ${context.path}/imagedata/${url} + ${context.path}/frame/${url} + + + + + + mysql + + com.mysql.jdbc.Driver + jdbc:mysql://localhost/venice + veniceuser + XYZZY0099 + + + + + + + + + + ${code.path}/modules + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top.js.vs + verify_email.js.vs?tgt=${tgt} + + + + + /velocity + + + + + + + + /xmlrpc/siteinfo-metadata.xml + + + + + + /xmlrpc/session-metadata.xml + + + + + /dialogs + + + + + + + + + + /mailmessages + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/logging-test.xml b/conf/logging-test.xml new file mode 100644 index 0000000..525cb17 --- /dev/null +++ b/conf/logging-test.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/logging-venice.xml b/conf/logging-venice.xml new file mode 100644 index 0000000..e5f935b --- /dev/null +++ b/conf/logging-venice.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/std_render_macro_library.vm b/conf/std_render_macro_library.vm new file mode 100644 index 0000000..f84e493 --- /dev/null +++ b/conf/std_render_macro_library.vm @@ -0,0 +1,31 @@ +#* + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the License. + You may obtain a copy of the License at . + + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + WARRANTY OF ANY KIND, either express or implied. See the License for the specific + language governing rights and limitations under the License. + + The Original Code is the Venice Web Communities System. + + The Initial Developer of the Original Code is Eric J. Bowersox , + for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + + Contributor(s): +*# + +## Define macros around the "std" object. +#macro( formatURL $type $url )$std.formatURL($type,$url)#end + +#macro( encodeHTML $data )$std.encodeHTML($data)#end + +#macro( encodeURL $data )$std.encodeURL($data)#end + +#macro( render $obj )$std.renderObject($obj)#end + +#macro( renderDialog $dlg )$std.renderDialog($dlg)#end + +#macro( stacktrace $thr )$std.getStackTrace($thr)#end + diff --git a/conf/venice-db-init-mysql.sql b/conf/venice-db-init-mysql.sql new file mode 100644 index 0000000..6b2668d --- /dev/null +++ b/conf/venice-db-init-mysql.sql @@ -0,0 +1,573 @@ +# The contents of this file are subject to the Mozilla Public License Version 1.1 +# (the "License"); you may not use this file except in compliance with the License. +# You may obtain a copy of the License at . +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +# + +############################################################################## +# Database Creation +############################################################################## + +DROP DATABASE IF EXISTS venice; +CREATE DATABASE venice; +USE venice; + +############################################################################## +# Table Creation +############################################################################## + +# The "namespace cache" table, used to map string namespaces (used in the code) to integer IDs +# (used in the database). +CREATE TABLE namespaces ( + nsid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + namespace VARCHAR(255) BINARY NOT NULL, + UNIQUE INDEX on_namespace (namespace) +); + +# The global properties table. +CREATE TABLE globalprop ( + nsid INT NOT NULL, + prop_name VARCHAR(255) BINARY NOT NULL, + prop_value VARCHAR(255), + PRIMARY KEY (nsid, prop_name) +); + +# The global "blocks" table, used to store fragments of text/HTML for later use. +CREATE TABLE globalblock ( + nsid INT NOT NULL, + block_name VARCHAR(255) BINARY NOT NULL, + block TEXT, + PRIMARY KEY (nsid, block_name) +); + +# The main user information table. +CREATE TABLE users ( + uid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(64) NOT NULL, + email VARCHAR(255) NOT NULL, + is_anon TINYINT DEFAULT 0, + locked TINYINT DEFAULT 0, + nospam TINYINT DEFAULT 0, + created DATETIME NOT NULL, + last_accessed DATETIME, + UNIQUE INDEX on_username (username) +); + +# The user authentication data table. We identify authentication methods by namespace ID +# and name, and provide "source data" to allow multiple sources for the same type of +# authentication (such as browser cookies for multiple browsers). +CREATE TABLE userauth ( + uid INT NOT NULL, + nsid INT NOT NULL, + method VARCHAR(255) BINARY NOT NULL, + source_data VARCHAR(255), + auth_data VARCHAR(255), + PRIMARY KEY (uid, nsid, method) +); + +# The user properties table. +CREATE TABLE userprop ( + uid INT NOT NULL, + nsid INT NOT NULL, + prop_name VARCHAR(255) BINARY NOT NULL, + prop_value VARCHAR(255), + PRIMARY KEY (uid, nsid, prop_name) +); + +# The groups table. +CREATE TABLE groups ( + gid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + groupname VARCHAR(64) NOT NULL, + gaclid INT NOT NULL DEFAULT -1, + UNIQUE INDEX on_groupname (groupname) +); + +# The group membership table. +CREATE TABLE groupmembers ( + gid INT NOT NULL, + uid INT NOT NULL, + PRIMARY KEY (gid, uid), + UNIQUE INDEX reverse_index (uid, gid) +); + +# The group properties table. +CREATE TABLE groupprop ( + gid INT NOT NULL, + nsid INT NOT NULL, + prop_name VARCHAR(255) BINARY NOT NULL, + prop_value VARCHAR(255), + PRIMARY KEY (gid, nsid, prop_name) +); + +# The main ACL table. Each ACL has a numeric ID, a name, an unordered collection of owners (which may +# be groups or users), and an ordered collection of entries (ACEs). +CREATE TABLE acl ( + aclid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + aclname VARCHAR(255) NOT NULL, + INDEX on_name (aclname) +); + +# The table of owners for ACLs. Each ACL has one or more owners. +# Flags Bit 0: 0=user, 1=group +CREATE TABLE aclowner ( + aclid INT NOT NULL, + ownerid INT NOT NULL, + flags TINYINT NOT NULL, + INDEX on_acl (aclid) +); + +# The table mapping ACLs to ACEs. Each ACL has zero or more ACEs. +CREATE TABLE acldata ( + aclid INT NOT NULL, + seq INT NOT NULL, + aceid INT NOT NULL, + PRIMARY KEY (aclid, seq) +); + +# The main ACE table. Each ACE has a numeric ID, a principal reference (which may be a user or +# group ID), a "negative" flag, and an unordered collection of permissions. +# Flags Bit 0: 0=user, 1=group +# Flags Bit 4: 0=positive ACE, 1=negative ACE +CREATE TABLE ace ( + aceid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + pri INT, + flags TINYINT NOT NULL DEFAULT 0 +); + +# The table mapping permissions into ACEs. Permissions are identified by namespace and name. +CREATE TABLE acedata ( + aceid INT NOT NULL, + perm_nsid INT NOT NULL, + perm_name VARCHAR(255) BINARY NOT NULL, + INDEX on_ace (aceid) +); + +# Global security data table. +CREATE TABLE globalsec ( + admin_uid INT NOT NULL, + admin_gid INT NOT NULL, + global_aclid INT NOT NULL, + alluser_gid INT NOT NULL, + verified_gid INT NOT NULL +); + +# The audit information table. Each audit "event" can have up to 8 properties defined with it, +# which are serialized as other "properties." +CREATE TABLE audit ( + record BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, + on_date DATETIME NOT NULL, + event INT NOT NULL, + uid INT NOT NULL, + subid INT NOT NULL DEFAULT 0, + ip VARCHAR(48), + prop0 VARCHAR(255), + prop1 VARCHAR(255), + prop2 VARCHAR(255), + prop3 VARCHAR(255), + prop4 VARCHAR(255), + prop5 VARCHAR(255), + prop6 VARCHAR(255), + prop7 VARCHAR(255), + INDEX by_date (on_date), + INDEX sub_view (subid, on_date) +); + +# The table where events are assigned "event IDs" in the master audit record, +# to cut down on space usage in the audit table. Event IDs can be predefined +# at database create time, or defined dynamically, or both. +CREATE TABLE auditevent ( + eventid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + event_nsid INT NOT NULL, + event_name VARCHAR(255) BINARY NOT NULL, + descr TINYTEXT, + UNIQUE INDEX by_event (event_nsid, event_name) +); + +# The image store table. This is used to store relatively small images like +# user photos and logos. +CREATE TABLE imagestore ( + imageid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + typecode INT NOT NULL, + ownerid INT NOT NULL, + ownerflag TINYINT NOT NULL DEFAULT 0, + mimetype VARCHAR(128), + length INT, + data MEDIUMBLOB +); + +# The image type table, used to differentiate between images stored in the table. +CREATE TABLE imagetype ( + typecode INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + nsid INT NOT NULL, + name VARCHAR(255) BINARY NOT NULL +); + +#### following this line are Venice-specific tables #### + +# The table which defines menus. +CREATE TABLE menus ( + menuid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + menu_nsid INT NOT NULL, + menu_name VARCHAR(255) BINARY NOT NULL, + title VARCHAR(255) NOT NULL, + subtitle VARCHAR(255) NULL, + UNIQUE INDEX by_name (menu_nsid, menu_name) +); + +# Definitions of variables for menus. +CREATE TABLE menuvars ( + menuid INT NOT NULL, + var_name VARCHAR(255) NOT NULL, + default_val VARCHAR(255) NULL, + PRIMARY KEY (menuid, var_name) +); + +# Definitions of menu items. +CREATE TABLE menuitems ( + menuid INT NOT NULL, + sequence INT NOT NULL, + itemtype VARCHAR(32) NOT NULL, + enable TINYINT NOT NULL DEFAULT 1, + indent INT NOT NULL DEFAULT 0, + text VARCHAR(255) NULL, + linktype VARCHAR(32) NULL, + link VARCHAR(255) NULL, + target VARCHAR(255) NULL, + title VARCHAR(255) NULL, + on_click VARCHAR(255) NULL, + perm_nsid INT NULL, + perm_name VARCHAR(255) BINARY NULL, + ifdef_var VARCHAR(255) NULL, + ifndef_var VARCHAR(255) NULL, + PRIMARY KEY (menuid, sequence) +); + +############################################################################## +# Set table access rights +############################################################################## + +# this is a test only - remove when we go to production +GRANT ALL PRIVILEGES ON venice.* + TO erbo@localhost IDENTIFIED BY 'meesatest' + WITH GRANT OPTION; + +GRANT INSERT, DELETE, UPDATE, SELECT, LOCK TABLES ON venice.* + TO veniceuser@localhost IDENTIFIED BY 'XYZZY0099'; + +############################################################################## +# Initialization data +############################################################################## + +# Initial namespaces setup +INSERT INTO namespaces (nsid, namespace) VALUES + (1, 'http://www.silverwrist.com/NS/venice/2002/12/21/frame.look.and.feel' ), + (2, 'http://www.silverwrist.com/NS/venice/2002/12/22/stylesheets' ), + (3, 'http://www.silverwrist.com/NS/dynamo/2002/12/13/user.information' ), + (4, 'http://www.silverwrist.com/NS/dynamo/2002/12/27/group.permissions' ), + (5, 'http://www.silverwrist.com/NS/venice/2002/12/28/mail.properties' ), + (6, 'http://www.silverwrist.com/NS/venice/2002/12/28/content.look.and.feel'), + (7, 'http://www.silverwrist.com/NS/venice/2002/12/30/session.control' ), + (8, 'http://www.silverwrist.com/NS/venice/2002/12/31/system.events' ), + (9, 'http://www.silverwrist.com/NS/venice/2002/12/31/user.events' ), + (10, 'http://www.silverwrist.com/NS/venice/2002/12/31/user.settings' ), + (11, 'http://www.silverwrist.com/NS/venice/2002/12/31/user.profile' ), + (12, 'http://www.silverwrist.com/NS/venice/2003/01/03/system.mail.messages' ); + +# Initial global properties setup +INSERT INTO globalprop (nsid, prop_name, prop_value) VALUES + (1, 'site.title', '!Venice Test' ), + (1, 'optionset', '_OS:AC' ), + (1, 'site.url', '!http://localhost:8080/venice/' ), + (1, 'site.logo.url', '!temp/site-logo.jpg' ), + (1, 'site.logo.url.type', '!IMAGE' ), + (1, 'site.logo.width', 'I140' ), + (1, 'site.logo.height', 'I80' ), + (1, 'frame.template', '!frame.vm' ), + (1, 'footer.logo.scale', 'I100' ), + (1, 'page.icon.url', '!venice-icon.png' ), + (1, 'page.icon.url.type', '!IMAGE' ), + (1, 'page.icon.type', '!image/png' ), + (1, 'page.favicon.url', '!venice-favicon.ico' ), + (1, 'page.favicon.url.type', '!IMAGE' ), + (2, 'sheet.base.normal', '!stylesheets/normal_base.vm' ), + (2, 'sheet.adv.normal', '!stylesheets/adv_base.vm' ), + (5, 'smtp.host', '!localhost' ), + (5, 'system.mail.from.addr', '!nobody@delenn.silverwrist.internal'), + (5, 'system.mail.from.name', '!Venice Mail System' ), + (5, 'mailer.name', '!Venice AutoMail System' ), + (5, 'user.info.header', '!X-Venice-User-Info' ), + (6, 'subdir.buttons', '!buttons/classic' ), + (6, 'std.button.width', 'I80' ), + (6, 'std.button.height', 'I24' ), + (6, 'bn.cancel', '!cancel.jpg' ), + (6, 'bnc.cancel', '!Cancel' ), + (6, 'bn.create', '!create.jpg' ), + (6, 'bnc.create', '!Create' ), + (6, 'bn.i.accept', '!user_accept.jpg' ), + (6, 'bnc.i.accept', '!I Accept' ), + (6, 'bn.i.decline', '!user_decline.jpg' ), + (6, 'bnc.i.decline', '!I Decline' ), + (6, 'bn.login', '!login.jpg' ), + (6, 'bnc.login', '!Log In' ), + (6, 'bn.ok', '!ok.jpg' ), + (6, 'bnc.ok', '!OK' ), + (6, 'bn.reminder', '!reminder.jpg' ), + (6, 'bnc.reminder', '!Reminder' ), + (6, 'bn.send.again', '!send_again.jpg' ), + (6, 'bnc.send.again', '!Send Again' ), + (6, 'bn.send.email', '!send_email.jpg' ), + (6, 'bnc.send.email', '!Send E-Mail' ), + (6, 'bn.set', '!set.jpg' ), + (6, 'bnc.set', '!Set' ), + (6, 'bn.update', '!update.jpg' ), + (6, 'bnc.update', '!Update' ), + (6, 'user.agreement.title', '!Venice User Agreement' ), + (6, 'user.photo.width', 'I100' ), + (6, 'user.photo.height', 'I100' ), + (6, 'user.nophoto.url', '!photo_not_avail.gif' ), + (6, 'user.nophoto.url.type', '!IMAGE' ), + (7, 'session.init.script', '!/util/session_init.js' ), + (7, 'login.cookie', '!VeniceAuth' ), + (7, 'login.cookie.maxage', 'I365' ), + (7, 'password.recovery.time', 'I60' ), + (10, 'timezone', '_TZ:UTC' ), + (10, 'locale', '_LOC:en_US' ), + (10, 'admin.flags', '_OS:' ), + (11, 'privacy', '_OS:' ), + (12, 'confirm.message.title', '!Venice E-Mail Confirmation' ), + (12, 'password.change.message.title', '!Venice Password Changed' ), + (12, 'reminder.message.title', '!Venice Password Reminder Message' ); + +# Initial global blocks setup +INSERT INTO globalblock (nsid, block_name, block) VALUES + (1, 'footer', +'All trademarks and copyrights on this page are owned by their respective companies. +All messages posted by users on this page are owned by those users. +The rest: Copyright © 2002-2003 Silverwrist Design Studios, All Rights Reserved. +See our Policy Page for our copyright and privacy policies.'), + (5, 'user.disclaimer', +'Message sent via Venice Web Communities System - +The Venice Project is not responsible for the contents of this message +Report abuses to: '), + (5, 'signature', +'Venice - community services, conferencing and more. '), + (6, 'content.header', +'$title +#if( $subtitle ) +   $subtitle +#end +
'), + (6, 'std.bullet', +'*'), + (6, 'error.box', +'

+ + +
+ #encodeHTML( $title ) +
+

#encodeHTML( $message )

+

+ #if( $back ) + Go back. + #else + Use your browser''s Back button to go back. + #end +

+

+#if( $except ) + +#end'), + (6, 'user.agreement', +'Text of this agreement is to be determined.'), + (12, 'confirm.message', +'Welcome to the Venice Web Communities System! In order to fully activate your +account after you register or change your E-mail address, you must provide a +confirmation number to the system. Please enter this number into the "Confirm +E-mail Address" dialog on the system when indicated. + +Your confirmation number for your account "$username" is $confnum. + +Access the E-mail verification dialog at . + +Thank you, and enjoy the Venice Web Communities System! + +-- The Management'), + (12, 'password.change.message', +'The password for your account "$username" has been changed. The new +password is "$password". + +You should log into Venice immediately and change the password to something +else. You can change the password for your account, once you are logged in, +by clicking on the "Profile" link in the top bar. + +If you did NOT request a password change on your account, please notify the +system administrator IMMEDIATELY. + +-- The Management'), + (12, 'reminder.message', +'Here is the password reminder for your account "$username" as you requested: + +$reminder + +If this reminder is not sufficient for you to remember what your password is, +then the system can change your password for you. To do so, please visit +the following URL: + +http://localhost/venice/passrecovery/$uid/$auth + +Your password will be changed and a new password will be E-mailed to you +at this address. + +If you did NOT request a password reminder, then this message was sent +by someone attempting to access your account without your knowledge. Do +not panic! Nothing has happened to your account or password yet, but +please do notify the system administrator. + +-- The Management'); + +# Initial users setup +# (UID 1 and 2) +INSERT INTO users (uid, username, email, is_anon, nospam, created) VALUES + (1, 'Anonymous_Honyak', 'nobody@localhost', 1, 1, '2002-12-15 12:00:00'), + (2, 'Administrator', 'root@localhost', 0, 0, '2002-12-26 18:00:00'); + +# Set up properties for Anonymous_Honyak. +INSERT INTO userprop (uid, nsid, prop_name, prop_value) VALUES + (1, 10, 'timezone', '_TZ:UTC' ), + (1, 10, 'locale', '_LOC:en_US'), + (1, 10, 'admin.flags', '_OS:A' ), + (1, 11, 'privacy', '_OS:' ), + (1, 11, 'name.given', '!Anonymous'), + (1, 11, 'name.family', '!Honyak' ), + (1, 11, 'locality', '!Nowhere' ), + (1, 11, 'region', '!XX' ), + (1, 11, 'postal.code', '!00000' ), + (1, 11, 'country', '_CTRY:US' ); + +# Add authentication for Administrator (no password by default) +INSERT INTO userauth (uid, nsid, method, source_data, auth_data) VALUES + (2, 3, 'default.hash.password', '', ''); + +# Set up properties for Administrator. +INSERT INTO userprop (uid, nsid, prop_name, prop_value) VALUES + (2, 10, 'timezone', '_TZ:UTC' ), + (2, 10, 'locale', '_LOC:en_US' ), + (2, 10, 'admin.flags', '_OS:' ), + (2, 11, 'privacy', '_OS:' ), + (2, 11, 'name.given', '!System' ), + (2, 11, 'name.family', '!Administrator'), + (2, 11, 'locality', '!Nowhere' ), + (2, 11, 'region', '!XX' ), + (2, 11, 'postal.code', '!00000' ), + (2, 11, 'country', '_CTRY:US' ); + +# Create a group for site administrators. +# (GID 1) +INSERT INTO groups (gid, groupname) VALUES (1, 'Site_Administration'); +INSERT INTO groupmembers (gid, uid) VALUES (1, 2); + +# Create an ACL for the site administrator group. The ACL is owned by Administrator +# and grants "add" and "remove" permissions to Administrator only. +# (ACL 1, ACE 1) +INSERT INTO acl (aclid, aclname) VALUES (1, 'Site_Administration'); +INSERT INTO aclowner (aclid, ownerid, flags) VALUES (1, 2, 0); +INSERT INTO ace (aceid, pri, flags) VALUES (1, 2, 0); +INSERT INTO acldata (aclid, seq, aceid) VALUES (1, 0, 1); +INSERT INTO acedata (aceid, perm_nsid, perm_name) VALUES + (1, 4, 'add.member' ), + (1, 4, 'remove.member'); +UPDATE groups SET gaclid = 1 WHERE gid = 1; + +# Create the "all users" group. +# (GID 2) +INSERT INTO groups (gid, groupname) VALUES (2, 'All_Users'); +INSERT INTO groupmembers (gid, uid) VALUES (2, 2); + +# Create the "all verified users" group. +# (GID 3) +INSERT INTO groups (gid, groupname) VALUES (3, 'Verified_Users'); +INSERT INTO groupmembers (gid, uid) VALUES (3, 2); + +# Create the global ACL. This ACL is owned by the Administrator and grants +# permissions to the site administration group and to the Administrator specifically. +# (ACL 2, ACEs 2 and 3) +INSERT INTO acl (aclid, aclname) VALUES (2, 'Global_Permissions'); +INSERT INTO aclowner (aclid, ownerid, flags) VALUES (2, 2, 0); +INSERT INTO ace (aceid, pri, flags) VALUES (2, 1, 1); +INSERT INTO acldata (aclid, seq, aceid) VALUES (2, 0, 2); +INSERT INTO acedata (aceid, perm_nsid, perm_name) VALUES + (2, 1, 'set.property' ), + (2, 1, 'set.block' ), + (2, 2, 'set.property' ), + (2, 3, 'edit.all' ), + (2, 3, 'bypass.email.verify'), + (2, 3, 'view.all' ), + (2, 5, 'set.property' ), + (2, 5, 'set.block' ), + (2, 6, 'set.property' ), + (2, 6, 'set.block' ), + (2, 7, 'set.property' ), + (2, 10, 'set.property' ), + (2, 10, 'remove.property' ), + (2, 11, 'set.property' ), + (2, 11, 'remove.property' ), + (2, 12, 'set.property' ), + (2, 12, 'set.block' ); +INSERT INTO ace (aceid, pri, flags) VALUES (3, 2, 0); +INSERT INTO acldata (aclid, seq, aceid) VALUES (2, 1, 3); +INSERT INTO acedata (aceid, perm_nsid, perm_name) VALUES + (3, 1, 'remove.property'), + (3, 1, 'remove.block' ), + (3, 2, 'remove.property'), + (3, 5, 'remove.property'), + (3, 5, 'remove.block' ), + (3, 6, 'remove.property'), + (3, 6, 'remove.block' ), + (3, 7, 'remove.property'), + (3, 12, 'remove.property'), + (3, 12, 'remove.block' ); + +# Create the entries in the global security table. +INSERT INTO globalsec (admin_uid, admin_gid, global_aclid, alluser_gid, verified_gid) + VALUES (2, 1, 2, 2, 3); + +# Insert some audit event type records. +INSERT INTO auditevent (eventid, event_nsid, event_name, descr) VALUES + (1, 8, 'system.startup', 'Venice Server Startup' ), + (2, 8, 'system.shutdown', 'Venice Server Shutdown' ), + (3, 9, 'login.ok', 'Successful User Login' ), + (4, 9, 'login.fail', 'Failed User Login' ), + (5, 9, 'verify.ok', 'Successful E-Mail Address Verification'), + (6, 9, 'verify.fail', 'Failed E-Mail Address Verification' ), + (7, 9, 'resend.confirm.email', 'Re-Sent E-Mail Confirmation Message' ), + (8, 9, 'send.confirm.email', 'Sent E-Mail Confirmation Message' ), + (9, 9, 'user.created', 'New User Created' ); + +# Insert some image types. +INSERT INTO imagetype (typecode, nsid, name) VALUES + (1, 11, 'user.photo'); + +#### following this line is initialization of Venice-specific tables #### + +# Create the "global" menu. +INSERT INTO menus (menuid, menu_nsid, menu_name, title, subtitle) + VALUES (1, 1, 'fixed.menu', 'About This Site', NULL); +INSERT INTO menuitems (menuid, sequence, itemtype, text, linktype, link) VALUES + (1, 0, 'TEXT', 'Documentation', 'ABSOLUTE', 'TODO' ), + (1, 1, 'TEXT', 'About Venice', 'FRAME', 'about-venice.html'); +UPDATE menuitems SET enable = 0 WHERE menuid = 1 AND sequence = 0; + diff --git a/conf/web-test.xml b/conf/web-test.xml new file mode 100644 index 0000000..24e3bda --- /dev/null +++ b/conf/web-test.xml @@ -0,0 +1,117 @@ + + + + + Dynamo Test Application + This is an application used to test components of the Dynamo framework. + + + + + logging.config + WEB-INF/logging.xml + + The path and file name of the Log4J logger configuration file, relative to the application root. + + + + + dynamo.config + WEB-INF/dynamo.xml + + The path and file name of the base Dynamo configuration file, relative to the application root. + The default, if not specified, is "WEB-INF/dynamo.xml". + + + + + + + ScriptExec + Executes a scripting file as a servlet. + com.silverwrist.dynamo.servlet.ScriptExecServlet + + remove.extension + vs + + The extension which is used in the servlet mapping to distinguish scripts to execute. This + extension is removed from the servlet path to create the script name. + + + + script.prefix + /scripts + + The resource prefix to use for scripts. This is prepended to the servlet path to create the + script name which is executed. + + + + + + XmlRpc + Executes XML-RPC requests. + com.silverwrist.dynamo.xmlrpc.XmlRpcServlet + + subsystem.object + xmlrpc + + The object name of the XML-RPC subsystem object. Must match the name configured for the + com.silverwrist.dynamo.xmlrpc.XmlRpcSubSystem object in dynamo.xml. + + + + + + TestServlet1 + Servlet test 1 + com.silverwrist.dynamo.test.TestServlet1 + + + + TestServlet2 + Servlet test 2 + com.silverwrist.dynamo.test.TestServlet2 + + + + + + ScriptExec + *.vs + + + + XmlRpc + /RPC2 + + + + TestServlet1 + /test1 + + + + TestServlet2 + /test2 + + + diff --git a/conf/web-venice.xml b/conf/web-venice.xml new file mode 100644 index 0000000..47c8132 --- /dev/null +++ b/conf/web-venice.xml @@ -0,0 +1,218 @@ + + + + + Venice Web Communities System + + Venice Web Communities System (TODO: fill out description) + + + + + + logging.config + WEB-INF/logging.xml + + The path and file name of the Log4J logger configuration file, relative to the application root. + + + + + dynamo.config + WEB-INF/dynamo.xml + + The path and file name of the base Dynamo configuration file, relative to the application root. + The default, if not specified, is "WEB-INF/dynamo.xml". + + + + + + + ScriptExec + Executes a scripting file as a servlet. + com.silverwrist.dynamo.servlet.ScriptExecServlet + + remove.extension + vs + + The extension which is used in the servlet mapping to distinguish scripts to execute. This + extension is removed from the servlet path to create the script name. + + + + script.prefix + /scripts + + The resource prefix to use for scripts. This is prepended to the servlet path to create the + script name which is executed. + + + + + + XmlRpc + Executes XML-RPC requests. + com.silverwrist.dynamo.xmlrpc.XmlRpcServlet + + subsystem.object + xmlrpc + + The object name of the XML-RPC subsystem object. Must match the name configured for the + com.silverwrist.dynamo.xmlrpc.XmlRpcSubSystem object in dynamo.xml. + + + + + + Remapper + Remaps URLs to other URLs programmatically. + com.silverwrist.dynamo.servlet.RemapperServlet + + data.object + remapper + + The object name of the remapper data object. Must match the name configured for the + com.silverwrist.dynamo.servlet.RemapperData object in dynamo.xml. + + + + + + Image + Serves up images from the ImageStore. + com.silverwrist.dynamo.servlet.ImageServlet + + image.store + images + + The object name of the image store object. Must match the name configured for the + com.silverwrist.dynamo.db.ImageStoreObject object in dynamo.xml. + + + + + + StyleSheet + Serves up CSS stylesheets for use by the frame. + com.silverwrist.venice.frame.StyleSheetServlet + + + + Frame + Frames static pages within the outer Venice frame. + com.silverwrist.venice.servlet.FrameServlet + + content.prefix + static + + The prefix to apply to the static content path before retrieving it. Interpreted + relative to the Web application root (i.e. where Web content normally gets linked from). + + + + cache.hard.limit + 5 + + Maximum number of documents that will be hard-cached by this servlet. Must be at least 1. + + + + cache.soft.limit + 10 + + Maximum number of documents that will be soft-cached by this servlet. Will always be at least + twice the number of hard-cached documents. + + + + + + PasswordRecovery + Used to access the password recovery feature; changes user passwords. + com.silverwrist.venice.session.PasswordRecoveryServlet + + + + User + Displays user profiles. + com.silverwrist.venice.servlet.UserServlet + + + + + + ScriptExec + *.vs + + + + XmlRpc + /RPC2 + + + + Remapper + /verifyemail + + + + Image + /imagedata/* + + + + StyleSheet + /stylesheet-base.css + + + + StyleSheet + /stylesheet-advanced.css + + + + Frame + /frame/* + + + + PasswordRecovery + /passrecovery/* + + + + User + /user/* + + + + + 60 + + + + + default.jsp + index.html + + + diff --git a/docs/buttons/.gitignore b/docs/buttons/.gitignore new file mode 100644 index 0000000..5c165d9 --- /dev/null +++ b/docs/buttons/.gitignore @@ -0,0 +1 @@ +.xvpics diff --git a/docs/buttons/bn_blank80.png b/docs/buttons/bn_blank80.png new file mode 100644 index 0000000..100bbd6 Binary files /dev/null and b/docs/buttons/bn_blank80.png differ diff --git a/docs/buttons/bn_delete.png b/docs/buttons/bn_delete.png new file mode 100644 index 0000000..084742a Binary files /dev/null and b/docs/buttons/bn_delete.png differ diff --git a/docs/buttons/bn_save.png b/docs/buttons/bn_save.png new file mode 100644 index 0000000..49df817 Binary files /dev/null and b/docs/buttons/bn_save.png differ diff --git a/docs/buttons/classic.xcf b/docs/buttons/classic.xcf new file mode 100644 index 0000000..e618a4a Binary files /dev/null and b/docs/buttons/classic.xcf differ diff --git a/docs/buttons/gelcap_green.xcf b/docs/buttons/gelcap_green.xcf new file mode 100644 index 0000000..e7fb605 Binary files /dev/null and b/docs/buttons/gelcap_green.xcf differ diff --git a/docs/buttons/gelcap_pink.xcf b/docs/buttons/gelcap_pink.xcf new file mode 100644 index 0000000..b83ecb0 Binary files /dev/null and b/docs/buttons/gelcap_pink.xcf differ diff --git a/docs/buttons/gelcap_red.xcf b/docs/buttons/gelcap_red.xcf new file mode 100644 index 0000000..b5ab477 Binary files /dev/null and b/docs/buttons/gelcap_red.xcf differ diff --git a/docs/buttons/gelcap_teal.xcf b/docs/buttons/gelcap_teal.xcf new file mode 100644 index 0000000..10e87c6 Binary files /dev/null and b/docs/buttons/gelcap_teal.xcf differ diff --git a/docs/buttons/gelcap_violet.xcf b/docs/buttons/gelcap_violet.xcf new file mode 100644 index 0000000..9537ae0 Binary files /dev/null and b/docs/buttons/gelcap_violet.xcf differ diff --git a/docs/buttons/gelcap_yellow.xcf b/docs/buttons/gelcap_yellow.xcf new file mode 100644 index 0000000..e65ae18 Binary files /dev/null and b/docs/buttons/gelcap_yellow.xcf differ diff --git a/docs/design-goals.html b/docs/design-goals.html new file mode 100644 index 0000000..047f4af --- /dev/null +++ b/docs/design-goals.html @@ -0,0 +1,103 @@ + + + + Design Goals of Venice/Dynamo + + +

Design Goals of Venice/Dynamo

+ Eric J. Bowersox, <erbo@silcom.com> - May 2003 +

Introduction - The Original Venice Goals

+

As is well-known, the Venice Web Communities System was originally founded for the purpose of providing + code on which the new Electric Minds server could be run. To this + end, it was designed along the lines of the CommunityWare platform, by Durand Communications, on which + Electric Minds was run for several years. (CommunityWare formed the nucleus of the WebbMe portal system + as well.) To that end, the original design goals of Venice looked like this:

+
    +
  1. A replacement for the CommunityWare/WebbMe conferencing system
  2. +
  3. Java/JSP/servlets implementation running under Apache Tomcat, MySQL backend
  4. +
  5. Multiple communities hosted per server, each with multiple conferences + (and other features); users logged into one server can join multiple communities
  6. +
  7. Conferencing functionality similar to CW/WebbMe: +
      +
    • Linear topics composed of HTML messages
    • +
    • View topics by new messages/unread/all messages/hidden topics/archived topics
    • +
    • Topics can be deleted/archived/made read-only by the conference host
    • +
    • Topics can be hidden from a user's personal view
    • +
    • Individual posts can be "hidden" or "scribbled" by owner or conference host
    • +
    • Posts can be previewed, with spellchecking and HTML formatting
    • +
    • Files can be "attached" to posts (up to 1 Mb in size)
    • +
    +
  8. +
  9. Enhancements to existing conference features: +
      +
    • Full text search of posts within a conference
    • +
    • Conference-level "bozo filters"
    • +
    • Individual posts can be "nuked" without a trace by the conference host
    • +
    +
  10. +
  11. Later, replace other CW/WebbMe functions: +
      +
    • Activity logs
    • +
    • Instant messaging and chat (use Jabber)
    • +
    • Calendaring
    • +
    • Newsletters via e-mail
    • +
    +
  12. +
  13. Features from CW/WebbMe we won't do: +
      +
    • Web hosting
    • +
    • Web-based email
    • +
    +
  14. +
  15. Blue sky features: +
      +
    • Output uses XML and gets formatted into [X]HTML via XSLT; "themeable"/"skinnable" interface
    • +
    • Conferencing/other functionality available via XML-RPC or SOAP calls
    • +
    • News page creation (see Slash, Squishdot, Scoop)
    • +
    • Member trust metrics (see Slashdot "karma," Scoop "mojo," Advogato distributed trust metric) + (Feature indefinitely shelved at the request of the EMinds community)
    • +
    • User diary pages (see Advogato, Kuro5hin)
    • +
    • Moderated discussions (see Slash, Scoop)
    • +
    • Collaborative database facility (see Wiki, Everything2)
    • +
    • Content management/distributed publishing
    • +
    +
  16. +
+

Evolution of The Original Venice Code

+

As time went on and the Venice code was put to use on Electric Minds and elsewhere, gradually, the enhanced + feature set described in "Enhancements," above, was implemented, as well as some additional enhancements (user + photos in posts, some limited customization capabilities). This was in response to the needs of Electric Minds + and other communities

+

Perhaps the biggest change, however, was a changeover from the original UI front end, which used a great many + "magic servlets," to a generalized system which employed a scripting engine built into Venice (actually, the + Bean Scripting Framework, which supports many different scripting languages), so that UI-level operations could + be written as scripts and executed directly by means of a single servlet. The JSP-based display front ends, too, + were updated, making heavy use of JSP tag libraries to minimize the amount of embedded code on a page.

+

A partial XML-RPC API was also implemented, and the "mailgate" program was written to take advantage of this, + providing a gateway from a mailing list to a Venice conferencing topic, with some success.

+

Dynamo - The Next Leap Forward

+

Currently, the Venice code is being rewritten to be even more modular than before, carrying the advantages + of the modularized, scriptable UI into other aspects of the code. As part of this effort, the lower-level + support elements of the application are being factored out into a code framework referred to as "Dynamo" (for + "DYNAMic Objects"). The goals of the new Dynamo-based Venice are as follows:

+
    +
  1. Even greater modularity than the original Venice, including dynamically-loadable modules. One should + be able to add a new service to Venice simply by dropping a JAR file into a directory on the server and + performing an installation process from within Venice's administrative UI.
  2. +
  3. Replacement of the JSP front-ends, which involve a high degree of overhead as well as the need to employ + external access protection to prevent them from being invoked directly by an end-user. Instead, a solution + based on the Velocity template system will be employed.
  4. +
  5. Refactoring of database access, to eventually allow the use of databases other than MySQL, especially + ones which employ stored procedures.
  6. +
  7. Improved search capabilities for posts, possibly employing the Lucene full-text search engine.
  8. +
  9. Shifting of configuration information from XML configuration files to the database, where it can be + modified without bringing down the server. A new "property" storage system will be employed for much of + this information.
  10. +
  11. Replacement of the original Venice security model, which employed a somewhat-confusing system of "security + levels." Instead, a more modern ACL-based system will be employed, for greater granularity.
  12. +
  13. Replacement of the front-page publishing model to allow people other than administrators to "publish" + posts there. Instead, a system of "channels" will be created, with each channel having its own ACL + to permit other people to access it.
  14. +
+ + diff --git a/docs/identifiers.html b/docs/identifiers.html new file mode 100644 index 0000000..b3b7892 --- /dev/null +++ b/docs/identifiers.html @@ -0,0 +1,46 @@ + + + + Doc: About Venice Identifiers + + + +

About Venice Identifiers

+ Eric J. Bowersox <erbo@silcom.com> - + January 26, 2001

+ + Venice identifiers are used for user IDs, community aliases, and conference aliases (and maybe other unique + identifiers in the future). A valid Venice ID consists of characters from the following character set + only: +

    +
  • Alphanumerics [A-Z, a-z, and 0-9]
  • +
  • Dash [-]
  • +
  • Underscore [_]
  • +
  • Tilde [~]
  • +
  • Asterisk [*]
  • +
  • Apostrophe [']
  • +
  • Dollar sign [$]
  • +

+ All characters are represented in the ISO 8859-1 character set. Also note that all Venice identifiers + are case-insensitive.

+ Rationale

+ The character set was defined starting with the list of characters allowable in URL path components + ("pchar" as defined in RFC 2396, section 3.3, page 14), so that Venice IDs would be usable as "path + information" in a URL.

+ The ampersand [&] was eliminated because of its possible confusion with a URL parameter separator, and + because it requires HTML escaping.

+ The at sign [@] was eliminated because of possible confusion with email addresses and Jabber IDs.

+ The plus sign [+] was eliminated because of possible confusion with a URL-encoded space character.

+ The comma [,] was eliminated because of its possible interpretation as a separator character.

+ The equals sign [=] was eliminated because of its possible confusion with a URL parameter/value + separator.

+ The colon [:] was withheld to provide for a possible future "namespace" expansion (as in XML + namespaces).

+ The parentheses [(, )] were eliminated because of possible confusion with user link syntax in + conferencing.

+ The period [.] was eliminated because of possible confusion with post link syntax in conferencing.

+ The exclamation point [!] was eliminated because of possible confusion with extended post link syntax in + conferencing. + + + diff --git a/docs/user-acl-truth-table.sxc b/docs/user-acl-truth-table.sxc new file mode 100644 index 0000000..46e2d4c Binary files /dev/null and b/docs/user-acl-truth-table.sxc differ diff --git a/drivers/.gitignore b/drivers/.gitignore new file mode 100644 index 0000000..b3b3865 --- /dev/null +++ b/drivers/.gitignore @@ -0,0 +1 @@ +mysql-connector-java-3.0.7-stable-bin.jar diff --git a/drivers/README.drivers b/drivers/README.drivers new file mode 100644 index 0000000..eb651f5 --- /dev/null +++ b/drivers/README.drivers @@ -0,0 +1,6 @@ +This is the directory where JDBC drivers get placed. + +MySQL +----- +Store the file "mysql-connector-java-3.0.7-stable-bin.jar" in this directory. + diff --git a/resources/dynamo-test-module/res1.txt b/resources/dynamo-test-module/res1.txt new file mode 100644 index 0000000..f7513f6 --- /dev/null +++ b/resources/dynamo-test-module/res1.txt @@ -0,0 +1 @@ +If you're reading this, we loaded the resource successfully! diff --git a/src/baseutil/com/silverwrist/util/AnyCharMatcher.java b/src/baseutil/com/silverwrist/util/AnyCharMatcher.java new file mode 100644 index 0000000..a454c0f --- /dev/null +++ b/src/baseutil/com/silverwrist/util/AnyCharMatcher.java @@ -0,0 +1,160 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +/** + * A class which performs the equivalent of String.indexOf(char), but using + * multiple characters. It locates the first instance within a string of any of + * the specified characters. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public final class AnyCharMatcher +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private char[] charset; // the set of characters to look for + private int[] locs; // a temporary array used for locations + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + /** + * Creates a new character matcher that matches the specified characters. + * + * @param charset The set of characters to be matched by this object, expressed as a character array. + */ + public AnyCharMatcher(char[] charset) + { + this.charset = charset; + this.locs = new int[charset.length]; + + } // end constructor + + /** + * Creates a new character matcher that matches the specified characters. + * + * @param charset The set of characters to be matched by this object, expressed as a string. + */ + public AnyCharMatcher(String charset) + { + this.charset = charset.toCharArray(); + this.locs = new int[charset.length()]; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * Returns the offset within the string of the first instance of any character in this + * character set. + * + * @param str The string to look through. If this parameter is null, + * the method returns -1. + * @return The 0-based index of the first instance of any character from this character + * matcher within str. If str contains no instances of + * any character from this character matcher, -1 is returned. + */ + public final int get(String str) + { + if (str==null) + return -1; + int numindexes = 0; + int i; + for (i=0; i=0) + locs[numindexes++] = tmp; + + } // end for + + if (numindexes==0) + return -1; // no characters found + else if (numindexes==1) + return locs[0]; // only one found + + int rc = locs[0]; + for (i=1; inull, + * the method returns -1. + * @return The 0-based index of the last instance of any character from this character + * matcher within str. If str contains no instances of + * any character from this character matcher, -1 is returned. + */ + public final int getLast(String str) + { + if (str==null) + return -1; + + int numindexes = 0; + int i; + for (i=0; i=0) + locs[numindexes++] = tmp; + + } // end for + + if (numindexes==0) + return -1; // no characters found + else if (numindexes==1) + return locs[0]; // only one found + + int rc = locs[0]; + int limit = str.length() - 1; + for (i=1; irc) + rc = locs[i]; // this is now the highest + + } // end for + + return rc; + + } // end getLast + +} // end class AnyCharMatcher diff --git a/src/baseutil/com/silverwrist/util/BooleanValues.properties b/src/baseutil/com/silverwrist/util/BooleanValues.properties new file mode 100644 index 0000000..cf97455 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/BooleanValues.properties @@ -0,0 +1,19 @@ +# The contents of this file are subject to the Mozilla Public License Version 1.1 +# (the "License"); you may not use this file except in compliance with the License. +# You may obtain a copy of the License at . +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +# --------------------------------------------------------------------------------- +# This file has been localized for the en_US locale +values.true=1|true|yes|on +values.false=0|false|no|off diff --git a/src/baseutil/com/silverwrist/util/Country.java b/src/baseutil/com/silverwrist/util/Country.java new file mode 100644 index 0000000..72e4016 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/Country.java @@ -0,0 +1,159 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +/** + * A utility class used by International that stores a country code and name pair. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + * @see International + */ +public final class Country implements Comparable +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String m_code; // the country code + private String m_name; // the country name + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Constructs a new Country object. + * + * @param code The country code. + * @param name The country name. + */ + Country(String code, String name) + { + m_code = code.trim().toUpperCase(); + m_name = name.trim(); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class Object + *-------------------------------------------------------------------------------- + */ + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param o The reference object with which to compare. + * @return true if this object is the same as the o argument; false otherwise. + */ + public boolean equals(Object o) + { + if ((o==null) || !(o instanceof Country)) + return false; + if (this==(Country)o) + return true; + Country other = (Country)o; + return m_code.equals(other.m_code); + + } // end equals + + /** + * Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those + * provided by java.util.Hashtable. + * + * @return A hash code value for this object. + */ + public int hashCode() + { + return m_code.hashCode(); + + } // end hashCode + + /** + * Returns a string representation of the object. In general, the toString method returns a string + * that "textually represents" this object. + * + * @return A string representation of the object. + */ + public String toString() + { + return m_name + " [" + m_code + "]"; + + } // end toString + + /*-------------------------------------------------------------------------------- + * Implementations from interface Comparable + *-------------------------------------------------------------------------------- + */ + + /** + * Compares this object with the specified object for order. Returns a negative integer, zero, or a positive + * integer as this object is less than, equal to, or greater than the specified object. Country + * objects are compared on their country name. + * + * @param o The Object to be compared. + * @return A negative integer, zero, or a positive integer as this object is less than, equal to, or greater than + * the specified object. + * @exception java.lang.ClassCastException If the specified object's type prevents it from being compared to + * this Object. + */ + public int compareTo(Object o) + { + if (o==null) + return 1; + if (o instanceof Country) + { // compare country names + Country c = (Country)o; + return m_name.compareTo(c.m_name); + + } // end if + + return m_name.compareTo(o.toString()); + + } // end compareTo + + /*-------------------------------------------------------------------------------- + * External getters + *-------------------------------------------------------------------------------- + */ + + /** + * Returns the 2-letter country code for this country. + * + * @return The 2-letter country code for this country. + */ + public final String getCode() + { + return m_code; + + } // end code + + /** + * Returns the name of this country. + * + * @return The name of this country. + */ + public final String getName() + { + return m_name; + + } // end name + +} // end class Country diff --git a/src/baseutil/com/silverwrist/util/HardSoftCache.java b/src/baseutil/com/silverwrist/util/HardSoftCache.java new file mode 100644 index 0000000..41a7a9b --- /dev/null +++ b/src/baseutil/com/silverwrist/util/HardSoftCache.java @@ -0,0 +1,329 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +import java.lang.ref.*; +import java.util.*; + +/** + * A class implementing a memory-sensitive cache. The cache is an LRU cache which uses two size limits, + * the soft limit and the hard limit. The soft limit dictates the maximum size of the + * cache; all elements in the cache have SoftReferences to them, which allows the JVM to expel + * them from memory if necessary. However, the most recent elements in the cache, up to the hard limit, + * have ordinary references on them, which prevents them from being expelled. Therefore, under low memory + * conditions, all elements in the cache may be discarded except for the most recent ones. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class HardSoftCache +{ + /*-------------------------------------------------------------------------------- + * Internal class to hold the hard hash entries + *-------------------------------------------------------------------------------- + */ + + private static class HardHashMap extends LinkedHashMap + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private int m_maxsize; // maximum size of the cache + + /*==================================================================== + * Constructor + *==================================================================== + */ + + private HardHashMap(int capacity) + { + super(capacity+2,0.95F,true); + m_maxsize = capacity; + + } // end constructor + + /*==================================================================== + * Overrides from class LinkedHashMap + *==================================================================== + */ + + protected boolean removeEldestEntry(Map.Entry eldest) + { + return (this.size()>m_maxsize); + + } // end removeEldestEntry + + } // end class HardHashMap + + /*-------------------------------------------------------------------------------- + * Internal class to hold the soft hash entries + *-------------------------------------------------------------------------------- + */ + + private static class SoftHashMap extends LinkedHashMap + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private int m_maxsize; // maximum size of the cache + + /*==================================================================== + * Constructor + *==================================================================== + */ + + private SoftHashMap(int capacity) + { + super(capacity+2,0.95F,true); + m_maxsize = capacity; + + } // end constructor + + /*==================================================================== + * Overrides from class HashMap + *==================================================================== + */ + + public Object put(Object key, Object value) + { + SoftReference newref = new SoftReference(value); + Reference r = (Reference)(super.put(key,newref)); + Object rc = null; + if (r!=null) + { // get the old object + rc = r.get(); + r.clear(); + + } // end if + + return rc; + + } // end put + + public void putAll(Map t) + { + Iterator it = t.entrySet().iterator(); + while (it.hasNext()) + { // run each item through our modified put() + Map.Entry ntry = (Map.Entry)(it.next()); + this.put(ntry.getKey(),ntry.getValue()); + + } // end while + + } // end putAll + + public Object remove(Object key) + { + Reference r = (Reference)(super.remove(key)); + Object rc = null; + if (r!=null) + { // get the old object + rc = r.get(); + r.clear(); + + } // end if + + return rc; + + } // end remove + + /*==================================================================== + * Overrides from class LinkedHashMap + *==================================================================== + */ + + public void clear() + { + Iterator it = this.values().iterator(); + while (it.hasNext()) + { // dump all the references we contain + Reference r = (Reference)(it.next()); + r.clear(); + + } // end while + + super.clear(); + + } // end clear + + public Object get(Object key) + { + Reference r = (Reference)(super.get(key)); + if (r==null) + return null; + Object rc = r.get(); + if (rc==null) + { // reference has been dumped - remove it from the map + super.remove(key); + r.clear(); + + } // end if + + return rc; + + } // end get + + protected boolean removeEldestEntry(Map.Entry eldest) + { + if (this.size()<=m_maxsize) + return false; + Reference r = (Reference)(eldest.getValue()); + r.clear(); + return true; + + } // end removeEldestEntry + + } // end class SoftHashMap + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private HardHashMap m_hard_map; // the "hard map" + private SoftHashMap m_soft_map; // the "soft map" + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Constructs a new cache object. + * + * @param hard_limit The "hard limit" for this cache. Has a minimum value of 1. + * @param soft_limit The "soft limit" for this cache. Has a minimum value of 2 times the value of the + * "hard limit." + */ + public HardSoftCache(int hard_limit, int soft_limit) + { + // Pre-condition the input parameters. + if (hard_limit<1) + hard_limit = 1; + if (soft_limit<(hard_limit * 2)) + soft_limit = hard_limit * 2; + m_hard_map = new HardHashMap(hard_limit); + m_soft_map = new SoftHashMap(soft_limit); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * Returns the value to which this cache maps the specified key. Returns null if the cache + * contains no mapping for this key. + * + * @param key The key whose associated value is to be returned. + * @return The value to which this cache maps the specified key. + */ + public synchronized Object get(Object key) + { + if (key==null) + throw new NullPointerException("HardSoftCache.get"); + Object hard_rc = m_hard_map.get(key); + Object soft_rc = m_soft_map.get(key); + return ((hard_rc!=null) ? hard_rc : soft_rc); + + } // end get + + /** + * Associates the specified value with the specified key in this cache. If the cache previously contained a + * mapping for this key, the old value is replaced. + * + * @param key The key with which the specified value is to be associated. + * @param value The value to be associated with the specified key. + */ + public synchronized void put(Object key, Object value) + { + if (key==null) + throw new NullPointerException("HardSoftCache.put(key)"); + if (value==null) + throw new NullPointerException("HardSoftCache.put(value)"); + m_hard_map.put(key,value); + m_soft_map.put(key,value); + + } // end put + + /** + * Removes the mapping for this key from this cache if present. + * + * @param key The key whose mapping is to be removed from the map. + */ + public synchronized void remove(Object key) + { + if (key==null) + throw new NullPointerException("HardSoftCache.remove"); + m_hard_map.remove(key); + m_soft_map.remove(key); + + } // end remove + + /** + * Returns the number of key-value mappings in this cache. + * + * @return The number of key-value mappings in this cache. + */ + public synchronized int size() + { + return m_soft_map.size(); + + } // end size + + /** + * Returns true if this cache contains no key-value mappings. + * + * @return true if this cache contains no key-value mappings. + */ + public synchronized boolean isEmpty() + { + return m_hard_map.isEmpty(); + + } // end isEmpty + + /** + * Removes all mappings from this cache. + */ + public synchronized void clear() + { + m_hard_map.clear(); + m_soft_map.clear(); + + } // end clear + + /** + * Returns true if this cache contains a mapping for the specified key. + * + * @param key The key whose presence in this cache is to be tested. + * @return true if this cache contains a mapping for the specified key. + */ + public synchronized boolean containsKey(Object key) + { + if (key==null) + throw new NullPointerException("HardSoftCache.containsKey"); + return (m_soft_map.get(key)!=null); + + } // end containsKey + +} // end class HardSoftCache diff --git a/src/baseutil/com/silverwrist/util/IOUtils.java b/src/baseutil/com/silverwrist/util/IOUtils.java new file mode 100644 index 0000000..d8edcf1 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/IOUtils.java @@ -0,0 +1,378 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +import java.io.*; + +/** + * A collection of IO-related static methods which are useful in various contexts.

+ * Some of the concepts in this class have been borrowed from Apache Jakarta Avalon Excalibur 4.0. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class IOUtils +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + /** + * The default buffer size to use for copying, if none is specified. + */ + public static int DEFAULT_BUFSIZE = 4096; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * IOUtils instances should NOT be constructed in standard programming. + * Instead, the class should be used as IOUtils.shutdown(stm);. + * This constructor is public to permit tools that require a JavaBean instance + * to operate. + */ + public IOUtils() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + /** + * Closes an input stream cleanly, without throwing an exception. + * + * @param stm The stream to be closed. + * @see java.io.InputStream#close() + */ + public static void shutdown(InputStream stm) + { + try + { // close the stream + stm.close(); + + } // end try + catch (IOException e) + { // throw away the exception + } // end catch + + } // end shutdown + + /** + * Closes an output stream cleanly, without throwing an exception. + * + * @param stm The stream to be closed. + * @see java.io.OutputStream#close() + */ + public static void shutdown(OutputStream stm) + { + try + { // close the stream + stm.close(); + + } // end try + catch (IOException e) + { // throw away the exception + } // end catch + + } // end shutdown + + /** + * Closes an input reader cleanly, without throwing an exception. + * + * @param stm The stream to be closed. + * @see java.io.Reader#close() + */ + public static void shutdown(Reader rdr) + { + try + { // close the stream + rdr.close(); + + } // end try + catch (IOException e) + { // throw away the exception + } // end catch + + } // end shutdown + + /** + * Closes an output reader cleanly, without throwing an exception. + * + * @param stm The stream to be closed. + * @see java.io.Writer#close() + */ + public static void shutdown(Writer wr) + { + try + { // close the stream + wr.close(); + + } // end try + catch (IOException e) + { // throw away the exception + } // end catch + + } // end shutdown + + /** + * Copies the contents of the given input stream to the given output stream. + * + * @param input The stream to copy binary data from. + * @param output The stream to copy binary data to. + * @param bufsize The size of the buffer to allocate for copying. + * @exception java.io.IOException If an exception occurred while reading or writing data. + */ + public static void copy(InputStream input, OutputStream output, int bufsize) throws IOException + { + byte[] buffer = new byte[bufsize]; + int rd = input.read(buffer); + while (rd>=0) + { // simple read-write loop to shove data out the door + if (rd>0) + output.write(buffer,0,rd); + rd = input.read(buffer); + + } // end while + + } // end copy + + /** + * Copies the contents of the given input stream to the given output stream. Uses a default + * buffer size. + * + * @param input The stream to copy binary data from. + * @param output The stream to copy binary data to. + * @exception java.io.IOException If an exception occurred while reading or writing data. + * @see #DEFAULT_BUFSIZE + * @see #copy(java.io.InputStream,java.io.OutputStream,int) + */ + public static void copy(InputStream input, OutputStream output) throws IOException + { + copy(input,output,DEFAULT_BUFSIZE); + + } // end copy + + /** + * Takes the contents of an input stream and returns it as an array of bytes. + * + * @param input The stream to load binary data from. + * @param bufsize The size of the buffer to allocate for copying. + * @return A new byte array containing the contents of the specified input stream. + * @exception java.io.IOException If an exception occurred while reading data. + * @see #copy(java.io.InputStream,java.io.OutputStream,int) + */ + public static byte[] load(InputStream input, int bufsize) throws IOException + { + ByteArrayOutputStream stm = new ByteArrayOutputStream(); + try + { // copy the data to the input stream + copy(input,stm,bufsize); + return stm.toByteArray(); + + } // end try + finally + { // close our byte array stream before we go + shutdown(stm); + + } // end finally + + } // end load + + /** + * Takes the contents of an input stream and returns it as an array of bytes. Uses a default + * buffer size. + * + * @param input The stream to load binary data from. + * @return A new byte array containing the contents of the specified input stream. + * @exception java.io.IOException If an exception occurred while reading data. + * @see #DEFAULT_BUFSIZE + * @see #load(java.io.InputStream,int) + */ + public static byte[] load(InputStream input) throws IOException + { + return load(input,DEFAULT_BUFSIZE); + + } // end load + + /** + * Takes the contents of a binary file and returns it as an array of bytes. + * + * @param file The file to load binary data from. + * @param bufsize The size of the buffer to allocate for copying. + * @return A new byte array containing the contents of the specified file. + * @exception java.io.IOException If an exception occurred while reading data. + * @see #load(java.io.InputStream,int) + */ + public static byte[] loadBinary(File file, int bufsize) throws IOException + { + FileInputStream stm = new FileInputStream(file); + try + { // now just load from the stream + return load(stm,bufsize); + + } // end try + finally + { // close the file before we leave + shutdown(stm); + + } // end finally + + } // end loadBinary + + /** + * Takes the contents of a binary file and returns it as an array of bytes. Uses a default + * buffer size. + * + * @param file The file to load binary data from. + * @return A new byte array containing the contents of the specified file. + * @exception java.io.IOException If an exception occurred while reading data. + * @see #DEFAULT_BUFSIZE + * @see #loadBinary(java.io.File,int) + */ + public static byte[] loadBinary(File file) throws IOException + { + return loadBinary(file,DEFAULT_BUFSIZE); + + } // end loadBinary + + /** + * Copies the contents of the given input reader to the given output writer. + * + * @param input The reader to copy character data from. + * @param output The writer to copy character data to. + * @param bufsize The size of the buffer to allocate for copying. + * @exception java.io.IOException If an exception occurred while reading or writing data. + */ + public static void copy(Reader input, Writer output, int bufsize) throws IOException + { + char[] buffer = new char[bufsize]; + int rd = input.read(buffer); + while (rd>=0) + { // simple read-write loop to shove data out the door + if (rd>0) + output.write(buffer,0,rd); + rd = input.read(buffer); + + } // end while + + } // end copy + + /** + * Copies the contents of the given input reader to the given output writer. Uses a default + * buffer size. + * + * @param input The reader to copy character data from. + * @param output The writer to copy character data to. + * @exception java.io.IOException If an exception occurred while reading or writing data. + * @see #DEFAULT_BUFSIZE + * @see #copy(java.io.Reader,java.io.Writer,int) + */ + public static void copy(Reader input, Writer output) throws IOException + { + copy(input,output,DEFAULT_BUFSIZE); + + } // end copy + + /** + * Takes the contents of an input reader and returns it as a StringBuffer. + * + * @param input The reader to copy character data from. + * @param bufsize The size of the buffer to allocate for copying. + * @return A new StringBuffer containing the contents of the specified reader. + * @exception java.io.IOException If an exception occurred while reading data. + * @see #copy(java.io.Reader,java.io.Writer,int) + */ + public static StringBuffer load(Reader input, int bufsize) throws IOException + { + StringWriter wr = new StringWriter(); + try + { // copy from reader to StringWriter + copy(input,wr,bufsize); + return wr.getBuffer(); + + } // end try + finally + { // make sure and close the StringWriter before we go + shutdown(wr); + + } // end finally + + } // end load + + /** + * Takes the contents of an input reader and returns it as a StringBuffer. Uses a + * default buffer size. + * + * @param input The reader to copy character data from. + * @return A new StringBuffer containing the contents of the specified reader. + * @exception java.io.IOException If an exception occurred while reading data. + * @see #DEFAULT_BUFSIZE + * @see #load(java.io.Reader,int) + */ + public static StringBuffer load(Reader input) throws IOException + { + return load(input,DEFAULT_BUFSIZE); + + } // end load + + /** + * Takes the contents of a text file and returns it as a StringBuffer. + * + * @param file The file to copy text from. + * @param bufsize The size of the buffer to allocate for copying. + * @return A new StringBuffer containing the contents of the specified text file. + * @exception java.io.IOException If an exception occurred while reading data. + * @see #load(java.io.Reader,int) + */ + public static StringBuffer loadText(File file, int bufsize) throws IOException + { + FileReader rdr = new FileReader(file); + try + { // load from the string reader + return load(rdr,bufsize); + + } // end try + finally + { // make sure and close the reader before we go + shutdown(rdr); + + } // end finally + + } // end load + + /** + * Takes the contents of a text file and returns it as a StringBuffer. + * + * @param file The file to copy text from. + * @return A new StringBuffer containing the contents of the specified text file. + * @exception java.io.IOException If an exception occurred while reading data. + * @see #DEFAULT_BUFSIZE + * @see #loadText(java.io.File,int) + */ + public static StringBuffer loadText(File file) throws IOException + { + return loadText(file,DEFAULT_BUFSIZE); + + } // end load + +} // end class IOUtils diff --git a/src/baseutil/com/silverwrist/util/International.java b/src/baseutil/com/silverwrist/util/International.java new file mode 100644 index 0000000..14f2a81 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/International.java @@ -0,0 +1,267 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +import java.io.*; +import java.util.*; + +/** + * A class which centralizes a number of "international" resources, such as locales, + * country lists, and language lists. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class International +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static International self = new International(); // me + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private List country_list = null; // list of Country objects + private Map country_map = null; // mapping from codes to Country objects + private List language_list = null; // list of Language objects + private Map language_map = null; // mapping from codes to Language objects + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Constructs a new instance of the International object. Only one instance + * of this object is ever created. + */ + private International() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + /** + * Loads the internal list of countries from a resource file. + * + * @exception RuntimeException If an I/O error occurred while loading the country list. + */ + private synchronized void loadCountryList() + { + if ((country_list!=null) || (country_map!=null)) + return; // already loaded + + // Create temporary list and map to hold read data. + ArrayList tmp_list = new ArrayList(); + HashMap tmp_map = new HashMap(); + + try + { // Load the country properties file. + BufferedReader data = + new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("countries.properties"))); + String l; // temporary line + while ((l = data.readLine())!=null) + { // read lines from the properties file + l = l.trim(); + if ((l.length()==0) || (l.startsWith("#"))) + continue; // blank line or comment line + int pos = l.indexOf('='); + if (pos<0) + continue; // no properties - just forget this line + Country c = new Country(l.substring(0,pos),l.substring(pos+1)); + tmp_list.add(c); + tmp_map.put(c.getCode(),c); + + } // end while + + } // end try + catch (IOException e) + { // IO error loading country properties... + throw new RuntimeException("Error loading country.properties: " + e.getMessage()); + + } // end catch + + // Set up the lists, which are considered "unmodifiable." + tmp_list.trimToSize(); + country_list = Collections.unmodifiableList(tmp_list); + country_map = Collections.unmodifiableMap(tmp_map); + + } // end loadCountryList + + /** + * Loads the internal list of languages from a resource file. + * + * @exception RuntimeException If an I/O error occurred while loading the language list. + */ + private synchronized void loadLanguageList() + { + if ((language_list!=null) || (language_map!=null)) + return; // already loaded + + // Create temporary list and map to hold read data. + ArrayList tmp_list = new ArrayList(); + HashMap tmp_map = new HashMap(); + + try + { // Load the language properties file. + BufferedReader data = + new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("languages.properties"))); + String l; // temporary line + while ((l = data.readLine())!=null) + { // read lines from the properties file + l = l.trim(); + if ((l.length()==0) || (l.startsWith("#"))) + continue; // blank line or comment line + int pos = l.indexOf('='); + if (pos<0) + continue; // no properties - just forget this line + Language lng = new Language(l.substring(0,pos),l.substring(pos+1)); + tmp_list.add(lng); + tmp_map.put(lng.getCode(),lng); + + } // end while + + } // end try + catch (IOException e) + { // IO error loading language properties... + throw new RuntimeException("Error loading language.properties: " + e.getMessage()); + + } // end catch + + // Set up the lists, which are considered "unmodifiable." + tmp_list.trimToSize(); + language_list = Collections.unmodifiableList(tmp_list); + language_map = Collections.unmodifiableMap(tmp_map); + + } // end loadLanguageList + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * Returns the list of defined countries. + * + * @return The list of Country objects that are currently defined. + */ + public List getCountryList() + { + loadCountryList(); + return country_list; + + } // end getCountryList + + /** + * Returns the Country object with the specified code. + * + * @param code The country code to match. + * @return The matching Country object, or null if no country matched. + */ + public Country getCountryForCode(String code) + { + if (code==null) + return null; + loadCountryList(); + return (Country)(country_map.get(code.trim().toUpperCase())); + + } // end getCountryForCode + + /** + * Returns the list of defined languages. + * + * @return The list of Language objects that are currently defined. + */ + public List getLanguageList() + { + loadLanguageList(); + return language_list; + + } // end getLanguageList + + /** + * Returns the Language object with the specified code. + * + * @param code The language code to match. + * @return The matching Language object, or null if no language matched. + */ + public Language getLanguageForCode(String code) + { + if (code==null) + return null; + loadLanguageList(); + return (Language)(language_map.get(code.trim())); + + } // end getLanguageForCode + + /** + * Creates a Locale from a standard descriptor string. + * + * @param streq The string equivalent of the Locale to be created. + * @return The corresponding Locale, or the default Locale if the parameter is + * null or the empty string. + */ + public Locale createLocale(String streq) + { + if ((streq==null) || (streq.length()==0)) + return Locale.getDefault(); // no locale + int p1 = streq.indexOf('_'); + if (p1<0) + return new Locale(streq,""); // language but no country specified + String x_lang = streq.substring(0,p1); + int p2 = streq.indexOf('_',p1+1); + if (p2<0) + { // there's only one underscore - figure out what part the last part is + String lastpart = streq.substring(p1+1); + if (lastpart.length()==2) + return new Locale(x_lang,lastpart); // language + country + else + return new Locale(x_lang,"",lastpart); // language + country(null) + variant + + } // end if + + // do all three variants + return new Locale(x_lang,streq.substring(p1+1,p2),streq.substring(p2+1)); + + } // end createLocale + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + /** + * Returns the singleton instance of the International object. + * + * @return The singleton instance of the International object. + */ + public static International get() + { + return self; + + } // end get() + +} // end class International diff --git a/src/baseutil/com/silverwrist/util/Language.java b/src/baseutil/com/silverwrist/util/Language.java new file mode 100644 index 0000000..fa9fb53 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/Language.java @@ -0,0 +1,159 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +/** + * A utility class used by International that stores a language code and name pair. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + * @see International + */ +public final class Language implements Comparable +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String m_code; // the language code + private String m_name; // the language name + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Constructs a new Language object. + * + * @param code The language code. + * @param name The language name. + */ + Language(String code, String name) + { + m_code = code.trim(); + m_name = name.trim(); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class Object + *-------------------------------------------------------------------------------- + */ + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param o The reference object with which to compare. + * @return true if this object is the same as the o argument; false otherwise. + */ + public boolean equals(Object o) + { + if ((o==null) || !(o instanceof Language)) + return false; + if (this==(Language)o) + return true; + Language other = (Language)o; + return m_code.equals(other.m_code); + + } // end equals + + /** + * Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those + * provided by java.util.Hashtable. + * + * @return A hash code value for this object. + */ + public int hashCode() + { + return m_code.hashCode(); + + } // end hashCode + + /** + * Returns a string representation of the object. In general, the toString method returns a string + * that "textually represents" this object. + * + * @return A string representation of the object. + */ + public String toString() + { + return m_name + " [" + m_code + "]"; + + } // end toString + + /*-------------------------------------------------------------------------------- + * Implementations from interface Comparable + *-------------------------------------------------------------------------------- + */ + + /** + * Compares this object with the specified object for order. Returns a negative integer, zero, or a positive + * integer as this object is less than, equal to, or greater than the specified object. Language + * objects are compared on their language name. + * + * @param o The Object to be compared. + * @return A negative integer, zero, or a positive integer as this object is less than, equal to, or greater than + * the specified object. + * @exception java.lang.ClassCastException If the specified object's type prevents it from being compared to + * this Object. + */ + public int compareTo(Object o) + { + if (o==null) + return 1; + if (o instanceof Language) + { // compare country names + Language c = (Language)o; + return m_name.compareTo(c.m_name); + + } // end if + + return m_name.compareTo(o.toString()); + + } // end compareTo + + /*-------------------------------------------------------------------------------- + * External getters + *-------------------------------------------------------------------------------- + */ + + /** + * Returns the RFC 1766 language code for this language. + * + * @return The RFC 1766 language code for this language. + */ + public final String getCode() + { + return m_code; + + } // end code + + /** + * Returns the name of this language. + * + * @return The name of this language. + */ + public final String getName() + { + return m_name; + + } // end name + +} // end class Language diff --git a/src/baseutil/com/silverwrist/util/MySQLUtils.java b/src/baseutil/com/silverwrist/util/MySQLUtils.java new file mode 100644 index 0000000..3838530 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/MySQLUtils.java @@ -0,0 +1,120 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +import java.sql.*; +import org.apache.log4j.Logger; + +/** + * A class containing miscellaneous public methods useful when working with MySQL databases. All + * public methods of {@link com.silverwrist.util.SQLUtils SQLUtils} are also accessible through this class. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class MySQLUtils extends SQLUtils +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(MySQLUtils.class); + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * MySQLUtils instances should NOT be constructed in standard programming. + * Instead, the class should be used as MySQLUtils.shutdown(statement);. + * This constructor is public to permit tools that require a JavaBean instance + * to operate. + */ + public MySQLUtils() + { + super(); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * Unlocks all database tables that were previously locked. Executes the MySQL statement "UNLOCK TABLES;". + * + * @param conn The connection on which one or more tables were previously locked. + */ + public static final void unlockTables(Connection conn) + { + Statement stmt = null; + try + { // do the update + stmt = conn.createStatement(); + stmt.executeUpdate("UNLOCK TABLES;"); + + } // end try + catch (SQLException e) + { // warn if there was an error here + logger.warn("DB error in unlockTables()",e); + + } // end catch + finally + { // shutdown the statement before we go + shutdown(stmt); + + } // end finally + + } // end unlockTables + + /** + * Gets the ID of the most recent insert made to a table with an AUTO_INCREMENT column. This assumes that the + * column is of integer type. Executes the MySQL statement "SELECT LAST_INSERT_ID();" and returns the value + * that that statement returns. + * + * @param conn Database connection on which to perform the operation. + * @return The value of the last inserted ID on this connection. + * @exception java.sql.SQLException If an error occurred in the execution, or if the SELECT statement returned + * no rows (which it should not do). + */ + public static final int getLastInsertInt(Connection conn) throws SQLException + { + Statement stmt = null; + ResultSet rs = null; + try + { // perform the operation + stmt = conn.createStatement(); + rs = stmt.executeQuery("SELECT LAST_INSERT_ID();"); + if (!(rs.next())) + throw new SQLException("internal error - getLastInsertInt SELECT should have returned OK"); + return rs.getInt(1); + + } // end try + finally + { // shut down the objects before we go + shutdown(rs); + shutdown(stmt); + + } // end finally + + } // end getLastInsertInt + +} // end class MySQLUtils diff --git a/src/baseutil/com/silverwrist/util/OptionSet.java b/src/baseutil/com/silverwrist/util/OptionSet.java new file mode 100644 index 0000000..2ff9564 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/OptionSet.java @@ -0,0 +1,424 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +import java.util.BitSet; + +/** + * A variant of the BitSet that can express itself as a character string. Each + * character in the resulting string represents a flag that is "set." Up to 91 flags can be + * specified per OptionSet. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + * @see java.util.BitSet + */ +public class OptionSet extends BitSet +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + // The alphabet to use to store individual flags. + private static final String ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + + "!#$%&()*+,-./:;<=>?@[]^_`{|}~"; + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + /** + * Creates a new OptionSet. All bits are initially false. + */ + public OptionSet() + { + super(); + + } // end constructor + + /** + * Creates an OptionSet whose initial size is large enough to explicitly represent bits with + * indices in the range 0 through nbits-1. All bits are initially false. The maximum + * size of the OptionSet is 91. + * + * @param nbits The initial size of the bit set. + * @exception java.lang.NegativeArraySizeException If the specified initial size is negative. + */ + public OptionSet(int nbits) + { + super(Math.min(nbits,ALPHA.length())); + + } // end constructor + + /** + * Creates an OptionSet from an array of characters representing "set" options. + * + * @param options The options to be set in the new OptionSet. + */ + public OptionSet(char[] options) + { + super(); // initialize all bits to 0 + for (int i=0; i=0) + super.set(ndx); + + } // end for + + } // end constructor + + /** + * Creates an OptionSet from a string of characters representing "set" options. + * + * @param options The options to be set in the new OptionSet. + */ + public OptionSet(String options) + { + this(options.toCharArray()); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal functions + *-------------------------------------------------------------------------------- + */ + + /** + * Returns a StringBuffer representing the current state of this OptionSet, + * with one character in it for each bit that is set. + * + * @return A StringBuffer containing the current state of the OptionSet. + */ + private StringBuffer asStringBuffer() + { + StringBuffer b = new StringBuffer(); + for (int i=0; ifalse. + * + * @param bitIndex The index of the bit to be cleared. + * @exception java.lang.IndexOutOfBoundsException If the specified index is negative or greater than the + * maximum option for an OptionSet. + */ + public void clear(int bitIndex) + { + if (bitIndex>=ALPHA.length()) + throw new IndexOutOfBoundsException(); + super.clear(bitIndex); + + } // end clear + + /** + * Sets the bits from the specified fromIndex (inclusive) to the specified toIndex + * (exclusive) to false. + * + * @param fromIndex Index of the first bit to be cleared. + * @param toIndex Index after the last bit to be cleared. + * @exception java.lang.IndexOutOfBoundException If fromIndex is negative, or fromIndex + * is greater than the maximum option for an OptionSet, or toIndex is negative, + * or toIndex is greater than the maximum option for an OptionSet, or + * fromIndex is larger than toIndex. + */ + public void clear(int fromIndex, int toIndex) + { + if ((fromIndex>=ALPHA.length()) || (toIndex>ALPHA.length())) + throw new IndexOutOfBoundsException(); + super.clear(fromIndex,toIndex); + + } // end clear + + /** + * Cloning this OptionSet produces a new OptionSet that is equal to it. The clone of the + * option set is another option set that has exactly the same bits set to true as this option set and the same + * current size. + * + * @return A clone of this option set. + */ + public Object clone() + { + OptionSet rc = new OptionSet(this.size()); + for (int i=this.nextSetBit(0); i>=0; i=this.nextSetBit(i+1)) + rc.set(i); + return rc; + + } // end clone + + /** + * Sets the bit at the specified index to to the complement of its current value. + * + * @param bitIndex The index of the bit to flip. + * @exception java.lang.IndexOutOfBoundsException If the specified index is negative or greater than the + * maximum option for an OptionSet. + */ + public void flip(int bitIndex) + { + if (bitIndex>=ALPHA.length()) + throw new IndexOutOfBoundsException(); + super.flip(bitIndex); + + } // end flip + + /** + * Sets the bits from the specified fromIndex (inclusive) to the specified toIndex + * (exclusive) to the complement of their current values. + * + * @param fromIndex Index of the first bit to be flipped. + * @param toIndex Index after the last bit to be flipped. + * @exception java.lang.IndexOutOfBoundException If fromIndex is negative, or fromIndex + * is greater than the maximum option for an OptionSet, or toIndex is negative, + * or toIndex is greater than the maximum option for an OptionSet, or + * fromIndex is larger than toIndex. + */ + public void flip(int fromIndex, int toIndex) + { + if ((fromIndex>=ALPHA.length()) || (toIndex>ALPHA.length())) + throw new IndexOutOfBoundsException(); + super.flip(fromIndex,toIndex); + + } // end flip + + /** + * Returns the value of the bit with the specified index. The value is true if the bit with + * the index bitIndex is currently set in this OptionSet; otherwise, the result + * is false. + * + * @param bitIndex The bit index. + * @return The value of the bit with the specified index. + * @exception java.lang.IndexOutOfBoundsException If the specified index is negative or greater than the + * maximum option for an OptionSet. + */ + public boolean get(int bitIndex) + { + if (bitIndex>=ALPHA.length()) + throw new IndexOutOfBoundsException(); + return super.get(bitIndex); + + } // end get + + /** + * Returns a new OptionSet composed of bits from this OptionSet from + * fromIndex (inclusive) to toIndex (exclusive). + * + * @param fromIndex Index of the first bit to be included. + * @param toIndex Index after the last bit to be included. + * @return A new OptionSet from a range of this OptionSet. + * @exception java.lang.IndexOutOfBoundException If fromIndex is negative, or fromIndex + * is greater than the maximum option for an OptionSet, or toIndex is negative, + * or toIndex is greater than the maximum option for an OptionSet, or + * fromIndex is larger than toIndex. + */ + public BitSet get(int fromIndex, int toIndex) + { + if ((fromIndex>=ALPHA.length()) || (toIndex>ALPHA.length())) + throw new IndexOutOfBoundsException(); + BitSet tmp = super.get(fromIndex,toIndex); + OptionSet rc = new OptionSet(tmp.size()); + for (int i=tmp.nextSetBit(0); i>=0; i=tmp.nextSetBit(i+1)) + rc.set(i); + return rc; + + } // end get + + /** + * Sets the bit specified by the index to true. + * + * @param bitIndex The index of the bit to be set. + * @exception java.lang.IndexOutOfBoundsException If the specified index is negative or greater than the + * maximum option for an OptionSet. + */ + public void set(int bitIndex) + { + if (bitIndex>=ALPHA.length()) + throw new IndexOutOfBoundsException(); + super.set(bitIndex); + + } // end set + + /** + * Sets the bit specified by the index to the specified value. + * + * @param bitIndex The index of the bit to be set. + * @param value A boolean value to set. + * @exception java.lang.IndexOutOfBoundsException If the specified index is negative or greater than the + * maximum option for an OptionSet. + */ + public void set(int bitIndex, boolean value) + { + if (bitIndex>=ALPHA.length()) + throw new IndexOutOfBoundsException(); + super.set(bitIndex,value); + + } // end set + + /** + * Sets the bits from the specified fromIndex (inclusive) to the specified toIndex + * (exclusive) to true. + * + * @param fromIndex Index of the first bit to be set. + * @param toIndex Index after the last bit to be set. + * @exception java.lang.IndexOutOfBoundException If fromIndex is negative, or fromIndex + * is greater than the maximum option for an OptionSet, or toIndex is negative, + * or toIndex is greater than the maximum option for an OptionSet, or + * fromIndex is larger than toIndex. + */ + public void set(int fromIndex, int toIndex) + { + if ((fromIndex>=ALPHA.length()) || (toIndex>ALPHA.length())) + throw new IndexOutOfBoundsException(); + super.set(fromIndex,toIndex); + + } // end set + + /** + * Sets the bits from the specified fromIndex (inclusive) to the specified toIndex + * (exclusive) to the specified value. + * + * @param fromIndex Index of the first bit to be set. + * @param toIndex Index after the last bit to be set. + * @param value A boolean value to set. + * @exception java.lang.IndexOutOfBoundException If fromIndex is negative, or fromIndex + * is greater than the maximum option for an OptionSet, or toIndex is negative, + * or toIndex is greater than the maximum option for an OptionSet, or + * fromIndex is larger than toIndex. + */ + public void set(int fromIndex, int toIndex, boolean value) + { + if ((fromIndex>=ALPHA.length()) || (toIndex>ALPHA.length())) + throw new IndexOutOfBoundsException(); + super.set(fromIndex,toIndex,value); + + } // end set + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * Sets the value of the specified bit in the OptionSet to a specified Boolean + * value, and returns an indication of whether that value was changed. + * + * @param ndx The index of the bit to be assigned. + * @param val true to set the corresponding bit, false to clear it. + * @return true if the value of the bit in the OptionSet was changed by this + * operation, false if not. + * @exception java.lang.IndexOutOfBoundsException If the specified index is negative or greater than the + * maximum option for an OptionSet. + */ + public boolean assign(int ndx, boolean val) + { + if (ndx>=ALPHA.length()) + throw new IndexOutOfBoundsException(); + boolean old = super.get(ndx); + super.set(ndx,val); + return (old!=val); + + } // end assign + + /** + * Resets the state of this OptionSet from an array of characters representing "set" options. + * + * @param options The options to be set in the new OptionSet. All options not specified will + * be cleared. + */ + public void assign(char[] options) + { + super.clear(); + + for (int i=0; i=0) + super.set(ndx); + + } // end for + + } // end assign + + /** + * Resets the state of this OptionSet from a string of characters representing "set" options. + * + * @param options The options to be set in the new OptionSet. All options not specified will + * be cleared. + */ + public void assign(String options) + { + if (options!=null) + assign(options.toCharArray()); + + } // end assign + + /** + * Returns a character array representing the current state of this OptionSet, + * with one character in it for each bit that is set. + * + * @return A character array containing the current state of the OptionSet. + */ + public char[] asCharArray() + { + return asStringBuffer().toString().toCharArray(); + + } // end asCharArray + + /** + * Returns a string representing the current state of this OptionSet, + * with one character in it for each bit that is set. + * + * @return A string containing the current state of the OptionSet. + */ + public String asString() + { + return asStringBuffer().toString(); + + } // end asString + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + /** + * Returns the character associated with a specific "option index" by all OptionSet instances. + * + * @param index The index of the character to retrieve. + * @return The character associated with that index. + * @exception java.lang.IndexOutOfBoundsException If the specified index is out of range. + */ + public static final char getOptionChar(int index) + { + if ((index<0) || (index>=ALPHA.length())) + throw new IndexOutOfBoundsException(); + return ALPHA.charAt(index); + + } // end getOptionChar + +} // end class OptionSet diff --git a/src/baseutil/com/silverwrist/util/SQLUtils.java b/src/baseutil/com/silverwrist/util/SQLUtils.java new file mode 100644 index 0000000..95f949f --- /dev/null +++ b/src/baseutil/com/silverwrist/util/SQLUtils.java @@ -0,0 +1,127 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +import java.sql.*; + +/** + * A class containing miscellaneous public methods useful when working with SQL databases. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class SQLUtils +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * SQLUtils instances should NOT be constructed in standard programming. + * Instead, the class should be used as SQLUtils.shutdown(statement);. + * This constructor is public to permit tools that require a JavaBean instance + * to operate. + */ + public SQLUtils() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * Closes a ResultSet cleanly, without throwing an exception. + * + * @param rs The ResultSet to be closed. + * @see java.sql.ResultSet#close() + */ + public static final void shutdown(ResultSet rs) + { + try + { // close the ResultSet + if (rs!=null) + rs.close(); + + } // end try + catch (SQLException e) + { // ignore any SQL errors + } // end catch + + } // end shutdown + + /** + * Closes a Statement cleanly, without throwing an exception. + * + * @param rs The Statement to be closed. + * @see java.sql.Statement#close() + */ + public static final void shutdown(Statement stmt) + { + try + { // close the Statement + if (stmt!=null) + stmt.close(); + + } // end try + catch (SQLException e) + { // ignore any SQL errors + } // end catch + + } // end shutdown + + /** + * Closes a Connection cleanly, without throwing an exception. + * + * @param rs The Connection to be closed. + * @see java.sql.Connection#close() + */ + public static final void shutdown(Connection conn) + { + try + { // close the Connection + if (conn!=null) + conn.close(); + + } // end try + catch (SQLException e) + { // ignore any SQL errors + } // end catch + + } // end shutdown + + /** + * Fetches the return count from a query such as "SELECT COUNT(*) FROM ...". All such queries will always + * return at least one row, with the count. + * + * @param rs The ResultSet returned from the query execution. + * @param column The column index in which the return value may be found. + * @return The value of that column (usually, the count you were querying for). + * @exception java.sql.SQLException If there was no returned row, or there was a data type mismatch on the column. + */ + public static final int getReturnCountInt(ResultSet rs, int column) throws SQLException + { + if (!(rs.next())) + throw new SQLException("expected return count row, not present"); + return rs.getInt(column); + + } // end getReturnCountInt + +} // end class SQLUtils diff --git a/src/baseutil/com/silverwrist/util/StringUtils.java b/src/baseutil/com/silverwrist/util/StringUtils.java new file mode 100644 index 0000000..a5da575 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/StringUtils.java @@ -0,0 +1,349 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.*; +import org.apache.log4j.Logger; + +/** + * Common string utilities. Inherits from the org.apache.commons.lang.StringUtils + * class, so it contains everything that contains. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class StringUtils extends org.apache.commons.lang.StringUtils +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(StringUtils.class); + + private static final char[] HTML_ENCODE_CHARS = { '"', '&', '<', '>' }; + + private static final String VAR_START = "${"; + private static final String VAR_END = "}"; + + private static final Set TRUE_STRINGS; + private static final Set FALSE_STRINGS; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * StringUtils instances should NOT be constructed in standard programming. + * Instead, the class should be used as StringUtils.trim(" foo ");. + * This constructor is public to permit tools that require a JavaBean instance + * to operate. + */ + public StringUtils() + { + super(); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * Performs HTML encoding of an arbitrary string. When a string is HTML encoded, the double-quote ("), + * ampersand (&), less-than (<), and greater-than (>) characters are transformed to their HTML + * entity equivalents; all other characters are left untouched. + * + * @param str The string to be HTML-encoded. May be null. + * @return The HTML-encoded equivalent of str. If str is + * null, returns null. + */ + public static final String encodeHTML(String str) + { + if (str==null) + return null; // safety feature + AnyCharMatcher nhc = new AnyCharMatcher(HTML_ENCODE_CHARS); + int ndx = nhc.get(str); + if (ndx<0) + return str; // trivial short-circuit case + StringBuffer buf = new StringBuffer(); + while (ndx>=0) + { // append the matched "head" and then the encoded character + if (ndx>0) + buf.append(str.substring(0,ndx)); + switch (str.charAt(ndx++)) + { + case '"': + buf.append("""); + break; + + case '&': + buf.append("&"); + break; + + case '<': + buf.append("<"); + break; + + case '>': + buf.append(">"); + break; + + } // end switch + + if (ndx==str.length()) + return buf.toString(); // munched the entire string - all done! + str = str.substring(ndx); + ndx = nhc.get(str); + + } // end while + + buf.append(str); // append the unmatched tail + return buf.toString(); + + } // end encodeHTML + + /** + * Translates a string into application/x-www-form-urlencoded format, using a UTF-8 encoding. + * + * @param s The string to be encoded. May be null. + * @return The translated string value, or null if null was passed in. + */ + public static final String encodeURL(String s) + { + try + { // the old URLEncoder.encode(str) method is deprecated as of JDK1.4, use the new one + return ((s==null) ? null : URLEncoder.encode(s,"UTF-8")); + + } // end try + catch (UnsupportedEncodingException e) + { // this should never happen, but we gotta catch it anyway + logger.fatal("WTF? encodeURL doesn't support UTF-8? You're crazy!"); + return null; + + } // end catch + + } // end encodeURL + + /** + * Returns true if the given string is a representation of a Boolean true value. + * Values that represent a valid Boolean true value include "true", "yes", "on", and "1". + * + * @param test The string to be tested. + * @return true if the string represents a Boolean true value, false if not. + */ + public static final boolean isBooleanTrue(String test) + { + if (test==null) + return false; + return TRUE_STRINGS.contains(test.trim().toLowerCase()); + + } // end isBooleanTrue + + /** + * Returns true if the given string is a representation of a Boolean false value. + * Values that represent a valid Boolean false value include "false", "no", "off", and "0". + * + * @param test The string to be tested. + * @return true if the string represents a Boolean false value, false if not. + */ + public static final boolean isBooleanFalse(String test) + { + if (test==null) + return false; + return FALSE_STRINGS.contains(test.trim().toLowerCase()); + + } // end isBooleanTrue + + /** + * Replaces variable substitutions in a string. Variable substitutions are strings of the form + * ${varname}. The varname names are looked up in the supplied + * Map, and the values of variables in that map are substituted.

+ * Only variable names that exist in the Map are replaced; other variable strings + * in the supplied string are left untouched. Variable substitution values may themselves contain + * variables; those variables are recursively replaced. (Caution: The code cannot + * detect variable substitutions that contain themselves, or two variables that contain each other. + * Avoid these situations.) + * + * @param base The string to be operated on. If this parameter is null, the + * method will return null. + * @param vars The mapping of variable name to value substitutions. If this parameter is + * null or an empty map, no substitutions will be performed on + * base. + * @return The base string with all variable substitutions made as detailed above. + */ + public static final String replaceAllVariables(String base, Map vars) + { + if ((base==null) || (vars==null) || vars.isEmpty()) + return base; // safety feature + + String work = base; + boolean did_replace = false; + boolean retest = true; + do + { // main loop for replacing all variables + did_replace = false; + Iterator it = vars.keySet().iterator(); + while (it.hasNext()) + { // variable start is there... + if (retest) + { // only perform this test on the first iteration and after we know we've replaced a variable + if (work.indexOf(VAR_START)<0) + return work; // no more variables in text - all done! + retest = false; + + } // end if + + // get variable name and see if it's present + String vname = it.next().toString(); + String var_full = VAR_START + vname + VAR_END; + if (work.indexOf(var_full)>=0) + { // OK, this variable is in place + work = replace(work,var_full,vars.get(vname).toString()); + did_replace = true; + retest = true; + + } // end if + + } // end while + + } while (did_replace); // end do + + return work; // all done! + + } // end replaceAllVariables + + /** + * Splits the provided text into a list, based on a given separator. The separator is not included in the + * returned String list. The maximum number of splits to perfom can be controlled. + * + * @param text The string to parse. + * @param separator Character used as the delimiter. + * @param limit The maximum number of elements to include in the list. A zero or negative value implies no limit. + * @return A list of parsed Strings. + */ + public static final List split1List(String text, char separator, int limit) + { + if (text==null) + return Collections.EMPTY_LIST; + if (limit<=0) + limit = Integer.MAX_VALUE; + ArrayList rc = new ArrayList(); + String work = text; + int p = work.indexOf(separator); + while ((work.length()>0) && (p>=0) && (--limit>0)) + { // add elements to the ArrayList + if (p==0) + rc.add(""); + else + rc.add(work.substring(0,p)); + work = work.substring(p+1); + p = work.indexOf(separator); + + } // end while + + rc.add(work); + rc.trimToSize(); + return rc; + + } // end split1list + + /** + * Splits the provided text into a list, based on a given separator. The separator is not included in the + * returned String list. + * + * @param text The string to parse. + * @param separator Character used as the delimiter. + * @return A list of parsed Strings. + */ + public static final List split1List(String text, char separator) + { + return split1List(text,separator,0); + + } // end split1list + + /** + * Splits the provided text into a list, based on a given separator. The separator is not included in the + * returned String array. The maximum number of splits to perfom can be controlled. + * + * @param text The string to parse. + * @param separator Character used as the delimiter. + * @param limit The maximum number of elements to include in the list. A zero or negative value implies no limit. + * @return An array of parsed Strings. + */ + public static final String[] split1(String text, char separator, int limit) + { + List tmp = split1List(text,separator,limit); + String[] rc = new String[tmp.size()]; + tmp.toArray(rc); + return rc; + + } // end split1 + + /** + * Splits the provided text into a list, based on a given separator. The separator is not included in the + * returned String array. + * + * @param text The string to parse. + * @param separator Character used as the delimiter. + * @return An array of parsed Strings. + */ + public static final String[] split1(String text, char separator) + { + return split1(text,separator,0); + + } // end split1 + + /*-------------------------------------------------------------------------------- + * Static initializer + *-------------------------------------------------------------------------------- + */ + + static + { // get the boolean values resource + ResourceBundle bv = ResourceBundle.getBundle("com.silverwrist.util.BooleanValues"); + + // Load the Boolean "true" values. + String[] values = split(bv.getString("values.true"),"|"); + HashSet tmp = new HashSet(); + for (int i=0; i. +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +# ------------------------------------------------------------------------------------- +# This list of countries is taken from the ISO 3166 standard list of country names and +# 2-letter codes . When adding new +# entries to this file, make sure and add it in sorted order by country NAME! You can +# re-sort the country entries with "sort -t = -k 2 input > output", but then make sure +# the "XX=(unknown)" entry appears first! +XX=(unknown) +AF=Afghanistan +AL=Albania +DZ=Algeria +AS=American Samoa +AD=Andorra +AO=Angola +AI=Anguilla +AQ=Antarctica +AG=Antigua and Barbuda +AR=Argentina +AM=Armenia +AW=Aruba +AU=Australia +AT=Austria +AZ=Azerbaijan +BS=Bahamas +BH=Bahrain +BD=Bangladesh +BB=Barbados +BY=Belarus +BE=Belgium +BZ=Belize +BJ=Benin +BM=Bermuda +BT=Bhutan +BO=Bolivia +BA=Bosnia and Herzegovina +BW=Botswana +BV=Bouvet Island +BR=Brazil +IO=British Indian Ocean Territory +BN=Brunei Darussalam +BG=Bulgaria +BF=Burkina Faso +BI=Burundi +KH=Cambodia +CM=Cameroon +CA=Canada +CV=Cape Verde +KY=Cayman Islands +CF=Central African Republic +TD=Chad +CL=Chile +CN=China +CX=Chrismas Island +CC=Cocos (Keeling) Islands +CO=Colombia +KM=Comoros +CG=Congo +CD=Congo (Democratic Republic of) +CK=Cook Islands +CR=Costa Rica +CI=Cote D''Ivoire +HR=Croatia +CU=Cuba +CY=Cyprus +CZ=Czech Republic +DK=Denmark +DJ=Djibouti +DM=Dominica +DO=Dominican Republic +TP=East Timor +EC=Ecuador +EG=Egypt +SV=El Salvador +GQ=Equatorial Guinea +ER=Eritrea +EE=Estonia +ET=Ethiopia +FK=Falkland Islands (Malvinas) +FO=Faroe Islands +FJ=Fiji +FI=Finland +FR=France +GF=French Guiana +PF=French Polynesia +TF=French Southern Territories +GA=Gabon +GM=Gambia +GE=Georgia +DE=Germany +GH=Ghana +GI=Gibraltar +GR=Greece +GL=Greenland +GD=Grenada +GP=Guadeloupe +GU=Guam +GT=Guatemala +GN=Guinea +GW=Guinea-Bissau +GY=Guyana +HT=Haiti +HM=Heard Island and McDonald Islands +VA=Holy See (Vatican City State) +HN=Honduras +HK=Hong Kong +HU=Hungary +IS=Iceland +IN=India +ID=Indonesia +IR=Iran (Islamic Republic of) +IQ=Iraq +IE=Ireland +IL=Israel +IT=Italy +JM=Jamaica +JP=Japan +JO=Jordan +KZ=Kazakhstan +KE=Kenya +KI=Kiribati +KP=Korea (Democratic People's Republic of) +KR=Korea (Republic of) +KW=Kuwait +KG=Kyrgyzstan +LA=Lao People's Democratic Republic +LV=Latvia +LB=Lebanon +LS=Lesotho +LR=Liberia +LY=Libyan Arab Jamahirya +LI=Liechtenstein +LT=Lithuania +LU=Luxembourg +MO=Macau +MK=Macedonia (Former Yugoslav Republic of) +MG=Madagascar +MW=Malawi +MY=Malaysia +MV=Maldives +ML=Mali +MT=Malta +MH=Marshall Islands +MQ=Martinique +MR=Mauritania +MU=Mauritius +YT=Mayotte +MX=Mexico +FM=Micronesia (Federated States of) +MD=Moldova, Republic of +MC=Monaco +MN=Mongolia +MS=Montserrat +MA=Morocco +MZ=Mozambique +MM=Myanmar +NA=Namibia +NR=Nauru +NP=Nepal +NL=Netherlands +AN=Netherlands Antillies +NC=New Caledonia +NZ=New Zealand +NI=Nicaragua +NE=Niger +NG=Nigeria +NU=Niue +NF=Norfolk Island +MP=Northern Mariana Islands'), +NO=Norway +OM=Oman +PK=Pakistan +PW=Palau +PS=Palestinian Territory, Occupied +PA=Panama +PG=Papua New Guinea +PY=Paraguay +PE=Peru +PH=Phillipines +PN=Pitcairn +PL=Poland +PT=Portugal +PR=Puerto Rico +QA=Qatar +RE=Reunion +RO=Romania +RU=Russian Federation +RW=Rwanda +SH=Saint Helena +KN=Saint Kitts and Nevis +LC=Saint Lucia +PM=Saint Pierre and Miquelon +VC=Saint Vincent and The Grenadines +WS=Samoa +SM=San Marino +ST=Sao Tome and Principe +SA=Saudi Arabia +SN=Senegal +SC=Seychelles +SL=Sierra Leone +SG=Singapore +SK=Slovakia +SI=Slovenia +SB=Solomon Islands +SO=Somalia +ZA=South Africa +GS=South Georgia and the South Sandwich Islands +ES=Spain +LK=Sri Lanka +SD=Sudan +SR=Suriname +SJ=Svalbard and Jan Mayen +SZ=Swaziland +SE=Sweden +CH=Switzerland +SY=Syrian Arab Republic +TW=Taiwan (Province of China) +TJ=Tajikistan +TZ=Tanzania, United Republic of +TH=Thailand +TG=Togo +TK=Tokelau +TO=Tonga +TT=Trinidad and Tobago +TN=Tunisia +TR=Turkey +TM=Turkmenistan +TC=Turks and Caicos Islands +TV=Tuvalu +UG=Uganda +UA=Ukraine +AE=United Arab Emirates +GB=United Kingdom +US=United States +UM=United States Minor Outlying Islands +UY=Uruguay +UZ=Uzbekistan +VU=Vanatu +VE=Venezuela +VN=Viet Nam +VG=Virgin Islands (British) +VI=Virgin Islands (U.S.) +WF=Wallis and Futuna +EH=Western Sahara +YE=Yemen +YU=Yugoslavia +ZM=Zambia +ZW=Zimbabwe diff --git a/src/baseutil/com/silverwrist/util/image/ImageNormalizer.java b/src/baseutil/com/silverwrist/util/image/ImageNormalizer.java new file mode 100644 index 0000000..bc72afd --- /dev/null +++ b/src/baseutil/com/silverwrist/util/image/ImageNormalizer.java @@ -0,0 +1,272 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util.image; + +import java.awt.RenderingHints; +import java.awt.image.*; +import java.awt.image.renderable.ParameterBlock; +import java.io.*; +import java.util.*; +import javax.imageio.*; +import javax.imageio.stream.*; +import javax.media.jai.*; + +/** + * A class that performs "normalization" on an image to fit within a bounding box of a specified pixel + * size. "Normalized" images are scaled down proportionally to fit the bounding box, then centered over + * a black backdrop (so the image will be "letterboxed" if it has a larger H:V aspect ratio than the bounding + * box, or "pillarboxed" if it has a smaller H:V aspect ratio than the bounding box). + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class ImageNormalizer +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * ImageNormalizer instances should NOT be constructed in standard programming. + * Instead, the class should be used as ImageNormalizer.normalizeImage(...);. + * This constructor is public to permit tools that require a JavaBean instance + * to operate. + */ + public ImageNormalizer() + { + super(); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * "Normalizes" an image to fit within a bounding box of a specified pixel size. "Normalized" images are + * scaled down proportionally to fit the bounding box, then centered over a black backdrop (so the image + * will be "letterboxed" if it has a larger H:V aspect ratio than the bounding box, or "pillarboxed" if it + * has a smaller H:V aspect ratio than the bounding box). + * + * @param image_data Raw image data from the input, in any ImageIO-recognized format. + * @param width The width of the bounding box to use to normalize the image. + * @param height The height of the bounding box to use to normalize the image. + * @param output_type The desired MIME type for output (such as "image/jpeg"). + * @return The normalized image data as a byte array. + * @exception com.silverwrist.util.image.ImageNormalizerException An error occurred in the image data or + * the image transformation process. + * @see ImageNormalizerException + */ + public static byte[] normalizeImage(InputStream image_data, int width, int height, String output_type) + throws ImageNormalizerException + { + PlanarImage img1; // initial image + try + { // get an image input stream for the image + ImageInputStream iistm = ImageIO.createImageInputStream(image_data); + + // create the "ImageRead" operation to load the image; it will autodetect the + // image format and create an appropriate ImageReader + ParameterBlock pb = new ParameterBlock(); + pb.add(iistm); + pb.add(new Integer(0)); + pb.add(Boolean.FALSE); + pb.add(Boolean.FALSE); + RenderedOp rop = JAI.create("ImageRead",pb); + img1 = rop.getRendering(); + + } // end try + catch (IOException e) + { // try to create the ImageInputStream + throw new ImageNormalizerException("Unable to load image",e); + + } // end catch + catch (RuntimeException re) + { // unable to get the rendering here! + throw new ImageNormalizerException("Image data not a valid image format",re); + + } // end catch + + try + { // Compute the scaling factors required to get the image down to the appropriate size, then choose + // the smaller of the two to use as the final scaling factor. Note that we always scale DOWN, + // not UP. + Float scale_width = null, scale_height = null; + if (img1.getWidth()>width) + scale_width = new Float((float)width / (float)(img1.getWidth())); + if (img1.getHeight()>height) + scale_height = new Float((float)height / (float)(img1.getHeight())); + Float scale = null; + if (scale_width!=null) + { // we can scale by width, how about height? + if (scale_height!=null) + { // yes, height too...pick the smaller of the two + if (scale_width.floatValue()ImageNormalizer, which reads an image from one file, + * normalizes it, and writes it to a second file. + * + * @param args Command-line arguments. The first of these should be the name of the input file, and the + * second should be the name of the output file. + * @return (Exit code) 0 on success, 1 on error. + */ + public static void main(String[] args) + { + if (args.length<2) + { // make sure we have 2 arguments + System.out.println("Usage: ImageNormalizer input-file output-file"); + System.exit(1); + + } // end if + + try + { // very simple, very easy + FileInputStream instm = new FileInputStream(args[0]); + byte[] outdata = normalizeImage(instm,100,100,"image/jpeg"); + instm.close(); + FileOutputStream outstm = new FileOutputStream(args[1]); + outstm.write(outdata); + outstm.close(); + System.out.println(args[0] + " => " + args[1]); + + } // end try + catch (Exception e) + { // dump exception on error + e.printStackTrace(); + System.exit(1); + + } // end catch + + System.exit(0); + + } // end main + +} // end class ImageNormalizer diff --git a/src/baseutil/com/silverwrist/util/image/ImageNormalizerException.java b/src/baseutil/com/silverwrist/util/image/ImageNormalizerException.java new file mode 100644 index 0000000..3737256 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/image/ImageNormalizerException.java @@ -0,0 +1,77 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util.image; + +/** + * Indicates an error in the image normalization process. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + * @see com.silverwrist.util.image.ImageNormalizer#normalizeImage(java.io.InputStream,int,int,java.lang.String) + */ +public class ImageNormalizerException extends Exception +{ + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + /** + * Constructs a new ImageNormalizerException. + */ + public ImageNormalizerException() + { + super(); + + } // end constructor + + /** + * Constructs a new ImageNormalizerException. + * + * @param message Message for the exception. + */ + public ImageNormalizerException(String message) + { + super(message); + + } // end constructor + + /** + * Constructs a new ImageNormalizerException. + * + * @param t The exception to be wrapped by this one. + */ + public ImageNormalizerException(Throwable t) + { + super(t); + + } // end constructor + + /** + * Constructs a new ImageNormalizerException. + * + * @param message Message for the exception. + * @param t The exception to be wrapped by this one. + */ + public ImageNormalizerException(String message, Throwable t) + { + super(message,t); + + } // end constructor + +} // end class ImageNormalizerException diff --git a/src/baseutil/com/silverwrist/util/languages.properties b/src/baseutil/com/silverwrist/util/languages.properties new file mode 100644 index 0000000..f9d0e97 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/languages.properties @@ -0,0 +1,254 @@ +# The contents of this file are subject to the Mozilla Public License Version 1.1 +# (the "License"); you may not use this file except in compliance with the License. +# You may obtain a copy of the License at . +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +# ------------------------------------------------------------------------------------- +# This list of languages is styled on RFC 1766, based on ISO 639 language code listings, +# from , and ISO 3166 country code listings, +# from . Language variants by country taken +# from WINNT.H header file, Microsoft Windows Platform SDK. Additional language codes +# (i- names and expanded zh- names) from IANA, . +# Changes to Indonesian, Hebrew, and Yiddish noted from Java 2 SDK documentation. +# When adding new entries to this file, make sure and add it in sorted order by language NAME! +# You can re-sort the language entries with "sort -t = -k 2 input > output", but then make sure +# the "i-default=(unknown)" entry appears first! +i-default=(unknown) +ab=Abkhazian +aa=Afar +af=Afrikaans +sq=Albanian +am=Amharic +i-ami=Amis +ar=Arabic +ar-DZ=Arabic (Algeria) +ar-BH=Arabic (Bahrain) +ar-EG=Arabic (Egypt) +ar-IQ=Arabic (Iraq) +ar-JO=Arabic (Jordan) +ar-KW=Arabic (Kuwait) +ar-LB=Arabic (Lebanon) +ar-LY=Arabic (Libya) +ar-MA=Arabic (Morocco) +ar-OM=Arabic (Oman) +ar-QA=Arabic (Qatar) +ar-SA=Arabic (Saudi Arabia) +ar-SY=Arabic (Syria) +ar-TN=Arabic (Tunisia) +ar-AE=Arabic (U.A.E.) +ar-YE=Arabic (Yemen) +hy=Armenian +as=Assamese +ay=Aymara +az=Azerbaijani +ba=Bashkir +eu=Basque +bn=Bengali +bh=Bihari +bi=Bislama +br=Breton +bg=Bulgarian +i-bnn=Bunun +my=Burmese +be=Byelorussian +km=Cambodian +ca=Catalan +zh=Chinese +zh-yue=Chinese (Cantonese) +zh-gan=Chinese (Gan) +zh-hakka=Chinese (Hakka) +zh-HK=Chinese (Hong Kong) +zh-xiang=Chinese (Hunan) +zh-guoyu=Chinese (Mandarin) +zh-wuu=Chinese (Shanghai) +zh-CN=Chinese (Simplified) +zh-SG=Chinese (Singapore) +zh-min=Chinese (Taiwanese) +zh-TW=Chinese (Traditional) +co=Corsican +hr=Croatian +cs=Czech +da=Danish +nl=Dutch +nl-BE=Dutch (Belgian) +dz=Dzongkha +en=English +en-AU=English (Australian) +en-BZ=English (Belize) +en-CA=English (Canadian) +en-caribbean=English (Caribbean) +en-IE=English (Irish) +en-JM=English (Jamaica) +en-NZ=English (New Zealand) +en-scouse=English (Scouse) +en-ZA=English (South Africa) +en-TT=English (Trinidad) +en-GB=English (United Kingdom) +en-US=English (United States) +eo=Esperanto +et=Estonian +fo=Faeroese +fj=Fiji +fi=Finnish +fr=French +fr-BE=French (Belgian) +fr-CA=French (Canadian) +fr-LU=French (Luxembourg) +fr-CH=French (Swiss) +fy=Frisian +gl=Gallegan +ka=Georgian +de=German +de-AT=German (Austria) +de-LI=German (Liechtenstein) +de-LU=German (Luxembourg) +de-CH=German (Swiss) +el=Greek +kl=Greenlandic +gn=Guarani +gu=Gujarati +i-hak=Hakka +ha=Hausa +he=Hebrew +hi=Hindi +hu=Hungarian +is=Icelandic +id=Indonesian +ia=Interlingua +ie=Interlingue +iu=Inuktitut +ik=Inupiak +ga=Irish +it=Italian +it-CH=Italian (Swiss) +ja=Japanese +jw=Javanese +kn=Kannada +ks=Kashmiri +km=Khmer +kk=Kazakh +rw=Kinyarwanda +ky=Kirghiz +rn=Kirundi +i-klingon=Klingon +ko=Korean +ko-johab=Korean (Johab) +ku=Kurdish +oc=Langue d'Oc +lo=Lao +la=Latin +lv=Latvian +ln=Lingala +lt=Lithuanian +i-lux=Luxembourgish +mk=Macedonian +mg=Malagasy +ms=Malay +ml=Maltese +mi=Maori +mr=Marathi +i-mingo=Mingo +mo=Moldavian +mn=Mongolian +na=Nauru +i-navajo=Navajo +ne=Nepali +no=Norwegian +no-bok=Norwegian (Bokmal) +no-nyn=Norwegian (Nynorsk) +oc=Occitan +or=Oriya +om=Oromo +i-pwn=Paiwan +pa=Panjabi +ps=Pashto +fa=Persian +pl=Polish +pt=Portuguese +pt-BR=Portuguese (Brazilian) +ps=Pushto +qu=Quechua +rm=Rhaeto-Romance +ro=Romanian +rn=Rundi +ru=Russian +sm=Samoan +sg=Sango +sa=Sanskrit +gd=Scots Gaelic +sr-cyrillic=Serbian (Cyrillic) +sr=Serbian (Latin) +sh=Serbo-Croatian +st=Sesotho +sn=Shona +sd=Sindhi +si=Singhalese +ss=Siswant +sk=Slovak +sl=Slovenian +so=Somali +st=Sotho +es-AR=Spanish (Argentina) +es-BO=Spanish (Bolivia) +es-ES=Spanish (Castilian) +es-CL=Spanish (Chile) +es-CO=Spanish (Colombia) +es-CR=Spanish (Costa Rica) +es-DO=Spanish (Dominican Republic) +es-EC=Spanish (Ecuador) +es-SV=Spanish (El Salvador) +es-GT=Spanish (Guatemala) +es-HN=Spanish (Honduras) +es-MX=Spanish (Mexican) +es=Spanish (Modern) +es-NI=Spanish (Nicaragua) +es-PA=Spanish (Panama) +es-PY=Spanish (Paraguay) +es-PE=Spanish (Peru) +es-PR=Spanish (Puerto Rico) +es-UY=Spanish (Uruguay) +es-VE=Spanish (Venezuela) +su=Sudanese +sw=Swahili +sv=Swedish +sv-FI=Swedish (Finland) +tl=Tagalog +tg=Tajik +ta=Tamil +i-tao=Tao +tt=Tatar +i-tay=Tayal +te=Tegulu +th=Thai +bo=Tibetan +ti=Tigrinya +to=Tonga +ts=Tsonga +i-tsu=Tsou +tn=Tswana +tr=Turkish +tk=Turkmen +tw=Twi +ug=Uighur +uk=Ukrainian +ur=Urdu +uz=Uzbek +vi=Vietnamese +vo=Volapuk +cy=Welsh +wo=Wolof +xh=Xhosa +yi=Yiddish +yo=Yoruba +za=Zhuang +zu=Zulu diff --git a/src/baseutil/com/silverwrist/util/xml/DOMElementHelper.java b/src/baseutil/com/silverwrist/util/xml/DOMElementHelper.java new file mode 100644 index 0000000..0a17517 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/xml/DOMElementHelper.java @@ -0,0 +1,489 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util.xml; + +import org.w3c.dom.*; +import com.silverwrist.util.StringUtils; + +/** + * A class which wraps around the DOM Element class, providing some + * additional functionality. Written to DOM Level 2. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + * @see org.w3c.dom.Element + */ +public final class DOMElementHelper +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private Element m_elt; // element housed by this helper class + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Constructs a new DOMElementHelper to wrap a specific Element. + * + * @param elt The Element to be wrapped. + */ + public DOMElementHelper(Element elt) + { + m_elt = elt; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal static operations + *-------------------------------------------------------------------------------- + */ + + /** + * Returns the content of all text nodes underneath a specified Element, concatenated + * together into a single string. + * + * @param e The Element to extract text from. + * @return The text content under this Element node. If the specified Element + * has no text nodes underneath it, returns null. + */ + private static final String getTextOfElement(Element e) + { + NodeList kids = e.getChildNodes(); + if (kids==null) + return null; // no text? + + StringBuffer b = null; + for (int i=0; iElement, expressed as an integer. + * + * @param e The Element to extract text from. + * @return An Integer object containing the value of the specified element. If + * the Element has no text, or if the text cannot be expressed as an integer, + * returns null. + */ + private static final Integer getIntegerFromElement(Element e) + { + try + { // extract the text and create an Integer around it + String s = getTextOfElement(e); + return ((s==null) ? null : new Integer(s.trim())); + + } // end try + catch (NumberFormatException nfe) + { // value cannot be parsed as an integer + return null; + + } // end catch + + } // end getIntegerFromElement + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * Returns the Element wrapped by this object. + * + * @return See above. + */ + public final Element getElement() + { + return m_elt; + + } // end getElement + + /** + * Searches for the first sub-element of the wrapped Element with the given name. + * + * @param name Name of the sub-element to search for. + * @return The first sub-element of the wrapped Element with the specified name. + * If the Element has no child Elements with the given name, + * the method returns null. + */ + public final Element getSubElement(String name) + { + NodeList kids = m_elt.getChildNodes(); + if (kids==null) + return null; // no children? + for (int i=0; iElement with the given name. + * + * @param namespaceURI Namespace URI for the sub-element to search for. + * @param name Name of the sub-element to search for. + * @return The first sub-element of the wrapped Element with the specified URI/name. + * If the Element has no child Elements with the given URI/name, + * the method returns null. + */ + public final Element getSubElementNS(String namespaceURI, String name) + { + NodeList kids = m_elt.getChildNodes(); + if (kids==null) + return null; // no children? + for (int i=0; iElement, concatenated + * together into a single string. + * + * @return The text content under the wrapped Element node. If the wrapped Element + * has not text nodes underneath it, returns null. + */ + public final String getElementText() + { + return getTextOfElement(m_elt); + + } // end getElementText + + /** + * Returns the value of the text of the wrapped Element, expressed as an integer. + * + * @return An Integer object containing the value of the wrapped element. If + * the Element has no text, or if the text cannot be expressed as an integer, + * returns null. + */ + public final Integer getElementInt() + { + return getIntegerFromElement(m_elt); + + } // end getElementInt + + /** + * Returns the content of all text nodes underneath the first sub-element of the wrapped + * Element, with the given name, concatenated together into a single string. + * + * @param name The name of the sub-element to search for. + * @return The text content under the specified sub-element of the wrapped Element node. + * If the wrapped Element does not have a sub-element with the given name, or + * that sub-element has no text nodes underneath it, returns null. + */ + public final String getSubElementText(String name) + { + Element se = getSubElement(name); + return ((se==null) ? null : getTextOfElement(se)); + + } // end getSubElementText + + /** + * Returns the content of all text nodes underneath the first sub-element of the wrapped + * Element, with the given name, concatenated together into a single string. + * + * @param namespaceURI Namespace URI for the sub-element to search for. + * @param name The name of the sub-element to search for. + * @return The text content under the specified sub-element of the wrapped Element node. + * If the wrapped Element does not have a sub-element with the given URI/name, or + * that sub-element has no text nodes underneath it, returns null. + */ + public final String getSubElementTextNS(String namespaceURI, String name) + { + Element se = getSubElementNS(namespaceURI,name); + return ((se==null) ? null : getTextOfElement(se)); + + } // end getSubElementTextNS + + /** + * Returns the value of the text underneath the first sub-element of the wrapped + * Element, with the given name, expressed as an integer. + * + * @param name The name of the sub-element to search for. + * @return An Integer object containing the value of the specified element. If + * the wrapped Element does not have a sub-element with the given name, or that + * sub-element has no text, or if the text cannot be expressed as an integer, returns + * null. + */ + public final Integer getSubElementInt(String name) + { + Element se = getSubElement(name); + return ((se==null) ? null : getIntegerFromElement(se)); + + } // end getSubElementInt + + /** + * Returns the value of the text underneath the first sub-element of the wrapped + * Element, with the given name, expressed as an integer. + * + * @param namespaceURI Namespace URI for the sub-element to search for. + * @param name The name of the sub-element to search for. + * @return An Integer object containing the value of the specified element. If + * the wrapped Element does not have a sub-element with the given URI/name, or that + * sub-element has no text, or if the text cannot be expressed as an integer, returns + * null. + */ + public final Integer getSubElementIntNS(String namespaceURI, String name) + { + Element se = getSubElementNS(namespaceURI,name); + return ((se==null) ? null : getIntegerFromElement(se)); + + } // end getSubElementIntNS + + /** + * Determines whether the wrapped Element has a sub-element with the given name. + * + * @param name Name of the sub-element to search for. + * @return true if the wrapped Element has a sub-element with the + * specified name, false if not. + */ + public final boolean hasChildElement(String name) + { + return (getSubElement(name)!=null); + + } // end hasChildElement + + /** + * Determines whether the wrapped Element has a sub-element with the given name. + * + * @param namespaceURI Namespace URI for the sub-element to search for. + * @param name Name of the sub-element to search for. + * @return true if the wrapped Element has a sub-element with the + * specified name, false if not. + */ + public final boolean hasChildElementNS(String namespaceURI, String name) + { + return (getSubElementNS(namespaceURI,name)!=null); + + } // end hasChildElementNS + + /** + * Determines whether the wrapped Element has an attribute with the given name. + * + * @param name Name of the attribute to search for. + * @return true if the wrapped Element has an attribute with the + * specified name, false if not. + */ + public final boolean hasAttribute(String name) + { + return m_elt.hasAttribute(name); + + } // end hasAttribute + + /** + * Determines whether the wrapped Element has an attribute with the given name. + * + * @param namespaceURI Namespace URI for the attribute to search for. + * @param name Name of the attribute to search for. + * @return true if the wrapped Element has an attribute with the + * specified URI/name, false if not. + */ + public final boolean hasAttributeNS(String namespaceURI, String name) + { + return m_elt.hasAttributeNS(namespaceURI,name); + + } // end hasAttributeNS + + /** + * Returns the value of a specified attribute of the wrapped Element, expressed as + * an integer. + * + * @param name Name of the attribute to search for. + * @return An Integer object containing the value of the specified attribute. If + * the wrapped Element has no such attribute, or if the attribute's value + * cannot be expressed as an integer, returns null. + */ + public final Integer getAttributeInt(String name) + { + String tmp = m_elt.getAttribute(name); + if (StringUtils.isEmpty(tmp)) + return null; + try + { // convert to an Integer + return new Integer(tmp.trim()); + + } // end try + catch (NumberFormatException nfe) + { // return a null value on error + return null; + + } // end catch + + } // end getAttributeInt + + /** + * Returns the value of a specified attribute of the wrapped Element, expressed as + * an integer. + * + * @param namespaceURI Namespace URI for the attribute to search for. + * @param name Name of the attribute to search for. + * @return An Integer object containing the value of the specified attribute. If + * the wrapped Element has no such attribute, or if the attribute's value + * cannot be expressed as an integer, returns null. + */ + public final Integer getAttributeIntNS(String namespaceURI, String name) + { + String tmp = m_elt.getAttributeNS(namespaceURI,name); + if (StringUtils.isEmpty(tmp)) + return null; + try + { // convert to an Integer + return new Integer(tmp.trim()); + + } // end try + catch (NumberFormatException nfe) + { // return a null value on error + return null; + + } // end catch + + } // end getAttributeInt + + /** + * Returns the value of a specified attribute of the wrapped Element, expressed as + * a Boolean. Uses the Boolean string methods on {@link com.silverwrist.util.StringUtils StringUtils} to + * determine the state of the attribute value. + * + * @param name Name of the attribute to search for. + * @return Boolean.TRUE if the attribute value represents a "true" Boolean value; + * Boolean.FALSE if the attribute value represents a "false" Boolean value; null + * otherwise. + * @see com.silverwrist.util.StringUtils#isBooleanTrue(java.lang.String) + * @see com.silverwrist.util.StringUtils#isBooleanFalse(java.lang.String) + */ + public final Boolean getAttributeBoolean(String name) + { + String tmp = m_elt.getAttribute(name); + if (StringUtils.isBooleanTrue(tmp)) + return Boolean.TRUE; + else if (StringUtils.isBooleanFalse(tmp)) + return Boolean.FALSE; + else + return null; + + } // end getAttributeBoolean + + /** + * Returns the value of a specified attribute of the wrapped Element, expressed as + * a Boolean. Uses the Boolean string methods on {@link com.silverwrist.util.StringUtils StringUtils} to + * determine the state of the attribute value. + * + * @param namespaceURI Namespace URI for the attribute to search for. + * @param name Name of the attribute to search for. + * @return Boolean.TRUE if the attribute value represents a "true" Boolean value; + * Boolean.FALSE if the attribute value represents a "false" Boolean value; null + * otherwise. + * @see com.silverwrist.util.StringUtils#isBooleanTrue(java.lang.String) + * @see com.silverwrist.util.StringUtils#isBooleanFalse(java.lang.String) + */ + public final Boolean getAttributeBooleanNS(String namespaceURI, String name) + { + String tmp = m_elt.getAttributeNS(namespaceURI,name); + if (StringUtils.isBooleanTrue(tmp)) + return Boolean.TRUE; + else if (StringUtils.isBooleanFalse(tmp)) + return Boolean.FALSE; + else + return null; + + } // end getAttributeBooleanNS + + /** + * Returns the value of a specified attribute of the wrapped Element, expressed as + * a Boolean. Uses the Boolean string methods on {@link com.silverwrist.util.StringUtils StringUtils} to + * determine the state of the attribute value. + * + * @param name Name of the attribute to search for. + * @param default_val Default value for the attribute. + * @return Boolean.TRUE if the attribute value represents a "true" Boolean value; + * Boolean.FALSE if the attribute value represents a "false" Boolean value; the + * Boolean object corresponding to default_val if the attribute is missing; + * null otherwise. + * @see com.silverwrist.util.StringUtils#isBooleanTrue(java.lang.String) + * @see com.silverwrist.util.StringUtils#isBooleanFalse(java.lang.String) + */ + public final Boolean getAttributeBoolean(String name, boolean default_val) + { + if (this.hasAttribute(name)) + return this.getAttributeBoolean(name); + else + return (default_val ? Boolean.TRUE : Boolean.FALSE); + + } // end getAttributeBoolean + + /** + * Returns the value of a specified attribute of the wrapped Element, expressed as + * a Boolean. Uses the Boolean string methods on {@link com.silverwrist.util.StringUtils StringUtils} to + * determine the state of the attribute value. + * + * @param namespaceURI Namespace URI for the attribute to search for. + * @param name Name of the attribute to search for. + * @param default_val Default value for the attribute. + * @return Boolean.TRUE if the attribute value represents a "true" Boolean value; + * Boolean.FALSE if the attribute value represents a "false" Boolean value; the + * Boolean object corresponding to default_val if the attribute is missing; + * null otherwise. + * @see com.silverwrist.util.StringUtils#isBooleanTrue(java.lang.String) + * @see com.silverwrist.util.StringUtils#isBooleanFalse(java.lang.String) + */ + public final Boolean getAttributeBooleanNS(String namespaceURI, String name, boolean default_val) + { + if (this.hasAttributeNS(namespaceURI,name)) + return this.getAttributeBooleanNS(namespaceURI,name); + else + return (default_val ? Boolean.TRUE : Boolean.FALSE); + + } // end getAttributeBooleanNS + +} // end class DOMElementHelper diff --git a/src/baseutil/com/silverwrist/util/xml/XMLLoadException.java b/src/baseutil/com/silverwrist/util/xml/XMLLoadException.java new file mode 100644 index 0000000..9dd7c32 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/xml/XMLLoadException.java @@ -0,0 +1,155 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util.xml; + +import org.w3c.dom.*; + +/** + * An exception type thrown by the {@link com.silverwrist.util.xml.XMLLoader XMLLoader} when it encounters + * a parse error, value error, or other erroneous condition. It contains a reference to the node in the DOM + * tree where the error occured, if such is possible to determine. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class XMLLoadException extends Exception +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private Node m_locus = null; // locus of the error + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + /** + * Constructs a new XMLLoadException. + */ + public XMLLoadException() + { + super(); + + } // end constructor + + /** + * Constructs a new XMLLoadException. + * + * @param msg The error message to be thrown. + */ + public XMLLoadException(String msg) + { + super(msg); + + } // end constructor + + /** + * Constructs a new XMLLoadException. + * + * @param inner The exception wrapped by this XMLLoadException. + */ + public XMLLoadException(Throwable inner) + { + super(inner); + + } // end constructor + + /** + * Constructs a new XMLLoadException. + * + * @param msg The error message to be thrown. + * @param inner The exception wrapped by this XMLLoadException. + */ + public XMLLoadException(String msg, Throwable inner) + { + super(msg,inner); + + } // end constructor + + /** + * Constructs a new XMLLoadException. + * + * @param locus The Node in the DOM tree where the error occurred. + */ + public XMLLoadException(Node locus) + { + super("Error in <" + locus.getNodeName() + "/> section of input"); + m_locus = locus; + + } // end constructor + + /** + * Constructs a new XMLLoadException. + * + * @param msg The error message to be thrown. + * @param locus The Node in the DOM tree where the error occurred. + */ + public XMLLoadException(String msg, Node locus) + { + super("Error in <" + locus.getNodeName() + "/> section of input - " + msg); + m_locus = locus; + + } // end constructor + + /** + * Constructs a new XMLLoadException. + * + * @param inner The exception wrapped by this XMLLoadException. + * @param locus The Node in the DOM tree where the error occurred. + */ + public XMLLoadException(Throwable inner, Node locus) + { + super("Error in <" + locus.getNodeName() + "/> section of input - " + inner.getMessage(),inner); + m_locus = locus; + + } // end constructor + + /** + * Constructs a new XMLLoadException. + * + * @param msg The error message to be thrown. + * @param inner The exception wrapped by this XMLLoadException. + * @param locus The Node in the DOM tree where the error occurred. + */ + public XMLLoadException(String msg, Throwable inner, Node locus) + { + super("Error in <" + locus.getNodeName() + "/> section of input - " + msg,inner); + m_locus = locus; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * Returns the locus of the error contained in this exception. + * + * @return The Node that indicates wherre in the DOM tree the error occurred. + */ + public Node getLocus() + { + return m_locus; + + } // end getLocus + +} // end class XMLLoadException diff --git a/src/baseutil/com/silverwrist/util/xml/XMLLoader.java b/src/baseutil/com/silverwrist/util/xml/XMLLoader.java new file mode 100644 index 0000000..9886ba6 --- /dev/null +++ b/src/baseutil/com/silverwrist/util/xml/XMLLoader.java @@ -0,0 +1,824 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util.xml; + +import java.io.*; +import java.util.*; +import javax.xml.parsers.*; +import org.apache.log4j.Logger; +import org.w3c.dom.*; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import com.silverwrist.util.StringUtils; + +/** + * A simple class which is commonly used for the loading of XML documents as configuration files. Various + * methods on this object load XML documents as DOM trees and extract portions of the information therein. + * It is implemented as a Singleton. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class XMLLoader +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(XMLLoader.class); + + private static XMLLoader self = null; // our singleton instance + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Internal constructor for XMLLoader. Only one instance is ever constructed. + */ + private XMLLoader() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * Parses an XML document into a DOM tree. + * + * @param stm The XML document to be parsed, expressed as an InputStream. + * @param namespacing true if we want this XML document parsed in a namespace-aware fashion, + * false if not. + * @return The Document that results from parsing the XML document. + * @exception java.io.IOException If there was an I/O error reading from the XML document. + * @exception com.silverwrist.util.xml.XMLLoaderException If there was a parse error in the XML, or other error + * accessing the XML parser. + */ + public final Document load(InputStream stm, boolean namespacing) throws IOException, XMLLoadException + { + try + { // create a simple DOM parser by using the Java XML parsing API + DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance(); + fac.setNamespaceAware(namespacing); + fac.setValidating(false); + DocumentBuilder parser = fac.newDocumentBuilder(); + if (parser.isNamespaceAware()!=namespacing) + throw new XMLLoadException("XML parser namespacing parameter is not consistent"); + + // access the config file and parse it into our config data tree + return parser.parse(stm); + + } // end try + catch (FactoryConfigurationError fce) + { // if the document builder factory could not be created + throw new XMLLoadException("XML parser factory could not be created - " + fce.getMessage()); + + } // end catch + catch (ParserConfigurationException pce) + { // if the XML parser itself could not be created + throw new XMLLoadException("XML parser could not be created - " + pce.getMessage(),pce); + + } // end catch + catch (SAXException se) + { // if the XML parser choked on our document + if (se instanceof SAXParseException) + { // we have a detailed message - make a proper exception + SAXParseException spe = (SAXParseException)se; + throw new XMLLoadException("Error in XML data: " + spe.getMessage() + " at line " + + spe.getLineNumber() + ", column " + spe.getColumnNumber(),spe); + + } // end if + else + { // generic exception - just send up a simple error message + throw new XMLLoadException("Error in XML data - " + se.getMessage(),se); + + } // end else + + } // end catch + + } // end load + + /** + * Parses an XML document into a DOM tree. + * + * @param stm The XML document to be parsed, expressed as a File object. + * @param namespacing true if we want this XML document parsed in a namespace-aware fashion, + * false if not. + * @return The Document that results from parsing the XML document. + * @exception java.io.IOException If there was an I/O error reading from the XML document. + * @exception com.silverwrist.util.xml.XMLLoaderException If there was a parse error in the XML, or other error + * accessing the XML parser. + */ + public final Document load(File file, boolean namespacing) throws IOException, XMLLoadException + { + return this.load(new FileInputStream(file),namespacing); + + } // end load + + /** + * Gets the root element of a parsed XML DOM tree, and verifies that it matches a specific name. + * + * @param doc The document to get the root element of. + * @param expected_name The expected name of the root element. + * @return The root Element of the document, + * @exception com.silverwrist.util.XMLLoadException If the root element of the document does not match the + * expected_name. + */ + public final Element getRootElement(Document doc, String expected_name) throws XMLLoadException + { + Element rc = doc.getDocumentElement(); + if (rc.getTagName().equals(expected_name)) + return rc; // we're OK + throw new XMLLoadException("expected <" + expected_name + "/> root element",rc); + + } // end getRootElement + + /** + * Gets the root element of a parsed XML DOM tree, and verifies that it matches a specific name. + * + * @param doc The document to get the root element of. + * @param expected_namespace The expected namespace for the root element of the document. + * @param expected_name The expected name of the root element. + * @return The root Element of the document, + * @exception com.silverwrist.util.XMLLoadException If the root element of the document does not match the + * expected_namespace and expected_name. + */ + public final Element getRootElementNS(Document doc, String expected_namespace, + String expected_name) throws XMLLoadException + { + Element rc = doc.getDocumentElement(); + if (rc.getNamespaceURI().equals(expected_namespace) && rc.getTagName().equals(expected_name)) + return rc; // we're OK + throw new XMLLoadException("expected <" + expected_namespace + ":" + expected_name + "/> root element",rc); + + } // end getRootElementNS + + /** + * Gets the text contained in an Element wrapped in a + * {@link com.silverwrist.util.xml.DOMElementHelper DOMElementHelper}. + * + * @param h The DOMElementHelper to extract the text from. + * @return The text contained in the element. + * @exception com.silverwrist.util.XMLLoadException If there is no text contained in the element. + */ + public final String getText(DOMElementHelper h) throws XMLLoadException + { + String rc = h.getElementText(); + if (rc!=null) + return rc; // we're OK + throw new XMLLoadException("no text found under element",h.getElement()); + + } // end getText + + /** + * Gets the text contained in an Element. + * + * @param elt The Element to extract the text from. + * @return The text contained in the element. + * @exception com.silverwrist.util.XMLLoadException If there is no text contained in the element. + */ + public final String getText(Element elt) throws XMLLoadException + { + return getText(new DOMElementHelper(elt)); + + } // end getText + + /** + * Gets the text contained in a named sub-element of an Element wrapped in a + * {@link com.silverwrist.util.xml.DOMElementHelper DOMElementHelper}. + * + * @param h The DOMElementHelper to extract the text from. + * @param elt_name The name of the sub-element to look for text in. + * @return The text contained in the sub-element. + * @exception com.silverwrist.util.XMLLoadException If the sub-element is not found, or there is no text + * contained in the sub-element. + */ + public final String getSubElementText(DOMElementHelper h, String elt_name) throws XMLLoadException + { + String rc = h.getSubElementText(elt_name); + if (rc!=null) + return rc; // we're OK + throw new XMLLoadException("sublement <" + elt_name + "/> not found",h.getElement()); + + } // end getSubElementText + + /** + * Gets the text contained in a named sub-element of an Element. + * + * @param elt The Element to extract the text from. + * @param subelt_name The name of the sub-element to look for text in. + * @return The text contained in the sub-element. + * @exception com.silverwrist.util.XMLLoadException If the sub-element is not found, or there is no text + * contained in the sub-element. + */ + public final String getSubElementText(Element elt, String subelt_name) throws XMLLoadException + { + return getSubElementText(new DOMElementHelper(elt),subelt_name); + + } // end getSubElementText + + /** + * Gets the text contained in a named sub-element of an Element wrapped in a + * {@link com.silverwrist.util.xml.DOMElementHelper DOMElementHelper}. + * + * @param h The DOMElementHelper to extract the text from. + * @param namespace The namespace URI of the sub-element to look for text in. + * @param elt_name The name of the sub-element to look for text in. + * @return The text contained in the sub-element. + * @exception com.silverwrist.util.XMLLoadException If the sub-element is not found, or there is no text + * contained in the sub-element. + */ + public final String getSubElementTextNS(DOMElementHelper h, String namespace, String elt_name) + throws XMLLoadException + { + String rc = h.getSubElementTextNS(namespace,elt_name); + if (rc!=null) + return rc; // we're OK + throw new XMLLoadException("sublement <" + namespace + ":" + elt_name + "/> not found",h.getElement()); + + } // end getSubElementTextNS + + /** + * Gets the text contained in a named sub-element of an Element. + * + * @param elt The Element to extract the text from. + * @param namespace The namespace URI of the sub-element to look for text in. + * @param subelt_name The name of the sub-element to look for text in. + * @return The text contained in the sub-element. + * @exception com.silverwrist.util.XMLLoadException If the sub-element is not found, or there is no text + * contained in the sub-element. + */ + public final String getSubElementTextNS(Element elt, String namespace, String subelt_name) + throws XMLLoadException + { + return getSubElementTextNS(new DOMElementHelper(elt),namespace,subelt_name); + + } // end getSubElementTextNS + + /** + * Gets a named sub-element of an Element wrapped in a + * {@link com.silverwrist.util.xml.DOMElementHelper DOMElementHelper}. + * + * @param h The DOMElementHelper to extract the sub-element from. + * @param name The name of the sub-element to look for. + * @return The sub-element. + * @exception com.silverwrist.util.XMLLoadException If the sub-element is not found. + */ + public final Element getSubElement(DOMElementHelper h, String name) throws XMLLoadException + { + Element rc = h.getSubElement(name); + if (rc!=null) + return rc; // we're OK + throw new XMLLoadException("sublement <" + name + "/> not found",h.getElement()); + + } // end getSubElement + + /** + * Gets a named sub-element of an Element. + * + * @param sect The Element to extract the sub-element from. + * @param name The name of the sub-element to look for. + * @return The sub-element. + * @exception com.silverwrist.util.XMLLoadException If the sub-element is not found. + */ + public final Element getSubElement(Element sect, String name) throws XMLLoadException + { + return getSubElement(new DOMElementHelper(sect),name); + + } // end getSubElement + + /** + * Gets a named sub-element of an Element wrapped in a + * {@link com.silverwrist.util.xml.DOMElementHelper DOMElementHelper}. + * + * @param h The DOMElementHelper to extract the sub-element from. + * @param namespace The namespace URI of the sub-element to look for. + * @param name The name of the sub-element to look for. + * @return The sub-element. + * @exception com.silverwrist.util.XMLLoadException If the sub-element is not found. + */ + public final Element getSubElementNS(DOMElementHelper h, String namespace, String name) + throws XMLLoadException + { + Element rc = h.getSubElementNS(namespace,name); + if (rc!=null) + return rc; // we're OK + throw new XMLLoadException("sublement <" + namespace + ":" + name + "/> not found",h.getElement()); + + } // end getSubElementNS + + /** + * Gets a named sub-element of an Element. + * + * @param sect The Element to extract the sub-element from. + * @param namespace The namespace URI of the sub-element to look for. + * @param name The name of the sub-element to look for. + * @return The sub-element. + * @exception com.silverwrist.util.XMLLoadException If the sub-element is not found. + */ + public final Element getSubElementNS(Element sect, String namespace, String name) throws XMLLoadException + { + return getSubElementNS(new DOMElementHelper(sect),namespace,name); + + } // end getSubElementNS + + /** + * Returns all sub-elements of an Element element that have a specific name. + * + * @param sect The Element to extract the sub-elements from. + * @param name The name of the sub-elements to look for. + * @return A java.util.List containing all the sub-elements of the given Element with + * the specified name. If there are no matching sub-elements, an empty list is returned. + */ + public final List getMatchingSubElements(Element sect, String name) + { + ArrayList rc = new ArrayList(); + NodeList nl = sect.getChildNodes(); + for (int i=0; iElement element that have a specific name. + * + * @param sect The Element to extract the sub-elements from. + * @param namespace The namespace URI of the sub-elements to look for. + * @param name The name of the sub-elements to look for. + * @return A java.util.List containing all the sub-elements of the given Element with + * the specified namespace and name. If there are no matching sub-elements, an empty list is returned. + */ + public final List getMatchingSubElementsNS(Element sect, String namespace, String name) + { + ArrayList rc = new ArrayList(); + NodeList nl = sect.getChildNodes(); + for (int i=0; iNode to test the name of. + * @param name The name to test the node against. + * @param enclosing_sect The Element that contains this node as a child, used in constructing + * the exception if the test fails. + * @exception com.silverwrist.util.xml.XMLLoadException If the name of the node does not match. + */ + public final void verifyNodeName(Node n, String name, Element enclosing_sect) throws XMLLoadException + { + if (n.getNodeName().equals(name)) + return; + throw new XMLLoadException("node <" + n.getNodeName() + "/> should be <" + name + "/>",enclosing_sect); + + } // end verifyNodeName + + /** + * Checks to make sure that the name of a given node is what we expect, and throws an + * {@link com.silverwrist.util.xml.XMLLoadException XMLLoadException} if it isn't. + * + * @param n The Node to test the name of. + * @param name The name to test the node against. + * @exception com.silverwrist.util.xml.XMLLoadException If the name of the node does not match. + */ + public final void verifyNodeName(Node n, String name) throws XMLLoadException + { + verifyNodeName(n,name,(Element)(n.getParentNode())); + + } // end verifyNodeName + + /** + * Checks to make sure that the name of a given node is what we expect, and throws an + * {@link com.silverwrist.util.xml.XMLLoadException XMLLoadException} if it isn't. + * + * @param n The Node to test the name of. + * @param namespace The namespace URI to test the node against. + * @param name The name to test the node against. + * @param enclosing_sect The Element that contains this node as a child, used in constructing + * the exception if the test fails. + * @exception com.silverwrist.util.xml.XMLLoadException If the name of the node does not match. + */ + public final void verifyNodeNameNS(Node n, String namespace, String name, Element enclosing_sect) + throws XMLLoadException + { + if (n.getNamespaceURI().equals(namespace) && n.getNodeName().equals(name)) + return; + throw new XMLLoadException("node <" + n.getNamespaceURI() + ":" + n.getNodeName() + "/> should be <" + + namespace + ":" + name + "/>",enclosing_sect); + + } // end verifyNodeNameNS + + /** + * Checks to make sure that the name of a given node is what we expect, and throws an + * {@link com.silverwrist.util.xml.XMLLoadException XMLLoadException} if it isn't. + * + * @param n The Node to test the name of. + * @param namespace The namespace URI to test the node against. + * @param name The name to test the node against. + * @exception com.silverwrist.util.xml.XMLLoadException If the name of the node does not match. + */ + public final void verifyNodeNameNS(Node n, String namespace, String name) throws XMLLoadException + { + verifyNodeNameNS(n,namespace,name,(Element)(n.getParentNode())); + + } // end verifyNodeNameNS + + /** + * Checks to make sure that the name of a given tag element is what we expect, and throws an + * {@link com.silverwrist.util.xml.XMLLoadException XMLLoadException} if it isn't. + * + * @param tag The Element to test the name of. + * @param name The name to test the element against. + * @exception com.silverwrist.util.xml.XMLLoadException If the name of the element does not match. + */ + public final void verifyTagName(Element tag, String name) throws XMLLoadException + { + if (tag.getTagName().equals(name)) + return; + throw new XMLLoadException("expected <" + name + "/> element",tag); + + } // end verifyTagName + + /** + * Checks to make sure that the name of a given tag element is what we expect, and throws an + * {@link com.silverwrist.util.xml.XMLLoadException XMLLoadException} if it isn't. + * + * @param tag The Element to test the name of. + * @param namespace The namespace URI to test the element against. + * @param name The name to test the element against. + * @exception com.silverwrist.util.xml.XMLLoadException If the name of the element does not match. + */ + public final void verifyTagNameNS(Element tag, String namespace, String name) throws XMLLoadException + { + if (tag.getNamespaceURI().equals(namespace) && tag.getTagName().equals(name)) + return; + throw new XMLLoadException("expected <" + namespace + ":" + name + "/> element",tag); + + } // end verifyTagNameNS + + /** + * Gets the value of an attribute on an Element. + * + * @param elt The Element to retrieve the attribute from. + * @param attr_name The name of the attribute to retrieve. + * @return The attribute value. + * @exception com.silverwrist.util.xml.XMLLoadException If the attribute did not exist on the element. + */ + public final String getAttribute(Element elt, String attr_name) throws XMLLoadException + { + String rc = elt.getAttribute(attr_name); + if (!(StringUtils.isEmpty(rc))) + return rc; + throw new XMLLoadException("no " + attr_name + "= attribute found",elt); + + } // end getAttribute + + /** + * Gets the value of an attribute on an Element. + * + * @param elt The Element to retrieve the attribute from. + * @param attr_name The name of the attribute to retrieve. + * @param default_val The default value of the attribute. + * @return The attribute value, or the value of default_val if the attribute didn't exist. + */ + public final String getAttribute(Element elt, String attr_name, String default_val) + { + String rc = elt.getAttribute(attr_name); + return (StringUtils.isEmpty(rc) ? default_val : rc); + + } // end getAttribute + + /** + * Gets the value of an attribute on an Element. + * + * @param elt The Element to retrieve the attribute from. + * @param namespace The namespace URI of the attribute to retrieve. + * @param attr_name The name of the attribute to retrieve. + * @return The attribute value. + * @exception com.silverwrist.util.xml.XMLLoadException If the attribute did not exist on the element. + */ + public final String getAttributeNS(Element elt, String namespace, String attr_name) throws XMLLoadException + { + String rc = elt.getAttributeNS(namespace,attr_name); + if (!(StringUtils.isEmpty(rc))) + return rc; + throw new XMLLoadException("no " + namespace + ":" + attr_name + "= attribute found",elt); + + } // end getAttributeNS + + /** + * Gets the value of an attribute on an Element. + * + * @param elt The Element to retrieve the attribute from. + * @param namespace The namespace URI of the attribute to retrieve. + * @param attr_name The name of the attribute to retrieve. + * @param default_val The default value of the attribute. + * @return The attribute value, or the value of default_val if the attribute didn't exist. + */ + public final String getAttributeNS(Element elt, String namespace, String attr_name, String default_val) + { + String rc = elt.getAttributeNS(namespace,attr_name); + return (StringUtils.isEmpty(rc) ? default_val : rc); + + } // end getAttributeNS + + /** + * Gets the value of an attribute on an Element, expressed as an integer. + * + * @param elt The Element to retrieve the attribute from. + * @param attr_name The name of the attribute to retrieve. + * @return The attribute value. + * @exception com.silverwrist.util.xml.XMLLoadException If the attribute did not exist on the element, or + * it could not be parsed as an integer. + */ + public final int getAttributeInt(Element elt, String attr_name) throws XMLLoadException + { + String tmp = elt.getAttribute(attr_name); + if (StringUtils.isEmpty(tmp)) + { // the attribute is not present + throw new XMLLoadException("no " + attr_name + "= attribute found",elt); + + } // end if + + try + { // parse out the integer value + return Integer.parseInt(tmp.trim()); + + } // end try + catch (NumberFormatException nfe) + { // but it's not a valid integer - throw something else! + throw new XMLLoadException(attr_name + "= attribute value is not a valid integer",elt); + + } // end catch + + } // end getAttributeInt + + /** + * Gets the value of an attribute on an Element, expressed as an integer. + * + * @param elt The Element to retrieve the attribute from. + * @param attr_name The name of the attribute to retrieve. + * @param default_val The default value of the attribute. + * @return The attribute value, or the value of default_val if the attribute didn't exist. + * @exception com.silverwrist.util.xml.XMLLoadException If the attribute could not be parsed as an integer. + */ + public final int getAttributeInt(Element elt, String attr_name, int default_val) throws XMLLoadException + { + String tmp = elt.getAttribute(attr_name); + if (StringUtils.isEmpty(tmp)) + return default_val; // the attribute is not present + + try + { // parse out the integer value + return Integer.parseInt(tmp.trim()); + + } // end try + catch (NumberFormatException nfe) + { // but it's not a valid integer - throw something else! + throw new XMLLoadException(attr_name + "= attribute value is not a valid integer",elt); + + } // end catch + + } // end getAttributeInt + + /** + * Gets the value of an attribute on an Element, expressed as an integer. + * + * @param elt The Element to retrieve the attribute from. + * @param namespace The namespace URI of the attribute to retrieve. + * @param attr_name The name of the attribute to retrieve. + * @return The attribute value. + * @exception com.silverwrist.util.xml.XMLLoadException If the attribute did not exist on the element, or + * it could not be parsed as an integer. + */ + public final int getAttributeIntNS(Element elt, String namespace, String attr_name) throws XMLLoadException + { + String tmp = elt.getAttributeNS(namespace,attr_name); + if (StringUtils.isEmpty(tmp)) + { // the attribute is not present + throw new XMLLoadException("no " + namespace + ":" + attr_name + "= attribute found",elt); + + } // end if + + try + { // parse out the integer value + return Integer.parseInt(tmp.trim()); + + } // end try + catch (NumberFormatException nfe) + { // but it's not a valid integer - throw something else! + throw new XMLLoadException(namespace + ":" + attr_name + "= attribute value is not a valid integer",elt); + + } // end catch + + } // end getAttributeIntNS + + /** + * Gets the value of an attribute on an Element, expressed as an integer. + * + * @param elt The Element to retrieve the attribute from. + * @param namespace The namespace URI of the attribute to retrieve. + * @param attr_name The name of the attribute to retrieve. + * @param default_val The default value of the attribute. + * @return The attribute value, or the value of default_val if the attribute didn't exist. + * @exception com.silverwrist.util.xml.XMLLoadException If the attribute could not be parsed as an integer. + */ + public final int getAttributeIntNS(Element elt, String namespace, String attr_name, int default_val) + throws XMLLoadException + { + String tmp = elt.getAttributeNS(namespace,attr_name); + if (StringUtils.isEmpty(tmp)) + return default_val; // the attribute is not present + + try + { // parse out the integer value + return Integer.parseInt(tmp.trim()); + + } // end try + catch (NumberFormatException nfe) + { // but it's not a valid integer - throw something else! + throw new XMLLoadException(namespace + ":" + attr_name + "= attribute value is not a valid integer",elt); + + } // end catch + + } // end getAttributeIntNS + + /** + * Gets the value of an attribute on an Element, expressed as a Boolean. Uses the Boolean string + * methods on {@link com.silverwrist.util.StringUtils StringUtils} to determine the state of the attribute value. + * + * @param elt The Element to retrieve the attribute from. + * @param attr_name The name of the attribute to retrieve. + * @return The attribute value. + * @exception com.silverwrist.util.xml.XMLLoadException If the attribute did not exist on the element, or + * it could not be parsed as a Boolean. + * @see com.silverwrist.util.StringUtils#isBooleanTrue(java.lang.String) + * @see com.silverwrist.util.StringUtils#isBooleanFalse(java.lang.String) + */ + public final boolean getAttributeBoolean(Element elt, String attr_name) + throws XMLLoadException + { + String tmp = elt.getAttribute(attr_name); + if (StringUtils.isEmpty(tmp)) + throw new XMLLoadException("no " + attr_name + "= attribute found",elt); + if (StringUtils.isBooleanTrue(tmp)) + return true; + if (StringUtils.isBooleanFalse(tmp)) + return false; + throw new XMLLoadException(attr_name + "= attribute value is not a valid Boolean",elt); + + } // end getAttributeBoolean + + /** + * Gets the value of an attribute on an Element, expressed as a Boolean. Uses the Boolean string + * methods on {@link com.silverwrist.util.StringUtils StringUtils} to determine the state of the attribute value. + * + * @param elt The Element to retrieve the attribute from. + * @param attr_name The name of the attribute to retrieve. + * @param default_val The default value of the attribute. + * @return The attribute value, or the value of default_val if the attribute didn't exist. + * @exception com.silverwrist.util.xml.XMLLoadException If the attribute could not be parsed as a Boolean. + * @see com.silverwrist.util.StringUtils#isBooleanTrue(java.lang.String) + * @see com.silverwrist.util.StringUtils#isBooleanFalse(java.lang.String) + */ + public final boolean getAttributeBoolean(Element elt, String attr_name, boolean default_val) + throws XMLLoadException + { + String tmp = elt.getAttribute(attr_name); + if (StringUtils.isEmpty(tmp)) + return default_val; + if (StringUtils.isBooleanTrue(tmp)) + return true; + if (StringUtils.isBooleanFalse(tmp)) + return false; + throw new XMLLoadException(attr_name + "= attribute value is not a valid Boolean",elt); + + } // end getAttributeBoolean + + /** + * Gets the value of an attribute on an Element, expressed as a Boolean. Uses the Boolean string + * methods on {@link com.silverwrist.util.StringUtils StringUtils} to determine the state of the attribute value. + * + * @param elt The Element to retrieve the attribute from. + * @param namespace The namespace URI of the attribute to retrieve. + * @param attr_name The name of the attribute to retrieve. + * @param default_val The default value of the attribute. + * @return The attribute value, or the value of default_val if the attribute didn't exist. + * @exception com.silverwrist.util.xml.XMLLoadException If the attribute could not be parsed as a Boolean. + * @see com.silverwrist.util.StringUtils#isBooleanTrue(java.lang.String) + * @see com.silverwrist.util.StringUtils#isBooleanFalse(java.lang.String) + */ + public final boolean getAttributeBooleanNS(Element elt, String namespace, String attr_name, + boolean default_val) throws XMLLoadException + { + String tmp = elt.getAttributeNS(namespace,attr_name); + if (StringUtils.isEmpty(tmp)) + return default_val; + if (StringUtils.isBooleanTrue(tmp)) + return true; + if (StringUtils.isBooleanFalse(tmp)) + return false; + throw new XMLLoadException(namespace + ":" + attr_name + "= attribute value is not a valid Boolean",elt); + + } // end getAttributeBooleanNS + + /** + * Checks to make sure that the value of a given attribute is what we expect, and throws an + * {@link com.silverwrist.util.xml.XMLLoadException XMLLoadException} if it isn't. + * + * @param elt The Element to test the attribute of. + * @param attr_name The name of the attribute to test. + * @param attr_value The value to test the attribute against. + * @exception com.silverwrist.util.xml.XMLLoadException If the attribute does not exist, or its value does not match. + */ + public final void verifyAttributeValue(Element elt, String attr_name, String attr_value) + throws XMLLoadException + { + String tmp = this.getAttribute(elt,attr_name); + if (!(tmp.equals(attr_value))) + throw new XMLLoadException("attribute " + attr_name + "= should be '" + attr_value + "', but is '" + + tmp + "'",elt); + + } // end verifyAttributeValue + + /** + * Checks to make sure that the value of a given attribute is what we expect, and throws an + * {@link com.silverwrist.util.xml.XMLLoadException XMLLoadException} if it isn't. + * + * @param elt The Element to test the attribute of. + * @param namespace The namespace URI of the attribute to test. + * @param attr_name The name of the attribute to test. + * @param attr_value The value to test the attribute against. + * @exception com.silverwrist.util.xml.XMLLoadException If the attribute does not exist, or its value does not match. + */ + public final void verifyAttributeValueNS(Element elt, String namespace, String attr_name, String attr_value) + throws XMLLoadException + { + String tmp = this.getAttributeNS(elt,namespace,attr_name); + if (!(tmp.equals(attr_value))) + throw new XMLLoadException("attribute " + namespace + ":" + attr_name + "= should be '" + attr_value + + "', but is '" + tmp + "'",elt); + + } // end verifyAttributeValueNS + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + /** + * Gets the Singleton instance of the XMLLoader object. + * + * @return The Singleton instance of the XMLLoader object. + */ + public static final synchronized XMLLoader get() + { + if (self==null) + self = new XMLLoader(); + return self; + + } // end get + +} // end class XMLLoader diff --git a/src/dynamo-framework/com/silverwrist/dynamo/BrowserFlag.java b/src/dynamo-framework/com/silverwrist/dynamo/BrowserFlag.java new file mode 100644 index 0000000..691856f --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/BrowserFlag.java @@ -0,0 +1,189 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo; + +import java.util.*; +import org.apache.commons.lang.enum.*; + +/** + * A type-safe enumerated type that indicates the capabilities of a browser. These objects are returned + * in a set by the {@link com.silverwrist.dynamo.iface.BrowserData#getBrowserFlags() BrowserData.getBrowserFlags()} + * method. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public final class BrowserFlag extends Enum +{ + /*-------------------------------------------------------------------------------- + * The actual enumeration values + *-------------------------------------------------------------------------------- + */ + + /** + * Indicates that the browser supports frames (the <FRAMESET> and <FRAME> tags). + */ + public static final BrowserFlag FRAMES = new BrowserFlag("FRAMES"); + + /** + * Indicates that the browser supports in-line frames (the <IFRAME> tag). + */ + public static final BrowserFlag IFRAMES = new BrowserFlag("IFRAMES"); + + /** + * Indicates that the browser supports tables. + */ + public static final BrowserFlag TABLES = new BrowserFlag("TABLES"); + + /** + * Indicates that the browser supports cookies. + */ + public static final BrowserFlag COOKIES = new BrowserFlag("COOKIES"); + + /** + * Indicates that the browser supports background sounds (the <BGSOUND> tag). + */ + public static final BrowserFlag BACKGROUND_SOUNDS = new BrowserFlag("BACKGROUND_SOUNDS"); + + /** + * Indicates that the browser supports client-side scripting using Visual Basic Script. + */ + public static final BrowserFlag VBSCRIPT = new BrowserFlag("VBSCRIPT"); + + /** + * Indicates that the browser supports client-side scripting using JavaScript (JScript). + */ + public static final BrowserFlag JAVASCRIPT = new BrowserFlag("JAVASCRIPT"); + + /** + * Indicates that the browser supports client-side Java applets. + */ + public static final BrowserFlag JAVA_APPLETS = new BrowserFlag("JAVA_APPLETS"); + + /** + * Indicates that the browser supports client-side ActiveX controls. + */ + public static final BrowserFlag ACTIVEX_CONTROLS = new BrowserFlag("ACTIVEX_CONTROLS"); + + /** + * Indicates that the browser supports CDF. + */ + public static final BrowserFlag CDF = new BrowserFlag("CDF"); + + /** + * Indicates that this browser is an America Online client. + */ + public static final BrowserFlag AOL = new BrowserFlag("AOL"); + + /** + * Indicates that this browser is a beta version. + */ + public static final BrowserFlag BETA = new BrowserFlag("BETA"); + + /** + * Indicates that the browser is running on a 16-bit Windows operating system. + */ + public static final BrowserFlag WIN16 = new BrowserFlag("WIN16"); + + /** + * Indicates that this browser is not a browser at all, but a "crawler," which may be used to index the + * site's content by a search engine, or for other (nefarious) purposes. + */ + public static final BrowserFlag CRAWLER = new BrowserFlag("CRAWLER"); + + /** + * Indicates that this browser is not a browser at all, but a "stripper," which is copying the HTML of the + * site to another location. This may or may not be benign. + */ + public static final BrowserFlag STRIPPER = new BrowserFlag("STRIPPER"); + + /** + * Indicates that the browser is a cellphone or other handheld device, possibly supporting + * Wireless Access Protocol (WAP). + */ + public static final BrowserFlag WAP = new BrowserFlag("WAP"); + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Internal constructor which creates a new element of this enumerated type. + * + * @param name The name of the BrowserFlag to be created. + */ + private BrowserFlag(String name) + { + super(name); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Standard static method implementations + *-------------------------------------------------------------------------------- + */ + + /** + * Gets a BrowserFlag by name. + * + * @param name The name of the BrowserFlag to get; may be null. + * @return The BrowserFlag object, or null if the BrowserFlag does not exist. + */ + public static BrowserFlag getEnum(String name) + { + return (BrowserFlag)getEnum(BrowserFlag.class,name); + + } // end getEnum + + /** + * Gets the Map of BrowserFlag objects by name. + * + * @return The BrowserFlag object Map. + */ + public static Map getEnumMap() + { + return getEnumMap(BrowserFlag.class); + + } // end getEnumMap + + /** + * Gets the List of BrowserFlag objects, in the order in which the objects are listed + * in the code above. + * + * @return The BrowserFlag object List. + */ + public static List getEnumList() + { + return getEnumList(BrowserFlag.class); + + } // end getEnumList + + /** + * Gets an iterator over all BrowserFlag objects, in the order in which the objects are listed + * in the code above. + * + * @return The BrowserFlag object iterator. + */ + public static Iterator iterator() + { + return iterator(BrowserFlag.class); + + } // end iterator + +} // end class BrowserFlag diff --git a/src/dynamo-framework/com/silverwrist/dynamo/DynamoVersion.java b/src/dynamo-framework/com/silverwrist/dynamo/DynamoVersion.java new file mode 100644 index 0000000..b5a3744 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/DynamoVersion.java @@ -0,0 +1,33 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo; + +/** + * Class that holds the Dynamo version number. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public final class DynamoVersion +{ + /** + * The current version number of the Dynamo framework. + */ + public static final String VERSION = "0.05"; + +} // end class DynamoVersion diff --git a/src/dynamo-framework/com/silverwrist/dynamo/HttpStatusCode.java b/src/dynamo-framework/com/silverwrist/dynamo/HttpStatusCode.java new file mode 100644 index 0000000..68d09cd --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/HttpStatusCode.java @@ -0,0 +1,482 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo; + +import java.util.*; +import org.apache.commons.lang.enum.*; +import javax.servlet.http.HttpServletResponse; + +/** + * A type-safe enumerated type that encapsulates the HTTP status codes. We use an enumerated type here + * so that it can be extended to support additional status codes (the ones defined, say, by WebDAV) + * without affecting HttpServletResponse. + *

The descriptions of the status codes are taken from the HTTP 1.1 Specification, + * RFC 2616. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class HttpStatusCode extends ValuedEnum +{ + /*-------------------------------------------------------------------------------- + * The actual enumeration values + *-------------------------------------------------------------------------------- + */ + + // N.B.: We copy the status codes here to allow extending them independent of the codes + // listed in HttpServletResponse, but we point to the originals in HttpServletResponse + // to maintain compatibility. + + /** + * 100 Continue. The client SHOULD continue with its request. This interim response is used to + * inform the client that the initial part of the request has been received and has not yet been rejected + * by the server. The client SHOULD continue by sending the remainder of the request or, if the request + * has already been completed, ignore this response. The server MUST send a final response after the + * request has been completed. + */ + public static final HttpStatusCode I_CONTINUE = + new HttpStatusCode("I_CONTINUE",HttpServletResponse.SC_CONTINUE); + + /** + * 101 Switching Protocols. The server understands and is willing to comply with the client's request, + * via the Upgrade message header field, for a change in the application protocol being used on this connection. + * The server will switch protocols to those defined by the response's Upgrade header field immediately after + * the empty line which terminates the 101 response. + */ + public static final HttpStatusCode I_SWITCH = + new HttpStatusCode("I_SWITCH",HttpServletResponse.SC_SWITCHING_PROTOCOLS); + + /** + * 200 OK. The request has succeeded. The information returned with the response is dependent on + * the method used in the request. (Default status code) + */ + public static final HttpStatusCode S_OK = + new HttpStatusCode("S_OK",HttpServletResponse.SC_OK); + + /** + * 201 Created. The request has been fulfilled and resulted in a new resource being created. The + * newly created resource can be referenced by the URI(s) returned in the entity of the response, with + * the most specific URI for the resource given by a Location header field. The response SHOULD include + * an entity containing a list of resource characteristics and location(s) from which the user or user + * agent can choose the one most appropriate. The entity format is specified by the media type given in + * the Content-Type header field. The origin server MUST create the resource before returning the 201 + * status code. If the action cannot be carried out immediately, the server SHOULD respond with 202 + * (Accepted) response instead. + */ + public static final HttpStatusCode S_CREATED = + new HttpStatusCode("S_CREATED",HttpServletResponse.SC_CREATED); + + /** + * 202 Accepted. The request has been accepted for processing, but the processing has not been + * completed. The request might or might not eventually be acted upon, as it might be disallowed when + * processing actually takes place. + */ + public static final HttpStatusCode S_ACCEPTED = + new HttpStatusCode("S_ACCEPTED",HttpServletResponse.SC_ACCEPTED); + + /** + * 203 Non-Authoritative Information. The returned metainformation in the entity-header is not the + * definitive set as available from the origin server, but is gathered from a local or a third-party copy. + * The set presented MAY be a subset or superset of the original version. For example, including local + * annotation information about the resource might result in a superset of the metainformation known by + * the origin server. Use of this response code is not required and is only appropriate when the response + * would otherwise be 200 (OK). + */ + public static final HttpStatusCode S_NONAUTHORITATIVE = + new HttpStatusCode("S_NONAUTHORITATIVE",HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION); + + /** + * 204 No Content. The server has fulfilled the request but does not need to return an entity-body, + * and might want to return updated metainformation. The response MAY include new or updated metainformation + * in the form of entity-headers, which if present SHOULD be associated with the requested variant. If the + * client is a user agent, it SHOULD NOT change its document view from that which caused the request to be + * sent. This response is primarily intended to allow input for actions to take place without causing a + * change to the user agent's active document view, although any new or updated metainformation SHOULD be + * applied to the document currently in the user agent's active view. + */ + public static final HttpStatusCode S_NODATA = + new HttpStatusCode("S_NODATA",HttpServletResponse.SC_NO_CONTENT); + + /** + * 205 Reset Content. The server has fulfilled the request and the user agent SHOULD reset the document + * view which caused the request to be sent. This response is primarily intended to allow input for actions + * to take place via user input, followed by a clearing of the form in which the input is given so that the + * user can easily initiate another input action. + */ + public static final HttpStatusCode S_RESET = + new HttpStatusCode("S_RESET",HttpServletResponse.SC_RESET_CONTENT); + + /** + * 206 Partial Content. The server has fulfilled the partial GET request for the resource. The + * request MUST have included a Range header field indicating the desired range, and MAY have included + * an If-Range header field to make the request conditional. + */ + public static final HttpStatusCode S_PARTIAL = + new HttpStatusCode("S_PARTIAL",HttpServletResponse.SC_PARTIAL_CONTENT); + + /** + * 300 Multiple Choices. The requested resource corresponds to any one of a set of representations, + * each with its own specific location, and agent-driven negotiation information is being provided so that + * the user (or user agent) can select a preferred representation and redirect its request to that location. + */ + public static final HttpStatusCode S_CHOICE = + new HttpStatusCode("S_CHOICE",HttpServletResponse.SC_MULTIPLE_CHOICES); + + /** + * 301 Moved Permanently. The requested resource has been assigned a new permanent URI and any future + * references to this resource SHOULD use one of the returned URIs. Clients with link editing capabilities + * ought to automatically re-link references to the Request-URI to one or more of the new references returned + * by the server, where possible. + */ + public static final HttpStatusCode S_MOVED = + new HttpStatusCode("S_MOVED",HttpServletResponse.SC_MOVED_PERMANENTLY); + + /** + * 302 Moved Temporarily (Redirect). The requested resource resides temporarily under a different URI. + * Since the redirection might be altered on occasion, the client SHOULD continue to use the Request-URI for + * future requests. + */ + public static final HttpStatusCode S_REDIRECT = + new HttpStatusCode("S_REDIRECT",HttpServletResponse.SC_MOVED_TEMPORARILY); + + /** + * 303 See Other. The response to the request can be found under a different URI and SHOULD be + * retrieved using a GET method on that resource. This method exists primarily to allow the output of a + * POST-activated script to redirect the user agent to a selected resource. The new URI is not a + * substitute reference for the originally requested resource. + */ + public static final HttpStatusCode S_SEE_OTHER = + new HttpStatusCode("S_SEE_OTHER",HttpServletResponse.SC_SEE_OTHER); + + /** + * 304 Not Modified. If the client has performed a conditional GET request and access is allowed, + * but the document has not been modified, the server SHOULD respond with this status code. + */ + public static final HttpStatusCode S_NOTMODIFIED = + new HttpStatusCode("S_NOTMODIFIED",HttpServletResponse.SC_NOT_MODIFIED); + + /** + * 305 Use Proxy. The requested resource MUST be accessed through the proxy given by the Location + * field. The Location field gives the URI of the proxy. The recipient is expected to repeat this single + * request via the proxy. + */ + public static final HttpStatusCode S_USE_PROXY = + new HttpStatusCode("S_USEPROXY",HttpServletResponse.SC_USE_PROXY); + + /** + * 307 Temporary Redirect. The requested resource resides temporarily under a different URI. + * Since the redirection MAY be altered on occasion, the client SHOULD continue to use the Request-URI + * for future requests. + */ + public static final HttpStatusCode S_REDIRECT_TEMP = + new HttpStatusCode("S_REDIRECT_TEMP",HttpServletResponse.SC_TEMPORARY_REDIRECT); + + /** + * 400 Bad Request. The request could not be understood by the server due to malformed syntax. The + * client SHOULD NOT repeat the request without modifications. + */ + public static final HttpStatusCode E_BAD_REQUEST = + new HttpStatusCode("E_BAD_REQUEST",HttpServletResponse.SC_BAD_REQUEST); + + /** + * 401 Unauthorized. The request requires user authentication. The response MUST include a + * WWW-Authenticate header field containing a challenge applicable to the requested resource. The client + * MAY repeat the request with a suitable Authorization header field. If the request already included + * Authorization credentials, then the 401 response indicates that authorization has been refused for those + * credentials. If the 401 response contains the same challenge as the prior response, and the user agent + * has already attempted authentication at least once, then the user SHOULD be presented the entity that + * was given in the response, since that entity might include relevant diagnostic information. + */ + public static final HttpStatusCode E_AUTH = + new HttpStatusCode("E_AUTH",HttpServletResponse.SC_UNAUTHORIZED); + + /** + * 402 Payment Required. This code is reserved for future use. + */ + public static final HttpStatusCode E_PAYMENT = + new HttpStatusCode("E_PAYMENT",HttpServletResponse.SC_PAYMENT_REQUIRED); + + /** + * 403 Forbidden. The server understood the request, but is refusing to fulfill it. Authorization + * will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server + * wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the + * refusal in the entity. If the server does not wish to make this information available to the client, + * the status code 404 (Not Found) can be used instead. + */ + public static final HttpStatusCode E_FORBIDDEN = + new HttpStatusCode("E_FORBIDDEN",HttpServletResponse.SC_FORBIDDEN); + + /** + * 404 Not Found. The server has not found anything matching the Request-URI. No indication is given + * of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the + * server knows, through some internally configurable mechanism, that an old resource is permanently + * unavailable and has no forwarding address. This status code is commonly used when the server does not + * wish to reveal exactly why the request has been refused, or when no other response is applicable. + */ + public static final HttpStatusCode E_NOTFOUND = + new HttpStatusCode("E_NOTFOUND",HttpServletResponse.SC_NOT_FOUND); + + /** + * 405 Method Not Allowed. The method specified in the Request-Line is not allowed for the resource + * identified by the Request-URI. The response MUST include an Allow header containing a list of valid + * methods for the requested resource. + */ + public static final HttpStatusCode E_METHOD = + new HttpStatusCode("E_METHOD",HttpServletResponse.SC_METHOD_NOT_ALLOWED); + + /** + * 406 Not Acceptable. The resource identified by the request is only capable of generating response + * entities which have content characteristics not acceptable according to the accept headers sent in the request. + */ + public static final HttpStatusCode E_NOTACCEPTABLE = + new HttpStatusCode("E_NOTACCEPTABLE",HttpServletResponse.SC_NOT_ACCEPTABLE); + + /** + * 407 Proxy Authentication Required. This code is similar to 401 (Unauthorized), but indicates that + * the client must first authenticate itself with the proxy. The proxy MUST return a Proxy-Authenticate + * header field containing a challenge applicable to the proxy for the requested resource. The client MAY + * repeat the request with a suitable Proxy-Authorization header field. + */ + public static final HttpStatusCode E_PROXY_AUTH = + new HttpStatusCode("E_PROXY_AUTH",HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED); + + /** + * 408 Request Timeout. The client did not produce a request within the time that the server was + * prepared to wait. The client MAY repeat the request without modifications at any later time. + */ + public static final HttpStatusCode E_TIMEOUT = + new HttpStatusCode("E_TIMEOUT",HttpServletResponse.SC_REQUEST_TIMEOUT); + + /** + * 409 Conflict. The request could not be completed due to a conflict with the current state of the + * resource. This code is only allowed in situations where it is expected that the user might be able to + * resolve the conflict and resubmit the request. The response body SHOULD include enough information for + * the user to recognize the source of the conflict. Ideally, the response entity would include enough + * information for the user or user agent to fix the problem; however, that might not be possible and is + * not required. + */ + public static final HttpStatusCode E_CONFLICT = + new HttpStatusCode("E_CONFLICT",HttpServletResponse.SC_CONFLICT); + + /** + * 410 Gone. The requested resource is no longer available at the server and no forwarding address + * is known. This condition is expected to be considered permanent. Clients with link editing capabilities + * SHOULD delete references to the Request-URI after user approval. If the server does not know, or has no + * facility to determine, whether or not the condition is permanent, the status code 404 (Not Found) SHOULD + * be used instead. + */ + public static final HttpStatusCode E_GONE = + new HttpStatusCode("E_GONE",HttpServletResponse.SC_GONE); + + /** + * 411 Length Required. The server refuses to accept the request without a defined Content-Length. + * The client MAY repeat the request if it adds a valid Content-Length header field containing the length + * of the message-body in the request message. + */ + public static final HttpStatusCode E_NOLENGTH = + new HttpStatusCode("E_NOLENGTH",HttpServletResponse.SC_LENGTH_REQUIRED); + + /** + * 412 Precondition Failed. The precondition given in one or more of the request-header fields + * evaluated to false when it was tested on the server. This response code allows the client to place + * preconditions on the current resource metainformation (header field data) and thus prevent the + * requested method from being applied to a resource other than the one intended. + */ + public static final HttpStatusCode E_PRECONDITION = + new HttpStatusCode("E_PRECONDITION",HttpServletResponse.SC_PRECONDITION_FAILED); + + /** + * 413 Request Entity Too Large. The server is refusing to process a request because the request + * entity is larger than the server is willing or able to process. The server MAY close the connection to + * prevent the client from continuing the request. If the condition is temporary, the server SHOULD include + * a Retry-After header field to indicate that it is temporary and after what time the client MAY try again. + */ + public static final HttpStatusCode E_ENTITYTOOBIG = + new HttpStatusCode("E_ENTITYTOOBIG",HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE); + + /** + * 414 Request URI Too Long. The server is refusing to service the request because the Request-URI is + * longer than the server is willing to interpret. This rare condition is only likely to occur when a client + * has improperly converted a POST request to a GET request with long query information, when the client has + * descended into a URI "black hole" of redirection (e.g., a redirected URI prefix that points to a suffix of + * itself), or when the server is under attack by a client attempting to exploit security holes present in + * some servers using fixed-length buffers for reading or manipulating the Request-URI. + */ + public static final HttpStatusCode E_URITOOLONG = + new HttpStatusCode("E_URITOOLONG",HttpServletResponse.SC_REQUEST_URI_TOO_LONG); + + /** + * 415 Media Type Not Supported. The server is refusing to service the request because the entity of + * the request is in a format not supported by the requested resource for the requested method. + */ + public static final HttpStatusCode E_BAD_TYPE = + new HttpStatusCode("E_BAD_TYPE",HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); + + /** + * 416 Requested Range Not Satisfiable. A server SHOULD return a response with this status code if + * a request included a Range request-header field, and none of the range-specifier values in this field + * overlap the current extent of the selected resource, and the request did not include an If-Range + * request-header field. (For byte-ranges, this means that the first-byte-pos of all of the byte-range-spec + * values were greater than the current length of the selected resource.) When this status code is returned + * for a byte-range request, the response SHOULD include a Content-Range entity-header field specifying the + * current length of the selected resource. This response MUST NOT use the multipart/byteranges content-type. + */ + public static final HttpStatusCode E_BAD_RANGE = + new HttpStatusCode("E_BAD_RANGE",HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); + + /** + * 417 Expectation Failed. The expectation given in an Expect request-header field could not be met by + * this server, or, if the server is a proxy, the server has unambiguous evidence that the request could not + * be met by the next-hop server. + */ + public static final HttpStatusCode E_EXPECTATION = + new HttpStatusCode("E_EXPECTATION",HttpServletResponse.SC_EXPECTATION_FAILED); + + /** + * 500 Internal Server Error. The server encountered an unexpected condition which prevented it + * from fulfilling the request. + */ + public static final HttpStatusCode E_INTERNAL = + new HttpStatusCode("E_INTERNAL",HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + + /** + * 501 Not Implemented. The server does not support the functionality required to fulfill the request. + * This is the appropriate response when the server does not recognize the request method and is not capable + * of supporting it for any resource. + */ + public static final HttpStatusCode E_NOTIMPL = + new HttpStatusCode("E_NOTIMPL",HttpServletResponse.SC_NOT_IMPLEMENTED); + + /** + * 502 Bad Gateway. The server, while acting as a gateway or proxy, received an invalid response from + * the upstream server it accessed in attempting to fulfill the request. + */ + public static final HttpStatusCode E_BAD_GATEWAY = + new HttpStatusCode("E_BAD_GATEWAY",HttpServletResponse.SC_BAD_GATEWAY); + + /** + * 503 Service Unavailable. The server is currently unable to handle the request due to a temporary + * overloading or maintenance of the server. The implication is that this is a temporary condition which will + * be alleviated after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. + * If no Retry-After is given, the client SHOULD handle the response as it would for a 500 response. + */ + public static final HttpStatusCode E_UNAVAILABLE = + new HttpStatusCode("E_UNAVAILABLE",HttpServletResponse.SC_SERVICE_UNAVAILABLE); + + /** + * 504 Gateway Timeout. The server, while acting as a gateway or proxy, did not receive a timely + * response from the upstream server specified by the URI (e.g. HTTP, FTP, LDAP) or some other auxiliary + * server (e.g. DNS) it needed to access in attempting to complete the request. + */ + public static final HttpStatusCode E_GATEWAY_TIMEOUT = + new HttpStatusCode("E_GATEWAY_TIMEOUT",HttpServletResponse.SC_GATEWAY_TIMEOUT); + + /** + * 505 HTTP Version Not Supported. The server does not support, or refuses to support, the HTTP + * protocol version that was used in the request message. The server is indicating that it is unable or + * unwilling to complete the request using the same major version as the client, other than with this + * error message. The response SHOULD contain an entity describing why that version is not supported and + * what other protocols are supported by that server. + */ + public static final HttpStatusCode E_BAD_VERSION = + new HttpStatusCode("E_BAD_VERSION",HttpServletResponse.SC_HTTP_VERSION_NOT_SUPPORTED); + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Internal constructor which creates a new element of this enumerated type. + * + * @param name The name of the HttpStatusCode to be created. + * @param value The numeric value to assign to the HttpStatusCode. + */ + private HttpStatusCode(String name, int value) + { + super(name,value); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Standard static method implementations + *-------------------------------------------------------------------------------- + */ + + /** + * Gets a HttpStatusCode by name. + * + * @param name The name of the HttpStatusCode to get; may be null. + * @return The HttpStatusCode object, or null if the HttpStatusCode + * does not exist. + */ + public static HttpStatusCode getEnum(String name) + { + return (HttpStatusCode)getEnum(HttpStatusCode.class,name); + + } // end getEnum + + /** + * Gets a HttpStatusCode by numeric value. + * + * @param code The numeric value of the HttpStatusCode to get. + * @return The HttpStatusCode object, or null if the HttpStatusCode + * does not exist. + */ + public static HttpStatusCode getEnum(int code) + { + return (HttpStatusCode)getEnum(HttpStatusCode.class,code); + + } // end getEnum + + /** + * Gets the Map of HttpStatusCode objects by name. + * + * @return The HttpStatusCode object Map. + */ + public static Map getEnumMap() + { + return getEnumMap(HttpStatusCode.class); + + } // end getEnumMap + + /** + * Gets the List of HttpStatusCode objects, in the order in which the objects are listed + * in the code above. + * + * @return The HttpStatusCode object List. + */ + public static List getEnumList() + { + return getEnumList(HttpStatusCode.class); + + } // end getEnumList + + /** + * Gets an iterator over all HttpStatusCode objects, in the order in which the objects are listed + * in the code above. + * + * @return The HttpStatusCode object iterator. + */ + public static Iterator iterator() + { + return iterator(HttpStatusCode.class); + + } // end iterator + +} // end class HttpStatusCode diff --git a/src/dynamo-framework/com/silverwrist/dynamo/Namespaces.java b/src/dynamo-framework/com/silverwrist/dynamo/Namespaces.java new file mode 100644 index 0000000..99c9f53 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/Namespaces.java @@ -0,0 +1,77 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo; + +/** + * Contains various namespaces which are used to designate objects in the global + * {@link com.silverwrist.dynamo.iface.ObjectProvider ObjectProvider} and other contexts. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public interface Namespaces +{ + /** + * Namespace used for objects provided by the application substrate object. + */ + public static final String SUBSTRATE_NAMESPACE = + "http://www.silverwrist.com/NS/dynamo/2002/11/29/substrate.objects"; + + /** + * Namespace used to retrieve servlet initialization parameters. + */ + public static final String SERVLET_INIT_NAMESPACE = + "http://www.silverwrist.com/NS/dynamo/2002/12/22/servlet.init.params"; + + /** + * Namespace used to retrieve servlet context initialization parameters. + */ + public static final String SERVLET_CONTEXT_NAMESPACE = + "http://www.silverwrist.com/NS/dynamo/2002/12/22/servlet.context.params"; + + /** + * Namespace under which the database connections are stored. + */ + public static final String DATABASE_CONNECTIONS_NAMESPACE = + "http://www.silverwrist.com/NS/dynamo/2002/12/08/database.connections"; + + /** + * Namespace under which the Dynamo objects are stored. + */ + public static final String DYNAMO_OBJECT_NAMESPACE = + "http://www.silverwrist.com/NS/dynamo/2002/12/07/dynamo.objects"; + + /** + * Namespace under which the Dynamo application-level objects are stored. + */ + public static final String DYNAMO_APPLICATION_NAMESPACE = + "http://www.silverwrist.com/NS/dynamo/2002/12/08/dynamo.application"; + + /** + * Namespace used to retrieve user information for mail messages. + */ + public static final String DYNAMO_USER_INFO_NAMESPACE = + "http://www.silverwrist.com/NS/dynamo/2002/12/13/user.information"; + + /** + * Namespace used to designate group permissions. + */ + public static final String GROUP_PERMISSIONS_NAMESPACE = + "http://www.silverwrist.com/NS/dynamo/2002/12/27/group.permissions"; + +} // end interface Namespaces diff --git a/src/dynamo-framework/com/silverwrist/dynamo/RequestType.java b/src/dynamo-framework/com/silverwrist/dynamo/RequestType.java new file mode 100644 index 0000000..1b954d2 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/RequestType.java @@ -0,0 +1,142 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo; + +import java.util.*; +import org.apache.commons.lang.enum.*; + +/** + * A type-safe enumerated type that indicates the type of a {@link com.silverwrist.dynamo.iface.Request Request} + * that comes in from the framework. It is also used to indicate the type of a + * {@link com.silverwrist.dynamo.iface.SessionInfo SessionInfo} object. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public final class RequestType extends Enum +{ + /*-------------------------------------------------------------------------------- + * The actual enumeration values + *-------------------------------------------------------------------------------- + */ + + /** + * A "null" request type, only used to label certain sessions. + * + * @see com.silverwrist.dynamo.util.NullSessionInfo + */ + public static final RequestType _NULL = new RequestType("_NULL"); + + /** + * This RequestType is used to label the {@link com.silverwrist.dynamo.iface.Request Request} passed + * along with the event that is fired when the application starts up. + * + * @see com.silverwrist.dynamo.event.ApplicationEvent + */ + public static final RequestType _APPLICATION = new RequestType("_APPLICATION"); + + /** + * This RequestType is used to label the {@link com.silverwrist.dynamo.iface.Request Request} passed + * along with the event that is fired when a new session is created. + * + * @see com.silverwrist.dynamo.event.SessionInfoEvent + */ + public static final RequestType _SESSION = new RequestType("_SESSION"); + + /** + * Designates a {@link com.silverwrist.dynamo.iface.Request Request} or + * {@link com.silverwrist.dynamo.iface.SessionInfo SessionInfo} associated with standard HTTP requests. + */ + public static final RequestType HTTP = new RequestType("HTTP"); + + /** + * Designates a {@link com.silverwrist.dynamo.iface.Request Request} or + * {@link com.silverwrist.dynamo.iface.SessionInfo SessionInfo} associated with XML-RPC requests, usually + * transmitted over HTTP. + */ + public static final RequestType XMLRPC = new RequestType("XMLRPC"); + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Internal constructor which creates a new element of this enumerated type. + * + * @param name The name of the RequestType to be created. + */ + private RequestType(String name) + { + super(name); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Standard static method implementations + *-------------------------------------------------------------------------------- + */ + + /** + * Gets a RequestType by name. + * + * @param name The name of the RequestType to get; may be null. + * @return The RequestType object, or null if the RequestType does not exist. + */ + public static RequestType getEnum(String name) + { + return (RequestType)getEnum(RequestType.class,name); + + } // end getEnum + + /** + * Gets the Map of RequestType objects by name. + * + * @return The RequestType object Map. + */ + public static Map getEnumMap() + { + return getEnumMap(RequestType.class); + + } // end getEnumMap + + /** + * Gets the List of RequestType objects, in the order in which the objects are listed + * in the code above. + * + * @return The RequestType object List. + */ + public static List getEnumList() + { + return getEnumList(RequestType.class); + + } // end getEnumList + + /** + * Gets an iterator over all RequestType objects, in the order in which the objects are listed + * in the code above. + * + * @return The RequestType object iterator. + */ + public static Iterator iterator() + { + return iterator(RequestType.class); + + } // end iterator + +} // end class RequestType diff --git a/src/dynamo-framework/com/silverwrist/dynamo/UserInfoNamespace.java b/src/dynamo-framework/com/silverwrist/dynamo/UserInfoNamespace.java new file mode 100644 index 0000000..7156b06 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/UserInfoNamespace.java @@ -0,0 +1,64 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo; + +/** + * Describes the attributes used by the Dynamo mail component to retrieve user information. Also contains + * the name for the default authenticator and default user permissons. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public interface UserInfoNamespace +{ + /** + * The property namespace that contains the user information. + */ + public static final String NAMESPACE = Namespaces.DYNAMO_USER_INFO_NAMESPACE; + + /** + * Property name designating the user's full name. + */ + public static final String ATTR_FULLNAME = "full.name"; + + /** + * Property name designating the user E-mail address. + */ + public static final String ATTR_EMAIL_ADDRESS = "email.address"; + + /** + * Property name designating the numeric user ID. + */ + public static final String ATTR_ID = "user.id"; + + /** + * Property name designating the user name. + */ + public static final String ATTR_USERNAME = "user.name"; + + /** + * Used to designate the default hash password authenticator. + */ + public static final String AUTH_DEFAULT = "default.hash.password"; + + /** + * The permission that allows user information to be edited. + */ + public static final String PERM_EDIT_ALL = "edit.all"; + +} // end interface UserInfoNamespace diff --git a/src/dynamo-framework/com/silverwrist/dynamo/Verb.java b/src/dynamo-framework/com/silverwrist/dynamo/Verb.java new file mode 100644 index 0000000..a4ee2b1 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/Verb.java @@ -0,0 +1,132 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo; + +import java.util.*; +import org.apache.commons.lang.enum.*; + +/** + * A type-safe enumerated type that indicates the action of a {@link com.silverwrist.dynamo.iface.Request Request} + * that comes in from the framework. Verb objects correspond roughly to HTTP methods. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public final class Verb extends Enum +{ + /*-------------------------------------------------------------------------------- + * The actual enumeration values + *-------------------------------------------------------------------------------- + */ + + /** + * Indicates a request to delete a resource identified by a URI. Corresponds to HTTP DELETE method. + */ + public static final Verb DELETE = new Verb("DELETE"); // (standard) + + /** + * Indicates a request to retrieve a resource identified by a URI. Corresponds to HTTP GET method. + */ + public static final Verb GET = new Verb("GET"); // (standard) + + /** + * Indicates a request to interact with a resource identified by a URI. Corresponds to HTTP POST method. + * All XML-RPC requests use this verb. + */ + public static final Verb POST = new Verb("POST"); // (standard) + + /** + * Indicates a request to overwrite a resource identified by a URI. Corresponds to HTTP PUT method. + */ + public static final Verb PUT = new Verb("PUT"); // (standard) + + /** + * Indicates a request to get the last modification time of a resource identified by a URI. Often associated + * with a HTTP GET method. + */ + public static final Verb _LASTMOD = new Verb("_LASTMOD"); // extended for getLastModified + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Internal constructor which creates a new element of this enumerated type. + * + * @param name The name of the Verb to be created. + */ + private Verb(String name) + { + super(name); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Standard static method implementations + *-------------------------------------------------------------------------------- + */ + + /** + * Gets a Verb by name. + * + * @param name The name of the Verb to get; may be null. + * @return The Verb object, or null if the Verb does not exist. + */ + public static Verb getEnum(String name) + { + return (Verb)getEnum(Verb.class,name); + + } // end getEnum + + /** + * Gets the Map of Verb objects by name. + * + * @return The Verb object Map. + */ + public static Map getEnumMap() + { + return getEnumMap(Verb.class); + + } // end getEnumMap + + /** + * Gets the List of Verb objects, in the order in which the objects are listed + * in the code above. + * + * @return The Verb object List. + */ + public static List getEnumList() + { + return getEnumList(Verb.class); + + } // end getEnumList + + /** + * Gets an iterator over all Verb objects, in the order in which the objects are listed + * in the code above. + * + * @return The Verb object iterator. + */ + public static Iterator iterator() + { + return iterator(Verb.class); + + } // end iterator + +} // end class Verb diff --git a/src/dynamo-framework/com/silverwrist/dynamo/WebConstants.java b/src/dynamo-framework/com/silverwrist/dynamo/WebConstants.java new file mode 100644 index 0000000..fc173ba --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/WebConstants.java @@ -0,0 +1,134 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo; + +/** + * Contains the names of various application, session, and request attributes and initialization parameters + * used by the Dynamo servlet interface. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public interface WebConstants +{ + /** + * Prefix for all Dynamo-specific application (ServletContext) attributes. + */ + public static final String APPLICATION_PREFIX = "com.silverwrist.dynamo."; + + /** + * Application attribute that records whether or not logging has been initiated. + */ + public static final String LOGGING_ATTRIBUTE = APPLICATION_PREFIX + "LoggingStarted"; + + /** + * Application attribute that holds the Dynamo + * {@link com.silverwrist.dynamo.app.ApplicationContainer ApplicationContainer} object. + */ + public static final String APPLICATION_ATTRIBUTE = APPLICATION_PREFIX + "app.ApplicationContainer"; + + /** + * Application attribute used to store the {@link com.silverwrist.dynamo.iface.MIMETypeMapper MIMETypeMapper} + * object created to tap into the servlet container's MIME type maps. + */ + public static final String SERVLET_MAPPER_ATTRIBUTE = APPLICATION_PREFIX + "servlet.MIMETypeMapper"; + + /** + * Servlet context initialization parameter that tells Dynamo where to find the logging configuration file. + */ + public static final String LOGGING_INIT_PARAM = "logging.config"; + + /** + * Servlet context initialization parameter that tells Dynamo where to find the Dynamo XML configuration file. + */ + public static final String CONFIG_INIT_PARAM = "dynamo.config"; + + /** + * Prefix for all Dynamo-specific session (HttpSession) attributes. + */ + public static final String SESSION_PREFIX = "com.silverwrist.dynamo."; + + /** + * Session attribute used to store the HTTP-specific {@link com.silverwrist.dynamo.iface.SessionInfo SessionInfo} + * object. + */ + public static final String SESSION_PARAM = SESSION_PREFIX + "session"; + + /** + * Session attribute used to store the connection-specific + * {@link com.silverwrist.dynamo.iface.BrowserData BrowserData} object. + */ + public static final String SESSION_BROWSER_DATA_PARAM = SESSION_PREFIX + "browser.data"; + + /** + * Prefix for all Dynamo-specific request (ServletRequest) attributes. + */ + public static final String REQUEST_PREFIX = "com.silverwrist.dynamo."; + + /** + * Request attribute which stores the per-request + * {@link com.silverwrist.dynamo.iface.SessionInfoProvider SessionInfoProvider} object. + */ + public static final String REQUEST_SESSION_PROVIDER_ATTR = REQUEST_PREFIX + "session.provider"; + + /** + * Request attribute which contains a reference to a new HTTP session that must be initialized. + */ + public static final String REQUEST_SESSIONINIT_ATTR = REQUEST_PREFIX + "HTTPsession.init"; + + /** + * Request attribute which contains a reference to the connection-specific + * {@link com.silverwrist.dynamo.iface.BrowserData BrowserData} object. + */ + public static final String REQUEST_BROWSER_DATA_ATTR = REQUEST_PREFIX + "browser.data"; + + /** + * Request attribute which contains a reference to the set of all cookies currently defined + * on the connection. + */ + public static final String REQUEST_COOKIESET_ATTR = REQUEST_PREFIX + "browser.cookieset"; + + /** + * Request attribute containing a list of all new cookies set on the output, which cannot be set until + * the start of the output phase. + */ + public static final String REQUEST_NEWCOOKIEHOLDER_ATTR = REQUEST_PREFIX + "browser.NewCookieHolder"; + + /** + * Request attribute containing a list of all new headers set on the output, which cannot be set until + * the start of the output phase. + */ + public static final String REQUEST_NEWHEADERHOLDER_ATTR = REQUEST_PREFIX + "servlet.NewHeaderHolder"; + + /** + * Request attribute containing a backreference to the {@link com.silverwrist.dynamo.iface.Request Request} + * object for the current request. + */ + public static final String REQUEST_SELF_ATTR = REQUEST_PREFIX + "request.self"; + + /** + * The HTTP header which requests a page only if it's been modified since a specific time. + */ + public static final String HDR_IF_MODIFIED_SINCE = "If-Modified-Since"; + + /** + * The HTTP header which returns when a page was last modified. + */ + public static final String HDR_LAST_MODIFIED = "Last-Modified"; + +} // end interface WebConstants diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/ApplicationContainer.java b/src/dynamo-framework/com/silverwrist/dynamo/app/ApplicationContainer.java new file mode 100644 index 0000000..436ab23 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/ApplicationContainer.java @@ -0,0 +1,1292 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import org.apache.commons.collections.*; +import org.apache.log4j.Logger; +import org.w3c.dom.*; +import com.silverwrist.util.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.DynamoVersion; +import com.silverwrist.dynamo.Namespaces; +import com.silverwrist.dynamo.event.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.script.ScriptController; +import com.silverwrist.dynamo.util.*; + +/** + * The main "engine" class of the Dynamo framework, which holds most of the service providers and other + * classes registered (usually by the defined {@link com.silverwrist.dynamo.iface.Application Application} class). + * Exactly one of these is created per Dynamo instance; for Dynamo Web applications, a reference to it is saved + * in the servlet context attributes. It is also responsible for reading and parsing the Dynamo XML configuration + * file and instantiating components defined therein. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class ApplicationContainer + implements ResourceProvider, ResourceProviderManager, RendererRegistration, ObjectProvider, + EventListenerRegistration, OutputObjectFilterRegistration, QueryRenderer, PostDynamicUpdate, + RenderImmediate, RequestPreprocessorRegistration, ExceptionTranslatorRegistration +{ + /*-------------------------------------------------------------------------------- + * Internal class recording renderer registrations and providing a + * "shutdown hook" + *-------------------------------------------------------------------------------- + */ + + private class RegisteredRenderer implements ComponentShutdown + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private Renderer m_renderer; + private HashSet m_known_classes; + + /*==================================================================== + * Constructors + *==================================================================== + */ + + RegisteredRenderer(Class klass, Renderer renderer) + { + m_renderer = renderer; + m_known_classes = new HashSet(); + m_known_classes.add(klass); + + } // end constructor + + RegisteredRenderer(DynamicClass dclass, Renderer renderer) + { + m_renderer = renderer; + m_known_classes = new HashSet(); + m_known_classes.add(dclass); + + } // end constructor + + /*==================================================================== + * Implementations from interface ComponentShutdown + *==================================================================== + */ + + public synchronized void shutdown() + { + Iterator it = m_known_classes.iterator(); + while (it.hasNext()) + { // remove all class rendering entries registered with this "event" + Object obj = it.next(); + if (obj instanceof Class) + m_class_renderers.remove(obj); + else if (obj instanceof DynamicClass) + m_class_renderers.remove(obj); + + } // end while + + m_known_classes.clear(); + + } // end shutdown + + /*==================================================================== + * External operations + *==================================================================== + */ + + public Renderer getRenderer() + { + return m_renderer; + + } // end getRenderer + + public synchronized void add(Class klass) + { + m_known_classes.add(klass); + + } // end add + + public synchronized void add(DynamicClass dclass) + { + m_known_classes.add(dclass); + + } // end add + + } // end class RegisteredRenderer + + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(ApplicationContainer.class); + + private static final String[] SUBSTRATE_MAP_KEYS = + { ApplicationSubstrate.OBJ_BASE_PATH, ApplicationSubstrate.OBJ_CODE_PATH, + ApplicationSubstrate.OBJ_CLASSES_PATH, ApplicationSubstrate.OBJ_LIBS_PATH + }; + + private static final ApplicationListener[] APP_LISTENER_TEMPLATE = new ApplicationListener[0]; + private static final SessionInfoListener[] SESSION_LISTENER_TEMPLATE = new SessionInfoListener[0]; + + private static final String TEMPLATE_CLASSNAME = "$$$BLORT$$$"; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private int m_refs; // reference count + private ApplicationSubstrate m_substrate; // application substrate object + private File m_resource_base; // base directory for resources + private Vector m_resource_providers = new Vector(); // resource providers + private LinkedList m_shutdown_list = new LinkedList(); // list of objects to shut down + private HashMap m_connections = new HashMap(); // list of connection pools + private HashMap m_objects = new HashMap(); // list of base objects + private Application m_application = null; // the application object + private Hashtable m_class_renderers = new Hashtable(); // renderers for static classes + private Hashtable m_dclass_renderers = new Hashtable(); // renderers for dynamic classes + private Vector m_application_listeners = new Vector(); // application event listeners + private Vector m_session_listeners = new Vector(); // session event listeners + private BackgroundProcessor m_background; // background processor + private ScriptController m_script_ctrl; // script controller + private ApplicationServiceManager m_app_sm; // application service manager + private PropertySerializationSupport m_pss; // property serialization support + private Set m_known_sessions; // known sessions + private String m_identity; // server identity + private Map m_rewrite_rules; // URL rewriting rules + private Vector m_output_filters = new Vector(); // output filters + private HashMap m_update_listeners = new HashMap(); // update listeners + private Vector m_request_preprocessors = new Vector(); // request preprocessors + private Vector m_exception_xlators = new Vector(); // exception translators + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Creates the application container. + * + * @param config_file A reference to the Dynamo XML configuration file. + * @param substrate A reference to the {@link com.silverwrist.dynamo.iface.ApplicationSubstrate ApplicationSubstrate} + * object, which provides certain services and object references to the + * ApplicationContainer. (Usually, this will be specific to the Dynamo application + * type, for example, Web application.) + * @exception com.silverwrist.dynamo.except.ConfigException If there is an error in the configuration which will + * not allow Dynamo to be initialized. + */ + public ApplicationContainer(File config_file, ApplicationSubstrate substrate) throws ConfigException + { + if (logger.isDebugEnabled()) + logger.debug("new ApplicationContainer - config file is " + config_file.getAbsolutePath()); + substrate.initialize(); + m_substrate = substrate; + m_refs = 1; + m_app_sm = new ApplicationServiceManager(); + m_pss = new PropertySerializationSupport(); + m_known_sessions = Collections.synchronizedSet(new HashSet()); + XMLLoader loader = XMLLoader.get(); + + // Initialize the init services and runtime services with defaults. + m_app_sm.addInitService(ResourceProvider.class,(ResourceProvider)this); + m_app_sm.addInitService(ResourceProviderManager.class,(ResourceProviderManager)this); + m_app_sm.addInitService(RendererRegistration.class,(RendererRegistration)this); + m_app_sm.addInitService(ObjectProvider.class,(ObjectProvider)this); + m_app_sm.addInitService(EventListenerRegistration.class,(EventListenerRegistration)this); + m_app_sm.addInitService(OutputObjectFilterRegistration.class,(OutputObjectFilterRegistration)this); + m_app_sm.addInitService(PropertySerializer.class,(PropertySerializer)m_pss); + m_app_sm.addInitService(PropertySerializerRegistration.class,(PropertySerializerRegistration)m_pss); + m_app_sm.addInitService(PostDynamicUpdate.class,(PostDynamicUpdate)this); + m_app_sm.addInitService(RequestPreprocessorRegistration.class,(RequestPreprocessorRegistration)this); + m_app_sm.addInitService(ExceptionTranslatorRegistration.class,(ExceptionTranslatorRegistration)this); + + m_app_sm.addRuntimeService(ResourceProvider.class,(ResourceProvider)this); + m_app_sm.addRuntimeService(ObjectProvider.class,(ObjectProvider)this); + m_app_sm.addRuntimeService(EventListenerRegistration.class,(EventListenerRegistration)this); + m_app_sm.addRuntimeService(PropertySerializer.class,(PropertySerializer)m_pss); + m_app_sm.addRuntimeService(PostDynamicUpdate.class,(PostDynamicUpdate)this); + m_app_sm.addRuntimeService(RenderImmediate.class,(RenderImmediate)this); + + m_app_sm.addOutputService(ResourceProvider.class,(ResourceProvider)this); + m_app_sm.addOutputService(ObjectProvider.class,(ObjectProvider)this); + m_app_sm.addOutputService(QueryRenderer.class,(QueryRenderer)this); + + // Create initialization services interface object. + ServiceProvider init_svcs = m_app_sm.createInitServices(); + + try + { // load the configuration file + Document config_doc = loader.load(config_file,false); + Element root = loader.getRootElement(config_doc,"configuration"); + + // get the element and process it + Element control = loader.getSubElement(root,"control"); + processControlSection(control); + m_shutdown_list.addFirst(m_background); + m_app_sm.addInitService(BackgroundScheduler.class,m_background); + m_app_sm.addRuntimeService(BackgroundScheduler.class,m_background); + + // initialize some default renderers + m_shutdown_list.addFirst(registerRenderer(DataItem.class,new DataItemRenderer())); + m_shutdown_list.addFirst(registerRenderer(java.util.List.class,new ListRenderer())); + + // initialize the scripting engine + m_script_ctrl = new ScriptController(); + m_script_ctrl.initialize(control,init_svcs); + m_shutdown_list.addFirst(m_script_ctrl); + + // add the scripting engine's services so they can be used by external components + m_app_sm.addInitService(ScriptEngineConfig.class,m_script_ctrl); + m_app_sm.addRuntimeService(ScriptExecute.class,m_script_ctrl); + + // get all database connection configurations + List l = loader.getMatchingSubElements(root,"dbconnection"); + Iterator it = l.iterator(); + Element elt; + while (it.hasNext()) + { // get each element in turn + elt = (Element)(it.next()); + DBConnectionPool pool = (DBConnectionPool)createNamedObject(elt,init_svcs,DBConnectionPool.class, + "no.notDBPool"); + m_connections.put(pool.getName(),pool); + + } // end while + + m_app_sm.addInitService(HookServiceProviders.class,m_app_sm); + + // Sort the "object" definitions by priority order to determine in what order to instantiate them. + l = loader.getMatchingSubElements(root,"object"); + if (!(l.isEmpty())) + { // copy elements into binary heap + it = l.iterator(); + BinaryHeap prioheap = new BinaryHeap(l.size()); + while (it.hasNext()) + { // sort elements by priority + elt = (Element)(it.next()); + prioheap.insert(new HeapContents(elt)); + + } // end while + + while (prioheap.size()>0) + { // now remove and instantiate the elements + HeapContents hc = (HeapContents)(prioheap.remove()); + NamedObject nobj = createNamedObject(hc.getElement(),init_svcs,null,null); + m_objects.put(nobj.getName(),nobj); + + } // end while + + } // end if + + // Find the application definition and initialize the application. + elt = loader.getSubElement(root,"application"); + m_application = (Application)createNamedObject(elt,init_svcs,Application.class,"no.notApp"); + + } // end try + catch (IOException e) + { // unable to read config file - send back a ConfigException + logger.fatal("ApplicationContainer config read failed",e); + ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages", + "creation.ioError",e); + ce.setParameter(0,config_file.getAbsolutePath()); + throw ce; + + } // end catch + catch (XMLLoadException e) + { // XML loader failed - send back a ConfigException + logger.fatal("ApplicationContainer config load failed",e); + throw new ConfigException(e); + + } // end catch + + // Create the "server identity" string. + StringBuffer buf = new StringBuffer(); + String app_id = m_application.getIdentity(); + if (app_id!=null) + buf.append(app_id).append(' '); + buf.append("Dynamo/").append(DynamoVersion.VERSION); + m_identity = buf.toString(); + logger.info("Server: " + m_identity); + + // Fire the "application initialized" events. + ApplicationListener[] listeners = + (ApplicationListener[])(m_application_listeners.toArray(APP_LISTENER_TEMPLATE)); + if (listeners.length>0) + { // call the event handlers... + if (logger.isDebugEnabled()) + logger.debug("ApplicationContainer: " + listeners.length + " init handler(s) to call"); + ApplicationEventRequest req = new ApplicationEventRequest(m_app_sm.createRuntimeServices(),true); + ApplicationEvent evt = new ApplicationEvent(req,m_application); + for (int i=0; iComponentInitialize associated with the object, or null + * if there is no such instance. + */ + private static final ComponentInitialize getComponentInitialize(Object obj) + { + if (obj instanceof ComponentInitialize) + return (ComponentInitialize)obj; + if (obj instanceof ServiceProvider) + { // it may be a service provider interface + try + { // look for ComponentInitialize as a service + ServiceProvider sp = (ServiceProvider)obj; + ComponentInitialize rc = (ComponentInitialize)(sp.queryService(ComponentInitialize.class)); + return rc; + + } // end try + catch (NoSuchServiceException e) + { // do nothing here + } // end catch + + } // end if + + return null; // no dice! + + } // end getComponentInitialize + + /** + * Finds an instance of the {@link com.silverwrist.dynamo.iface.ComponentShutdown ComponentShutdown} interface + * associated with the given object, either through implementation of the interface, or by querying its + * {@link com.silverwrist.dynamo.iface.ServiceProvider ServiceProvider} implementation. + * + * @param obj The object to be queried. + * @return The instance of ComponentShutdown associated with the object, or null + * if there is no such instance. + */ + private static final ComponentShutdown getComponentShutdown(Object obj) + { + if (obj instanceof ComponentShutdown) + return (ComponentShutdown)obj; + if (obj instanceof ServiceProvider) + { // it may be a service provider interface + try + { // look for ComponentShutdown as a service + ServiceProvider sp = (ServiceProvider)obj; + ComponentShutdown rc = (ComponentShutdown)(sp.queryService(ComponentShutdown.class)); + return rc; + + } // end try + catch (NoSuchServiceException e) + { // do nothing here + } // end catch + + } // end if + + return null; // no dice! + + } // end getComponentShutdown + + /** + * Destroys all data associated with this ApplicationContainer. + */ + private final synchronized void destroy() + { + if (logger.isDebugEnabled()) + logger.debug("ApplicationContainer.destroy(): " + m_known_sessions.size() + " sessions to shutdown"); + Iterator it = m_known_sessions.iterator(); + while (it.hasNext()) + { // shut down each session + ComponentShutdown cs = (ComponentShutdown)(it.next()); + cs.shutdown(); + + } // end while + + m_known_sessions.clear(); + + // Fire the "application exiting" events. + ApplicationListener[] listeners = + (ApplicationListener[])(m_application_listeners.toArray(APP_LISTENER_TEMPLATE)); + if (logger.isDebugEnabled()) + logger.debug("ApplicationContainer.destroy(): " + listeners.length + " exit handlers to call"); + if (listeners.length>0) + { // call the event handlers... + ApplicationEventRequest req = new ApplicationEventRequest(m_app_sm.createRuntimeServices(),false); + ApplicationEvent evt = new ApplicationEvent(req,m_application); + for (int i=0; i0) + { // shut down all components in reverse order of creation + ComponentShutdown sd = (ComponentShutdown)(m_shutdown_list.removeFirst()); + sd.shutdown(); + + } // end while + + if (logger.isDebugEnabled()) + logger.debug("ApplicationContainer.destroy(): clearing internal data structures"); + m_connections.clear(); + m_objects.clear(); + m_class_renderers.clear(); + m_dclass_renderers.clear(); + m_application = null; + m_resource_providers.clear(); + m_application_listeners.clear(); + m_session_listeners.clear(); + + if (logger.isDebugEnabled()) + logger.debug("ApplicationContainer.destroy(): terminating substrate"); + m_substrate.terminate(); + m_substrate = null; + + } // end destroy + + private final Map getSubstrateReplaceMap() + { + HashMap rc = new HashMap(); + for (int i=0; imax_munch) + { // found one that munches more...save it + wrp = tmp; + max_munch = test; + + } // end if + + } // end while + + } // end synchronized block + + return wrp; + + } // end locateResourceProvider + + private final InputStream getResourceInternal(ComponentResName crn) throws IOException + { + File res_file = new File(m_resource_base,crn.getStringValue(0,false)); + if (!(res_file.exists()) || res_file.isDirectory() || !(res_file.canRead())) + throw new NoSuchResourceException(crn.getStringValue(0,true)); + return new FileInputStream(res_file); + + } // end getResourceInternal + + private final long getResourceModTimeInternal(ComponentResName crn) + { + File res_file = new File(m_resource_base,crn.getStringValue(0,false)); + if (!(res_file.exists()) || res_file.isDirectory() || !(res_file.canRead())) + return 0; + return res_file.lastModified(); + + } // end getResourceModTimeInternal + + private final RegisteredRenderer searchDClassRenderers(DynamicClass dclass) + { + return (RegisteredRenderer)(m_dclass_renderers.get(dclass)); + + } // end searchDClassRenderer + + private final RegisteredRenderer searchArrayRenderers(Class klass, String template) + { + if (klass.isPrimitive() || (klass==Object.class)) + return null; // should have been picked up already + + // look at this level for the class member + RegisteredRenderer rc = null; + try + { // load the array class corresponding to the right depth, then check the renderer map + Class tmp = Class.forName(StringUtils.replace(template,TEMPLATE_CLASSNAME,klass.getName())); + rc = (RegisteredRenderer)(m_class_renderers.get(tmp)); + if (rc!=null) + return rc; + + } // end try + catch (ClassNotFoundException e) + { // this class was not found, so it can't be present + rc = null; + + } // end catch + + // Try all interfaces implemented by the object. + Class[] ifaces = klass.getInterfaces(); + for (int i=0; iObjectProvider. + * + * @param namespace The namespace to interpret the name relative to. + * @param name The name of the object to be retrieved. + * @return The object reference specified. + */ + public Object getObject(String namespace, String name) + { + if (namespace.equals(Namespaces.SUBSTRATE_NAMESPACE)) + return m_substrate.getObject(namespace,name); + + if (namespace.equals(Namespaces.DATABASE_CONNECTIONS_NAMESPACE)) + { // get a database connection + Object rc = m_connections.get(name); + if (rc!=null) + return rc; + + } // end if + + if (namespace.equals(Namespaces.DYNAMO_OBJECT_NAMESPACE)) + { // get an object + Object rc = m_objects.get(name); + if (rc!=null) + return rc; + + } // end if + + if (namespace.equals(Namespaces.DYNAMO_APPLICATION_NAMESPACE)) + { // return one of the application data elements + if (name.equals("application")) + return m_application; + else if (name.equals("identity")) + return m_identity; + else if (name.equals("__container__")) + return this; + + } // end if + + throw new NoSuchObjectException("ApplicationContainer",namespace,name); + + } // end getObject + + /*-------------------------------------------------------------------------------- + * Implementations from interface EventListenerRegistration + *-------------------------------------------------------------------------------- + */ + + public ComponentShutdown registerApplicationListener(ApplicationListener listener) + { + m_application_listeners.add(listener); + return new ShutdownVectorRemove(m_application_listeners,listener); + + } // end registerApplicationListener + + public ComponentShutdown registerSessionInfoListener(SessionInfoListener listener) + { + m_session_listeners.add(listener); + return new ShutdownVectorRemove(m_session_listeners,listener); + + } // end registerSessionInfoListener + + public synchronized ComponentShutdown registerDynamicUpdateListener(Class event_type, + DynamicUpdateListener listener) + { + if (!(DynamicUpdateEvent.class.isAssignableFrom(event_type))) + throw new IllegalArgumentException("event type is not valid"); + Vector vec = (Vector)(m_update_listeners.get(event_type)); + if (vec==null) + { // creatr vector for this event type + vec = new Vector(); + m_update_listeners.put(event_type,vec); + + } // end if + + vec.add(listener); + return new ShutdownVectorRemove(vec,listener); + + } // end registerDynamicUpdateListener + + /*-------------------------------------------------------------------------------- + * Implementations from interface OutputObjectFilterRegistration + *-------------------------------------------------------------------------------- + */ + + public ComponentShutdown registerOutputObjectFilter(OutputObjectFilter filter) + { + if (logger.isDebugEnabled()) + logger.debug("Registering new OutputObjectFilter: " + filter); + m_output_filters.add(filter); + return new ShutdownVectorRemove(m_output_filters,filter); + + } // end registerOutputObjectFilter + + /*-------------------------------------------------------------------------------- + * Implementations from interface QueryRenderer + *-------------------------------------------------------------------------------- + */ + + public Renderer getRendererForObject(Object obj) + { + RegisteredRenderer rc = null; + if (obj instanceof DynamicObject) + { // this is a dynamic object - search by its dynamic class first + DynamicClass dclass = ((DynamicObject)obj).getDClass(); + rc = (RegisteredRenderer)(m_dclass_renderers.get(dclass)); + if (rc==null) + { // search for ancestor class, "snap" reference if possible + rc = searchDClassRenderers(dclass); + if (rc!=null) + { // add this class to the mapping + m_dclass_renderers.put(dclass,rc); + rc.add(dclass); + + } // end if + + } // end if + + if (rc!=null) + return rc.getRenderer(); + + } // end if + + Class klass = obj.getClass(); + rc = (RegisteredRenderer)(m_class_renderers.get(klass)); + if (rc==null) + { // search for ancestor class, "snap" reference if possible + rc = searchClassRenderers(klass); + if (rc!=null) + { // found it - add this class to the mapping + m_class_renderers.put(klass,rc); + rc.add(klass); + + } // end if + + } // end if + + return ((rc==null) ? null : rc.getRenderer()); + + } // end getRendererForObject + + /*-------------------------------------------------------------------------------- + * Implementations from interface PostDynamicUpdate + *-------------------------------------------------------------------------------- + */ + + public void postUpdate(DynamicUpdateEvent event) + { + if (logger.isDebugEnabled()) + logger.debug("PostDynamicUpdate: posting an event of type " + event.getClass().getName()); + Class klass = event.getClass(); + for (;;) + { // get the event listeners + Vector vec = (Vector)(m_update_listeners.get(klass)); + if (vec!=null) + { // call the event handlers + Iterator it = vec.iterator(); + while (it.hasNext()) + ((DynamicUpdateListener)(it.next())).updateReceived(event); + + } // end if + + if (klass==DynamicUpdateEvent.class) + break; + + klass = klass.getSuperclass(); + + } // end for (ever) + + } // end postUpdate + + /*-------------------------------------------------------------------------------- + * Implementations from interface RenderImmediate + *-------------------------------------------------------------------------------- + */ + + public String renderTextObject(Object obj) throws IOException, RenderingException + { + if (logger.isDebugEnabled()) + logger.debug("RenderImmediate rendering an object of type " + obj.getClass().getName()); + BufferTextRenderControl control = new BufferTextRenderControl(wrapOutputServices(null)); + control.renderSubObject(obj); + return control.getData(); + + } // end renderTextObject + + /*-------------------------------------------------------------------------------- + * Implementations from interface RequestPreprocessorRegistration + *-------------------------------------------------------------------------------- + */ + + public ComponentShutdown registerRequestPreprocessor(RequestPreprocessor rp) + { + if (logger.isDebugEnabled()) + logger.debug("Registering new RequestPreprocessor: " + rp); + m_request_preprocessors.add(rp); + return new ShutdownVectorRemove(m_request_preprocessors,rp); + + } // end registerRequestPreprocessor + + /*-------------------------------------------------------------------------------- + * Implementations from interface ExceptionTranslatorRegistration + *-------------------------------------------------------------------------------- + */ + + public ComponentShutdown registerExceptionTranslator(ExceptionTranslator xlat) + { + if (logger.isDebugEnabled()) + logger.debug("Registering new ExceptionTranslator: " + xlat); + m_exception_xlators.add(xlat); + return new ShutdownVectorRemove(m_exception_xlators,xlat); + + } // end registerExceptionTranslator + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + /** + * Adds a reference to the reference count of the ApplicationContainer. Each servlet + * or other initializing component that attempts to initialize the ApplicationContainer + * increases its reference count by 1. + */ + public synchronized void addRef() + { + ++m_refs; + if (logger.isDebugEnabled()) + logger.debug("ApplicationContainer.addRef(): refcount now " + m_refs); + + } // end addRef + + /** + * Removes a reference from the reference count of the ApplicationContainer. Each servlet that + * references the ApplicationContainer and is destroyed decreases the reference count by 1. + * When the reference count reaches 0, the ApplicationContainer is destroyed. + * + * @return true if the ApplicationContainer was destroyed, false if not. + */ + public synchronized boolean release() + { + if (--m_refs==0) + { // clean up this stuff + if (logger.isDebugEnabled()) + logger.debug("ApplicationContainer.release(): refcount now 0 - destroying!"); + destroy(); + return true; + + } // end if + + if (logger.isDebugEnabled()) + logger.debug("ApplicationContainer.release(): refcount now " + m_refs); + + return false; + + } // end release + + /** + * Returns the instance of the {@link com.silverwrist.dynamo.iface.Application Application} object defined in + * the Dynamo XML configuration file and instantiated when the ApplicationContainer was created. + * + * @return The Application object. + */ + public Application getApplication() + { + return m_application; + + } // end getApplication + + public ServiceProvider getInitServices() + { + return m_app_sm.createInitServices(); + + } // end getInitServices + + public ServiceProvider wrapServices(ServiceProvider sp) + { + return m_app_sm.createRuntimeServices(sp); + + } // end wrapServices + + public ServiceProvider wrapOutputServices(ServiceProvider sp) + { + return m_app_sm.createOutputServices(sp); + + } // end wrapOutputServices + + /** + * Returns a list of all registered {@link com.silverwrist.dynamo.event.SessionInfoListener SessionInfoListener} + * objects. + * + * @return A list of all registered SessionInfoListener objects. + */ + public SessionInfoListener[] getSessionListeners() + { + return (SessionInfoListener[])(m_session_listeners.toArray(SESSION_LISTENER_TEMPLATE)); + + } // end getSessionListeners + + /** + * Adds a session to our list of known sessions, which will be shut down when the application container + * is itself destroyed. + * + * @param link The link to the session. + */ + public void addSessionLink(ComponentShutdown link) + { + m_known_sessions.add(link); + + } // end addSessionLink + + /** + * Removes a session from our list of known sessions, so it will no longer be automatically shut down + * when the application container is itself destroyed. + * + * @param link The link to the session. + */ + public void removeSessionLink(ComponentShutdown link) + { + m_known_sessions.remove(link); + + } // end removeSessionLink + + public void setServerHeader(HttpServletResponse resp) + { + resp.setHeader("Server",m_identity); + + } // end setServerHeader + + public Map getRewriteRuleMap() + { + return m_rewrite_rules; + + } // end getRewriteRuleMap + + public Object filterOutput(Object out, Request r) throws RenderingException + { + Object rc = out; + for (int i=(m_output_filters.size()-1); i>=0; i--) + { // look for new objects that filter this one + OutputObjectFilter filt = (OutputObjectFilter)(m_output_filters.get(i)); + Object tmp_rc = filt.filterObject(rc,r); + if (tmp_rc!=null) + rc = tmp_rc; + + } // end for + + return rc; + + } // end filterOutput + + public void preprocessRequest(Request r) + { + for (int i=(m_request_preprocessors.size()-1); i>=0; i--) + { // preprocess the request, if we have any preprocessors installed + RequestPreprocessor rp = (RequestPreprocessor)(m_request_preprocessors.get(i)); + rp.preprocessRequest(r); + + } // end for + + } // end preprocessRequest + + public Object translateException(Request r, Exception e) + { + for (int i=(m_exception_xlators.size()-1); i>=0; i--) + { // try to translate exceptions + ExceptionTranslator xlat = (ExceptionTranslator)(m_exception_xlators.get(i)); + Object o = xlat.translateException(r,e); + if (o!=null) + return o; // found a translation + + } // end for + + return e; // return the exception itself as a last resort + + } // end translateException + + public String translateSubstratePathName(String input) + { + return StringUtils.replaceAllVariables(input,getSubstrateReplaceMap()); + + } // end translateSubstratePathName + +} // end class ApplicationContainer diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/ApplicationContainerMessages.properties b/src/dynamo-framework/com/silverwrist/dynamo/app/ApplicationContainerMessages.properties new file mode 100644 index 0000000..17f1c65 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/ApplicationContainerMessages.properties @@ -0,0 +1,27 @@ +# The contents of this file are subject to the Mozilla Public License Version 1.1 +# (the "License"); you may not use this file except in compliance with the License. +# You may obtain a copy of the License at . +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +# --------------------------------------------------------------------------------- +# This file has been localized for the en_US locale +creation.ioError=Unable to read from configuration file {0}. +no.classNotFound=The object class {0} was not found. +no.createError=Unable to create new object of class {0}. +no.notDynamo=The object class {0} is not a valid Dynamo NamedObject, +no.notDBPool=The object class {0} is not a valid Dynamo database connection pool. +no.notApp=The object class {0} is not a valid Dynamo application. +resource.rootErr=The resource root directory {0} does not exist. +mountRP.badName=Invalid mount path for resources: {0} +mountRP.already=Resource provider already mounted on path {0}. +registerRenderer.already=Renderer already registered for class {0}. diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/ApplicationServiceManager.java b/src/dynamo-framework/com/silverwrist/dynamo/app/ApplicationServiceManager.java new file mode 100644 index 0000000..00125f3 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/ApplicationServiceManager.java @@ -0,0 +1,675 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import java.util.*; +import org.apache.log4j.Logger; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +class ApplicationServiceManager implements HookServiceProviders +{ + /*-------------------------------------------------------------------------------- + * Internal class implementing initialization services + *-------------------------------------------------------------------------------- + */ + + private class InitServices extends BaseDelegatingServiceProvider + { + /*==================================================================== + * Constructors + *==================================================================== + */ + + InitServices() + { + super("Initialization Services"); + + } // end constructor + + InitServices(ServiceProvider sp) + { + super("Initialization Services",sp); + + } // end constructor + + /*==================================================================== + * Overrides from class BaseDelegatingServiceProvider + *==================================================================== + */ + + /** + * Queries this object for a specified service. + * + * @param klass The class of the object that should be returned as a service. + * @return A service object. The service object is guaranteed to be of the class + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass) + { + Object rc = m_init_service_cache.get(klass); + if (rc!=null) // found in the cache! + return rc; + + for (int i=(m_init_service_hooks.size()-1); i>=0; i--) + { // call the hooks + try + { // get hooks in reverse order of installation and try them + ServiceProvider sp = (ServiceProvider)(m_init_service_hooks.get(i)); + rc = sp.queryService(klass); + m_init_service_cache.put(klass,rc); + return rc; + + } // end try + catch (NoSuchServiceException e) + { // cycle around and keep trying + } // end catch + + } // end for + + rc = m_init_services.get(klass); + if (rc!=null) + { // cache the service + m_init_service_cache.put(klass,rc); + return rc; + + } // end if + + return super.queryService(klass); + + } // end queryService + + /** + * Queries this object for a specified service. + * + * @param klass The class of the object that should be returned as a service. + * @param serviceid ID for the service to be requested, to further discriminate between requests. + * @return A service object. The service object is guaranteed to be of the class + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass, String serviceid) + { + ServiceKey key = new ServiceKey(klass,serviceid); + Object rc = m_init_service_cache.get(key); + if (rc!=null) + return rc; + + for (int i=(m_init_service_hooks.size()-1); i>=0; i--) + { // call the hooks + try + { // get hooks in reverse order of installation and try them + ServiceProvider sp = (ServiceProvider)(m_init_service_hooks.get(i)); + rc = sp.queryService(klass,serviceid); + m_init_service_cache.put(key,rc); + return rc; + + } // end try + catch (NoSuchServiceException e) + { // cycle around and keep trying + } // end catch + + } // end for + + try + { // call through to superclass + return super.queryService(klass,serviceid); + + } // end try + catch (NoSuchServiceException e) + { // OK, try it without the service ID + rc = queryService(klass); + m_init_service_cache.put(key,rc); + return rc; + + } // end catch + + } // end queryService + + } // end class InitServices + + /*-------------------------------------------------------------------------------- + * Internal class implementing runtime services + *-------------------------------------------------------------------------------- + */ + + private class RuntimeServices extends BaseDelegatingServiceProvider + { + /*==================================================================== + * Constructors + *==================================================================== + */ + + RuntimeServices() + { + super("Application Services"); + + } // end constructor + + RuntimeServices(ServiceProvider sp) + { + super("Application Services",sp); + + } // end constructor + + /*==================================================================== + * Overrides from class BaseDelegatingServiceProvider + *==================================================================== + */ + + /** + * Queries this object for a specified service. + * + * @param klass The class of the object that should be returned as a service. + * @return A service object. The service object is guaranteed to be of the class + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass) + { + Object rc = m_runtime_service_cache.get(klass); + if (rc!=null) + return rc; + + for (int i=(m_runtime_service_hooks.size()-1); i>=0; i--) + { // call the hooks + try + { // get hooks in reverse order of installation and try them + ServiceProvider sp = (ServiceProvider)(m_runtime_service_hooks.get(i)); + rc = sp.queryService(klass); + m_runtime_service_cache.put(klass,rc); + return rc; + + } // end try + catch (NoSuchServiceException e) + { // cycle around and keep trying + } // end catch + + } // end for + + rc = m_runtime_services.get(klass); + if (rc!=null) + { // cache the service + m_runtime_service_cache.put(klass,rc); + return rc; + + } // end if + + return super.queryService(klass); + + } // end queryService + + /** + * Queries this object for a specified service. + * + * @param klass The class of the object that should be returned as a service. + * @param serviceid ID for the service to be requested, to further discriminate between requests. + * @return A service object. The service object is guaranteed to be of the class + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass, String serviceid) + { + ServiceKey key = new ServiceKey(klass,serviceid); + Object rc = m_runtime_service_cache.get(key); + if (rc!=null) + return rc; + + for (int i=(m_runtime_service_hooks.size()-1); i>=0; i--) + { // call the hooks + try + { // get hooks in reverse order of installation and try them + ServiceProvider sp = (ServiceProvider)(m_runtime_service_hooks.get(i)); + rc = sp.queryService(klass,serviceid); + m_runtime_service_cache.put(key,rc); + return rc; + + } // end try + catch (NoSuchServiceException e) + { // cycle around and keep trying + } // end catch + + } // end for + + try + { // call through to superclass + return super.queryService(klass,serviceid); + + } // end try + catch (NoSuchServiceException e) + { // OK, try it without the service ID + rc = queryService(klass); + m_runtime_service_cache.put(key,rc); + return rc; + + } // end catch + + } // end queryService + + } // end class RuntimeServices + + /*-------------------------------------------------------------------------------- + * Internal class implementing output services + *-------------------------------------------------------------------------------- + */ + + private class OutputServices extends BaseDelegatingServiceProvider + { + /*==================================================================== + * Constructors + *==================================================================== + */ + + OutputServices() + { + super("Application Output Services"); + + } // end constructor + + OutputServices(ServiceProvider sp) + { + super("Application Output Services",sp); + + } // end constructor + + /*==================================================================== + * Overrides from class BaseDelegatingServiceProvider + *==================================================================== + */ + + /** + * Queries this object for a specified service. + * + * @param klass The class of the object that should be returned as a service. + * @return A service object. The service object is guaranteed to be of the class + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass) + { + Object rc = m_output_service_cache.get(klass); + if (rc!=null) + return rc; + + for (int i=(m_output_service_hooks.size()-1); i>=0; i--) + { // call the hooks + try + { // get hooks in reverse order of installation and try them + ServiceProvider sp = (ServiceProvider)(m_output_service_hooks.get(i)); + rc = sp.queryService(klass); + m_output_service_cache.put(klass,rc); + return rc; + + } // end try + catch (NoSuchServiceException e) + { // cycle around and keep trying + } // end catch + + } // end for + + rc = m_output_services.get(klass); + if (rc!=null) + { // cache the service + m_output_service_cache.put(klass,rc); + return rc; + + } // end if + + return super.queryService(klass); + + } // end queryService + + /** + * Queries this object for a specified service. + * + * @param klass The class of the object that should be returned as a service. + * @param serviceid ID for the service to be requested, to further discriminate between requests. + * @return A service object. The service object is guaranteed to be of the class + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass, String serviceid) + { + ServiceKey key = new ServiceKey(klass,serviceid); + Object rc = m_output_service_cache.get(key); + if (rc!=null) + return rc; + + for (int i=(m_output_service_hooks.size()-1); i>=0; i--) + { // call the hooks + try + { // get hooks in reverse order of installation and try them + ServiceProvider sp = (ServiceProvider)(m_output_service_hooks.get(i)); + rc = sp.queryService(klass,serviceid); + m_output_service_cache.put(key,rc); + return rc; + + } // end try + catch (NoSuchServiceException e) + { // cycle around and keep trying + } // end catch + + } // end for + + try + { // call through to superclass + return super.queryService(klass,serviceid); + + } // end try + catch (NoSuchServiceException e) + { // OK, try it without the service ID + rc = queryService(klass); + m_output_service_cache.put(key,rc); + return rc; + + } // end catch + + } // end queryService + + } // end class OutputServices + + /*-------------------------------------------------------------------------------- + * Internal class implementing removal of init service hook + *-------------------------------------------------------------------------------- + */ + + private class RemoveInitServiceHook implements ComponentShutdown + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private ServiceProvider m_sp; + + /*==================================================================== + * Constructor + *==================================================================== + */ + + RemoveInitServiceHook(ServiceProvider sp) + { + m_sp = sp; + + } // end constructor + + /*==================================================================== + * Implementations from interface ComponentShutdown + *==================================================================== + */ + + public void shutdown() + { + m_init_service_hooks.remove(m_sp); + m_init_service_cache.clear(); + + } // end shutdown + + } // end class RemoveInitServiceHook + + /*-------------------------------------------------------------------------------- + * Internal class implementing removal of runtime service hook + *-------------------------------------------------------------------------------- + */ + + private class RemoveRuntimeServiceHook implements ComponentShutdown + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private ServiceProvider m_sp; + + /*==================================================================== + * Constructor + *==================================================================== + */ + + RemoveRuntimeServiceHook(ServiceProvider sp) + { + m_sp = sp; + + } // end constructor + + /*==================================================================== + * Implementations from interface ComponentShutdown + *==================================================================== + */ + + public void shutdown() + { + m_runtime_service_hooks.remove(m_sp); + m_runtime_service_cache.clear(); + + } // end shutdown + + } // end class RemoveRuntimeServiceHook + + /*-------------------------------------------------------------------------------- + * Internal class implementing removal of output service hook + *-------------------------------------------------------------------------------- + */ + + private class RemoveOutputServiceHook implements ComponentShutdown + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private ServiceProvider m_sp; + + /*==================================================================== + * Constructor + *==================================================================== + */ + + RemoveOutputServiceHook(ServiceProvider sp) + { + m_sp = sp; + + } // end constructor + + /*==================================================================== + * Implementations from interface ComponentShutdown + *==================================================================== + */ + + public void shutdown() + { + m_output_service_hooks.remove(m_sp); + m_output_service_cache.clear(); + + } // end shutdown + + } // end class RemoveOutputServiceHook + + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(ApplicationServiceManager.class); + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private Hashtable m_init_services = new Hashtable(); // initializing services + private Vector m_init_service_hooks = new Vector(); // hooks for initializing services + private Hashtable m_init_service_cache = new Hashtable(); // cache of init services + private Hashtable m_runtime_services = new Hashtable(); // runtime services + private Vector m_runtime_service_hooks = new Vector(); // hooks for runtime services + private Hashtable m_runtime_service_cache = new Hashtable(); // cache of runtime services + private Hashtable m_output_services = new Hashtable(); // output services + private Vector m_output_service_hooks = new Vector(); // hooks for output services + private Hashtable m_output_service_cache = new Hashtable(); // cache of output services + private InitServices m_solo_init = null; // only one "null" init service + private RuntimeServices m_solo_runtime = null; // only one "null" runtime service + private OutputServices m_solo_output = null; // only one "null" output service + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + ApplicationServiceManager() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface HookServiceProviders + *-------------------------------------------------------------------------------- + */ + + public ServiceProvider getCurrentInitServices() + { + return createInitServices(); + + } // end getCurrentInitServices + + public ServiceProvider getCurrentRuntimeServices() + { + return createRuntimeServices(); + + } // end getCurrentRuntimeServices + + public ServiceProvider getCurrentOutputServices() + { + return createOutputServices(); + + } // end getCurrentOutputServices + + public ComponentShutdown hookInitServiceProvider(ServiceProvider sp) + { + m_init_service_hooks.add(sp); + m_init_service_cache.clear(); + return new RemoveInitServiceHook(sp); + + } // end hookInitServiceProvider + + public ComponentShutdown hookRuntimeServiceProvider(ServiceProvider sp) + { + m_runtime_service_hooks.add(sp); + m_runtime_service_cache.clear(); + return new RemoveRuntimeServiceHook(sp); + + } // end hookRuntimeServiceProvider + + public ComponentShutdown hookOutputServiceProvider(ServiceProvider sp) + { + m_output_service_hooks.add(sp); + m_output_service_cache.clear(); + return new RemoveOutputServiceHook(sp); + + } // end hookOutputServiceProvider + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + void addInitService(Class klass, Object svc) + { + m_init_services.put(klass,svc); + + } // end addInitService + + void addRuntimeService(Class klass, Object svc) + { + m_runtime_services.put(klass,svc); + + } // end addRuntimeService + + void addOutputService(Class klass, Object svc) + { + m_output_services.put(klass,svc); + + } // end addRuntimeService + + ServiceProvider createInitServices() + { + if (m_solo_init==null) + m_solo_init = new InitServices(); + return m_solo_init; + + } // end createInitServices + + ServiceProvider createInitServices(ServiceProvider sp) + { + if (sp==null) + return createInitServices(); + return new InitServices(sp); + + } // end createRuntimeServices + + ServiceProvider createRuntimeServices() + { + if (m_solo_runtime==null) + m_solo_runtime = new RuntimeServices(); + return m_solo_runtime; + + } // end createRuntimeServices + + ServiceProvider createRuntimeServices(ServiceProvider sp) + { + if (sp==null) + return createRuntimeServices(); + return new RuntimeServices(sp); + + } // end createRuntimeServices + + ServiceProvider createOutputServices() + { + if (m_solo_output==null) + m_solo_output = new OutputServices(); + return m_solo_output; + + } // end createOutputServices + + ServiceProvider createOutputServices(ServiceProvider sp) + { + if (sp==null) + return createOutputServices(); + return new OutputServices(sp); + + } // end createOutputServices + +} // end class ApplicationServiceManager diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/BackgroundProcessor.java b/src/dynamo-framework/com/silverwrist/dynamo/app/BackgroundProcessor.java new file mode 100644 index 0000000..d44f228 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/BackgroundProcessor.java @@ -0,0 +1,490 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import java.util.*; +import org.apache.log4j.Logger; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +/** + * A class used internally by the {@link com.silverwrist.dynamo.app.ApplicationContainer ApplicationContainer} + * to handle background execution of tasks. It implements the + * {@link com.silverwrist.dynamo.iface.BackgroundScheduler BackgroundScheduler} service. + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +class BackgroundProcessor implements BackgroundScheduler, ComponentShutdown +{ + /*-------------------------------------------------------------------------------- + * Internal thread class for scheduling normal-priority background tasks + *-------------------------------------------------------------------------------- + */ + + private class NormalPriorityThread extends Thread + { + /*==================================================================== + * Constructor + *==================================================================== + */ + + NormalPriorityThread(int index) + { + super("BG-Normal-" + index); + setPriority(NORM_PRIORITY); + + } // end constructor + + /*==================================================================== + * Overrides from class Thread + *==================================================================== + */ + + public void run() + { + while (m_running) + { // get tasks then execute them + BackgroundTask task = null; + synchronized (m_normal_sync) + { // test and remove from normal queue + boolean get_task = true; + while (get_task && m_normal_queue.isEmpty()) + { // nothing to run right now... + try + { // sleep waiting for a new background task + m_normal_sync.wait(); + + } // end try + catch (InterruptedException e) + { // don't bother getting a task + get_task = false; + + } // end catch + + } // end if + + if (get_task) + task = (BackgroundTask)(m_normal_queue.removeFirst()); + + } // end synchronized block + + if (task!=null) + { // found a task to run, now execute it + try + { // run the task + task.run(m_services); + task = null; + + } // end try + catch (Exception e) + { // whoops! don't let this stop us + logger.warn("BackgroundTask threw exception",e); + + } // end catch + + } // end if + + } // end while + + } // end run + + } // end class NormalPriorityThread + + /*-------------------------------------------------------------------------------- + * Internal thread class for scheduling low-priority background tasks + *-------------------------------------------------------------------------------- + */ + + private class LowPriorityThread extends Thread + { + /*==================================================================== + * Constructor + *==================================================================== + */ + + LowPriorityThread(int index) + { + super("BG-Low-" + index); + setPriority(MIN_PRIORITY); + + } // end constructor + + /*==================================================================== + * Overrides from class Thread + *==================================================================== + */ + + public void run() + { + while (m_running) + { // get tasks then execute them + BackgroundTask task = null; + synchronized (m_lp_sync) + { // test and remove from normal queue + boolean get_task = true; + while (get_task && m_lp_queue.isEmpty()) + { // nothing to run right now... + try + { // sleep waiting for a new background task + m_lp_sync.wait(); + + } // end try + catch (InterruptedException e) + { // don't bother getting a task + get_task = false; + + } // end catch + + } // end if + + // Get the task we waited for. + if (get_task) + task = (BackgroundTask)(m_lp_queue.removeFirst()); + + } // end synchronized block + + if (task!=null) + { // found a task to run, now execute it + try + { // run the task + task.run(m_services); + task = null; + + } // end try + catch (Exception e) + { // whoops! don't let this stop us + logger.warn("BackgroundTask threw exception",e); + + } // end catch + + } // end if + + } // end while + + } // end run + + } // end class LowPriorityThread + + /*-------------------------------------------------------------------------------- + * Internal class for timer operations + *-------------------------------------------------------------------------------- + */ + + private class MyTimerTask extends TimerTask implements ComponentShutdown + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private BackgroundTask m_task; + + /*==================================================================== + * Constructor + *==================================================================== + */ + + MyTimerTask(BackgroundTask task) + { + super(); + m_task = task; + + } // end constructor + + /*==================================================================== + * Overrides from class TimerTask + *==================================================================== + */ + + public void run() + { + try + { // run the task + m_task.run(m_services); + + } // end try + catch (Exception e) + { // whoops! don't let this stop us + logger.warn("BackgroundTask threw exception",e); + + } // end catch + + } // end run + + /*==================================================================== + * Implementations from interface ComponentShutdown + *==================================================================== + */ + + /** + * Shuts down the component associated with this interface, in a component-specific manner. + */ + public void shutdown() + { + cancel(); + + } // end shutdown + + } // end class MyTimerTask + + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(BackgroundProcessor.class); + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private ServiceProvider m_services; + private volatile boolean m_running = true; + private Object m_normal_sync = new Object(); + private LinkedList m_normal_queue = new LinkedList(); + private Thread[] m_normal_threads; + private Object m_lp_sync = new Object(); + private LinkedList m_lp_queue = new LinkedList(); + private Thread[] m_lp_threads; + private Timer m_timer; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Constructs the instance of the BackgroundProcessor internal to the + * {@link com.silverwrist.dynamo.app.ApplicationContainer ApplicationContainer}. + * + * @param num_normal_threads Number of "normal" threads in our runtime thread pool. + * @param num_lp_threads Number of "low priority" threads in our runtime thread pool. + * @param services The {@link com.silverwrist.dynamo.iface.ServiceProvider ServiceProvider} to be supplied + * to all {@link com.silverwrist.dynamo.iface.BackgroundTask BackgroundTask}s. + */ + BackgroundProcessor(int num_norm_threads, int num_lp_threads, ServiceProvider services) + { + m_services = new SingletonServiceProvider("BackgroundProcessor",services,BackgroundScheduler.class,this); + + // Create the normal priority background threads. + m_normal_threads = new Thread[num_norm_threads]; + int i; + for (i=0; itrue, the task is handled by a pool of low-priority threads + * instead of by a pool of normal-priority threads. Low-priority threads will generally + * execute only after normal-priority threads, but are not guaranteed to. + */ + public void runTaskLater(BackgroundTask task, boolean low_priority) + { + if (low_priority) + { // add to low priority queue + synchronized (m_lp_sync) + { // add item and notify a thread to wake up + m_lp_queue.addLast(task); + m_lp_sync.notify(); + + } // end synchronized block + + } // end if + else + { // add to normal queue + synchronized (m_normal_sync) + { // add item and notify a thread to wake up + m_normal_queue.addLast(task); + m_normal_sync.notify(); + + } // end synchronized block + + } // end else + + } // end runTaskLater + + /** + * Schedule a task to be run on a one-shot basis after a delay. + * + * @param task The task to be scheduled to run. + * @param delay The delay, in milliseconds, before this task is to be run. The actual delay may be longer + * than this. + * @return An instance of a {@link com.silverwrist.dynamo.iface.ComponentShutdown ComponentShutdown} object, + * whose {@link com.silverwrist.dynamo.iface.ComponentShutdown#shutdown() shutdown()} method may be + * called to abort the execution of this task at any time before it is actually run. If this is called + * after the task is run, it has no effect. + */ + public ComponentShutdown runTaskAfter(BackgroundTask task, long delay) + { + MyTimerTask my_task = new MyTimerTask(task); + m_timer.schedule(my_task,delay); + return my_task; + + } // end runTaskAfter + + /** + * Schedule a task to be run on a one-shot basis at a certain time. + * + * @param task The task to be scheduled to run. + * @param when The date/time at which the task is to be run. The actual task start time may be any time + * after this. + * @return An instance of a {@link com.silverwrist.dynamo.iface.ComponentShutdown ComponentShutdown} object, + * whose {@link com.silverwrist.dynamo.iface.ComponentShutdown#shutdown() shutdown()} method may be + * called to abort the execution of this task at any time before it is actually run. If this is called + * after the task is run, it has no effect. + */ + public ComponentShutdown runTaskAt(BackgroundTask task, Date when) + { + MyTimerTask my_task = new MyTimerTask(task); + m_timer.schedule(my_task,when); + return my_task; + + } // end runTaskAt + + /** + * Schedule a task to be run periodically, after a delay. + * + * @param task The task to be scheduled to run. + * @param delay The delay, in milliseconds, before this task is to be run for the first time. The actual + * delay may be longer than this. + * @param period The time, in milliseconds, between successive executions of the task. The task will be + * scheduled for repeated execution, delaying at least this long between executions. + * @return An instance of a {@link com.silverwrist.dynamo.iface.ComponentShutdown ComponentShutdown} object, + * whose {@link com.silverwrist.dynamo.iface.ComponentShutdown#shutdown() shutdown()} method may be + * called to abort the periodic execution of this task at any time. + */ + public ComponentShutdown runTaskPeriodic(BackgroundTask task, long delay, long period) + { + MyTimerTask my_task = new MyTimerTask(task); + m_timer.schedule(my_task,delay,period); + return my_task; + + } // end runTaskPeriodic + + /** + * Schedule a task to be run periodically, beginning at a specified time. + * + * @param task The task to be scheduled to run. + * @param when The date/time at which the task is to be run for the first time. The actual task start time + * may be any time after this. + * @param period The time, in milliseconds, between successive executions of the task. The task will be + * scheduled for repeated execution, delaying at least this long between executions. + * @return An instance of a {@link com.silverwrist.dynamo.iface.ComponentShutdown ComponentShutdown} object, + * whose {@link com.silverwrist.dynamo.iface.ComponentShutdown#shutdown() shutdown()} method may be + * called to abort the periodic execution of this task at any time. + */ + public ComponentShutdown runTaskPeriodic(BackgroundTask task, Date start, long period) + { + MyTimerTask my_task = new MyTimerTask(task); + m_timer.schedule(my_task,start,period); + return my_task; + + } // end runTaskPeriodic + + /** + * Schedule a task to be run periodically, after a delay. + * + * @param task The task to be scheduled to run. + * @param delay The delay, in milliseconds, before this task is to be run for the first time. The actual + * delay may be longer than this. + * @param period The time, in milliseconds, between successive executions of the task. The task will be + * scheduled for repeated execution, with the task being started with roughly this many + * milliseconds between each start attempt. If execution is delayed, this task will try to + * "catch up" by scheduling executions more frequently. + * @return An instance of a {@link com.silverwrist.dynamo.iface.ComponentShutdown ComponentShutdown} object, + * whose {@link com.silverwrist.dynamo.iface.ComponentShutdown#shutdown() shutdown()} method may be + * called to abort the periodic execution of this task at any time. + */ + public ComponentShutdown runTaskFixedRate(BackgroundTask task, long delay, long period) + { + MyTimerTask my_task = new MyTimerTask(task); + m_timer.scheduleAtFixedRate(my_task,delay,period); + return my_task; + + } // end runTaskFixedRate + + /** + * Schedule a task to be run periodically, beginning at a specified time. + * + * @param task The task to be scheduled to run. + * @param when The date/time at which the task is to be run for the first time. The actual task start time + * may be any time after this. + * @param period The time, in milliseconds, between successive executions of the task. The task will be + * scheduled for repeated execution, with the task being started with roughly this many + * milliseconds between each start attempt. If execution is delayed, this task will try to + * "catch up" by scheduling executions more frequently. + * @return An instance of a {@link com.silverwrist.dynamo.iface.ComponentShutdown ComponentShutdown} object, + * whose {@link com.silverwrist.dynamo.iface.ComponentShutdown#shutdown() shutdown()} method may be + * called to abort the periodic execution of this task at any time. + */ + public ComponentShutdown runTaskFixedRate(BackgroundTask task, Date start, long period) + { + MyTimerTask my_task = new MyTimerTask(task); + m_timer.scheduleAtFixedRate(my_task,start,period); + return my_task; + + } // end runTaskFixedRate + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentShutdown + *-------------------------------------------------------------------------------- + */ + + /** + * Shuts down the BackgroundProcessor, stopping all its associated threads and tasks. + */ + public void shutdown() + { + m_timer.cancel(); + m_running = false; + int i; + for (i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import com.silverwrist.util.*; +import com.silverwrist.dynamo.except.*; + +class ComponentResName +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String[] m_components; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + ComponentResName(String resource_path) + { + if (!(resource_path.startsWith("/"))) + throw new NoSuchResourceException(resource_path); + m_components = StringUtils.split(resource_path.substring(1),"/"); + if ((m_components==null) || (m_components.length==0)) + throw new NoSuchResourceException(resource_path); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class Object + *-------------------------------------------------------------------------------- + */ + + public boolean equals(Object obj) + { + if ((obj==null) || !(obj instanceof ComponentResName)) + return false; + ComponentResName other = (ComponentResName)obj; + if (m_components.length!=other.m_components.length) + return false; + return (getMatchCount(other)==m_components.length); + + } // end equals + + public int hashCode() + { + int rc = 0; + for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import java.util.*; +import org.w3c.dom.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +public class ConnectionManager implements NamedObject, ComponentInitialize, ComponentShutdown +{ + /*-------------------------------------------------------------------------------- + * Internal class implementing the initialization service hook + *-------------------------------------------------------------------------------- + */ + + private class InitService implements ServiceProvider, ConnectionFrontEnd, ConnectionBackEnd + { + /*==================================================================== + * Constructor + *==================================================================== + */ + + InitService() + { // do nothing + } // end constructor + + /*==================================================================== + * Implementations from interface ServiceProvider + *==================================================================== + */ + + /** + * Queries this object for a specified service. + * + * @param klass The class of the object that should be returned as a service. + * @return A service object. The service object is guaranteed to be of the class + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass) + { + if (klass==ConnectionFrontEnd.class) + return (ConnectionFrontEnd)this; + if (klass==ConnectionBackEnd.class) + return (ConnectionBackEnd)this; + throw new NoSuchServiceException("ConnectionManager.InitService",klass); + + } // end queryService + + /** + * Queries this object for a specified service. + * + * @param klass The class of the object that should be returned as a service. + * @param serviceid ID for the service to be requested, to further discriminate between requests. + * @return A service object. The service object is guaranteed to be of the class + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass, String serviceid) + { + if (klass==ConnectionFrontEnd.class) + return (ConnectionFrontEnd)this; + if (klass==ConnectionBackEnd.class) + return (ConnectionBackEnd)this; + throw new NoSuchServiceException("ConnectionManager.InitService",klass,serviceid); + + } // end queryService + + /*==================================================================== + * Implementations from interface ConnectionFrontEnd + *==================================================================== + */ + + public Object getInterface(String connection_point, Class expected_class) throws ConfigException + { + return getConnectionPoint(connection_point).getInterface(expected_class); + + } // end getInterface + + /*==================================================================== + * Implementations from interface ConnectionBackEnd + *==================================================================== + */ + + public void connectObject(String connection_point, Object object) throws ConfigException + { + getConnectionPoint(connection_point).connectObject(object); + + } // end connectObject + + } // end class InitService + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String m_name; + private Hashtable m_connection_points = new Hashtable(); + private ComponentShutdown m_shutdown_hook; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public ConnectionManager() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private final ConnectionPoint getConnectionPoint(String name) throws ConfigException + { + ConnectionPoint rc = (ConnectionPoint)(m_connection_points.get(name)); + if (rc!=null) + return rc; + ConfigException ce = new ConfigException(ConnectionPoint.class,"ConnectionMessages","cpoint.notFound"); + ce.setParameter(0,name); + throw ce; + + } // end getConnectionPoint + + /*-------------------------------------------------------------------------------- + * Implementations from interface NamedObject + *-------------------------------------------------------------------------------- + */ + + public String getName() + { + return m_name; + + } // end getName + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentInitialize + *-------------------------------------------------------------------------------- + */ + + public void initialize(Element config_root, ServiceProvider services) throws ConfigException + { + XMLLoader loader = XMLLoader.get(); + try + { // verify the right node name + loader.verifyNodeName(config_root,"object"); + + // get the object's name + m_name = loader.getAttribute(config_root,"name"); + + // get the connection points list and try to load them + List l = loader.getMatchingSubElements(config_root,"connection-point"); + Iterator it = l.iterator(); + while (it.hasNext()) + { // create the connection points + Element elt = (Element)(it.next()); + ConnectionPoint cpoint = new ConnectionPoint(elt); + m_connection_points.put(cpoint.getName(),cpoint); + + } // end while + + } // end try + catch (XMLLoadException e) + { // error loading XML config data + throw new ConfigException(e); + + } // end catch + + // Hook the init service provider to provide our services. + HookServiceProviders hooker = (HookServiceProviders)(services.queryService(HookServiceProviders.class)); + m_shutdown_hook = hooker.hookInitServiceProvider(new InitService()); + + } // end initialize + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentShutdown + *-------------------------------------------------------------------------------- + */ + + public void shutdown() + { + m_shutdown_hook.shutdown(); + + Iterator it = m_connection_points.values().iterator(); + while (it.hasNext()) + { // shut down those connection points + ComponentShutdown cs = (ComponentShutdown)(it.next()); + cs.shutdown(); + + } // end while + + m_connection_points.clear(); + + } // end shutdown + +} // end class ConnectionManager diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/ConnectionMessages.properties b/src/dynamo-framework/com/silverwrist/dynamo/app/ConnectionMessages.properties new file mode 100644 index 0000000..e0b4242 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/ConnectionMessages.properties @@ -0,0 +1,23 @@ +# The contents of this file are subject to the Mozilla Public License Version 1.1 +# (the "License"); you may not use this file except in compliance with the License. +# You may obtain a copy of the License at . +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +# --------------------------------------------------------------------------------- +# This file has been localized for the en_US locale +cpoint.noInterface=Unable to find the connection point interface class "{0}". +cpoint.notValid=The connection point class "{0}" is not a valid interface. +iface.type=Connection point "{0}"'s interface type {1} cannot be assigned to the desired type {2}. +connect.already=The connection point "{0}" has already been connected. +connect.wrongType=The connection point "{0}" expects to connect to an object of type {1}. +cpoint.notFound=No connection point "{0}" defined. diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/ConnectionPoint.java b/src/dynamo-framework/com/silverwrist/dynamo/app/ConnectionPoint.java new file mode 100644 index 0000000..91d35e3 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/ConnectionPoint.java @@ -0,0 +1,179 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import java.lang.reflect.*; +import org.w3c.dom.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +class ConnectionPoint implements NamedObject, InvocationHandler, ComponentShutdown +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String m_name; // name of this connection point + private Class m_interface; // interface associated with this connection point + private Object m_proxy_obj; // proxy object that provides the "head end" of the cpoint + private Object m_target_obj = null; // object on the "tail end" of the cpoint + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + ConnectionPoint(Element config) throws ConfigException + { + XMLLoader loader = XMLLoader.get(); + String iface_name = null; + try + { // verify the right node name + loader.verifyNodeName(config,"connection-point"); + + // get the connection point's name + m_name = loader.getAttribute(config,"name"); + + // get the interface represented by this proxy + iface_name = loader.getAttribute(config,"interface"); + m_interface = Class.forName(iface_name); + if (!(m_interface.isInterface())) + { // the class name does not specify an interface + ConfigException ce = new ConfigException(ConnectionPoint.class,"ConnectionMessages", + "cpoint.notValid"); + ce.setParameter(0,iface_name); + throw ce; + + } // end if + + // Create the proxy object. + Class[] arg = new Class[1]; + arg[0] = m_interface; + m_proxy_obj = Proxy.newProxyInstance(m_interface.getClassLoader(),arg,this); + + } // end try + catch (XMLLoadException e) + { // error loading XML config data + throw new ConfigException(e); + + } // end catch + catch (ClassNotFoundException e) + { // unable to find the interface + ConfigException ce = new ConfigException(ConnectionPoint.class,"ConnectionMessages", + "cpoint.noInterface",e); + ce.setParameter(0,iface_name); + throw ce; + + } // end catch + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface NamedObject + *-------------------------------------------------------------------------------- + */ + + public String getName() + { + return m_name; + + } // end getName + + /*-------------------------------------------------------------------------------- + * Implementations from interface InvocationHandler + *-------------------------------------------------------------------------------- + */ + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + if (m_target_obj==null) + throw new ProxyException(new NullPointerException("target not yet connected for " + m_name + "/" + + m_interface.getName())); + try + { // invoke the method on the real target! + return method.invoke(m_target_obj,args); + + } // end try + catch (IllegalAccessException e) + { // turn into the runtime ProxyException + throw new ProxyException(e); + + } // end catch + catch (InvocationTargetException e) + { // "unwrap" this exception type and throw it + throw e.getCause(); + + } // end catch + + } // end invoke + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentShutdown + *-------------------------------------------------------------------------------- + */ + + public void shutdown() + { + m_proxy_obj = null; + m_target_obj = null; + + } // end shutdown + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + Object getInterface(Class expected_class) throws ConfigException + { + if (expected_class.isAssignableFrom(m_interface)) + return m_proxy_obj; + ConfigException ce = new ConfigException(ConnectionPoint.class,"ConnectionMessages","iface.type"); + ce.setParameter(0,m_name); + ce.setParameter(1,m_interface.getName()); + ce.setParameter(2,expected_class.getName()); + throw ce; + + } // end getInterface + + synchronized void connectObject(Object obj) throws ConfigException + { + if (m_target_obj!=null) + { // this connection point has already been connected + ConfigException ce = new ConfigException(ConnectionPoint.class,"ConnectionMessages","connect.already"); + ce.setParameter(0,m_name); + throw ce; + + } // end if + + if (!(m_interface.isInstance(obj))) + { // the object is of the wrong type + ConfigException ce = new ConfigException(ConnectionPoint.class,"ConnectionMessages","connect.wrongType"); + ce.setParameter(0,m_name); + ce.setParameter(1,m_interface.getName()); + throw ce; + + } // end if + + m_target_obj = obj; + + } // end connectObject + +} // end class ConnectionPoint diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/DataItemRenderer.java b/src/dynamo-framework/com/silverwrist/dynamo/app/DataItemRenderer.java new file mode 100644 index 0000000..5790572 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/DataItemRenderer.java @@ -0,0 +1,52 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import java.io.*; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.except.RenderingException; +import com.silverwrist.dynamo.iface.*; + +class DataItemRenderer implements BinaryRenderer +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + DataItemRenderer() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface BinaryRenderer + *-------------------------------------------------------------------------------- + */ + + public void render(Object obj, BinaryRenderControl control) throws IOException, RenderingException + { + DataItem di = (DataItem)obj; + control.setContentType(di.getMimeType()); + control.setContentLength(di.getSize()); + OutputStream stm = control.getStream(); + IOUtils.copy(di.getDataStream(),stm); + stm.flush(); + + } // end render + +} // end class DataItemRenderer diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/HeapContents.java b/src/dynamo-framework/com/silverwrist/dynamo/app/HeapContents.java new file mode 100644 index 0000000..e1a07a3 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/HeapContents.java @@ -0,0 +1,88 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import org.w3c.dom.Element; +import com.silverwrist.util.xml.*; + +class HeapContents implements Comparable +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + Element m_elt; // element we're sorting + int m_priority; // its priority + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + HeapContents(Element elt) throws XMLLoadException + { + m_elt = elt; + m_priority = XMLLoader.get().getAttributeInt(elt,"priority",0); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class Object + *-------------------------------------------------------------------------------- + */ + + public boolean equals(Object o) + { + if (!(o instanceof HeapContents)) + return false; + HeapContents other = (HeapContents)o; + return (m_priority==other.m_priority); + + } // end equals + + public int hashCode() + { + return m_priority; + + } // end hashCode + + /*-------------------------------------------------------------------------------- + * Implementations from interface Comparable + *-------------------------------------------------------------------------------- + */ + + public int compareTo(Object o) + { + HeapContents other = (HeapContents)o; // may throw ClassCastException + return m_priority - other.m_priority; + + } // end compareTo + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + Element getElement() + { + return m_elt; + + } // end getElement + +} // end class HeapContents diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/ListRenderer.java b/src/dynamo-framework/com/silverwrist/dynamo/app/ListRenderer.java new file mode 100644 index 0000000..4075d2e --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/ListRenderer.java @@ -0,0 +1,50 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import java.io.IOException; +import java.util.*; +import com.silverwrist.dynamo.except.RenderingException; +import com.silverwrist.dynamo.iface.*; + +class ListRenderer implements TextRenderer +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + ListRenderer() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface TextRenderer + *-------------------------------------------------------------------------------- + */ + + public void render(Object obj, TextRenderControl control) throws IOException, RenderingException + { + List list = (List)obj; + Iterator it = list.iterator(); + while (it.hasNext()) + control.renderSubObject(it.next()); + + } // end render + +} // end class ListRenderer diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/PropertySerializationSupport.java b/src/dynamo-framework/com/silverwrist/dynamo/app/PropertySerializationSupport.java new file mode 100644 index 0000000..bcff801 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/PropertySerializationSupport.java @@ -0,0 +1,270 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import java.text.*; +import java.util.*; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +class PropertySerializationSupport implements PropertySerializer, PropertySerializerRegistration +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final Map SIMPLE_TYPE_SERIALIZE; + + private static final DateFormat s_iso8601; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private static Vector m_extern_calls = new Vector(); + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + PropertySerializationSupport() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private final String builtinSerialize(Object value) + { + String prefix = (String)(SIMPLE_TYPE_SERIALIZE.get(value.getClass())); + if (prefix!=null) + return prefix + value.toString(); + + if (value instanceof Boolean) + return (((Boolean)value).booleanValue() ? "Y" : "Z"); + + if (value instanceof java.util.Date) + return "T" + s_iso8601.format((java.util.Date)value); + + if (value instanceof TimeZone) + return "_TZ:" + ((TimeZone)value).getID(); + + if (value instanceof Language) + return "_LANG:" + ((Language)value).getCode(); + + if (value instanceof Country) + return "_CTRY:" + ((Country)value).getCode(); + + if (value instanceof OptionSet) + return "_OS:" + ((OptionSet)value).asString(); + + return null; + + } // end builtInSerialize + + private final Object extendedDecode(String s) + { + if (s.startsWith("_LOC:")) + { // need to break down + s = s.substring(5); + int p = s.indexOf('_'); + if (p>=0) + { // language + country, maybe + variant + String language = s.substring(0,p); + s = s.substring(p+1); + p = s.indexOf('_'); + if (p>=0) + return new Locale(language,s.substring(0,p),s.substring(p+1)); + else + return new Locale(language,s); + + } // end if + else // just language + return new Locale(s); + + } // end if + else if (s.startsWith("_TZ:")) + return TimeZone.getTimeZone(s.substring(4)); + else if (s.startsWith("_LANG:")) + return International.get().getLanguageForCode(s.substring(6)); + else if (s.startsWith("_CTRY:")) + return International.get().getCountryForCode(s.substring(6)); + else if (s.startsWith("_OS:")) + return new OptionSet(s.substring(4)); + else + return null; + + } // end extendedDecode + + /*-------------------------------------------------------------------------------- + * Implementations from interface PropertySerializer + *-------------------------------------------------------------------------------- + */ + + public String serializeProperty(Object value) + { + if (value==null) + return null; + + String rc = builtinSerialize(value); + if (rc!=null) + return rc; + + Iterator it = m_extern_calls.iterator(); + while (it.hasNext()) + { // try the external serializers + PropertySerializer psz = (PropertySerializer)(it.next()); + rc = psz.serializeProperty(value); + if (rc!=null) + return "." + rc; + + } // end while + + return null; // cannot serialize + + } // end serializeProperty + + public Object deserializeProperty(String value) + { + if (value==null) + return null; + + try + { // the first character is the flag... + switch (value.charAt(0)) + { + case 'B': + return new Byte(value.substring(1)); + + case 'C': + return new Character(value.charAt(1)); + + case 'D': + return new Double(value.substring(1)); + + case 'F': + return new Float(value.substring(1)); + + case 'I': + return new Integer(value.substring(1)); + + case 'J': + return new Long(value.substring(1)); + + case 'S': + return new Short(value.substring(1)); + + case 'T': + return s_iso8601.parse(value.substring(1)); + + case 'Y': + return Boolean.TRUE; + + case 'Z': + return Boolean.FALSE; + + case '!': + return value.substring(1); + + case '_': + return extendedDecode(value); + + case '.': + { // run through the external decoders + String s = value.substring(1); + Iterator it = m_extern_calls.iterator(); + while (it.hasNext()) + { // try the external serializers + PropertySerializer psz = (PropertySerializer)(it.next()); + Object rc = psz.deserializeProperty(s); + if (rc!=null) + return rc; + + } // end while + + } // end case + break; + + default: + break; + + } // end switch + + } // end try + catch (ParseException e) + { // if we threw this, we're h0s3d anyway + return null; + + } // end catch + + return null; + + } // end deserializeProperty + + /*-------------------------------------------------------------------------------- + * Implementations from interface PropertySerializerRegistration + *-------------------------------------------------------------------------------- + */ + + public ComponentShutdown registerPropertySerializer(PropertySerializer psz) + { + m_extern_calls.add(psz); + return new ShutdownVectorRemove(m_extern_calls,psz); + + } // end registerPropertySerializer + + /*-------------------------------------------------------------------------------- + * Static initializer + *-------------------------------------------------------------------------------- + */ + + static + { + HashMap tmp = new HashMap(); + tmp.put(Byte.class,"B"); + tmp.put(Byte.TYPE,"B"); + tmp.put(Character.class,"C"); + tmp.put(Character.TYPE,"C"); + tmp.put(Double.class,"D"); + tmp.put(Double.TYPE,"D"); + tmp.put(Float.class,"F"); + tmp.put(Float.TYPE,"F"); + tmp.put(Integer.class,"I"); + tmp.put(Integer.TYPE,"I"); + tmp.put(Long.class,"J"); + tmp.put(Long.TYPE,"J"); + tmp.put(Short.class,"S"); + tmp.put(Short.TYPE,"S"); + tmp.put(String.class,"!"); + tmp.put(StringBuffer.class,"!"); + tmp.put(Locale.class,"_LOC:"); + SIMPLE_TYPE_SERIALIZE = Collections.unmodifiableMap(tmp); + + SimpleDateFormat iso = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss"); + iso.setCalendar(new GregorianCalendar(new SimpleTimeZone(0,"UTC"))); + s_iso8601 = iso; + + } // end static initializer + +} // end class PropertySerializationSupport diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/RewriteRule.java b/src/dynamo-framework/com/silverwrist/dynamo/app/RewriteRule.java new file mode 100644 index 0000000..bea9837 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/RewriteRule.java @@ -0,0 +1,71 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import org.w3c.dom.*; +import com.silverwrist.util.xml.*; + +public class RewriteRule +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String m_name; + private boolean m_encode; + private String m_template; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + RewriteRule(Element elt) throws XMLLoadException + { + XMLLoader loader = XMLLoader.get(); + m_name = loader.getAttribute(elt,"type").trim().toUpperCase(); + m_encode = loader.getAttributeBoolean(elt,"encode"); + m_template = loader.getText(elt); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Public getters + *-------------------------------------------------------------------------------- + */ + + public String getName() + { + return m_name; + + } // end getName + + public boolean getEncode() + { + return m_encode; + + } // end getEncode + + public String getTemplate() + { + return m_template; + + } // end getTemplate + +} // end class RewriteRule diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/ServiceKey.java b/src/dynamo-framework/com/silverwrist/dynamo/app/ServiceKey.java new file mode 100644 index 0000000..1eeeddb --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/ServiceKey.java @@ -0,0 +1,62 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +class ServiceKey +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private Class m_class; + private String m_serviceid; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + ServiceKey(Class klass, String serviceid) + { + m_class = klass; + m_serviceid = serviceid; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class Object + *-------------------------------------------------------------------------------- + */ + + public boolean equals(Object obj) + { + if ((obj==null) || !(obj instanceof ServiceKey)) + return false; + ServiceKey other = (ServiceKey)obj; + return (m_class==other.m_class) && m_serviceid.equals(other.m_serviceid); + + } // end equals + + public int hashCode() + { + return m_class.hashCode() ^ m_serviceid.hashCode(); + + } // end hashCode + +} // end class ServiceKey diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/WrappedResourceProvider.java b/src/dynamo-framework/com/silverwrist/dynamo/app/WrappedResourceProvider.java new file mode 100644 index 0000000..c2346be --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/app/WrappedResourceProvider.java @@ -0,0 +1,98 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.app; + +import java.io.InputStream; +import java.io.IOException; +import com.silverwrist.dynamo.except.NoSuchResourceException; +import com.silverwrist.dynamo.iface.ResourceProvider; + +class WrappedResourceProvider +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private ComponentResName m_mount_point; + private ResourceProvider m_provider; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + WrappedResourceProvider(ComponentResName mount_point, ResourceProvider provider) + { + m_mount_point = mount_point; + m_provider = provider; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class Object + *-------------------------------------------------------------------------------- + */ + + public boolean equals(Object obj) + { + if ((obj==null) || !(obj instanceof WrappedResourceProvider)) + return false; + WrappedResourceProvider other = (WrappedResourceProvider)obj; + return m_mount_point.equals(other.m_mount_point); + + } // end equals + + public int hashCode() + { + return m_mount_point.hashCode(); + + } // end hashCode + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + int getMatchCount(ComponentResName crn) + { + int rc = m_mount_point.getMatchCount(crn); + if (rc!=m_mount_point.getComponentCount()) + return -1; + return rc; + + } // end getMatchCount + + InputStream getResource(ComponentResName crn) throws IOException + { + if (m_mount_point.getMatchCount(crn)!=m_mount_point.getComponentCount()) + throw new NoSuchResourceException(crn.getStringValue(0,true)); + return m_provider.getResource(crn.getStringValue(m_mount_point.getComponentCount(),true)); + + } // end getResource + + long getResourceModTime(ComponentResName crn) + { + if (m_mount_point.getMatchCount(crn)!=m_mount_point.getComponentCount()) + return 0; + return m_provider.getResourceModTime(crn.getStringValue(m_mount_point.getComponentCount(),true)); + + } // end getResourceModTime + +} // end class WrappedResourceProvider + diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/DBUtilitiesImpl.java b/src/dynamo-framework/com/silverwrist/dynamo/db/DBUtilitiesImpl.java new file mode 100644 index 0000000..17c032c --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/DBUtilitiesImpl.java @@ -0,0 +1,141 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.lang.reflect.*; +import java.sql.*; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.iface.DBUtilities; + +abstract class DBUtilitiesImpl implements DBUtilities +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final Class[] ARGS_TYPE = new Class[0]; + private static final Object[] ARGS = new Object[0]; + + private static final String SQL_WILDCARD_CHARS = "%_'"; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + protected DBUtilitiesImpl() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface DBUtilities + *-------------------------------------------------------------------------------- + */ + + public String encodeString(String data) + { + if (data==null) + return null; // safety feature + int ndx = data.indexOf('\''); + if (ndx<0) + return data; + StringBuffer buf = new StringBuffer(); + while (ndx>=0) + { // convert each single quote mark to a pair of them + if (ndx>0) + buf.append(data.substring(0,ndx)); + buf.append("''"); + data = data.substring(ndx+1); + ndx = data.indexOf('\''); + + } // end while + + buf.append(data); + return buf.toString(); + + } // end encodeString + + public String encodeStringWildcards(String data) + { + if (data==null) + return null; // safety feature + AnyCharMatcher nhc = new AnyCharMatcher(SQL_WILDCARD_CHARS); + int ndx = nhc.get(data); + if (ndx<0) + return data; // trivial short-circuit case + StringBuffer buf = new StringBuffer(); + while (ndx>=0) + { // append the matched "head" and then the encoded character + if (ndx>0) + buf.append(data.substring(0,ndx)); + switch (data.charAt(ndx++)) + { + case '%': + buf.append("\\%"); + break; + + case '_': + buf.append("\\_"); + break; + + case '\'': + buf.append("\'\'"); + break; + + } // end switch + + if (ndx==data.length()) + return buf.toString(); // munched the entire string - all done! + data = data.substring(ndx); + ndx = nhc.get(data); + + } // end while + + buf.append(data); // append the unmatched tail + return buf.toString(); + + } // end encodeStringWildcards + + /*-------------------------------------------------------------------------------- + * Abstract declarations from interface DBUtilities + *-------------------------------------------------------------------------------- + */ + + public abstract java.util.Date getDateTime(ResultSet rs, String column) throws SQLException; + + public abstract java.util.Date getDateTime(ResultSet rs, int column) throws SQLException; + + public abstract void setDateTime(PreparedStatement stmt, int index, java.util.Date date) throws SQLException; + + public abstract void testDatabase(Connection conn) throws SQLException; + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + public static DBUtilities get(String type) throws Exception + { + String impl_class_name = DBUtilitiesImpl.class.getName() + "_" + type.toLowerCase(); + Method m = Class.forName(impl_class_name).getMethod("get",ARGS_TYPE); + return (DBUtilities)(m.invoke(null,ARGS)); + + } // end get + +} // end class DBUtilitiesImpl diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/DBUtilitiesImpl_mysql.java b/src/dynamo-framework/com/silverwrist/dynamo/db/DBUtilitiesImpl_mysql.java new file mode 100644 index 0000000..9a8971e --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/DBUtilitiesImpl_mysql.java @@ -0,0 +1,201 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.sql.*; +import java.util.*; +import com.silverwrist.util.SQLUtils; +import com.silverwrist.dynamo.iface.DBUtilities; + +public class DBUtilitiesImpl_mysql extends DBUtilitiesImpl +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static DBUtilitiesImpl_mysql _self = null; + + // used to convert dates and times to UTC for sending to SQL + private static SimpleTimeZone utc = new SimpleTimeZone(0,"UTC"); + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + private DBUtilitiesImpl_mysql() + { + super(); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + /** + * Converts a date-and-time string (an SQL DATETIME value) to a standard Java date. + * + * @param dstr The date-and-time string to convert, presumed to be in UTC. + * @return The converted date and time. + * @exception java.sql.SQLException The date and time string was in an invalid format. + */ + private static final java.util.Date convertDateTimeString(String dstr) throws SQLException + { + if (dstr==null) + return null; // null values are the same + + try + { // do almost the reverse process of formatting it into a string + GregorianCalendar cal = new GregorianCalendar(utc); + cal.set(Calendar.YEAR,Integer.parseInt(dstr.substring(0,4))); + cal.set(Calendar.MONTH,Integer.parseInt(dstr.substring(5,7)) - 1 + Calendar.JANUARY); + cal.set(Calendar.DAY_OF_MONTH,Integer.parseInt(dstr.substring(8,10))); + cal.set(Calendar.HOUR_OF_DAY,Integer.parseInt(dstr.substring(11,13))); + cal.set(Calendar.MINUTE,Integer.parseInt(dstr.substring(14,16))); + cal.set(Calendar.SECOND,Integer.parseInt(dstr.substring(17,19))); + return cal.getTime(); + + } // end try + catch (NumberFormatException e) + { // the NumberFormatException becomes an SQLException + throw new SQLException("invalid DATETIME field format"); + + } // end catch + + } // end convertDateString + + /** + * Encodes a date as an SQL date/time string, expressed in UTC. + * + * @param d The date to be encoded. + * @return The string equivalent of that date. + */ + private static final String encodeDate(java.util.Date d) + { + // Break down the date as a UTC value. + GregorianCalendar cal = new GregorianCalendar(utc); + cal.setTime(d); + + // Create the two string buffers converting the date. + StringBuffer rc = new StringBuffer(); + StringBuffer conv = new StringBuffer(); + String c; + + // Encode the year first. + conv.append("0000").append(cal.get(Calendar.YEAR)); + c = conv.toString(); + rc.append(c.substring(c.length()-4)).append('-'); + + // Now the month... + conv.setLength(0); + conv.append("00").append(cal.get(Calendar.MONTH) - Calendar.JANUARY + 1); + c = conv.toString(); + rc.append(c.substring(c.length()-2)).append('-'); + + // And the day... + conv.setLength(0); + conv.append("00").append(cal.get(Calendar.DAY_OF_MONTH)); + c = conv.toString(); + rc.append(c.substring(c.length()-2)).append(' '); + + // And the hour... + conv.setLength(0); + conv.append("00").append(cal.get(Calendar.HOUR_OF_DAY)); + c = conv.toString(); + rc.append(c.substring(c.length()-2)).append(':'); + + // And the minute... + conv.setLength(0); + conv.append("00").append(cal.get(Calendar.MINUTE)); + c = conv.toString(); + rc.append(c.substring(c.length()-2)).append(':'); + + // And the second... + conv.setLength(0); + conv.append("00").append(cal.get(Calendar.SECOND)); + c = conv.toString(); + rc.append(c.substring(c.length()-2)); + + // This is the resulting date/time value. + return rc.toString(); + + } // end encodeDate + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class DBUtilitiesImpl + *-------------------------------------------------------------------------------- + */ + + public java.util.Date getDateTime(ResultSet rs, String column) throws SQLException + { + return convertDateTimeString(rs.getString(column)); + + } // end getDateTime + + public java.util.Date getDateTime(ResultSet rs, int column) throws SQLException + { + return convertDateTimeString(rs.getString(column)); + + } // end getDateTime + + public void setDateTime(PreparedStatement stmt, int index, java.util.Date date) throws SQLException + { + stmt.setString(index,encodeDate(date)); + + } // end setDateTime + + public void testDatabase(Connection conn) throws SQLException + { + Statement stmt = null; + ResultSet rs = null; + try + { // execute a simple SQL statement + stmt = conn.createStatement(); + rs = stmt.executeQuery("SELECT 1;"); + if (!rs.next()) + throw new SQLException("MySQL database test failed(1)"); + if (rs.getInt(1)!=1) + throw new SQLException("MySQL database test failed(2)"); + + } // end try + finally + { // close down statement and result set + SQLUtils.shutdown(rs); + SQLUtils.shutdown(conn); + + } // end finally + + } // end testDatabase + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + public static DBUtilities get() + { + if (_self==null) + _self = new DBUtilitiesImpl_mysql(); + return _self; + + } // end get + +} // end class DBUtilitiesImpl_mysql diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/DatabaseConnectionPool.java b/src/dynamo-framework/com/silverwrist/dynamo/db/DatabaseConnectionPool.java new file mode 100644 index 0000000..a3298af --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/DatabaseConnectionPool.java @@ -0,0 +1,652 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.sql.*; +import java.util.*; +import org.apache.log4j.Logger; +import org.w3c.dom.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.Namespaces; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +/** + * A simple pooling system for JDBC connections, which allows connections to be kept in a pool until + * they're needed, avoiding the overhead of opening and closing connections for each transaction, or + * keeping one database connection open for each user.

+ * Based on some code from Marty Hall's Core Servlets and Java Server Pages (Prentice Hall/ + * Sun Microsystems, 2000). + * + * @author Eric J. Bowersox <erbo@silcom.com> + * @version X + */ +public class DatabaseConnectionPool implements DBConnectionPool, ComponentInitialize, ComponentShutdown +{ + /*-------------------------------------------------------------------------------- + * Internal background thread object + *-------------------------------------------------------------------------------- + */ + + private class BackgroundThread extends Thread + { + /*==================================================================== + * Constructor + *==================================================================== + */ + + BackgroundThread() + { + super("DatabaseConnectionPool_bkgd_" + (s_thread_counter++)); + + } // end constructor + + /*==================================================================== + * Overrides from class Thread + *==================================================================== + */ + + public void run() + { + try + { // attempt to create another connection in the background + Connection c = makeNewConnection(); + synchronized (DatabaseConnectionPool.this) + { // we've got a new available connection - let everyone know + if (logger.isDebugEnabled()) + logger.debug("created new connection in the background"); + m_avail_connections.addElement(c); + m_pending = false; + DatabaseConnectionPool.this.notifyAll(); + + } // end synchronized block + + } // end try + catch (Exception e) + { // caught an SQLException or an OutOfMemory exception + logger.warn("background connection thread caught exception",e); + // ditch this new connection and wait until an existing one frees up + + } // end catch + + } // end run + + } // end BackgroundThread + + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(DatabaseConnectionPool.class); + + private static final Map INFER_TYPE_MAP; // used to infer database type from JDBC driver classname + + private static int s_thread_counter = 1; // counter for data pool threads + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String m_name; // name of connection pool + private String m_dbtype; // database type + private String m_driver; // name of JDBC driver class + private String m_url; // URL for JDBC connection + private String m_username; // username for JDBC connection + private String m_password; // password for JDBC connection + private int m_max_conns; // maximum number of possible connections + private boolean m_wait_if_busy; // do we wait for a connection if none is available? + private boolean m_pending = false; // pending connection being created? + private Vector m_avail_connections = null; // connections which are available for use + private Vector m_busy_connections = null; // connections which are currently in use + private DBUtilities m_util_object; // utilities object + private PropertySerializer m_psz; // property serializer object + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + /** + * Creates a new DatabaseCOnnectionPool object. Commonly called at initialization time, + * when the objects are created from the Dynamo XML configuration file. + */ + public DatabaseConnectionPool() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + /** + * Creates a standard database exception. + * + * @param message The message ID from the "DatabaseMessages" bundle to load. + * @return The new exception object. + */ + private static final DatabaseException newException(String message) + { + return new DatabaseException(DatabaseConnectionPool.class,"DatabaseMessages",message); + + } // end newException + + /** + * Creates a standard database exception. + * + * @param message The message ID from the "DatabaseMessages" bundle to load. + * @param inner The exception to wrap in the new + * {@link com.silverwrist.dynamo.except.DatabaseException DatabaseException} object. + * @return The new exception object. + */ + private static final DatabaseException newException(String message, Throwable inner) + { + return new DatabaseException(DatabaseConnectionPool.class,"DatabaseMessages",message,inner); + + } // end newException + + /** + * Closes all database connections in the specified vector. + * + * @param vconn Vector of connections to be closed. + */ + private static final void closeConnections(Vector vconn) + { + if (logger.isDebugEnabled()) + logger.debug("closeConnections(" + vconn.size() + " to be closed)"); + + for (int i=0; iklass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass) + { + if (klass==DBUtilities.class) + return m_util_object; + if (klass==PropertySerializer.class) + return m_psz; + if (klass==DBConnectionPool.class) + return (DBConnectionPool)this; + throw new NoSuchServiceException("DatabaseConnectionPool",klass); + + } // end queryService + + /** + * Queries this object for a specified service. + * + * @param klass The class of the object that should be returned as a service. + * @param serviceid ID for the service to be requested, to further discriminate between requests. + * @return A service object. The service object is guaranteed to be of the class + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass, String serviceid) + { + return this.queryService(klass); + + } // end queryService + + /*-------------------------------------------------------------------------------- + * Implementations from interface DBConnectionPool + *-------------------------------------------------------------------------------- + */ + + /** + * Returns a simple string identifying the database type. This is commonly used in database operations + * classes to create classnames that are dynamically loaded. + * + * @return The database identifier. + */ + public String getDatabaseType() + { + return m_dbtype; + + } // end getDatabaseType + + /** + * Returns the number of connections currently being managed by this connection pool. + * + * @return The number of connections currently being managed by this connection pool. + */ + public int numConnections() + { + if (m_busy_connections==null) + return 0; + int rc = m_avail_connections.size() + m_busy_connections.size(); + if (logger.isDebugEnabled()) + logger.debug("numConnections() => " + rc); + return rc; + + } // end numConnections + + /** + * Obtains a database connection object from the connection pool. + * + * @return The Connection object. + * @exception com.silverwrist.dynamo.except.DatabaseException If a connection could not be obtained. + */ + public synchronized Connection getConnection() throws DatabaseException + { + if (m_busy_connections==null) + throw newException("dbx.notInitialized"); + + for (;;) + { // loop until we get a connection or throw an exception + if (m_avail_connections.isEmpty()) + { // no connections available - we may need to make a new one + if (logger.isDebugEnabled()) + logger.debug("no connections available - looking to get one"); + if ((numConnections() < m_max_conns) && !m_pending) + makeBackgroundConnection(); // try to create a new connection + else if (!m_wait_if_busy) + { // don't want to wait? tough, we're h0sed! + logger.error("exhausted maximum connection limit (" + m_max_conns + ")"); + throw newException("dbx.connectionLimit"); + + } // end else if + + // Wait for the background connect attempt to finish, or for + // someone to return a connection. + try + { // park the thread here until we know what's up + wait(); + + } // end try + catch (InterruptedException e) + { // do nothing + } // end catch + + // now fall through the loop and try again + + } // end if + else + { // pull the last connection off the available list... + int ndx = m_avail_connections.size() - 1; + Connection rc = (Connection)(m_avail_connections.elementAt(ndx)); + m_avail_connections.removeElementAt(ndx); + try + { // see if this is a good connection or not... + if (rc.isClosed()) + { // this connection is closed - discard it, and notify any waiters that a slot + // has opened up + if (logger.isDebugEnabled()) + logger.debug("discarding closed connection"); + notifyAll(); + rc = null; + // fall out to the end of the loop and try again + + } // end if + else + { // this connection is OK - return it + m_busy_connections.addElement(rc); + return rc; + + } // end else + + } // end try + catch (SQLException e) + { // if isClosed() throws a SQLException, the connection is somehow broken + logger.warn("connection is borked, discarding",e); + notifyAll(); + rc = null; + // fall out to the end of the loop and try again + + } // end catch + + } // end else (at least one connection available) + + } // end for (ever) + + } // end getConnection + + /** + * Returns a database connection object to the connection pool. + * + * @param conn The Connection object to be released. + * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error returning the connection. + */ + public synchronized void releaseConnection(Connection conn) throws DatabaseException + { + if (m_busy_connections==null) + throw newException("dbx.notInitialized"); + + if (conn!=null) + { // move from one vector to another + m_busy_connections.removeElement(conn); + m_avail_connections.addElement(conn); + notifyAll(); // wake up! Got a new connection for you! + + } // end if + + } // end releaseConnection + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentInitialize + *-------------------------------------------------------------------------------- + */ + + /** + * Initialize the database connection. + * + * @param config_root Pointer to the <dbconnection/> section of the Dynamo XML configuration file that + * configures this database connection. This is to be considered "read-only" by the component. + * @param services An implementation of {@link com.silverwrist.dynamo.iface.ServiceProvider ServiceProvider} + * which provides initialization services to the component. This will include an implementation + * of {@link com.silverwrist.dynamo.iface.ObjectProvider ObjectProvider} which may be used to + * get information about other objects previously initialized by the application. + * @exception com.silverwrist.dynamo.except.ConfigException If an error is encountered in the component + * configuration. + */ + public void initialize(Element config_root, ServiceProvider services) throws ConfigException + { + XMLLoader loader = XMLLoader.get(); + try + { // verify the right node name + loader.verifyNodeName(config_root,"dbconnection"); + + // get the object's name + m_name = loader.getAttribute(config_root,"name"); + + // get the various settings + DOMElementHelper h = new DOMElementHelper(config_root); + m_dbtype = h.getSubElementText("dbtype"); + if (logger.isDebugEnabled() && (m_dbtype!=null)) + logger.debug("DatabaseConnectionPool specified database type: " + m_dbtype); + + m_driver = loader.getSubElementText(h,"driver"); + if (logger.isDebugEnabled()) + logger.debug("DatabaseConnectionPool driver: " + m_driver); + + // If the database type is not known, try to infer it from the driver name. + if (m_dbtype==null) + m_dbtype = (String)(INFER_TYPE_MAP.get(m_driver)); + if (m_dbtype==null) + { // wasn't specified, can't infer it - we are HOSED! + ConfigException ce = new ConfigException(DatabaseConnectionPool.class,"DatabaseMessages", + "config.inferType"); + ce.setParameter(0,m_driver); + throw ce; + + } // end if + else if (logger.isDebugEnabled()) + logger.debug("DatabaseConnectionPool inferred database type: " + m_dbtype); + + m_url = loader.getSubElementText(h,"uri"); + if (logger.isDebugEnabled()) + logger.debug("DatabaseConnectionPool URI: " + m_url); + + m_username = loader.getSubElementText(h,"username"); + if (logger.isDebugEnabled()) + logger.debug("DatabaseConnectionPool user name: " + m_username); + + m_password = loader.getSubElementText(h,"password"); + + Element elt = loader.getSubElement(h,"connections"); + int initial_conn = loader.getAttributeInt(elt,"initial",0); + if (initial_conn<0) + throw new ConfigException(DatabaseConnectionPool.class,"DatabaseMessages","config.initialConn"); + if (logger.isDebugEnabled()) + logger.debug("DatabaseConnectionPool initial connections: " + initial_conn); + + m_max_conns = loader.getAttributeInt(elt,"max"); + if (m_max_conns<0) + throw new ConfigException(DatabaseConnectionPool.class,"DatabaseMessages","config.maxConn"); + if (logger.isDebugEnabled()) + logger.debug("DatabaseConnectionPool maximum connections: " + m_max_conns); + + m_wait_if_busy = loader.getAttributeBoolean(elt,"busywait",true); + if (logger.isDebugEnabled()) + logger.debug("DatabaseConnectionPool wait if busy: " + m_wait_if_busy); + + if (initial_conn>m_max_conns) + { // fix initial value if above maximum + if (logger.isDebugEnabled()) + logger.debug("N.B.: reducing configured initial connections"); + initial_conn = m_max_conns; + + } // end if + + try + { // get the appropriate utilities object + m_util_object = DBUtilitiesImpl.get(m_dbtype); + + } // end if + catch (Exception e) + { // the utilities are not implemented + ConfigException ce = new ConfigException(DatabaseConnectionPool.class,"DatabaseMessages", + "utils.impl",e); + ce.setParameter(0,m_dbtype); + throw ce; + + } // end catch + + // Get the master property serializer so we can offer it as a service. + m_psz = (PropertySerializer)(services.queryService(PropertySerializer.class)); + + // Create the vectors that hold connections. + m_avail_connections = new Vector(initial_conn); + m_busy_connections = new Vector(); + + // Populate the "available connection" vector. + for (int i=0; iConnection objects. + */ + public void shutdown() + { + closeConnections(m_avail_connections); + m_avail_connections = null; + closeConnections(m_busy_connections); + m_busy_connections = null; + + } // end shutdown + + /*-------------------------------------------------------------------------------- + * Static initializer + *-------------------------------------------------------------------------------- + */ + + static + { // Create the database type inference map. + HashMap map = new HashMap(); + map.put("com.mysql.jdbc.Driver","mysql"); + map.put("org.gjt.mm.mysql.Driver","mysql"); + INFER_TYPE_MAP = Collections.unmodifiableMap(map); + + } // end static initializer + +} // end class DatabaseConnectionPool diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/DatabaseMessages.properties b/src/dynamo-framework/com/silverwrist/dynamo/db/DatabaseMessages.properties new file mode 100644 index 0000000..6ca3d36 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/DatabaseMessages.properties @@ -0,0 +1,58 @@ +# The contents of this file are subject to the Mozilla Public License Version 1.1 +# (the "License"); you may not use this file except in compliance with the License. +# You may obtain a copy of the License at . +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +# --------------------------------------------------------------------------------- +# This file has been localized for the en_US locale +dbx.notInitialized=The connection pool object has not been initialized +dbx.classNotFound=Can't find JDBC driver class: {0} +dbx.illegalAccess=Can't access JDBC driver class: {0} +dbx.instantiation=Can't create JDBC driver class: {0} +dbx.sqlMakeNewConn=Can't create new database connection +dbx.connectionLimit=Connection limit reached +dbx.testfail=Test failed on database {0} (url {1}): {2} +config.inferType=Database type was not specified, and unable to infer it from JDBC driver name "{0}". +config.initialConn=Invalid initial connections parameter +config.maxConn=Invalid maximum connections parameter +config.create=Unable to create initial database connections +utils.impl=Database utilities are not implemented for database type "{0}". +load.opsClass=Unable to load {2} class for database "{1}": {0} +general=Database access failure: {0} +nsCache.notFound=Unknown namespace ID seen; possible internal error. +property.serialize=The value of property "{0}" could not be serialized. +property.deserialize=The value of property "{0}" could not be deserialized. +ose.setProperty=Unable to set the value of property "{1}" in namespace "{0}". +ose.removeProperty=Unable to remove the value of property "{1}" in namespace "{0}". +ose.getNamespaces=Unable to enumerate the namespaces in this ObjectStore. +ose.getNames=Unable to enumerate the object names in namespace "{0}". +auth.register=Authenticator already registered for namespace "{0}", name "{1}". +auth.notFound=No authenticator registered for namespace "{0}", name "{1}". +auth.noUserData=User cannot authenticate with authenticator namespace "{0}", name "{1}". +ose.setBlock=Unable to set the value of block "{1}" in namespace "{0}". +ose.removeBlock=Unable to remove the value of block "{1}" in namespace "{0}". +sec.changeUser=You are not permitted to change the attributes of user "{0}". +sec.needSec=You cannot perform this operation on a group without specifying a user making the change. +sec.setGroupProperty=You are not permitted to set property values for group "{0}". +sec.removeGroupProperty=You are not permitted to remove property values from group "{0}". +sec.addGroupMember=You are not permitted to add members to group "{0}". +sec.removeGroupMember=You are not permitted to remove members from group "{0}". +sec.setGroupAcl=You are not permitted to change the access control list of group "{0}". +sec.setGlobalProperty=You are not permitted to set the global property. +sec.removeGlobalProperty=You are not permitted to remove the global property. +sec.setGlobalBlock=You are not permitted to set the global block. +sec.removeGlobalBlock=You are not permitted to remove the global block. +img.loadFail=Failed to load image {0} due to I/O error. +img.badOwner=Invalid owner for new image. +img.notOwner=You are not the owner of image {0}. +img.normalize=Image normalization of {0} failed: {1}. diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/DefaultHashAuthenticator.java b/src/dynamo-framework/com/silverwrist/dynamo/db/DefaultHashAuthenticator.java new file mode 100644 index 0000000..b0767b3 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/DefaultHashAuthenticator.java @@ -0,0 +1,111 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.security.MessageDigest; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +class DefaultHashAuthenticator implements Authenticator +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + DefaultHashAuthenticator() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * IMplementations from interface Authenticator + *-------------------------------------------------------------------------------- + */ + + public boolean authenticate(String stored_data, String input_data) throws AuthenticationException + { + return stored_data.equals(hashPassword(input_data)); + + } // end authenticate + + public String processInputData(String input_data) throws AuthenticationException + { + return hashPassword(input_data); + + } // end processInputData + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + public static final String hashPassword(String password) + { + if ((password!=null) && (password.length()>0)) + { // hash the password and save the hash value + MessageDigest hasher; + + try + { // get a hasher implementing the Secure Hashing Algorithm + hasher = MessageDigest.getInstance("SHA"); + + } // end try + catch (java.security.NoSuchAlgorithmException e) + { // SHA should be a standard algorithm...if it isn't, we're h0sed + throw new RuntimeException("HOSED JRE - SHA should be a standard algorithm"); + + } // end catch + + try + { // update the hasher with the UTF-8 bytes of the password + hasher.update(password.getBytes("UTF8")); + + } // end try + catch (java.io.UnsupportedEncodingException e) + { // WTF? How can the JRE NOT know about UTF-8? HOW?!? + throw new RuntimeException("HOSED JRE - UTF-8 encoding should be supported"); + + } // end catch + + // Retrieve the raw hash value (should be 160 bits, or 20 bytes) + byte[] raw_hash = hasher.digest(); + + // Convert the hash value to a hexadecimal string (40 chars in length) + StringBuffer hash_buf = new StringBuffer(raw_hash.length * 2); + StringBuffer tmp_buf = new StringBuffer(); + String tmp; + for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.util.*; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.event.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.security.SecurityReferenceMonitor; +import com.silverwrist.dynamo.util.*; + +class GlobalBlocksObject implements SecureObjectStore +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private GlobalBlocksOps m_ops; // operations object + private NamespaceCache m_ns_cache; // namespace cache + private SecurityReferenceMonitor m_srm; // security reference monitor + private PostDynamicUpdate m_post; // where we post dynamic events + private HardSoftCache m_cache; // our cache + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + GlobalBlocksObject(DBConnectionPool pool, NamespaceCache ns_cache, SecurityReferenceMonitor srm, + PostDynamicUpdate post, int hard_limit, int soft_limit) throws ConfigException + { + m_ops = GlobalBlocksOps.get(pool); + m_ns_cache = ns_cache; + m_srm = srm; + m_post = post; + m_cache = new HardSoftCache(hard_limit,soft_limit); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private final void testPermission(DynamoUser caller, String perm_namespace, String perm_name, + String fail_message) throws DatabaseException, DynamoSecurityException + { + if (caller.equals(m_srm.getAdminUser())) + return; // Administrator can do anything + if (m_srm.getGlobalAcl().testPermission(caller,perm_namespace,perm_name)) + return; // we have the right permission in the ACL + throw new DynamoSecurityException(GroupObject.class,"DatabaseMessages",fail_message); + + } // end testPermission + + /*-------------------------------------------------------------------------------- + * Implementations from interface ObjectProvider + *-------------------------------------------------------------------------------- + */ + + /** + * Retrieves an object from this ObjectProvider. + * + * @param namespace The namespace to interpret the name relative to. + * @param name The name of the object to be retrieved. + * @return The object reference specified. + */ + public Object getObject(String namespace, String name) + { + try + { // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + Object rc = null; + synchronized (this) + { // start by looking in the block cache + rc = m_cache.get(key); + if (rc==null) + { // no use - need to try the database + rc = m_ops.getBlock(key); + if (rc!=null) + m_cache.put(key,rc); + + } // end if + + } // end synchronized block + + if (rc==null) + throw new NoSuchObjectException(this.toString(),namespace,name); + return rc; + + } // end try + catch (DatabaseException e) + { // translate into our NoSuchObjectException but retain the DatabaseException + throw new NoSuchObjectException(this.toString(),namespace,name,e); + + } // end catch + + } // end getObject + + /*-------------------------------------------------------------------------------- + * Implementations from interface SecureObjectStore + *-------------------------------------------------------------------------------- + */ + + public Object setObject(DynamoUser caller, String namespace, String name, Object value) + throws DatabaseException, DynamoSecurityException + { + testPermission(caller,namespace,"set.block","sec.setGlobalBlock"); + Object rc = null; + // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + synchronized (this) + { // start by setting the database value + rc = m_ops.putBlock(key,value.toString()); + + // and cache it, too + m_cache.put(key,value.toString()); + + } // end synchronized block + + m_post.postUpdate(new GlobalBlockUpdateEvent(this,namespace,name)); + return rc; + + } // end setObject + + public Object removeObject(DynamoUser caller, String namespace, String name) + throws DatabaseException, DynamoSecurityException + { + testPermission(caller,namespace,"remove.block","sec.removeGlobalBlock"); + Object rc = null; + // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + synchronized (this) + { // start by killing the database value + rc = m_ops.removeBlock(key); + + // and remove the cached value, too + m_cache.remove(key); + + } // end synchronized block + + m_post.postUpdate(new GlobalBlockUpdateEvent(this,namespace,name)); + return rc; + + } // end removeObject + + public Collection getNamespaces() throws DatabaseException + { + // call through to the database to get the list of namespace IDs + int[] ids = m_ops.getBlockNamespaceIDs(); + + ArrayList rc = new ArrayList(ids.length); + for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.util.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.util.*; + +abstract class GlobalBlocksOps extends OpsBase +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + protected GlobalBlocksOps(DBConnectionPool pool) + { + super(pool); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class OpsBase + *-------------------------------------------------------------------------------- + */ + + public void dispose() + { + super.dispose(); + + } // end dispose + + /*-------------------------------------------------------------------------------- + * Abstract operations + *-------------------------------------------------------------------------------- + */ + + abstract String getBlock(PropertyKey key) throws DatabaseException; + + abstract String putBlock(PropertyKey key, String data) throws DatabaseException; + + abstract String removeBlock(PropertyKey key) throws DatabaseException; + + abstract int[] getBlockNamespaceIDs() throws DatabaseException; + + abstract Collection getAllBlockNames(int nsid) throws DatabaseException; + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + static GlobalBlocksOps get(DBConnectionPool pool) throws ConfigException + { + return (GlobalBlocksOps)get(pool,GlobalBlocksOps.class.getClassLoader(), + GlobalBlocksOps.class.getName() + "_","GlobalBlocksOps"); + + } // end get + +} // end class GlobalBlocksOps diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/GlobalBlocksOps_mysql.java b/src/dynamo-framework/com/silverwrist/dynamo/db/GlobalBlocksOps_mysql.java new file mode 100644 index 0000000..59b4d69 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/GlobalBlocksOps_mysql.java @@ -0,0 +1,284 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.sql.*; +import java.util.*; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +public class GlobalBlocksOps_mysql extends GlobalBlocksOps +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private DBUtilities m_utils; // reference to utilities object + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public GlobalBlocksOps_mysql(DBConnectionPool pool) + { + super(pool); + m_utils = (DBUtilities)(pool.queryService(DBUtilities.class)); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class GlobalBlocksOps + *-------------------------------------------------------------------------------- + */ + + String getBlock(PropertyKey key) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // look up the block + stmt = conn.prepareStatement("SELECT block FROM globalblock WHERE nsid = ? AND block_name = ?;"); + stmt.setInt(1,key.getNamespaceID()); + stmt.setString(2,key.getName()); + rs = stmt.executeQuery(); + if (!(rs.next())) + return null; // block not found + return rs.getString(1); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + } // end getBlock + + String putBlock(PropertyKey key, String data) throws DatabaseException + { + String old_value = null; + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the table + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES globalblock WRITE;"); + + // look to see if the block value is already there + stmt = conn.prepareStatement("SELECT block FROM globalblock WHERE nsid = ? AND block_name = ?;"); + stmt.setInt(1,key.getNamespaceID()); + stmt.setString(2,key.getName()); + rs = stmt.executeQuery(); + if (rs.next()) + old_value = rs.getString(1); + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + + if (old_value!=null) + { // prepare the statement to update the existing record + stmt = conn.prepareStatement("UPDATE globalblock SET block = ? WHERE nsid = ? AND block_name = ?;"); + stmt.setString(1,data); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + + } // end if + else + { // prepare the statement to insert a new record + stmt = conn.prepareStatement("INSERT INTO globalblock (nsid, block_name, block) VALUES (?, ?, ?);"); + stmt.setInt(1,key.getNamespaceID()); + stmt.setString(2,key.getName()); + stmt.setString(3,data); + + } // end else + + stmt.executeUpdate(); // execute it! + + return old_value; // return previous value + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end putBlock + + String removeBlock(PropertyKey key) throws DatabaseException + { + String old_value = null; + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the table + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES globalblock WRITE;"); + + // look to see if the property value is already there + stmt = conn.prepareStatement("SELECT block FROM globalblock WHERE nsid = ? AND block_name = ?;"); + stmt.setInt(1,key.getNamespaceID()); + stmt.setString(2,key.getName()); + rs = stmt.executeQuery(); + if (rs.next()) + old_value = rs.getString(1); + else + return null; // no need to remove anything + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + + // delete the database row + stmt = conn.prepareStatement("DELETE FROM globalblock WHERE nsid = ? AND block_name = ?;"); + stmt.setInt(1,key.getNamespaceID()); + stmt.setString(2,key.getName()); + stmt.executeUpdate(); + + return old_value; + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end removeBlock + + int[] getBlockNamespaceIDs() throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // execute the query! + stmt = conn.prepareStatement("SELECT DISTINCT nsid FROM globalblock;"); + rs = stmt.executeQuery(); + + // read out a list of the namespace IDs + ArrayList tmp = new ArrayList(); + while (rs.next()) + tmp.add(new Integer(rs.getInt(1))); + + // create and return the array + int[] rc = new int[tmp.size()]; + for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import org.w3c.dom.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.security.SecurityReferenceMonitor; +import com.silverwrist.dynamo.util.*; + +public class GlobalDataManagerObject + implements NamedObject, ComponentInitialize, ComponentShutdown, ServiceProvider +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final int DEFAULT_HARD_LIMIT = 5; + private static final int DEFAULT_SOFT_LIMIT = 20; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String m_name; // object name + private DBConnectionPool m_pool; // database connection pool + private NamespaceCache m_ns_cache; // namespace cache object + private SecurityReferenceMonitor m_srm; // security reference monitor + private PostDynamicUpdate m_post; // dynamic update poster + private GlobalPropertiesObject m_properties; // global properties object + private GlobalBlocksObject m_blocks; // global blocks object + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public GlobalDataManagerObject() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface NamedObject + *-------------------------------------------------------------------------------- + */ + + public String getName() + { + return m_name; + + } // end getName + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentInitialize + *-------------------------------------------------------------------------------- + */ + + public void initialize(Element config_root, ServiceProvider services) throws ConfigException + { + String conn_name = null; + String nscache_name = null; + String srm_name = null; + int hard_limit = DEFAULT_HARD_LIMIT; + int soft_limit = DEFAULT_SOFT_LIMIT; + XMLLoader loader = XMLLoader.get(); + try + { // verify the right node name + loader.verifyNodeName(config_root,"object"); + + // get the object's name + m_name = loader.getAttribute(config_root,"name"); + + // get the database configuration connection + DOMElementHelper config_root_h = new DOMElementHelper(config_root); + Element elt = loader.getSubElement(config_root_h,"database"); + conn_name = loader.getAttribute(elt,"connection"); + nscache_name = loader.getAttribute(elt,"namespaces"); + + // get the security reference monitor reference + elt = loader.getSubElement(config_root_h,"security"); + srm_name = loader.getAttribute(elt,"object"); + + // get the block cache information + elt = config_root_h.getSubElement("block-cache"); + if (elt!=null) + { // get the cache limits + hard_limit = loader.getAttributeInt(elt,"hardlimit",DEFAULT_HARD_LIMIT); + soft_limit = loader.getAttributeInt(elt,"softlimit",DEFAULT_SOFT_LIMIT); + + } // end if + + } // end try + catch (XMLLoadException e) + { // error loading XML config data + throw new ConfigException(e); + + } // end catch + + // Get the database connection pool and the namespace cache. + m_pool = GetObjectUtils.getDatabaseConnection(services,conn_name); + m_ns_cache = + (NamespaceCache)(GetObjectUtils.getDynamoComponent(services,NamespaceCache.class,nscache_name)); + m_srm = + (SecurityReferenceMonitor)(GetObjectUtils.getDynamoComponent(services,SecurityReferenceMonitor.class, + srm_name)); + m_post = (PostDynamicUpdate)(services.queryService(PostDynamicUpdate.class)); + + // Create the subobjects. + m_properties = new GlobalPropertiesObject(m_pool,m_ns_cache,m_srm,m_post); + m_blocks = new GlobalBlocksObject(m_pool,m_ns_cache,m_srm,m_post,hard_limit,soft_limit); + + } // end initialize + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentShutdown + *-------------------------------------------------------------------------------- + */ + + public void shutdown() + { + m_pool = null; + m_ns_cache = null; + m_srm = null; + m_post = null; + + } // end shutdown + + /*-------------------------------------------------------------------------------- + * Implementations from interface ServiceProvider + *-------------------------------------------------------------------------------- + */ + + /** + * Queries this object for a specified service. + * + * @param klass The class of the object that should be returned as a service. + * @return A service object. The service object is guaranteed to be of the class + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass) + { + if ((klass==SecureObjectStore.class) || (klass==ObjectProvider.class)) + return (SecureObjectStore)m_properties; + throw new NoSuchServiceException("GlobalDataManagerObject",klass); + + } // end queryService + + /** + * Queries this object for a specified service. + * + * @param klass The class of the object that should be returned as a service. + * @param serviceid ID for the service to be requested, to further discriminate between requests. + * @return A service object. The service object is guaranteed to be of the class + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) + * is true. + * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in + * the specified class. + */ + public Object queryService(Class klass, String serviceid) + { + if ((klass==SecureObjectStore.class) || (klass==ObjectProvider.class)) + { // return service + if ((serviceid==null) || serviceid.equals("properties")) + return (SecureObjectStore)m_properties; + if (serviceid.equals("blocks")) + return (SecureObjectStore)m_blocks; + throw new NoSuchServiceException("GlobalDataManagerObject",klass,serviceid); + + } // end if + + try + { // look for the class without a service ID + return this.queryService(klass); + + } // end try + catch (NoSuchServiceException e) + { // transform exception for return + throw new NoSuchServiceException(e.getContext(),klass,serviceid,e); + + } // end catch + + } // end queryService + +} // end class GlobalDataManagerObject diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/GlobalPropertiesObject.java b/src/dynamo-framework/com/silverwrist/dynamo/db/GlobalPropertiesObject.java new file mode 100644 index 0000000..11c5132 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/GlobalPropertiesObject.java @@ -0,0 +1,201 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.util.*; +import org.apache.commons.collections.*; +import com.silverwrist.dynamo.event.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.security.SecurityReferenceMonitor; +import com.silverwrist.dynamo.util.*; + +class GlobalPropertiesObject implements SecureObjectStore +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private GlobalPropertiesOps m_ops; // operations object + private NamespaceCache m_ns_cache; // namespace cache + private SecurityReferenceMonitor m_srm; // security reference monitor + private PostDynamicUpdate m_post; // where we post dynamic events + private ReferenceMap m_properties; // cached property values + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + GlobalPropertiesObject(DBConnectionPool pool, NamespaceCache ns_cache, SecurityReferenceMonitor srm, + PostDynamicUpdate post) throws ConfigException + { + m_ops = GlobalPropertiesOps.get(pool); + m_ns_cache = ns_cache; + m_srm = srm; + m_post = post; + m_properties = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private final void testPermission(DynamoUser caller, String perm_namespace, String perm_name, + String fail_message) throws DatabaseException, DynamoSecurityException + { + if (caller.equals(m_srm.getAdminUser())) + return; // Administrator can do anything + if (m_srm.getGlobalAcl().testPermission(caller,perm_namespace,perm_name)) + return; // we have the right permission in the ACL + throw new DynamoSecurityException(GroupObject.class,"DatabaseMessages",fail_message); + + } // end testPermission + + /*-------------------------------------------------------------------------------- + * Implementations from interface ObjectProvider + *-------------------------------------------------------------------------------- + */ + + /** + * Retrieves an object from this ObjectProvider. + * + * @param namespace The namespace to interpret the name relative to. + * @param name The name of the object to be retrieved. + * @return The object reference specified. + */ + public Object getObject(String namespace, String name) + { + try + { // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + Object rc = null; + synchronized (this) + { // start by looking in the properties map + rc = m_properties.get(key); + if (rc==null) + { // no use - need to try the database + rc = m_ops.getProperty(key); + if (rc!=null) + m_properties.put(key,rc); + + } // end if + + } // end synchronized block + + if (rc==null) + throw new NoSuchObjectException(this.toString(),namespace,name); + return rc; + + } // end try + catch (DatabaseException e) + { // translate into our NoSuchObjectException but retain the DatabaseException + throw new NoSuchObjectException(this.toString(),namespace,name,e); + + } // end catch + + } // end getObject + + /*-------------------------------------------------------------------------------- + * Implementations from interface SecureObjectStore + *-------------------------------------------------------------------------------- + */ + + public Object setObject(DynamoUser caller, String namespace, String name, Object value) + throws DatabaseException, DynamoSecurityException + { + testPermission(caller,namespace,"set.property","sec.setGlobalProperty"); + Object rc = null; + // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + synchronized (this) + { // start by setting the database value + rc = m_ops.setProperty(key,value); + + // and cache it, too + m_properties.put(key,value); + + } // end synchronized block + + m_post.postUpdate(new GlobalPropertyUpdateEvent(this,namespace,name)); + return rc; + + } // end setObject + + public Object removeObject(DynamoUser caller, String namespace, String name) + throws DatabaseException, DynamoSecurityException + { + testPermission(caller,namespace,"remove.property","sec.removeGlobalProperty"); + Object rc = null; + // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + synchronized (this) + { // start by killing the database value + rc = m_ops.removeProperty(key); + + // and remove the cached value, too + m_properties.remove(key); + + } // end synchronized block + + m_post.postUpdate(new GlobalPropertyUpdateEvent(this,namespace,name)); + return rc; + + } // end removeObject + + public Collection getNamespaces() throws DatabaseException + { + // call through to the database to get the list of namespace IDs + int[] ids = m_ops.getPropertyNamespaceIDs(); + + ArrayList rc = new ArrayList(ids.length); + for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.util.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.util.*; + +abstract class GlobalPropertiesOps extends OpsBase +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + protected GlobalPropertiesOps(DBConnectionPool pool) + { + super(pool); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class OpsBase + *-------------------------------------------------------------------------------- + */ + + public void dispose() + { + super.dispose(); + + } // end dispose + + /*-------------------------------------------------------------------------------- + * Abstract operations + *-------------------------------------------------------------------------------- + */ + + abstract Object getProperty(PropertyKey key) throws DatabaseException; + + abstract Object setProperty(PropertyKey key, Object value) throws DatabaseException; + + abstract Object removeProperty(PropertyKey key) throws DatabaseException; + + abstract int[] getPropertyNamespaceIDs() throws DatabaseException; + + abstract Map getAllProperties(int namespace) throws DatabaseException; + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + static GlobalPropertiesOps get(DBConnectionPool pool) throws ConfigException + { + return (GlobalPropertiesOps)get(pool,GlobalPropertiesOps.class.getClassLoader(), + GlobalPropertiesOps.class.getName() + "_","GlobalPropertiesOps"); + + } // end get + +} // end class GlobalPropertiesOps diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/GlobalPropertiesOps_mysql.java b/src/dynamo-framework/com/silverwrist/dynamo/db/GlobalPropertiesOps_mysql.java new file mode 100644 index 0000000..c04cbfb --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/GlobalPropertiesOps_mysql.java @@ -0,0 +1,344 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.sql.*; +import java.util.*; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +public class GlobalPropertiesOps_mysql extends GlobalPropertiesOps +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private DBUtilities m_utils; // reference to utilities object + private PropertySerializer m_psz; // reference to property serializer + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public GlobalPropertiesOps_mysql(DBConnectionPool pool) + { + super(pool); + m_utils = (DBUtilities)(pool.queryService(DBUtilities.class)); + m_psz = (PropertySerializer)(pool.queryService(PropertySerializer.class)); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class GlobalPropertiesOps + *-------------------------------------------------------------------------------- + */ + + Object getProperty(PropertyKey key) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + String rc_str = null; + try + { // get a connection + conn = getConnection(); + + // look up the property + stmt = conn.prepareStatement("SELECT prop_value FROM globalprop WHERE nsid = ? AND prop_name = ?;"); + stmt.setInt(1,key.getNamespaceID()); + stmt.setString(2,key.getName()); + rs = stmt.executeQuery(); + if (!(rs.next())) + return null; // property not found + + rc_str = rs.getString(1); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + // Deserialize the property value. + Object rc = m_psz.deserializeProperty(rc_str); + if (rc!=null) + return rc; + + // deserialization exception - throw it + DatabaseException de = new DatabaseException(GlobalPropertiesOps_mysql.class,"DatabaseMessages", + "property.deserialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end getProperty + + Object setProperty(PropertyKey key, Object value) throws DatabaseException + { + String serialized_value = m_psz.serializeProperty(value); + if (serialized_value==null) + { // serialization exception - throw it + DatabaseException de = new DatabaseException(GlobalPropertiesOps_mysql.class,"DatabaseMessages", + "property.serialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end if + + String old_value = null; + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the table + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES globalprop WRITE;"); + + // look to see if the property value is already there + stmt = conn.prepareStatement("SELECT prop_value FROM globalprop WHERE nsid = ? AND prop_name = ?;"); + stmt.setInt(1,key.getNamespaceID()); + stmt.setString(2,key.getName()); + rs = stmt.executeQuery(); + if (rs.next()) + old_value = rs.getString(1); + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + + if (old_value!=null) + { // prepare the statement to update the existing record + stmt = conn.prepareStatement("UPDATE globalprop SET prop_value = ? WHERE nsid = ? AND prop_name = ?;"); + stmt.setString(1,serialized_value); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + + } // end if + else + { // prepare the statement to insert a new record + stmt = conn.prepareStatement("INSERT INTO globalprop (nsid, prop_name, prop_value) VALUES (?, ?, ?);"); + stmt.setInt(1,key.getNamespaceID()); + stmt.setString(2,key.getName()); + stmt.setString(3,serialized_value); + + } // end else + + stmt.executeUpdate(); // execute it! + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + if (old_value==null) + return null; // no previous value + + // Deserialize the property value. + Object rc = m_psz.deserializeProperty(old_value); + if (rc!=null) + return rc; + + // deserialization exception - throw it + DatabaseException de = new DatabaseException(GlobalPropertiesOps_mysql.class,"DatabaseMessages", + "property.deserialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end setProperty + + Object removeProperty(PropertyKey key) throws DatabaseException + { + String old_value = null; + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the table + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES globalprop WRITE;"); + + // look to see if the property value is already there + stmt = conn.prepareStatement("SELECT prop_value FROM globalprop WHERE nsid = ? AND prop_name = ?;"); + stmt.setInt(1,key.getNamespaceID()); + stmt.setString(2,key.getName()); + rs = stmt.executeQuery(); + if (rs.next()) + old_value = rs.getString(1); + else + return null; // no need to remove anything + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + + // delete the database row + stmt = conn.prepareStatement("DELETE FROM globalprop WHERE nsid = ? AND prop_name = ?;"); + stmt.setInt(1,key.getNamespaceID()); + stmt.setString(2,key.getName()); + stmt.executeUpdate(); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + // Deserialize the property value. + Object rc = m_psz.deserializeProperty(old_value); + if (rc!=null) + return rc; + + // deserialization exception - throw it + DatabaseException de = new DatabaseException(GlobalPropertiesOps_mysql.class,"DatabaseMessages", + "property.deserialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end removeProperty + + int[] getPropertyNamespaceIDs() throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // execute the query! + stmt = conn.prepareStatement("SELECT DISTINCT nsid FROM globalprop;"); + rs = stmt.executeQuery(); + + // read out a list of the namespace IDs + ArrayList tmp = new ArrayList(); + while (rs.next()) + tmp.add(new Integer(rs.getInt(1))); + + // create and return the array + int[] rc = new int[tmp.size()]; + for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.security.Principal; +import java.security.acl.AclNotFoundException; +import java.util.*; +import org.apache.commons.collections.*; +import com.silverwrist.dynamo.Namespaces; +import com.silverwrist.dynamo.UserInfoNamespace; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.security.SecurityReferenceMonitor; +import com.silverwrist.dynamo.util.*; + +class GroupObject implements DynamoGroup +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final String PERM_NAMESPACE = Namespaces.GROUP_PERMISSIONS_NAMESPACE; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private GroupObjectOps m_ops; // operations object + private NamespaceCache m_ns_cache; // namespace cache object + private SecurityReferenceMonitor m_srm; // security reference monitor + private UserProxyManagement m_upm; // user proxy manager + private int m_gid; // group ID + private String m_groupname; // group name + private int m_gaclid; // group ACL ID + private ReferenceMap m_properties; // cached property values + private Object m_properties_sync = new Object(); // synchronization for above + private HashSet m_known_members = new HashSet(); // known members + private HashSet m_known_nonmembers = new HashSet(); // known nonmembers + private Object m_members_sync = new Object(); // synchronization for above + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + GroupObject(Map data, GroupObjectOps ops, NamespaceCache ns_cache, SecurityReferenceMonitor srm, + UserProxyManagement upm) + { + m_ops = ops; + m_ns_cache = ns_cache; + m_srm = srm; + m_upm = upm; + m_gid = ((Integer)(data.get(UserManagerOps.HMKEY_GID))).intValue(); + m_groupname = (String)(data.get(UserManagerOps.HMKEY_GROUPNAME)); + m_gaclid = ((Integer)(data.get(UserManagerOps.HMKEY_GACLID))).intValue(); + m_properties = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private static final int getPrincipalUID(Principal p) + { + if (p instanceof DynamoUser) + return ((DynamoUser)p).getUID(); + else + return -1; + + } // end getPrincipalUID + + private final void testOperationWithoutSecurity() + { + if (m_gaclid==-1) + return; + throw new GroupRuntimeException(new DynamoSecurityException(GroupObject.class,"DatabaseMessages", + "sec.needSec")); + + } // end testOperationWithoutSecurity + + private final void testPermission(DynamoUser caller, String perm_namespace, String perm_name, + String fail_message) throws DatabaseException, DynamoSecurityException + { + if (m_gaclid==-1) + return; + if (caller==null) + throw new DynamoSecurityException(GroupObject.class,"DatabaseMessages","sec.needSec"); + if (caller.equals(m_srm.getAdminUser())) + return; // Administrator can do anything + if (m_srm.testPermission(m_gaclid,caller,perm_namespace,perm_name)) + return; // we have the right permission in the ACL + DynamoSecurityException dse = new DynamoSecurityException(GroupObject.class,"DatabaseMessages", + fail_message); + dse.setParameter(0,m_groupname); + throw dse; + + } // end testPermission + + private final void testPermission(DynamoUser caller, int target_uid, String perm_namespace, String perm_name, + String perm2_name, String fail_message) + throws DatabaseException, DynamoSecurityException + { + if (m_gaclid==-1) + return; + if (caller==null) + throw new DynamoSecurityException(GroupObject.class,"DatabaseMessages","sec.needSec"); + if (caller.equals(m_srm.getAdminUser())) + return; // Administrator can do anything + if ((caller.getUID()==target_uid) && m_srm.testPermission(m_gaclid,caller,perm_namespace,perm2_name)) + return; // we can "join group" or "unjoin group" if we have the right permissions + if (m_srm.testPermission(m_gaclid,caller,perm_namespace,perm_name)) + return; // we have the right permission in the ACL + DynamoSecurityException dse = new DynamoSecurityException(GroupObject.class,"DatabaseMessages", + fail_message); + dse.setParameter(0,m_groupname); + throw dse; + + } // end testPermission + + private final void testAclOwner(DynamoUser caller) throws DatabaseException, DynamoSecurityException + { + if (m_gaclid==-1) + return; + if (caller==null) + throw new DynamoSecurityException(GroupObject.class,"DatabaseMessages","sec.needSec"); + if (caller.equals(m_srm.getAdminUser())) + return; // Administrator can do anything + if (m_srm.isOwnerOfAcl(m_gaclid,caller)) + return; // we own this ACL + DynamoSecurityException dse = new DynamoSecurityException(GroupObject.class,"DatabaseMessages", + "sec.setGroupAcl"); + dse.setParameter(0,m_groupname); + throw dse; + + } // end testAclOwner + + private final boolean addUIDInternal(int uid) throws DatabaseException + { + Integer key = new Integer(uid); + synchronized (m_members_sync) + { // look in the cache first + if (m_known_members.contains(key)) + return false; // we're already a known member + + // fiddle the database + boolean rc = m_ops.addMember(m_gid,uid); + m_known_members.add(key); // update the cache to reflect reality + if (m_known_nonmembers!=null) + m_known_nonmembers.remove(key); + return rc; + + } // end synchronized block + + } // end addUIDInternal + + private final boolean removeUIDInternal(int uid) throws DatabaseException + { + Integer key = new Integer(uid); + synchronized (m_members_sync) + { // look in the cache first + if (m_known_nonmembers!=null) + { // are we a known nonmember? + if (m_known_nonmembers.contains(key)) + return false; // already a nonmember + + } // end if + else + { // in this circumstance, everyone not in the members set is a nonmember + if (!(m_known_members.contains(key))) + return false; // already a nonmember + + } // end else + + // fiddle the database + boolean rc = m_ops.removeMember(m_gid,uid); + m_known_members.remove(key); // update the cache to reflect reality + if (m_known_nonmembers!=null) + m_known_nonmembers.add(key); + return rc; + + } // end synchronized block + + } // end removeUIDInternal + + /*-------------------------------------------------------------------------------- + * Implementations from interface Principal + *-------------------------------------------------------------------------------- + */ + + public boolean equals(Object another) + { + if (another==null) + return false; + if (another instanceof DynamoGroup) + return (m_gid==((DynamoGroup)another).getGID()); + return false; + + } // end equals + + public String toString() + { + return "group " + m_groupname; + + } // end toString + + public int hashCode() + { + return m_gid; + + } // end hashCode + + public String getName() + { + return m_groupname; + + } // end getName + + /*-------------------------------------------------------------------------------- + * Implementations from interface Group + *-------------------------------------------------------------------------------- + */ + + public boolean addMember(Principal user) + { + testOperationWithoutSecurity(); + try + { // break down the operations... + if (user instanceof DynamoUser) + return this.addUIDInternal(((DynamoUser)user).getUID()); + else if (user instanceof DynamoGroup) + { // add all UIDs contained in this group + int[] uids = ((DynamoGroup)user).getUIDs(); + boolean rc = false; + for (int i=0; iObjectProvider. + * + * @param namespace The namespace to interpret the name relative to. + * @param name The name of the object to be retrieved. + * @return The object reference specified. + */ + public Object getObject(String namespace, String name) + { + try + { // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + Object rc = null; + synchronized (m_properties_sync) + { // start by looking in the properties map + rc = m_properties.get(key); + if (rc==null) + { // no use - need to try the database + rc = m_ops.getProperty(m_gid,key); + if (rc!=null) + m_properties.put(key,rc); + + } // end if + + } // end synchronized block + + if (rc==null) + throw new NoSuchObjectException(this.toString(),namespace,name); + return rc; + + } // end try + catch (DatabaseException e) + { // translate into our NoSuchObjectException but retain the DatabaseException + throw new NoSuchObjectException(this.toString(),namespace,name,e); + + } // end catch + + } // end getObject + + /*-------------------------------------------------------------------------------- + * Implementations from interface SecureObjectStore + *-------------------------------------------------------------------------------- + */ + + public Object setObject(DynamoUser caller, String namespace, String name, Object value) + throws DatabaseException, DynamoSecurityException + { + testPermission(caller,namespace,"set.property","sec.setGroupProperty"); + Object rc = null; + // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + synchronized (m_properties_sync) + { // start by setting the database value + rc = m_ops.setProperty(m_gid,key,value); + + // and cache it, too + m_properties.put(key,value); + + } // end synchronized block + + return rc; + + } // end setObject + + public Object removeObject(DynamoUser caller, String namespace, String name) + throws DatabaseException, DynamoSecurityException + { + testPermission(caller,namespace,"remove.property","sec.removeGroupProperty"); + Object rc = null; + // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + synchronized (m_properties_sync) + { // start by killing the database value + rc = m_ops.removeProperty(m_gid,key); + + // and remove the cached value, too + m_properties.remove(key); + + } // end synchronized block + + return rc; + + } // end removeObject + + public Collection getNamespaces() throws DatabaseException + { + // call through to the database to get the list of namespace IDs + int[] ids = m_ops.getPropertyNamespaceIDs(m_gid); + + ArrayList rc = new ArrayList(ids.length); + for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.util.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.util.*; + +abstract class GroupObjectOps extends OpsBase +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + protected GroupObjectOps(DBConnectionPool pool) + { + super(pool); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract operations + *-------------------------------------------------------------------------------- + */ + + abstract Object getProperty(int gid, PropertyKey key) throws DatabaseException; + + abstract Object setProperty(int gid, PropertyKey key, Object value) throws DatabaseException; + + abstract Object removeProperty(int gid, PropertyKey key) throws DatabaseException; + + abstract int[] getPropertyNamespaceIDs(int gid) throws DatabaseException; + + abstract Map getAllProperties(int gid, int namespace) throws DatabaseException; + + abstract boolean testMember(int gid, int uid) throws DatabaseException; + + abstract boolean addMember(int gid, int uid) throws DatabaseException; + + abstract boolean removeMember(int gid, int uid) throws DatabaseException; + + abstract int[] getMembers(int gid) throws DatabaseException; + + abstract void setAclID(int gid, int aclid) throws DatabaseException; + +} // end class GroupObjectOps diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/GroupObjectOps_mysql.java b/src/dynamo-framework/com/silverwrist/dynamo/db/GroupObjectOps_mysql.java new file mode 100644 index 0000000..d82b59f --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/GroupObjectOps_mysql.java @@ -0,0 +1,556 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.sql.*; +import java.util.*; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +class GroupObjectOps_mysql extends GroupObjectOps +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private DBUtilities m_utils; + private PropertySerializer m_psz; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + GroupObjectOps_mysql(DBConnectionPool pool, DBUtilities utils) + { + super(pool); + m_utils = utils; + m_psz = (PropertySerializer)(pool.queryService(PropertySerializer.class)); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class GroupObjectOps + *-------------------------------------------------------------------------------- + */ + + Object getProperty(int gid, PropertyKey key) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + String rc_str = null; + try + { // get a connection + conn = getConnection(); + + // look up the property + stmt = conn.prepareStatement("SELECT prop_value FROM groupprop WHERE gid = ? AND nsid = ? " + + "AND prop_name = ?;"); + stmt.setInt(1,gid); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + rs = stmt.executeQuery(); + if (!(rs.next())) + return null; // property not found + + rc_str = rs.getString(1); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + // Deserialize the property value. + Object rc = m_psz.deserializeProperty(rc_str); + if (rc!=null) + return rc; + + // deserialization exception - throw it + DatabaseException de = new DatabaseException(GroupObjectOps_mysql.class,"DatabaseMessages", + "property.deserialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end getProperty + + Object setProperty(int gid, PropertyKey key, Object value) throws DatabaseException + { + String serialized_value = m_psz.serializeProperty(value); + if (serialized_value==null) + { // serialization exception - throw it + DatabaseException de = new DatabaseException(GroupObjectOps_mysql.class,"DatabaseMessages", + "property.serialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end if + + String old_value = null; + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the table + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES groupprop WRITE;"); + + // look to see if the property value is already there + stmt = conn.prepareStatement("SELECT prop_value FROM groupprop WHERE gid = ? AND nsid = ? " + + "AND prop_name = ?;"); + stmt.setInt(1,gid); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + rs = stmt.executeQuery(); + if (rs.next()) + old_value = rs.getString(1); + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + + if (old_value!=null) + { // prepare the statement to update the existing record + stmt = conn.prepareStatement("UPDATE groupprop SET prop_value = ? WHERE gid = ? " + + "AND nsid = ? AND prop_name = ?;"); + stmt.setString(1,serialized_value); + stmt.setInt(2,gid); + stmt.setInt(3,key.getNamespaceID()); + stmt.setString(4,key.getName()); + + } // end if + else + { // prepare the statement to insert a new record + stmt = conn.prepareStatement("INSERT INTO groupprop (gid, nsid, prop_name, prop_value) " + + "VALUES (?, ?, ?, ?);"); + stmt.setInt(1,gid); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + stmt.setString(4,serialized_value); + + } // end else + + stmt.executeUpdate(); // execute it! + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + if (old_value==null) + return null; // no previous value + + // Deserialize the property value. + Object rc = m_psz.deserializeProperty(old_value); + if (rc!=null) + return rc; + + // deserialization exception - throw it + DatabaseException de = new DatabaseException(GroupObjectOps_mysql.class,"DatabaseMessages", + "property.deserialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end setProperty + + Object removeProperty(int gid, PropertyKey key) throws DatabaseException + { + String old_value = null; + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the table + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES groupprop WRITE;"); + + // look to see if the property value is already there + stmt = conn.prepareStatement("SELECT prop_value FROM groupprop WHERE gid = ? AND nsid = ? " + + "AND prop_name = ?;"); + stmt.setInt(1,gid); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + rs = stmt.executeQuery(); + if (rs.next()) + old_value = rs.getString(1); + else + return null; // no need to remove anything + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + + // delete the database row + stmt = conn.prepareStatement("DELETE FROM groupprop WHERE gid = ? AND nsid = ? AND prop_name = ?;"); + stmt.setInt(1,gid); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + stmt.executeUpdate(); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + // Deserialize the property value. + Object rc = m_psz.deserializeProperty(old_value); + if (rc!=null) + return rc; + + // deserialization exception - throw it + DatabaseException de = new DatabaseException(GroupObjectOps_mysql.class,"DatabaseMessages", + "property.deserialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end removeProperty + + int[] getPropertyNamespaceIDs(int gid) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // execute the query! + stmt = conn.prepareStatement("SELECT DISTINCT nsid FROM groupprop WHERE gid = ?;"); + stmt.setInt(1,gid); + rs = stmt.executeQuery(); + + // read out a list of the namespace IDs + ArrayList tmp = new ArrayList(); + while (rs.next()) + tmp.add(new Integer(rs.getInt(1))); + + // create and return the array + int[] rc = new int[tmp.size()]; + for (int i=0; i0); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end removeMember + + int[] getMembers(int gid) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + ArrayList tmp = null; + try + { // get a connection + conn = getConnection(); + + // create a query to get all the UIDs + stmt = conn.prepareStatement("SELECT uid FROM groupmembers WHERE gid = ?;"); + stmt.setInt(1,gid); + rs = stmt.executeQuery(); + + // fill the intermediate ArrayList + tmp = new ArrayList(); + while (rs.next()) + tmp.add(new Integer(rs.getInt(1))); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + // now translate into an integer array + int[] rc = new int[tmp.size()]; + for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.security.Principal; +import java.security.acl.AclNotFoundException; +import java.util.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +abstract class GroupProxy implements DynamoGroup, DynamicWrapper +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + protected int m_gid; + protected String m_groupname; + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + protected GroupProxy(int gid) + { + m_gid = gid; + m_groupname = null; + + } // end constructor + + protected GroupProxy(int gid, String groupname) + { + m_gid = gid; + m_groupname = groupname; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract operations + *-------------------------------------------------------------------------------- + */ + + protected abstract DynamoGroup getRealGroup(); + + /*-------------------------------------------------------------------------------- + * Implementations from interface Principal + *-------------------------------------------------------------------------------- + */ + + public boolean equals(Object another) + { + if (another==null) + return false; + if (another instanceof DynamoGroup) + return (m_gid==((DynamoGroup)another).getGID()); + return false; + + } // end equals + + public String toString() + { + if (m_groupname!=null) + return "group " + m_groupname; + return getRealGroup().toString(); + + } // end toString + + public int hashCode() + { + return m_gid; + + } // end hashCode + + public String getName() + { + if (m_groupname!=null) + return m_groupname; + return getRealGroup().getName(); + + } // end getName + + /*-------------------------------------------------------------------------------- + * Implementations from interface Group + *-------------------------------------------------------------------------------- + */ + + public boolean addMember(Principal user) + { + return getRealGroup().addMember(user); + + } // end addMember + + public boolean removeMember(Principal user) + { + return getRealGroup().removeMember(user); + + } // end removeMember + + public boolean isMember(Principal member) + { + return getRealGroup().isMember(member); + + } // end isMember + + public Enumeration members() + { + return getRealGroup().members(); + + } // end members + + /*-------------------------------------------------------------------------------- + * Implementations from interface ObjectProvider + *-------------------------------------------------------------------------------- + */ + + /** + * Retrieves an object from this ObjectProvider. + * + * @param namespace The namespace to interpret the name relative to. + * @param name The name of the object to be retrieved. + * @return The object reference specified. + */ + public Object getObject(String namespace, String name) + { + return getRealGroup().getObject(namespace,name); + + } // end getObject + + /*-------------------------------------------------------------------------------- + * Implementations from interface SecureObjectStore + *-------------------------------------------------------------------------------- + */ + + public Object setObject(DynamoUser caller, String namespace, String name, Object value) + throws DatabaseException, DynamoSecurityException + { + return getRealGroup().setObject(caller,namespace,name,value); + + } // end setObject + + public Object removeObject(DynamoUser caller, String namespace, String name) + throws DatabaseException, DynamoSecurityException + { + return getRealGroup().removeObject(caller,namespace,name); + + } // end removeObject + + public Collection getNamespaces() throws DatabaseException + { + return getRealGroup().getNamespaces(); + + } // end getNamespaces + + public Collection getNamesForNamespace(String namespace) throws DatabaseException + { + return getRealGroup().getNamesForNamespace(namespace); + + } // end getNamesForNamespace + + /*-------------------------------------------------------------------------------- + * Implementations from interface DynamoGroup + *-------------------------------------------------------------------------------- + */ + + public int getGID() + { + return m_gid; + + } // end getGID + + public boolean addUID(DynamoUser caller, int uid) throws DatabaseException, DynamoSecurityException + { + return getRealGroup().addUID(caller,uid); + + } // end addUID + + public boolean removeUID(DynamoUser caller, int uid) throws DatabaseException, DynamoSecurityException + { + return getRealGroup().removeUID(caller,uid); + + } // end removeUID + + public boolean testUID(int uid) throws DatabaseException + { + return getRealGroup().testUID(uid); + + } // end testUID + + public int[] getUIDs() throws DatabaseException + { + return getRealGroup().getUIDs(); + + } // end getUIDs + + public boolean addMember(DynamoUser caller, Principal member) + throws DatabaseException, DynamoSecurityException + { + return getRealGroup().addMember(caller,member); + + } // end addMember + + public boolean removeMember(DynamoUser caller, Principal member) + throws DatabaseException, DynamoSecurityException + { + return getRealGroup().removeMember(caller,member); + + } // end removeMember + + public DynamoAcl getAcl() throws DatabaseException, AclNotFoundException + { + return getRealGroup().getAcl(); + + } // end getAcl + + public void setAcl(DynamoUser caller, DynamoAcl acl) throws DatabaseException, DynamoSecurityException + { + getRealGroup().setAcl(caller,acl); + + } // end setAcl + + /*-------------------------------------------------------------------------------- + * Implementations from interface DynamicWrapper + *-------------------------------------------------------------------------------- + */ + + public Object unwrap() + { + return getRealGroup(); + + } // end unwrap + +} // end class GroupProxy diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStore.java b/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStore.java new file mode 100644 index 0000000..5909667 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStore.java @@ -0,0 +1,42 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.security.Principal; +import com.silverwrist.dynamo.except.DatabaseException; +import com.silverwrist.dynamo.except.DynamoSecurityException; +import com.silverwrist.dynamo.iface.DataItem; +import com.silverwrist.dynamo.iface.DynamoUser; + +public interface ImageStore +{ + public DataItem getImage(int id) throws DatabaseException; + + public int saveNewImage(String type_namespace, String type_name, Principal owner, DataItem image) + throws DatabaseException; + + public void replaceImage(DynamoUser caller, int image_id, DataItem image) + throws DatabaseException, DynamoSecurityException; + + public int findImageID(String type_namespace, String type_name, Principal owner) throws DatabaseException; + + public void deleteImage(DynamoUser caller, int image_id) throws DatabaseException, DynamoSecurityException; + + public DataItem normalizeImage(DataItem source, int width, int height, String new_type) throws Exception; + +} // end interface ImageStore diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStoreObject.java b/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStoreObject.java new file mode 100644 index 0000000..ba7b48b --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStoreObject.java @@ -0,0 +1,249 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.security.Principal; +import java.util.*; +import org.w3c.dom.*; +import com.silverwrist.util.image.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +public class ImageStoreObject implements NamedObject, ComponentInitialize, ComponentShutdown, ImageStore +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String m_name; // object name + private NamespaceCache m_ns_cache; // namespace cache object + private ImageStoreOps m_ops; // image store operations + private Hashtable m_imagetype_tlb = new Hashtable(); // translates imagetypes + private Hashtable m_imagetype_rev_tlb = new Hashtable(); // translates imagetypes + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public ImageStoreObject() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private final int imageTypeToIndex(PropertyKey pkey) throws DatabaseException + { + Integer foo = (Integer)(m_imagetype_tlb.get(pkey)); + if (foo!=null) + return foo.intValue(); + + int rc = m_ops.imageTypeToIndex(pkey); + foo = new Integer(rc); + m_imagetype_tlb.put(pkey,foo); + m_imagetype_rev_tlb.put(foo,pkey); + return rc; + + } // end imageTypeToIndex + + private final int imageTypeToIndex(int nsid, String name) throws DatabaseException + { + return imageTypeToIndex(new PropertyKey(nsid,name)); + + } // end imageTypeToIndex + + private final int imageTypeToIndex(String namespace, String name) throws DatabaseException + { + return imageTypeToIndex(new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name)); + + } // end imageTypeToIndex + + /*-------------------------------------------------------------------------------- + * Implementations from interface NamedObject + *-------------------------------------------------------------------------------- + */ + + public String getName() + { + return m_name; + + } // end getName + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentInitialize + *-------------------------------------------------------------------------------- + */ + + public void initialize(Element config_root, ServiceProvider services) throws ConfigException + { + String conn_name = null; + String nscache_name = null; + XMLLoader loader = XMLLoader.get(); + try + { // verify the right node name + loader.verifyNodeName(config_root,"object"); + + // get the object's name + m_name = loader.getAttribute(config_root,"name"); + + // get the database configuration connection + DOMElementHelper config_root_h = new DOMElementHelper(config_root); + Element elt = loader.getSubElement(config_root_h,"database"); + conn_name = loader.getAttribute(elt,"connection"); + nscache_name = loader.getAttribute(elt,"namespaces"); + + } // end try + catch (XMLLoadException e) + { // error loading XML config data + throw new ConfigException(e); + + } // end catch + + // Get the database connection pool and namespace cache. + DBConnectionPool pool = GetObjectUtils.getDatabaseConnection(services,conn_name); + m_ns_cache = + (NamespaceCache)(GetObjectUtils.getDynamoComponent(services,NamespaceCache.class,nscache_name)); + + // Get the operations object. + m_ops = ImageStoreOps.get(pool); + + } // end initialize + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentShutdown + *-------------------------------------------------------------------------------- + */ + + public void shutdown() + { + m_ops.dispose(); + m_ops = null; + m_ns_cache = null; + + } // end shutdown + + /*-------------------------------------------------------------------------------- + * Implementations from interface ImageStore + *-------------------------------------------------------------------------------- + */ + + public DataItem getImage(int id) throws DatabaseException + { + return m_ops.getImage(id); + + } // end getImage + + public int saveNewImage(String type_namespace, String type_name, Principal owner, DataItem image) + throws DatabaseException + { + int image_type = imageTypeToIndex(type_namespace,type_name); + int owner_id = 0, owner_flag = 0; + if (owner instanceof DynamoUser) + owner_id = ((DynamoUser)owner).getUID(); + else if (owner instanceof DynamoGroup) + { // get the GID + owner_id = ((DynamoGroup)owner).getGID(); + owner_flag = 1; + + } // end else if + else + throw new DatabaseException(ImageStoreObject.class,"DatabaseMessages","img.badOwner"); + + // call down to the database to save it all off + return m_ops.saveNewImage(image_type,owner_id,owner_flag,image); + + } // end saveNewImage + + public void replaceImage(DynamoUser caller, int image_id, DataItem image) + throws DatabaseException, DynamoSecurityException + { + if (m_ops.canReplaceImage(caller.getUID(),image_id)) + m_ops.replaceImage(image_id,image); + else + { // throw a security exception here + DynamoSecurityException dse = new DynamoSecurityException(ImageStoreObject.class,"DatabaseMessages", + "img.notOwner"); + dse.setParameter(0,String.valueOf(image_id)); + throw dse; + + } // end else + + } // end replaceImage + + public int findImageID(String type_namespace, String type_name, Principal owner) throws DatabaseException + { + int image_type = imageTypeToIndex(type_namespace,type_name); + int owner_id = 0, owner_flag = 0; + if (owner instanceof DynamoUser) + owner_id = ((DynamoUser)owner).getUID(); + else if (owner instanceof DynamoGroup) + { // get the GID + owner_id = ((DynamoGroup)owner).getGID(); + owner_flag = 1; + + } // end else if + else + throw new DatabaseException(ImageStoreObject.class,"DatabaseMessages","img.badOwner"); + + // call down to find it + return m_ops.findImageID(image_type,owner_id,owner_flag); + + } // end findImageID + + public void deleteImage(DynamoUser caller, int image_id) throws DatabaseException, DynamoSecurityException + { + if (m_ops.canReplaceImage(caller.getUID(),image_id)) + m_ops.deleteImage(image_id); + else + { // throw a security exception here + DynamoSecurityException dse = new DynamoSecurityException(ImageStoreObject.class,"DatabaseMessages", + "img.notOwner"); + dse.setParameter(0,String.valueOf(image_id)); + throw dse; + + } // end else + + } // end deleteImage + + public DataItem normalizeImage(DataItem source, int width, int height, String new_type) throws Exception + { + try + { // normalize the image and encapsulate it in a StaticDataItem + byte[] data = ImageNormalizer.normalizeImage(source.getDataStream(),width,height,new_type); + return new StaticDataItem(source.getName() + "-converted",new_type,data.length,data); + + } // end try + catch (ImageNormalizerException e) + { // morph the exception + ExternalException ee = new ExternalException(ImageStoreObject.class,"DatabaseMessages", + "img.normalize",e); + ee.setParameter(0,source.getName()); + ee.setParameter(1,e.getMessage()); + throw ee; + + } // end catch + + } // end normalizeImage + +} // end class ImageStoreObject diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStoreOps.java b/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStoreOps.java new file mode 100644 index 0000000..de65d33 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStoreOps.java @@ -0,0 +1,80 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +abstract class ImageStoreOps extends OpsBase +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + protected ImageStoreOps(DBConnectionPool pool) + { + super(pool); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class OpsBase + *-------------------------------------------------------------------------------- + */ + + public void dispose() + { + super.dispose(); + + } // end dispose + + /*-------------------------------------------------------------------------------- + * Abstract operations + *-------------------------------------------------------------------------------- + */ + + abstract int imageTypeToIndex(PropertyKey pkey) throws DatabaseException; + + abstract DataItem getImage(int id) throws DatabaseException; + + abstract int saveNewImage(int typecode, int owner_id, int owner_flag, DataItem image) + throws DatabaseException; + + abstract boolean canReplaceImage(int uid, int image_id) throws DatabaseException; + + abstract void replaceImage(int image_id, DataItem image) throws DatabaseException; + + abstract int findImageID(int typecode, int owner_id, int owner_flag) throws DatabaseException; + + abstract void deleteImage(int image_id) throws DatabaseException; + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + static ImageStoreOps get(DBConnectionPool pool) throws ConfigException + { + return (ImageStoreOps)get(pool,ImageStoreOps.class.getClassLoader(), + ImageStoreOps.class.getName() + "_","ImageStoreOps"); + + } // end get + +} // end class ImageStoreOps diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStoreOps_mysql.java b/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStoreOps_mysql.java new file mode 100644 index 0000000..cfa1619 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/ImageStoreOps_mysql.java @@ -0,0 +1,363 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.io.*; +import java.sql.*; +import java.util.*; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +public class ImageStoreOps_mysql extends ImageStoreOps +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public ImageStoreOps_mysql(DBConnectionPool pool) + { + super(pool); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class ImageStoreOps + *-------------------------------------------------------------------------------- + */ + + int imageTypeToIndex(PropertyKey pkey) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the table while we work + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES imagetype WRITE;"); + + // first try to look the index up + stmt = conn.prepareStatement("SELECT typecode FROM imagetype WHERE nsid = ? AND name = ?;"); + stmt.setInt(1,pkey.getNamespaceID()); + stmt.setString(2,pkey.getName()); + rs = stmt.executeQuery(); + if (rs.next()) + return rs.getInt(1); + + // then add it + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + stmt = conn.prepareStatement("INSERT INTO imagetype (nsid, name) VALUES (?, ?);"); + stmt.setInt(1,pkey.getNamespaceID()); + stmt.setString(2,pkey.getName()); + stmt.executeUpdate(); + return MySQLUtils.getLastInsertInt(conn); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end imageTypeToIndex + + DataItem getImage(int id) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // Start by getting the MIME type and image length. + stmt = conn.prepareStatement("SELECT mimetype, length FROM imagestore WHERE imageid = ?;"); + stmt.setInt(1,id); + rs = stmt.executeQuery(); + if (!(rs.next())) + return null; + String mime_type = rs.getString(1); + int length = rs.getInt(2); + + // Now get the actual data blob. + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + stmt = conn.prepareStatement("SELECT data FROM imagestore WHERE imageid = ?;"); + stmt.setInt(1,id); + rs = stmt.executeQuery(); + if (!(rs.next())) + return null; + + // We need to copy the data blob into a local buffer. We also mesh the whole thing into a DataItem. + return new StaticDataItem("image" + id,mime_type,length,IOUtils.load(rs.getBinaryStream(1))); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + catch (IOException e) + { // turn IOException into DatabaseException too + DatabaseException de = new DatabaseException(ImageStoreOps_mysql.class,"DatabaseMessages", + "img.loadFail",e); + de.setParameter(0,String.valueOf(id)); + throw de; + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + } // end getImage + + int saveNewImage(int typecode, int owner_id, int owner_flag, DataItem image) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + try + { // get a connection + conn = getConnection(); + + // lock the table while we work + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES imagestore WRITE;"); + + // insert all the "base" information + stmt = conn.prepareStatement("INSERT INTO imagestore (typecode, ownerid, ownerflag, mimetype, length) " + + "VALUES (?, ?, ?, ?, ?);"); + stmt.setInt(1,typecode); + stmt.setInt(2,owner_id); + stmt.setInt(3,owner_flag); + stmt.setString(4,image.getMimeType()); + stmt.setInt(5,image.getSize()); + stmt.executeUpdate(); + int rc = MySQLUtils.getLastInsertInt(conn); + + // insert the file data itself + SQLUtils.shutdown(stmt); + stmt = conn.prepareStatement("UPDATE imagestore SET data = ? WHERE imageid = ?;"); + stmt.setBlob(1,image.getBlob()); + stmt.setInt(2,rc); + stmt.executeUpdate(); + + return rc; // all done! + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end saveNewImage + + boolean canReplaceImage(int uid, int image_id) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // get the owner ID and flag from the image records + stmt = conn.prepareStatement("SELECT ownerid, ownerflag FROM imagestore WHERE imageid = ?;"); + stmt.setInt(1,image_id); + rs = stmt.executeQuery(); + if (!(rs.next())) + return false; + int owner_id = rs.getInt(1); + if (rs.getInt(2)==0) // a user owns it + return (uid==owner_id); + + // Test group membership for ownership. + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + stmt = conn.prepareStatement("SELECT uid FROM groupmembers WHERE uid = ? AND gid = ?;"); + stmt.setInt(1,uid); + stmt.setInt(2,owner_id); + rs = stmt.executeQuery(); + return rs.next(); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + } // end canReplaceImage + + void replaceImage(int image_id, DataItem image) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + try + { // get a connection + conn = getConnection(); + + // lock the table while we work + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES imagestore WRITE;"); + + // poke in the basic data items first + stmt = conn.prepareStatement("UPDATE imagestore SET mimetype = ?, length = ?, data = NULL " + + "WHERE imageid = ?;"); + stmt.setString(1,image.getMimeType()); + stmt.setInt(2,image.getSize()); + stmt.setInt(3,image_id); + stmt.executeUpdate(); + + // insert the new file data itself + SQLUtils.shutdown(stmt); + stmt = conn.prepareStatement("UPDATE imagestore SET data = ? WHERE imageid = ?;"); + stmt.setBlob(1,image.getBlob()); + stmt.setInt(2,image_id); + stmt.executeUpdate(); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end replaceImage + + int findImageID(int typecode, int owner_id, int owner_flag) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // create statement and run it + stmt = conn.prepareStatement("SELECT imageid FROM imagestore WHERE typecode = ? AND ownerid = ? " + + "AND ownerflag = ?;"); + stmt.setInt(1,typecode); + stmt.setInt(2,owner_id); + stmt.setInt(3,owner_flag); + rs = stmt.executeQuery(); + if (rs.next()) + return rs.getInt(1); + else + return -1; + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + } // end findImageID + + void deleteImage(int image_id) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + try + { // get a connection + conn = getConnection(); + + // lock the table while we work + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES imagestore WRITE;"); + + // delete it! + stmt = conn.prepareStatement("DELETE FROM imagestore WHERE imageid = ?;"); + stmt.setInt(1,image_id); + stmt.executeUpdate(); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end deleteImage + +} // end class ImageStoreOps_mysql diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCache.java b/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCache.java new file mode 100644 index 0000000..9b1d375 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCache.java @@ -0,0 +1,28 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import com.silverwrist.dynamo.except.DatabaseException; + +public interface NamespaceCache +{ + public int namespaceNameToId(String name) throws DatabaseException; + + public String namespaceIdToName(int id) throws DatabaseException; + +} // end interface NamespaceCache diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCacheObject.java b/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCacheObject.java new file mode 100644 index 0000000..d157027 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCacheObject.java @@ -0,0 +1,143 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.util.*; +import org.w3c.dom.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.Namespaces; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +public class NamespaceCacheObject + implements NamedObject, ComponentInitialize, ComponentShutdown, NamespaceCache +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String m_name; // object name + private NamespaceCacheOps m_ops; // low-level database operations + private HashMap m_cache = new HashMap(); // namespace cache object + private HashMap m_rev_cache = new HashMap(); // namespace reverse cache object + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public NamespaceCacheObject() + { + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface NamedObject + *-------------------------------------------------------------------------------- + */ + + public String getName() + { + return m_name; + + } // end getName + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentInitialize + *-------------------------------------------------------------------------------- + */ + + public void initialize(Element config_root, ServiceProvider services) throws ConfigException + { + String conn_name = null; + XMLLoader loader = XMLLoader.get(); + try + { // verify the right node name + loader.verifyNodeName(config_root,"object"); + + // get the object's name + m_name = loader.getAttribute(config_root,"name"); + + // get the database configuration connection + Element elt = loader.getSubElement(config_root,"database"); + conn_name = loader.getAttribute(elt,"connection"); + + } // end try + catch (XMLLoadException e) + { // error loading XML config data + throw new ConfigException(e); + + } // end catch + + // Get the database connection pool. + DBConnectionPool pool = GetObjectUtils.getDatabaseConnection(services,conn_name); + + // Get the database operations class. + m_ops = NamespaceCacheOps.get(pool); + + } // end initialize + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentShutdown + *-------------------------------------------------------------------------------- + */ + + public void shutdown() + { + m_ops.dispose(); + m_ops = null; + + } // end shutdown + + /*-------------------------------------------------------------------------------- + * Implementations from interface NamespaceCache + *-------------------------------------------------------------------------------- + */ + + public synchronized int namespaceNameToId(String name) throws DatabaseException + { + Integer rc = (Integer)(m_cache.get(name)); + if (rc!=null) + return rc.intValue(); + int real_id = m_ops.namespaceNameToId(name); + rc = new Integer(real_id); + name = name.intern(); + m_cache.put(name,rc); + m_rev_cache.put(rc,name); + return real_id; + + } // end namespaceNameToId + + public synchronized String namespaceIdToName(int id) throws DatabaseException + { + Integer key = new Integer(id); + String rc = (String)(m_rev_cache.get(key)); + if (rc!=null) + return rc; + rc = m_ops.namespaceIdToName(id); + if (rc==null) + throw new DatabaseException(NamespaceCacheObject.class,"DatabaseMessages","nsCache.notFound"); + rc = rc.intern(); + m_cache.put(rc,key); + m_rev_cache.put(key,rc); + return rc; + + } // end namespaceIdToName + +} // end class NamespaceCacheObject diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCacheOps.java b/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCacheOps.java new file mode 100644 index 0000000..ad5d0c8 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCacheOps.java @@ -0,0 +1,69 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.lang.reflect.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +abstract class NamespaceCacheOps extends OpsBase +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + protected NamespaceCacheOps(DBConnectionPool pool) + { + super(pool); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class OpsBase + *-------------------------------------------------------------------------------- + */ + + public void dispose() + { + super.dispose(); + + } // end dispose + + /*-------------------------------------------------------------------------------- + * Abstract operations + *-------------------------------------------------------------------------------- + */ + + abstract int namespaceNameToId(String name) throws DatabaseException; + + abstract String namespaceIdToName(int id) throws DatabaseException; + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + static NamespaceCacheOps get(DBConnectionPool pool) throws ConfigException + { + return (NamespaceCacheOps)get(pool,NamespaceCacheOps.class.getClassLoader(), + NamespaceCacheOps.class.getName() + "_","NamespaceCacheOps"); + + } // end get + +} // end class NamespaceCacheOps diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCacheOps_mysql.java b/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCacheOps_mysql.java new file mode 100644 index 0000000..7b01d95 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/NamespaceCacheOps_mysql.java @@ -0,0 +1,132 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.sql.*; +import java.util.*; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +public class NamespaceCacheOps_mysql extends NamespaceCacheOps +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public NamespaceCacheOps_mysql(DBConnectionPool pool) + { + super(pool); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class NamespaceCacheOps + *-------------------------------------------------------------------------------- + */ + + int namespaceNameToId(String name) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the table while we do this + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES namespaces WRITE;"); + + // try the initial SELECT to see if it works + stmt = conn.prepareStatement("SELECT nsid FROM namespaces WHERE namespace = ?;"); + stmt.setString(1,name); + rs = stmt.executeQuery(); + if (rs.next()) + return rs.getInt(1); + + // it wasn't present - try adding it + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + stmt = conn.prepareStatement("INSERT INTO namespaces (namespace) VALUES (?);"); + stmt.setString(1,name); + stmt.executeUpdate(); + return MySQLUtils.getLastInsertInt(conn); + + } // end try + catch (SQLException e) + { // translate this to a DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end namespaceNameToId + + String namespaceIdToName(int id) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the table while we do this + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES namespaces READ;"); + + // try the SELECT to see if it works + stmt = conn.prepareStatement("SELECT namespace FROM namespaces WHERE nsid = ?;"); + stmt.setInt(1,id); + rs = stmt.executeQuery(); + if (rs.next()) + return rs.getString(1); + else + return null; + + } // end try + catch (SQLException e) + { // translate the exception and rethrow + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end namespaceIdToName + +} // end class NamespaceCacheOps_mysql diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/OpsBase.java b/src/dynamo-framework/com/silverwrist/dynamo/db/OpsBase.java new file mode 100644 index 0000000..bbc7a96 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/OpsBase.java @@ -0,0 +1,118 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.lang.reflect.*; +import java.sql.Connection; +import java.sql.SQLException; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +public class OpsBase +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final Class[] ARGS_CLASS = { DBConnectionPool.class }; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private DBConnectionPool m_pool; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + protected OpsBase(DBConnectionPool pool) + { + m_pool = pool; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + protected final DBConnectionPool getPool() + { + return m_pool; + + } // end getPool + + protected final Connection getConnection() throws DatabaseException + { + return new WrappedConnection(m_pool,m_pool.getConnection()); + + } // end getConnection + + protected final DatabaseException generalException(SQLException e) + { + DatabaseException dbe = new DatabaseException(OpsBase.class,"DatabaseMessages","general",e); + dbe.setParameter(0,e.getMessage()); + return dbe; + + } // end generalException + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + public void dispose() + { + m_pool = null; + + } // end dispose + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + protected static Object get(DBConnectionPool pool, ClassLoader loader, String stem_name, String type) + throws ConfigException + { + try + { // load the specified ops class and return a new instance + String klassname = stem_name + pool.getDatabaseType().toLowerCase(); + Constructor c = loader.loadClass(klassname).getConstructor(ARGS_CLASS); + Object[] args = new Object[1]; + args[0] = pool; + return c.newInstance(args); + + } // end try + catch (Exception e) + { // error loading the ops class... + ConfigException ce = new ConfigException(OpsBase.class,"DatabaseMessages","load.opsClass",e); + ce.setParameter(0,e.getMessage()); + ce.setParameter(1,pool.getDatabaseType()); + ce.setParameter(2,type); + throw ce; + + } // end catch + + } // end get + +} // end class OpsBase diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagement.java b/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagement.java new file mode 100644 index 0000000..52f420f --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagement.java @@ -0,0 +1,42 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.util.Collection; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +public interface UserManagement +{ + public DynamoUser getAnonymousUser() throws DatabaseException; + + public DynamoUser getUser(int id) throws DatabaseException; + + public DynamoUser getUser(String username) throws DatabaseException; + + public DynamoUser createUser(String username, String email) throws DatabaseException; + + public DynamoGroup getGroup(int id) throws DatabaseException; + + public DynamoGroup getGroup(String groupname) throws DatabaseException; + + public DynamoGroup createGroup(String groupname) throws DatabaseException; + + public void loadUserDefaults(DynamoUser user, Collection namespaces) throws DatabaseException; + +} // end interface UserManagement diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagerObject.java b/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagerObject.java new file mode 100644 index 0000000..6b84b3b --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagerObject.java @@ -0,0 +1,987 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.lang.ref.*; +import java.util.*; +import org.w3c.dom.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.UserInfoNamespace; +import com.silverwrist.dynamo.event.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.security.SecurityReferenceMonitor; +import com.silverwrist.dynamo.util.*; + +public class UserManagerObject + implements NamedObject, ComponentInitialize, ComponentShutdown, UserManagement, UserProxyManagement, + AuthenticatorRegistration, UserInfoNamespace, UserPropertyTranslatorInstall +{ + /*-------------------------------------------------------------------------------- + * Internal class implementing user proxies + *-------------------------------------------------------------------------------- + */ + + private class MyUserProxy extends UserProxy + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private DynamoUser m_real_user = null; + + /*==================================================================== + * Constructors + *==================================================================== + */ + + MyUserProxy(int uid) + { + super(uid); + + } // end constructor + + MyUserProxy(int uid, String username) + { + super(uid,username); + + } // end constructor + + /*==================================================================== + * Abstract implementations from class UserProxy + *==================================================================== + */ + + protected synchronized DynamoUser getRealUser() + { + if (m_real_user==null) + { // need to retrieve the real user... + try + { // get the real user... + m_real_user = UserManagerObject.this.getUser(m_uid); + + } // end try + catch (DatabaseException e) + { // wrap it in a runtime exception type + throw new ProxyException(e); + + } // end catch + + } // end if + + return m_real_user; + + } // end getRealUser + + } // end class MyUserProxy + + /*-------------------------------------------------------------------------------- + * Internal class implementing group proxies + *-------------------------------------------------------------------------------- + */ + + private class MyGroupProxy extends GroupProxy + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private DynamoGroup m_real_group = null; + + /*==================================================================== + * Constructors + *==================================================================== + */ + + MyGroupProxy(int gid) + { + super(gid); + + } // end constructor + + MyGroupProxy(int gid, String groupname) + { + super(gid,groupname); + + } // end constructor + + /*==================================================================== + * Abstract implementations from class UserProxy + *==================================================================== + */ + + protected synchronized DynamoGroup getRealGroup() + { + if (m_real_group==null) + { // need to retrieve the real group... + try + { // get the real group... + m_real_group = UserManagerObject.this.getGroup(m_gid); + + } // end try + catch (DatabaseException e) + { // wrap it in a runtime exception type + throw new ProxyException(e); + + } // end catch + + } // end if + + return m_real_group; + + } // end getRealGroup + + } // end class MyGroupProxy + + /*-------------------------------------------------------------------------------- + * Internal event listener class + *-------------------------------------------------------------------------------- + */ + + private class UpdateListener implements DynamicUpdateListener + { + /*==================================================================== + * Constructor + *==================================================================== + */ + + UpdateListener() + { // do nothing + } // end constructor + + /*==================================================================== + * Implementations from interface DynamicUpdateListener + *==================================================================== + */ + + public void updateReceived(DynamicUpdateEvent evt) + { + if (evt instanceof UserUpdateEvent) + { // try to pass the event on to the user + int uid = ((UserUpdateEvent)evt).getUID(); + Integer key = new Integer(uid); + synchronized (m_users_sync) + { // try looking in the cache for a UserObject + IDNameCacheObject cobj = (IDNameCacheObject)(m_id_to_user.get(key)); + if (cobj!=null) + { // got a cache object - retrieve the user value + UserObject target = (UserObject)(cobj.get()); + if (target==null) + { // the UserObject got kicked out! kick it out of the HashMaps + m_id_to_user.remove(key); + m_name_to_user.remove(cobj.getNameKey()); + cobj.clear(); + cobj = null; + + } // end if + else if (target!=evt.getSource()) + target.updated((UserUpdateEvent)evt); + + } // end if + + } // end synchronized block + + } // end if + + } // end updateReceived + + } // end class UpdateListener + + /*-------------------------------------------------------------------------------- + * Internal property serializer class + *-------------------------------------------------------------------------------- + */ + + private class UserGroupSerializer implements PropertySerializer + { + /*==================================================================== + * Constructor + *==================================================================== + */ + + UserGroupSerializer() + { // do nothing + } // end constructor + + /*==================================================================== + * Implementations from interface PropertySerializer + *==================================================================== + */ + + public String serializeProperty(Object value) + { + if (value instanceof DynamoUser) + return "User:" + String.valueOf(((DynamoUser)value).getUID()); + + if (value instanceof DynamoGroup) + return "Group:" + String.valueOf(((DynamoGroup)value).getGID()); + + return null; + + } // end serializeProperty + + public Object deserializeProperty(String value) + { + try + { // look for our known prefixes + if (value.startsWith("User:")) + return getUserProxy(Integer.parseInt(value.substring(5))); + + if (value.startsWith("Group:")) + return getGroupProxy(Integer.parseInt(value.substring(6))); + + return null; + + } // end try + catch (NumberFormatException e) + { // number parse blew up... + return null; + + } // end catch + + } // end deserializeProperty + + } // end UserGroupSerializer + + /*-------------------------------------------------------------------------------- + * Internal class implementing the adapter for UserPropertyTranslator + *-------------------------------------------------------------------------------- + */ + + class UserPropertyAdapter implements UserPropertyTranslator + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private UserPropertyTranslator m_upt = null; + + /*==================================================================== + * Constructor + *==================================================================== + */ + + UserPropertyAdapter() + { // do nothing + } // end constructor + + /*==================================================================== + * Implementations from interface UserPropertyTranslator + *==================================================================== + */ + + public String getUserFullName(DynamoUser user) + { + if (m_upt!=null) + return m_upt.getUserFullName(user); + else + return user.getName(); + + } // end getUserFullName + + /*==================================================================== + * External operations + *==================================================================== + */ + + void setTranslator(UserPropertyTranslator upt) + { + m_upt = upt; + + } // end setTranslator + + } // end class UserPropertyAdapter + + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final int MAX_USERNAME = 64; + private static final int MAX_GROUPNAME = 64; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private UserPropertyAdapter m_adapter; // user property adapter + private String m_name; // object name + private NamespaceCache m_ns_cache; // namespace cache object + private SecurityReferenceMonitor m_srm; // security reference monitor + private PostDynamicUpdate m_post; // dynamic update poster + private UserManagerOps m_ops; // database operations object + private UserObject m_anon_user = null; // permanent reference to anonymous user + private Object m_anon_user_sync = new Object(); // synchronization on the above field + private HashMap m_id_to_user = new HashMap(); // map from IDs (Integer) to objects + private HashMap m_name_to_user = new HashMap(); // map from names (DynamoIDKey) to objects + private ReferenceQueue m_rq = new ReferenceQueue(); // reference queue for old objects + private Object m_users_sync = new Object(); // synchronization for user HashMaps + private HashMap m_id_to_group = new HashMap(); // map from IDs (Integer) to groups + private HashMap m_name_to_group = new HashMap(); // map from names (DynamoIDKey) to groups + private ReferenceQueue m_group_rq = new ReferenceQueue(); // reference queue for group objects + private Object m_groups_sync = new Object(); // synchronization for group HashMaps + private Hashtable m_authenticators = new Hashtable(); // authenticators list + private ComponentShutdown m_hook_init; // hook for init service provider + private ComponentShutdown m_pszreg; // property serializer registration + private ComponentShutdown m_evt_user; // event registration + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public UserManagerObject() + { + m_adapter = new UserPropertyAdapter(); // create the adapter + + // Add some default authenticators. + m_authenticators.put(new QualifiedNameKey(NAMESPACE,AUTH_DEFAULT),new DefaultHashAuthenticator()); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface NamedObject + *-------------------------------------------------------------------------------- + */ + + public String getName() + { + return m_name; + + } // end getName + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentInitialize + *-------------------------------------------------------------------------------- + */ + + public void initialize(Element config_root, ServiceProvider services) throws ConfigException + { + String conn_name = null; + String nscache_name = null; + String srm_name = null; + String connect_name = null; + XMLLoader loader = XMLLoader.get(); + try + { // verify the right node name + loader.verifyNodeName(config_root,"object"); + + // get the object's name + m_name = loader.getAttribute(config_root,"name"); + + // get the database configuration connection + DOMElementHelper config_root_h = new DOMElementHelper(config_root); + Element elt = loader.getSubElement(config_root_h,"database"); + conn_name = loader.getAttribute(elt,"connection"); + nscache_name = loader.getAttribute(elt,"namespaces"); + + // get the security reference monitor reference + elt = loader.getSubElement(config_root_h,"security"); + srm_name = loader.getAttribute(elt,"object"); + + // get the name of the connection point to connect ourselves to + elt = config_root_h.getSubElement("connect-proxy-services"); + if (elt!=null) + connect_name = loader.getAttribute(elt,"cpoint"); + + } // end try + catch (XMLLoadException e) + { // error loading XML config data + throw new ConfigException(e); + + } // end catch + + // Get the database connection pool, namespace cache, and security reference monitor. + DBConnectionPool pool = GetObjectUtils.getDatabaseConnection(services,conn_name); + m_ns_cache = + (NamespaceCache)(GetObjectUtils.getDynamoComponent(services,NamespaceCache.class,nscache_name)); + m_srm = + (SecurityReferenceMonitor)(GetObjectUtils.getDynamoComponent(services,SecurityReferenceMonitor.class, + srm_name)); + m_post = (PostDynamicUpdate)(services.queryService(PostDynamicUpdate.class)); + + // Get the operations object. + m_ops = UserManagerOps.get(pool); + + // Connect our proxy services to the connection point. + if (connect_name!=null) + { // get the ConnectionBackend service and use it to jack in + ConnectionBackEnd backend = (ConnectionBackEnd)(services.queryService(ConnectionBackEnd.class)); + backend.connectObject(connect_name,this); + + } // end if + + // Register event listeners that forward events to the right location. + EventListenerRegistration reg = + (EventListenerRegistration)(services.queryService(EventListenerRegistration.class)); + UpdateListener ul = new UpdateListener(); + m_evt_user = reg.registerDynamicUpdateListener(UserUpdateEvent.class,ul); + + // Register our property serializer to let User and Group objects be serialized. + PropertySerializerRegistration psreg = + (PropertySerializerRegistration)(services.queryService(PropertySerializerRegistration.class)); + m_pszreg = psreg.registerPropertySerializer(new UserGroupSerializer()); + + // Add us to the initialization services. + HookServiceProviders hooker = (HookServiceProviders)(services.queryService(HookServiceProviders.class)); + SingletonServiceProvider ssp = new SingletonServiceProvider("UserManagerObject", + AuthenticatorRegistration.class, + (AuthenticatorRegistration)this); + m_hook_init = hooker.hookInitServiceProvider(ssp); + + } // end initialize + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentShutdown + *-------------------------------------------------------------------------------- + */ + + public void shutdown() + { + m_evt_user.shutdown(); + m_evt_user = null; + m_pszreg.shutdown(); + m_pszreg = null; + m_hook_init.shutdown(); + m_hook_init = null; + m_authenticators.clear(); + m_id_to_user.clear(); + m_name_to_user.clear(); + m_anon_user = null; + m_ops.dispose(); + m_ops = null; + m_post = null; + m_srm = null; + m_ns_cache = null; + + } // end shutdown + + /*-------------------------------------------------------------------------------- + * Implementations from interface UserManagement + *-------------------------------------------------------------------------------- + */ + + public DynamoUser getAnonymousUser() throws DatabaseException + { + synchronized (m_anon_user_sync) + { // get the anonymous user, if it doesn't already exist + if (m_anon_user==null) + { // get the data for the anonymous user + Map data = m_ops.getAnonymousUserData(); + if (data==null) + throw new DatabaseException(UserManagerObject.class,"UserMessages","anon.notFound"); + m_anon_user = new UserObject(data,true,m_ops.getObjectOps(),m_ns_cache,m_srm,this,m_post,m_adapter); + + } // end if + + return m_anon_user; + + } // end synchronized block + + } // end getAnonymousUser + + public DynamoUser getUser(int id) throws DatabaseException + { + DynamoUser rc = getAnonymousUser(); + if (rc.getUID()==id) + return rc; + + rc = null; + Integer key = new Integer(id); + synchronized (m_users_sync) + { // try to retrieve the user + IDNameCacheObject cobj = (IDNameCacheObject)(m_id_to_user.get(key)); + if (cobj!=null) + { // got a cache object - retrieve the user value + rc = (DynamoUser)(cobj.get()); + if (rc==null) + { // the UserObject got kicked out! kick it out of the HashMaps + m_id_to_user.remove(key); + m_name_to_user.remove(cobj.getNameKey()); + cobj.clear(); + cobj = null; + + } // end if + + } // end if + + if (rc==null) + { // OK, we have to go to the database to find the user + Map data = m_ops.getUserData(id); + if (data!=null) + { // create UserObject and add it to our cache maps + UserObject uobj = new UserObject(data,false,m_ops.getObjectOps(),m_ns_cache,m_srm,this,m_post, + m_adapter); + rc = uobj; + cobj = new IDNameCacheObject(key,uobj.getName(),uobj,m_rq); + m_id_to_user.put(cobj.getIDKey(),cobj); + m_name_to_user.put(cobj.getNameKey(),cobj); + + } // end if + // else user does not exist - return null + + } // end if + + } // end synchronized block + + return rc; + + } // end getUser + + public DynamoUser getUser(String username) throws DatabaseException + { + DynamoUser rc = getAnonymousUser(); + if (rc.getName().equalsIgnoreCase(username)) + return rc; + + rc = null; + DynamoIDKey key = new DynamoIDKey(username); + synchronized (m_users_sync) + { // try to retrieve the user + IDNameCacheObject cobj = (IDNameCacheObject)(m_name_to_user.get(key)); + if (cobj!=null) + { // got a cache object - retrieve the user value + rc = (DynamoUser)(cobj.get()); + if (rc==null) + { // the UserObject got kicked out! kick it out of the HashMaps + m_id_to_user.remove(cobj.getIDKey()); + m_name_to_user.remove(key); + cobj.clear(); + cobj = null; + + } // end if + + } // end if + + if (rc==null) + { // OK, we have to go to the database to find the user + Map data = m_ops.getUserData(username); + if (data!=null) + { // create user object and add it to our cache maps + UserObject uobj = new UserObject(data,false,m_ops.getObjectOps(),m_ns_cache,m_srm,this,m_post, + m_adapter); + rc = uobj; + cobj = new IDNameCacheObject(uobj.getUID(),key,uobj,m_rq); + m_id_to_user.put(cobj.getIDKey(),cobj); + m_name_to_user.put(cobj.getNameKey(),cobj); + + } // end if + // else user does not exist - return null + + } // end if + + } // end synchronized block + + return rc; + + } // end getUser + + public DynamoUser createUser(String username, String email) throws DatabaseException + { + DynamoUser rc = getAnonymousUser(); + if (rc.getName().equalsIgnoreCase(username)) + { // this user already exists + DatabaseException de = new DatabaseException(UserManagerObject.class,"UserMessages","user.exists"); + de.setParameter(0,username); + throw de; + + } // end if + + DynamoIDKey key = new DynamoIDKey(username); + if (!(key.isValid(MAX_USERNAME))) + { // the user ID is invalid... + DatabaseException de = new DatabaseException(UserManagerObject.class,"UserMessages","user.badID"); + de.setParameter(0,username); + throw de; + + } // end if + + rc = null; + synchronized (m_users_sync) + { // see if the user is in our cache already + IDNameCacheObject cobj = (IDNameCacheObject)(m_name_to_user.get(key)); + if (cobj!=null) + { // it's in the cache - we're going to fail this operation. But while we're here, if the + // actual user object has been kicked out, expunge the reference. + if (cobj.get()==null) + { // the UserObject got kicked out! kick it out of the HashMaps + m_id_to_user.remove(cobj.getIDKey()); + m_name_to_user.remove(key); + cobj.clear(); + cobj = null; + + } // end if + + // throw the exception saying that we exist + DatabaseException de = new DatabaseException(UserManagerObject.class,"UserMessages","user.exists"); + de.setParameter(0,username); + throw de; + + } // end if + + // OK, at this point, we can't be any surer the user doesn't already exist without + // hitting the database. So create it. (createNewUser will throw a DatabaseException if the + // user already exists.) + Map data = m_ops.createNewUser(username,email); + UserObject uobj = new UserObject(data,false,m_ops.getObjectOps(),m_ns_cache,m_srm,this,m_post,m_adapter); + rc = uobj; + cobj = new IDNameCacheObject(uobj.getUID(),key,uobj,m_rq); + m_id_to_user.put(cobj.getIDKey(),cobj); + m_name_to_user.put(cobj.getNameKey(),cobj); + + } // end synchronized block + + return rc; // new user created! + + } // end createUser + + public DynamoGroup getGroup(int id) throws DatabaseException + { + DynamoGroup rc = null; + Integer key = new Integer(id); + synchronized (m_groups_sync) + { // try to retrieve the group + IDNameCacheObject cobj = (IDNameCacheObject)(m_id_to_group.get(key)); + if (cobj!=null) + { // got a cache object - retrieve the group value + rc = (DynamoGroup)(cobj.get()); + if (rc==null) + { // the GroupObject got kicked out! kick it out of the HashMaps + m_id_to_group.remove(key); + m_name_to_group.remove(cobj.getNameKey()); + cobj.clear(); + cobj = null; + + } // end if + + } // end if + + if (rc==null) + { // OK, we have to go to the database to find the group + Map data = m_ops.getGroupData(id); + if (data!=null) + { // create GroupObject and add it to our cache maps + GroupObject gobj = new GroupObject(data,m_ops.getGroupOps(),m_ns_cache,m_srm,this); + rc = gobj; + cobj = new IDNameCacheObject(key,gobj.getName(),gobj,m_group_rq); + m_id_to_group.put(cobj.getIDKey(),cobj); + m_name_to_group.put(cobj.getNameKey(),cobj); + + } // end if + // else group does not exist - return null + + } // end if + + } // end synchronized block + + return rc; + + } // end getGroup + + public DynamoGroup getGroup(String groupname) throws DatabaseException + { + DynamoGroup rc = null; + DynamoIDKey key = new DynamoIDKey(groupname); + synchronized (m_groups_sync) + { // try to retrieve the group + IDNameCacheObject cobj = (IDNameCacheObject)(m_name_to_group.get(key)); + if (cobj!=null) + { // got a cache object - retrieve the group value + rc = (DynamoGroup)(cobj.get()); + if (rc==null) + { // the GroupObject got kicked out! kick it out of the HashMaps + m_id_to_group.remove(cobj.getIDKey()); + m_name_to_group.remove(key); + cobj.clear(); + cobj = null; + + } // end if + + } // end if + + if (rc==null) + { // OK, we have to go to the database to find the group + Map data = m_ops.getGroupData(groupname); + if (data!=null) + { // create group object and add it to our cache maps + GroupObject gobj = new GroupObject(data,m_ops.getGroupOps(),m_ns_cache,m_srm,this); + rc = gobj; + cobj = new IDNameCacheObject(gobj.getGID(),key,gobj,m_group_rq); + m_id_to_group.put(cobj.getIDKey(),cobj); + m_name_to_group.put(cobj.getNameKey(),cobj); + + } // end if + // else group does not exist - return null + + } // end if + + } // end synchronized block + + return rc; + + } // end getGroup + + public DynamoGroup createGroup(String groupname) throws DatabaseException + { + DynamoIDKey key = new DynamoIDKey(groupname); + if (!(key.isValid(MAX_GROUPNAME))) + { // the group ID is invalid... + DatabaseException de = new DatabaseException(UserManagerObject.class,"UserMessages","group.badID"); + de.setParameter(0,groupname); + throw de; + + } // end if + + DynamoGroup rc = null; + synchronized (m_groups_sync) + { // see if the group is in our cache already + IDNameCacheObject cobj = (IDNameCacheObject)(m_name_to_group.get(key)); + if (cobj!=null) + { // it's in the cache - we're going to fail this operation. But while we're here, if the + // actual group object has been kicked out, expunge the reference. + if (cobj.get()==null) + { // the GroupObject got kicked out! kick it out of the HashMaps + m_id_to_group.remove(cobj.getIDKey()); + m_name_to_group.remove(key); + cobj.clear(); + cobj = null; + + } // end if + + // throw the exception saying that we exist + DatabaseException de = new DatabaseException(UserManagerObject.class,"UserMessages","group.exists"); + de.setParameter(0,groupname); + throw de; + + } // end if + + // OK, at this point, we can't be any surer the group doesn't already exist without + // hitting the database. So create it. (createNewGroup will throw a DatabaseException if the + // group already exists.) + Map data = m_ops.createNewGroup(groupname); + GroupObject gobj = new GroupObject(data,m_ops.getGroupOps(),m_ns_cache,m_srm,this); + rc = gobj; + cobj = new IDNameCacheObject(gobj.getGID(),key,gobj,m_group_rq); + m_id_to_group.put(cobj.getIDKey(),cobj); + m_name_to_group.put(cobj.getNameKey(),cobj); + + } // end synchronized block + + return rc; // new group created! + + } // end createNewGroup + + public void loadUserDefaults(DynamoUser user, Collection namespaces) throws DatabaseException + { + // Start by translating all the namespaces to namespace IDs. + int[] nsids = new int[namespaces.size()]; + int i = 0; + Iterator it = namespaces.iterator(); + while (it.hasNext()) + nsids[i++] = m_ns_cache.namespaceNameToId(it.next().toString()); + + // Now feed it into the database operations. + m_ops.loadUserDefaults(user.getUID(),nsids); + + } // end loadUserDefaults + + /*-------------------------------------------------------------------------------- + * Implementations from interface UserProxyManagement + *-------------------------------------------------------------------------------- + */ + + public DynamoUser getUserProxy(int uid) + { + synchronized (m_anon_user_sync) + { // get the anonymous user, if it's there and matches + if ((m_anon_user!=null) && (m_anon_user.getUID()==uid)) + return m_anon_user; + + } // end synchronized block + + Integer key = new Integer(uid); + synchronized (m_users_sync) + { // try to retrieve the user + IDNameCacheObject cobj = (IDNameCacheObject)(m_id_to_user.get(key)); + if (cobj!=null) + { // got a cache object - retrieve the user value + DynamoUser rc = (DynamoUser)(cobj.get()); + if (rc==null) + { // the UserObject got kicked out! kick it out of the HashMaps + m_id_to_user.remove(key); + m_name_to_user.remove(cobj.getNameKey()); + rc = new MyUserProxy(uid,cobj.getNameKey().toString()); + cobj.clear(); + cobj = null; + + } // end if + + return rc; + + } // end if + + return new MyUserProxy(uid); // just return a proxy object + + } // end synchronized block + + } // end getUserProxy + + public DynamoUser getUserProxy(int uid, String username) + { + synchronized (m_anon_user_sync) + { // get the anonymous user, if it's there and matches + if ((m_anon_user!=null) && (m_anon_user.getUID()==uid)) + return m_anon_user; + + } // end synchronized block + + Integer key = new Integer(uid); + synchronized (m_users_sync) + { // try to retrieve the user + IDNameCacheObject cobj = (IDNameCacheObject)(m_id_to_user.get(key)); + if (cobj!=null) + { // got a cache object - retrieve the user value + DynamoUser rc = (DynamoUser)(cobj.get()); + if (rc==null) + { // the UserObject got kicked out! kick it out of the HashMaps + m_id_to_user.remove(key); + m_name_to_user.remove(cobj.getNameKey()); + rc = new MyUserProxy(uid,cobj.getNameKey().toString()); + cobj.clear(); + cobj = null; + + } // end if + + return rc; + + } // end if + + return new MyUserProxy(uid,username); // just return a proxy object + + } // end synchronized block + + } // end getUserProxy + + public DynamoGroup getGroupProxy(int gid) + { + Integer key = new Integer(gid); + synchronized (m_groups_sync) + { // try to retrieve the group + IDNameCacheObject cobj = (IDNameCacheObject)(m_id_to_group.get(key)); + if (cobj!=null) + { // got a cache object - retrieve the group value + DynamoGroup rc = (DynamoGroup)(cobj.get()); + if (rc==null) + { // the GroupObject got kicked out! kick it out of the HashMaps + m_id_to_group.remove(key); + m_name_to_group.remove(cobj.getNameKey()); + rc = new MyGroupProxy(gid,cobj.getNameKey().toString()); + cobj.clear(); + cobj = null; + + } // end if + + return rc; + + } // end if + + return new MyGroupProxy(gid); // just return a proxy object + + } // end synchronized block + + } // end getGroupProxy + + public DynamoGroup getGroupProxy(int gid, String groupname) + { + Integer key = new Integer(gid); + synchronized (m_groups_sync) + { // try to retrieve the group + IDNameCacheObject cobj = (IDNameCacheObject)(m_id_to_group.get(key)); + if (cobj!=null) + { // got a cache object - retrieve the group value + DynamoGroup rc = (DynamoGroup)(cobj.get()); + if (rc==null) + { // the GroupObject got kicked out! kick it out of the HashMaps + m_id_to_group.remove(key); + m_name_to_group.remove(cobj.getNameKey()); + rc = new MyGroupProxy(gid,cobj.getNameKey().toString()); + cobj.clear(); + cobj = null; + + } // end if + + return rc; + + } // end if + + return new MyGroupProxy(gid,groupname); // just return a proxy object + + } // end synchronized block + + } // end getGroupProxy + + /*-------------------------------------------------------------------------------- + * Implementations from interface AuthenticatorLookup + *-------------------------------------------------------------------------------- + */ + + public Authenticator findAuthenticator(String method_namespace, String method) + { + return (Authenticator)(m_authenticators.get(new QualifiedNameKey(method_namespace,method))); + + } // end findAuthenticator + + /*-------------------------------------------------------------------------------- + * Implementations from interface AuthenticatorRegistration + *-------------------------------------------------------------------------------- + */ + + public ComponentShutdown registerAuthenticator(String method_namespace, String method, Authenticator auth) + throws ConfigException + { + QualifiedNameKey key = new QualifiedNameKey(method_namespace,method); + if (m_authenticators.containsKey(key)) + { // dump out here + ConfigException ce = new ConfigException(UserManagerObject.class,"DatabaseMessages","auth.register"); + ce.setParameter(0,method_namespace); + ce.setParameter(1,method); + throw ce; + + } // end if + + m_authenticators.put(key,auth); + return new ShutdownHashtableRemove(m_authenticators,key); + + } // end registerAuthenticator + + /*-------------------------------------------------------------------------------- + * Implementations from interface UserPropertyTranslatorInstall + *-------------------------------------------------------------------------------- + */ + + public void installUserPropertyTranslator(UserPropertyTranslator upt) + { + m_adapter.setTranslator(upt); + + } // end installUserPropertyTranslator + +} // end class UserManagerObject diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagerOps.java b/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagerOps.java new file mode 100644 index 0000000..1abacb4 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagerOps.java @@ -0,0 +1,102 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.util.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +abstract class UserManagerOps extends OpsBase +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + static final String HMKEY_UID = "uid"; + static final String HMKEY_USERNAME = "username"; + static final String HMKEY_EMAIL = "email"; + static final String HMKEY_LOCKED = "locked"; + static final String HMKEY_NOSPAM = "nospam"; + static final String HMKEY_CREATED = "created"; + static final String HMKEY_LAST_ACCESS = "last_accessed"; + + static final String HMKEY_GID = "gid"; + static final String HMKEY_GROUPNAME = "groupname"; + static final String HMKEY_GACLID = "gaclid"; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + protected UserManagerOps(DBConnectionPool pool) + { + super(pool); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class OpsBase + *-------------------------------------------------------------------------------- + */ + + public void dispose() + { + super.dispose(); + + } // end dispose + + /*-------------------------------------------------------------------------------- + * Abstract operations + *-------------------------------------------------------------------------------- + */ + + abstract UserObjectOps getObjectOps(); + + abstract GroupObjectOps getGroupOps(); + + abstract Map getAnonymousUserData() throws DatabaseException; + + abstract Map getUserData(int id) throws DatabaseException; + + abstract Map getUserData(String username) throws DatabaseException; + + abstract Map createNewUser(String username, String email) throws DatabaseException; + + abstract Map getGroupData(int id) throws DatabaseException; + + abstract Map getGroupData(String groupname) throws DatabaseException; + + abstract Map createNewGroup(String groupname) throws DatabaseException; + + abstract void loadUserDefaults(int uid, int[] nsids) throws DatabaseException; + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + static UserManagerOps get(DBConnectionPool pool) throws ConfigException + { + return (UserManagerOps)get(pool,UserManagerOps.class.getClassLoader(), + UserManagerOps.class.getName() + "_","UserManagerOps"); + + } // end get + +} // end class UserManagerOps diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagerOps_mysql.java b/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagerOps_mysql.java new file mode 100644 index 0000000..2dbaed9 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/UserManagerOps_mysql.java @@ -0,0 +1,463 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.sql.*; +import java.util.*; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +public class UserManagerOps_mysql extends UserManagerOps +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final Integer GACLID_NONE = new Integer(-1); + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private DBUtilities m_utils; // reference to utilities object + private UserObjectOps m_obj_ops = null; // object operations object + private GroupObjectOps m_group_ops = null; // group operations object + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public UserManagerOps_mysql(DBConnectionPool pool) + { + super(pool); + m_utils = (DBUtilities)(pool.queryService(DBUtilities.class)); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class UserManagerOps + *-------------------------------------------------------------------------------- + */ + + synchronized UserObjectOps getObjectOps() + { + if (m_obj_ops==null) + m_obj_ops = new UserObjectOps_mysql(getPool(),m_utils); + return m_obj_ops; + + } // end getObjectOps + + synchronized GroupObjectOps getGroupOps() + { + if (m_group_ops==null) + m_group_ops = new GroupObjectOps_mysql(getPool(),m_utils); + return m_group_ops; + + } // end getGroupOps + + Map getAnonymousUserData() throws DatabaseException + { + Connection conn = null; + Statement stmt = null; + ResultSet rs = null; + try + { // get a connection and statement + conn = getConnection(); + stmt = conn.createStatement(); + rs = stmt.executeQuery("SELECT uid, username, email, created, last_accessed FROM users " + + "WHERE is_anon = 1;"); + if (!(rs.next())) + return null; // no anonymous user info (will throw exception later) + + // Create and return the Map containing the user data. + HashMap rc = new HashMap(); + rc.put(HMKEY_UID,new Integer(rs.getInt(1))); + rc.put(HMKEY_USERNAME,rs.getString(2)); + rc.put(HMKEY_EMAIL,rs.getString(3)); + rc.put(HMKEY_LOCKED,Boolean.FALSE); + rc.put(HMKEY_NOSPAM,Boolean.TRUE); + rc.put(HMKEY_CREATED,m_utils.getDateTime(rs,4)); + java.util.Date lacc = m_utils.getDateTime(rs,5); + if (lacc!=null) + rc.put(HMKEY_LAST_ACCESS,lacc); + return rc; + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + } // end getAnonymousUserData + + Map getUserData(int id) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // execute the statement to get the user data + stmt = conn.prepareStatement("SELECT username, email, locked, nospam, created, last_accessed FROM users " + + "WHERE uid = ? AND is_anon = 0;"); + stmt.setInt(1,id); + rs = stmt.executeQuery(); + if (!(rs.next())) + return null; // no user info + + // Create and return the Map containing the user data. + HashMap rc = new HashMap(); + rc.put(HMKEY_UID,new Integer(id)); + rc.put(HMKEY_USERNAME,rs.getString(1)); + rc.put(HMKEY_EMAIL,rs.getString(2)); + rc.put(HMKEY_LOCKED,Boolean.valueOf(rs.getBoolean(3))); + rc.put(HMKEY_NOSPAM,Boolean.valueOf(rs.getBoolean(4))); + rc.put(HMKEY_CREATED,m_utils.getDateTime(rs,5)); + java.util.Date lacc = m_utils.getDateTime(rs,6); + if (lacc!=null) + rc.put(HMKEY_LAST_ACCESS,lacc); + return rc; + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + } // end getUserData + + Map getUserData(String username) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // execute the statement to get the user data + stmt = conn.prepareStatement("SELECT uid, email, locked, nospam, created, last_accessed FROM users " + + "WHERE username = ? AND is_anon = 0;"); + stmt.setString(1,username); + rs = stmt.executeQuery(); + if (!(rs.next())) + return null; // no user info + + // Create and return the Map containing the user data. + HashMap rc = new HashMap(); + rc.put(HMKEY_UID,new Integer(rs.getInt(1))); + rc.put(HMKEY_USERNAME,username); + rc.put(HMKEY_EMAIL,rs.getString(2)); + rc.put(HMKEY_LOCKED,Boolean.valueOf(rs.getBoolean(3))); + rc.put(HMKEY_NOSPAM,Boolean.valueOf(rs.getBoolean(4))); + rc.put(HMKEY_CREATED,m_utils.getDateTime(rs,5)); + java.util.Date lacc = m_utils.getDateTime(rs,6); + if (lacc!=null) + rc.put(HMKEY_LAST_ACCESS,lacc); + return rc; + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + } // end getUserData + + Map createNewUser(String username, String email) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the users table + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES users WRITE;"); + + // see if the user already exists + stmt = conn.prepareStatement("SELECT uid FROM users WHERE username = ?;"); + stmt.setString(1,username); + rs = stmt.executeQuery(); + if (rs.next()) + { // user exists - our operation is blown + DatabaseException de = new DatabaseException(UserManagerOps_mysql.class,"UserMessages","user.exists"); + de.setParameter(0,username); + throw de; + + } // end if + + // close down previous statement in prep for next one + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + + // insert the new user record! + stmt = conn.prepareStatement("INSERT INTO users (username, email, created) VALUES (?, ?, ?);"); + stmt.setString(1,username); + stmt.setString(2,email); + java.util.Date created = new java.util.Date(); + m_utils.setDateTime(stmt,3,created); + stmt.executeUpdate(); + + // Generate the return Map, suitable for creating a new object. + HashMap rc = new HashMap(); + rc.put(HMKEY_UID,new Integer(MySQLUtils.getLastInsertInt(conn))); + rc.put(HMKEY_USERNAME,username); + rc.put(HMKEY_EMAIL,email); + rc.put(HMKEY_LOCKED,Boolean.FALSE); + rc.put(HMKEY_NOSPAM,Boolean.FALSE); + rc.put(HMKEY_CREATED,created); + return rc; + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end createNewUser + + Map getGroupData(int id) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // execute the statement to get the group data + stmt = conn.prepareStatement("SELECT groupname, gaclid FROM groups WHERE gid = ?;"); + stmt.setInt(1,id); + rs = stmt.executeQuery(); + if (!(rs.next())) + return null; // no group info + + // Create and return the Map containing the group data. + HashMap rc = new HashMap(); + rc.put(HMKEY_GID,new Integer(id)); + rc.put(HMKEY_GROUPNAME,rs.getString(1)); + rc.put(HMKEY_GACLID,new Integer(rs.getInt(2))); + return rc; + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + } // end getGroupData + + Map getGroupData(String groupname) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // execute the statement to get the group data + stmt = conn.prepareStatement("SELECT gid, gaclid FROM groups WHERE groupname = ?;"); + stmt.setString(1,groupname); + rs = stmt.executeQuery(); + if (!(rs.next())) + return null; // no group info + + // Create and return the Map containing the group data. + HashMap rc = new HashMap(); + rc.put(HMKEY_GID,new Integer(rs.getInt(1))); + rc.put(HMKEY_GROUPNAME,groupname); + rc.put(HMKEY_GACLID,new Integer(rs.getInt(2))); + return rc; + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + } // end getGroupData + + Map createNewGroup(String groupname) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the groups table + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES groups WRITE;"); + + // see if the group already exists + stmt = conn.prepareStatement("SELECT gid FROM groups WHERE groupname = ?;"); + stmt.setString(1,groupname); + rs = stmt.executeQuery(); + if (rs.next()) + { // group exists - our operation is blown + DatabaseException de = new DatabaseException(UserManagerOps_mysql.class,"UserMessages","group.exists"); + de.setParameter(0,groupname); + throw de; + + } // end if + + // close down previous statement in prep for next one + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + + // insert the new group record! + stmt = conn.prepareStatement("INSERT INTO groups (groupname) VALUES (?);"); + stmt.setString(1,groupname); + stmt.executeUpdate(); + + // Generate the return Map, suitable for creating a new object. + HashMap rc = new HashMap(); + rc.put(HMKEY_GID,new Integer(MySQLUtils.getLastInsertInt(conn))); + rc.put(HMKEY_GROUPNAME,groupname); + rc.put(HMKEY_GACLID,GACLID_NONE); + return rc; + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end createNewGroup + + void loadUserDefaults(int uid, int[] nsids) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt_insert = null; + Statement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the global and user properties tables + stmt = conn.createStatement(); + stmt.executeUpdate("LOCK TABLES userprop WRITE, globalprop READ;"); + + // prepare the fancy insert statement + stmt_insert = conn.prepareStatement("INSERT INTO userprop (uid, nsid, prop_name, prop_value) " + + "SELECT ?, globalprop.nsid, globalprop.prop_name, " + + "globalprop.prop_value FROM globalprop " + + "WHERE globalprop.nsid = ?;"); + for (int i=0; i. +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +# --------------------------------------------------------------------------------- +# This file has been localized for the en_US locale +anon.notFound=Internal Error: Unable to load information for the anonymous user. +user.exists=User "{0}" already exists in the database. +user.badID=The user name "{0}" is not valid. +group.exists=Group "{0}" already exists in the database. +group.badID=The group name "{0}" is not valid. diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/UserObject.java b/src/dynamo-framework/com/silverwrist/dynamo/db/UserObject.java new file mode 100644 index 0000000..5e84e17 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/UserObject.java @@ -0,0 +1,527 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.util.*; +import org.apache.commons.collections.*; +import com.silverwrist.dynamo.UserInfoNamespace; +import com.silverwrist.dynamo.event.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.security.SecurityReferenceMonitor; +import com.silverwrist.dynamo.util.*; + +class UserObject implements DynamoUser, UserInfoNamespace +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private UserObjectOps m_ops; // operations object + private NamespaceCache m_ns_cache; // namespace cache object + private SecurityReferenceMonitor m_srm; // security reference monitor + private AuthenticatorLookup m_auth_lookup; // authenticator lookup + private PostDynamicUpdate m_post; // where we post dynamic events + private UserPropertyTranslator m_upt; + private int m_uid; // user ID + private String m_username; // user name + private String m_email; // E-mail address + private java.util.Date m_created; // created date + private java.util.Date m_last_accessed; // last access date + private boolean m_anonymous; // is this the anonymous user? + private boolean m_locked; // is user locked? + private boolean m_nospam; // user "no-spam" flag + private ReferenceMap m_properties; // cached property values + private Object m_properties_sync = new Object(); // synchronization for above + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + UserObject(Map data, boolean anonymous, UserObjectOps ops, NamespaceCache ns_cache, + SecurityReferenceMonitor srm, AuthenticatorLookup auth_lookup, PostDynamicUpdate post, + UserPropertyTranslator upt) + { + m_ops = ops; + m_ns_cache = ns_cache; + m_srm = srm; + m_auth_lookup = auth_lookup; + m_post = post; + m_upt = upt; + m_uid = ((Integer)(data.get(UserManagerOps.HMKEY_UID))).intValue(); + m_username = (String)(data.get(UserManagerOps.HMKEY_USERNAME)); + m_email = (String)(data.get(UserManagerOps.HMKEY_EMAIL)); + m_created = (java.util.Date)(data.get(UserManagerOps.HMKEY_CREATED)); + m_last_accessed = (java.util.Date)(data.get(UserManagerOps.HMKEY_LAST_ACCESS)); + m_anonymous = anonymous; + m_locked = ((Boolean)(data.get(UserManagerOps.HMKEY_LOCKED))).booleanValue(); + m_nospam = ((Boolean)(data.get(UserManagerOps.HMKEY_NOSPAM))).booleanValue(); + m_properties = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private final void testChangeOK(DynamoUser caller) throws DatabaseException, DynamoSecurityException + { + if (equals(caller)) + return; // a user can always change their OWN information + + if (caller.equals(m_srm.getAdminUser())) + return; // Administrator can do anything + + if (m_srm.getGlobalAcl().testPermission(caller,NAMESPACE,PERM_EDIT_ALL)) + return; // and so can anyone else with "edit all" permission on the global ACL + + // Presume the change is forbidden - throw the exception + DynamoSecurityException dse = new DynamoSecurityException(UserObject.class,"DatabaseMessages", + "sec.changeUser"); + dse.setParameter(0,m_username); + throw dse; + + } // end testChangeOK + + /*-------------------------------------------------------------------------------- + * Implementations from interface Principal + *-------------------------------------------------------------------------------- + */ + + public boolean equals(Object another) + { + if (another==null) + return false; + if (another instanceof DynamoUser) + return (m_uid==((DynamoUser)another).getUID()); + return false; + + } // end equals + + public String toString() + { + return "user " + m_username; + + } // end toString + + public int hashCode() + { + return m_uid; + + } // end hashCode + + public String getName() + { + return m_username; + + } // end getName + + /*-------------------------------------------------------------------------------- + * Implementations from interface ObjectProvider + *-------------------------------------------------------------------------------- + */ + + /** + * Retrieves an object from this ObjectProvider. + * + * @param namespace The namespace to interpret the name relative to. + * @param name The name of the object to be retrieved. + * @return The object reference specified. + */ + public Object getObject(String namespace, String name) + { + if (NAMESPACE.equals(namespace)) + { // handle user info namespace specially + if (ATTR_FULLNAME.equals(name)) + return m_upt.getUserFullName(this); + else if (ATTR_EMAIL_ADDRESS.equals(name)) + return m_email; + else if (ATTR_ID.equals(name)) + return new Integer(m_uid); + else if (ATTR_USERNAME.equals(name)) + return m_username; + else + throw new NoSuchObjectException(this.toString(),namespace,name); + + } // end if + + try + { // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + Object rc = null; + synchronized (m_properties_sync) + { // start by looking in the properties map + rc = m_properties.get(key); + if (rc==null) + { // no use - need to try the database + rc = m_ops.getProperty(m_uid,key); + if (rc!=null) + m_properties.put(key,rc); + + } // end if + + } // end synchronized block + + if (rc==null) + throw new NoSuchObjectException(this.toString(),namespace,name); + return rc; + + } // end try + catch (DatabaseException e) + { // translate into our NoSuchObjectException but retain the DatabaseException + throw new NoSuchObjectException(this.toString(),namespace,name,e); + + } // end catch + + } // end getObject + + /*-------------------------------------------------------------------------------- + * Implementations from interface SecureObjectStore + *-------------------------------------------------------------------------------- + */ + + public Object setObject(DynamoUser caller, String namespace, String name, Object value) + throws DatabaseException, DynamoSecurityException + { + if (NAMESPACE.equals(namespace)) + { // can't set more data in restricted namespace + ObjectStoreException ose = new ObjectStoreException(UserObject.class,"DatabaseMessages", + "ose.setProperty"); + ose.setParameter(0,namespace); + ose.setParameter(1,name); + throw ose; + + } // end if + + testChangeOK(caller); + Object rc = null; + + // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + synchronized (m_properties_sync) + { // start by setting the database value + rc = m_ops.setProperty(m_uid,key,value); + + // and cache it, too + m_properties.put(key,value); + + } // end synchronized block + + m_post.postUpdate(new UserPropertyUpdateEvent(this,m_uid,namespace,name)); + return rc; + + } // end setObject + + public Object removeObject(DynamoUser caller, String namespace, String name) + throws DatabaseException, DynamoSecurityException + { + if (NAMESPACE.equals(namespace)) + { // can't set more data in restricted namespace + ObjectStoreException ose = new ObjectStoreException(UserObject.class,"DatabaseMessages", + "ose.removeProperty"); + ose.setParameter(0,namespace); + ose.setParameter(1,name); + throw ose; + + } // end if + + testChangeOK(caller); + Object rc = null; + // convert the namespace name to an ID here + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + synchronized (m_properties_sync) + { // start by killing the database value + rc = m_ops.removeProperty(m_uid,key); + + // and remove the cached value, too + m_properties.remove(key); + + } // end synchronized block + + m_post.postUpdate(new UserPropertyUpdateEvent(this,m_uid,namespace,name)); + return rc; + + } // end removeObject + + public Collection getNamespaces() throws DatabaseException + { + // call through to the database to get the list of namespace IDs + int[] ids = m_ops.getPropertyNamespaceIDs(m_uid); + + ArrayList rc = new ArrayList(ids.length); + for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.util.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.util.*; + +abstract class UserObjectOps extends OpsBase +{ + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + protected UserObjectOps(DBConnectionPool pool) + { + super(pool); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract operations + *-------------------------------------------------------------------------------- + */ + + abstract Object getProperty(int uid, PropertyKey key) throws DatabaseException; + + abstract Object setProperty(int uid, PropertyKey key, Object value) throws DatabaseException; + + abstract Object removeProperty(int uid, PropertyKey key) throws DatabaseException; + + abstract int[] getPropertyNamespaceIDs(int uid) throws DatabaseException; + + abstract Map getAllProperties(int uid, int namespace) throws DatabaseException; + + abstract void setLocked(int uid, boolean locked) throws DatabaseException; + + abstract void setNoSpam(int uid, boolean locked) throws DatabaseException; + + abstract void setEMailAddress(int uid, String addr) throws DatabaseException; + + abstract void setLastAccessed(int uid, java.util.Date date) throws DatabaseException; + + abstract String[] getAuthenticationData(int uid, int nsid, String method, String source_data) + throws DatabaseException; + + abstract void putAuthenticationData(int uid, int nsid, String method, String source_data, String auth_data) + throws DatabaseException; + + abstract void clearAuthenticationData(int uid, int nsid, String method, String source_data) + throws DatabaseException; + +} // end class UserObjectOps diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/UserObjectOps_mysql.java b/src/dynamo-framework/com/silverwrist/dynamo/db/UserObjectOps_mysql.java new file mode 100644 index 0000000..7abf77b --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/UserObjectOps_mysql.java @@ -0,0 +1,635 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.sql.*; +import java.util.*; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +class UserObjectOps_mysql extends UserObjectOps +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final String[] STRING_TEMPLATE = new String[0]; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private DBUtilities m_utils; + private PropertySerializer m_psz; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + UserObjectOps_mysql(DBConnectionPool pool, DBUtilities utils) + { + super(pool); + m_utils = utils; + m_psz = (PropertySerializer)(pool.queryService(PropertySerializer.class)); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class UserObjectOps + *-------------------------------------------------------------------------------- + */ + + Object getProperty(int uid, PropertyKey key) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + String rc_str = null; + try + { // get a connection + conn = getConnection(); + + // look up the property + stmt = conn.prepareStatement("SELECT prop_value FROM userprop WHERE uid = ? AND nsid = ? " + + "AND prop_name = ?;"); + stmt.setInt(1,uid); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + rs = stmt.executeQuery(); + if (!(rs.next())) + return null; // property not found + + rc_str = rs.getString(1); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(conn); + + } // end finally + + // Deserialize the property value. + Object rc = m_psz.deserializeProperty(rc_str); + if (rc!=null) + return rc; + + // deserialization exception - throw it + DatabaseException de = new DatabaseException(UserObjectOps_mysql.class,"DatabaseMessages", + "property.deserialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end getProperty + + Object setProperty(int uid, PropertyKey key, Object value) throws DatabaseException + { + String serialized_value = m_psz.serializeProperty(value); + if (serialized_value==null) + { // serialization exception - throw it + DatabaseException de = new DatabaseException(UserObjectOps_mysql.class,"DatabaseMessages", + "property.serialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end if + + String old_value = null; + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the table + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES userprop WRITE;"); + + // look to see if the property value is already there + stmt = conn.prepareStatement("SELECT prop_value FROM userprop WHERE uid = ? AND nsid = ? " + + "AND prop_name = ?;"); + stmt.setInt(1,uid); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + rs = stmt.executeQuery(); + if (rs.next()) + old_value = rs.getString(1); + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + + if (old_value!=null) + { // prepare the statement to update the existing record + stmt = conn.prepareStatement("UPDATE userprop SET prop_value = ? WHERE uid = ? " + + "AND nsid = ? AND prop_name = ?;"); + stmt.setString(1,serialized_value); + stmt.setInt(2,uid); + stmt.setInt(3,key.getNamespaceID()); + stmt.setString(4,key.getName()); + + } // end if + else + { // prepare the statement to insert a new record + stmt = conn.prepareStatement("INSERT INTO userprop (uid, nsid, prop_name, prop_value) " + + "VALUES (?, ?, ?, ?);"); + stmt.setInt(1,uid); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + stmt.setString(4,serialized_value); + + } // end else + + stmt.executeUpdate(); // execute it! + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + if (old_value==null) + return null; // no previous value + + // Deserialize the property value. + Object rc = m_psz.deserializeProperty(old_value); + if (rc!=null) + return rc; + + // deserialization exception - throw it + DatabaseException de = new DatabaseException(UserObjectOps_mysql.class,"DatabaseMessages", + "property.deserialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end setProperty + + Object removeProperty(int uid, PropertyKey key) throws DatabaseException + { + String old_value = null; + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the table + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES userprop WRITE;"); + + // look to see if the property value is already there + stmt = conn.prepareStatement("SELECT prop_value FROM userprop WHERE uid = ? AND nsid = ? " + + "AND prop_name = ?;"); + stmt.setInt(1,uid); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + rs = stmt.executeQuery(); + if (rs.next()) + old_value = rs.getString(1); + else + return null; // no need to remove anything + SQLUtils.shutdown(rs); + rs = null; + SQLUtils.shutdown(stmt); + + // delete the database row + stmt = conn.prepareStatement("DELETE FROM userprop WHERE uid = ? AND nsid = ? AND prop_name = ?;"); + stmt.setInt(1,uid); + stmt.setInt(2,key.getNamespaceID()); + stmt.setString(3,key.getName()); + stmt.executeUpdate(); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + // Deserialize the property value. + Object rc = m_psz.deserializeProperty(old_value); + if (rc!=null) + return rc; + + // deserialization exception - throw it + DatabaseException de = new DatabaseException(UserObjectOps_mysql.class,"DatabaseMessages", + "property.deserialize"); + de.setParameter(0,key.getName()); + throw de; + + } // end removeProperty + + int[] getPropertyNamespaceIDs(int uid) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // execute the query! + stmt = conn.prepareStatement("SELECT DISTINCT nsid FROM userprop WHERE uid = ?;"); + stmt.setInt(1,uid); + rs = stmt.executeQuery(); + + // read out a list of the namespace IDs + ArrayList tmp = new ArrayList(); + while (rs.next()) + tmp.add(new Integer(rs.getInt(1))); + + // create and return the array + int[] rc = new int[tmp.size()]; + for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import com.silverwrist.dynamo.iface.DynamoUser; + +public interface UserPropertyTranslator +{ + public String getUserFullName(DynamoUser user); + +} // end interface UserPropertyTranslator diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/UserPropertyTranslatorInstall.java b/src/dynamo-framework/com/silverwrist/dynamo/db/UserPropertyTranslatorInstall.java new file mode 100644 index 0000000..d7bdd2d --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/UserPropertyTranslatorInstall.java @@ -0,0 +1,24 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +public interface UserPropertyTranslatorInstall +{ + public void installUserPropertyTranslator(UserPropertyTranslator upt); + +} // end interface UserPropertyTranslatorInstall diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/UserProxy.java b/src/dynamo-framework/com/silverwrist/dynamo/db/UserProxy.java new file mode 100644 index 0000000..63136a9 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/UserProxy.java @@ -0,0 +1,260 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.util.*; +import com.silverwrist.dynamo.UserInfoNamespace; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +abstract class UserProxy implements DynamoUser, UserInfoNamespace, DynamicWrapper +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + protected int m_uid; + protected String m_username; + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + protected UserProxy(int uid) + { + m_uid = uid; + m_username = null; + + } // end constructor + + protected UserProxy(int uid, String username) + { + m_uid = uid; + m_username = username; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract operations + *-------------------------------------------------------------------------------- + */ + + protected abstract DynamoUser getRealUser(); + + /*-------------------------------------------------------------------------------- + * Implementations from interface Principal + *-------------------------------------------------------------------------------- + */ + + public boolean equals(Object another) + { + if (another==null) + return false; + if (another instanceof DynamoUser) + return (m_uid==((DynamoUser)another).getUID()); + return false; + + } // end equals + + public String toString() + { + if (m_username!=null) + return "user " + m_username; + return getRealUser().toString(); + + } // end toString + + public int hashCode() + { + return m_uid; + + } // end hashCode + + public String getName() + { + if (m_username!=null) + return m_username; + return getRealUser().getName(); + + } // end getName + + /*-------------------------------------------------------------------------------- + * Implementations from interface ObjectProvider + *-------------------------------------------------------------------------------- + */ + + /** + * Retrieves an object from this ObjectProvider. + * + * @param namespace The namespace to interpret the name relative to. + * @param name The name of the object to be retrieved. + * @return The object reference specified. + */ + public Object getObject(String namespace, String name) + { + return getRealUser().getObject(namespace,name); + + } // end getObject + + /*-------------------------------------------------------------------------------- + * Implementations from interface SecureObjectStore + *-------------------------------------------------------------------------------- + */ + + public Object setObject(DynamoUser caller, String namespace, String name, Object value) + throws DatabaseException, DynamoSecurityException + { + return getRealUser().setObject(caller,namespace,name,value); + + } // end setObject + + public Object removeObject(DynamoUser caller, String namespace, String name) + throws DatabaseException, DynamoSecurityException + { + return getRealUser().removeObject(caller,namespace,name); + + } // end removeObject + + public Collection getNamespaces() throws DatabaseException + { + return getRealUser().getNamespaces(); + + } // end getNamespaces + + public Collection getNamesForNamespace(String namespace) throws DatabaseException + { + return getRealUser().getNamesForNamespace(namespace); + + } // end getNamesForNamespace + + /*-------------------------------------------------------------------------------- + * Implementations from interface DynamoUser + *-------------------------------------------------------------------------------- + */ + + public int getUID() + { + return m_uid; + + } // end getUID + + public boolean isAnonymous() + { + return getRealUser().isAnonymous(); + + } // end isAnonymous + + public boolean isLocked() + { + return getRealUser().isLocked(); + + } // end isLocked + + public void setLocked(DynamoUser caller, boolean locked) throws DatabaseException, DynamoSecurityException + { + getRealUser().setLocked(caller,locked); + + } // end setLocked + + public boolean isNoSpam() + { + return getRealUser().isNoSpam(); + + } // end isNoSpam + + public void setNoSpam(DynamoUser caller, boolean nospam) throws DatabaseException, DynamoSecurityException + { + getRealUser().setNoSpam(caller,nospam); + + } // end setNoSpam + + public String getEMailAddress() + { + return getRealUser().getEMailAddress(); + + } // end getEMailAddress + + public boolean setEMailAddress(DynamoUser caller, String addr) + throws DatabaseException, DynamoSecurityException + { + return getRealUser().setEMailAddress(caller,addr); + + } // end setEMailAddress + + public boolean authenticate(String method_namespace, String method, String source_data, String auth_data) + throws DatabaseException, AuthenticationException + { + return getRealUser().authenticate(method_namespace,method,source_data,auth_data); + + } // end authenticate + + public void setAuthenticationData(DynamoUser caller, String method_namespace, String method, + String source_data, String auth_data) + throws DatabaseException, AuthenticationException, DynamoSecurityException + { + getRealUser().setAuthenticationData(caller,method_namespace,method,source_data,auth_data); + + } // end setAuthenticationData + + public void clearAuthenticationData(DynamoUser caller, String method_namespace, String method, + String source_data) throws DatabaseException, DynamoSecurityException + { + getRealUser().clearAuthenticationData(caller,method_namespace,method,source_data); + + } // end clearAuthenticationData + + public void clearAuthenticationData(DynamoUser caller, String method_namespace, String method) + throws DatabaseException, DynamoSecurityException + { + getRealUser().clearAuthenticationData(caller,method_namespace,method); + + } // end clearAuthenticationData + + public java.util.Date getCreationDate() + { + return getRealUser().getCreationDate(); + + } // end getCreationDate + + public java.util.Date getLastAccessDate() + { + return getRealUser().getLastAccessDate(); + + } // end getLastAccessDate + + public synchronized void setLastAccessDate(DynamoUser caller, java.util.Date date) + throws DatabaseException, DynamoSecurityException + { + getRealUser().setLastAccessDate(caller,date); + + } // end setLastAccessDate + + /*-------------------------------------------------------------------------------- + * Implementations from interface DynamicWrapper + *-------------------------------------------------------------------------------- + */ + + public Object unwrap() + { + return getRealUser(); + + } // end unwrap + +} // end class UserProxy diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/UserProxyManagement.java b/src/dynamo-framework/com/silverwrist/dynamo/db/UserProxyManagement.java new file mode 100644 index 0000000..7d5f97a --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/UserProxyManagement.java @@ -0,0 +1,32 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import com.silverwrist.dynamo.iface.*; + +public interface UserProxyManagement +{ + public DynamoUser getUserProxy(int uid); + + public DynamoUser getUserProxy(int uid, String username); + + public DynamoGroup getGroupProxy(int gid); + + public DynamoGroup getGroupProxy(int gid, String groupname); + +} // end interface UserProxyManagement diff --git a/src/dynamo-framework/com/silverwrist/dynamo/db/WrappedConnection.java b/src/dynamo-framework/com/silverwrist/dynamo/db/WrappedConnection.java new file mode 100644 index 0000000..d00f0ca --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/db/WrappedConnection.java @@ -0,0 +1,498 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.db; + +import java.sql.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +class WrappedConnection implements Connection +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private DBConnectionPool m_datapool; + private Connection m_conn; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + WrappedConnection(DBConnectionPool datapool, Connection conn) + { + m_datapool = datapool; + m_conn = conn; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class Object + *-------------------------------------------------------------------------------- + */ + + protected void finalize() throws Throwable + { + if (m_conn!=null) + this.close(); + super.finalize(); + + } // end finalize + + /*-------------------------------------------------------------------------------- + * Implementations from interface Connection + *-------------------------------------------------------------------------------- + */ + + /** + * Creates a Statement object for sending + * SQL statements to the database. + * + * @return a new Statement object + * @exception SQLException if a database access error occurs + */ + public Statement createStatement() throws SQLException + { + return m_conn.createStatement(); + + } // end createStatement + + /** + * Creates a PreparedStatement object for sending + * parameterized SQL statements to the database. + * + * @param sql a SQL statement that may contain one or more '?' IN parameter placeholders + * @return a new PreparedStatement object containing the pre-compiled statement + * @exception SQLException if a database access error occurs + */ + public PreparedStatement prepareStatement(String sql) throws SQLException + { + return m_conn.prepareStatement(sql); + + } // end prepareStatement + + /** + * Creates a CallableStatement object for calling + * database stored procedures. + * + * @param sql a SQL statement that may contain one or more '?' parameter placeholders. + * Typically this statement is a JDBC function call escape string. + * @return a new CallableStatement object containing the pre-compiled SQL statement + * @exception SQLException if a database access error occurs + */ + public CallableStatement prepareCall(String sql) throws SQLException + { + return m_conn.prepareCall(sql); + + } // end prepareCall + + /** + * Converts the given SQL statement into the system's native SQL grammar. + * + * @param sql a SQL statement that may contain one or more '?' parameter placeholders + * @return the native form of this statement + * @exception SQLException if a database access error occurs + */ + public String nativeSQL(String sql) throws SQLException + { + return m_conn.nativeSQL(sql); + + } // end nativeSQL + + /** + * Sets this connection's auto-commit mode. + * + * @param autoCommit true enables auto-commit; false disables auto-commit. + * @exception SQLException if a database access error occurs + */ + public void setAutoCommit(boolean autoCommit) throws SQLException + { + m_conn.setAutoCommit(autoCommit); + + } // end setAutoCommit + + /** + * Gets the current auto-commit state. + * + * @return the current state of auto-commit mode + * @exception SQLException if a database access error occurs + * @see #setAutoCommit + */ + public boolean getAutoCommit() throws SQLException + { + return m_conn.getAutoCommit(); + + } // end getAutoCommit + + /** + * Makes all changes made since the previous + * commit/rollback permanent and releases any database locks + * currently held by the Connection. This method should be + * used only when auto-commit mode has been disabled. + * + * @exception SQLException if a database access error occurs + * @see #setAutoCommit + */ + public void commit() throws SQLException + { + m_conn.commit(); + + } // end commit + + /** + * Drops all changes made since the previous + * commit/rollback and releases any database locks currently held + * by this Connection. This method should be used only when auto- + * commit has been disabled. + * + * @exception SQLException if a database access error occurs + * @see #setAutoCommit + */ + public void rollback() throws SQLException + { + m_conn.rollback(); + + } // end rollback + + /** + * Releases a Connection's database and JDBC resources + * immediately instead of waiting for them to be automatically released. + * + * @exception SQLException if a database access error occurs + */ + public synchronized void close() throws SQLException + { + try + { // blow away the connection + if (!(m_conn.getAutoCommit())) + m_conn.rollback(); + m_datapool.releaseConnection(m_conn); + m_conn = null; + + } // end try + catch (DatabaseException e) + { // database exception becomes SQLException + SQLException sqle = new SQLException(e.getMessage()); + sqle.initCause(e); + throw sqle; + + } // end catch + + } // end close + + /** + * Tests to see if a Connection is closed. + * + * @return true if the connection is closed; false if it's still open + * @exception SQLException if a database access error occurs + */ + public boolean isClosed() throws SQLException + { + return (m_conn==null) ? true : m_conn.isClosed(); + + } // end isClosed + + /** + * Gets the metadata regarding this connection's database. + * + * @return a DatabaseMetaData object for this Connection + * @exception SQLException if a database access error occurs + */ + public DatabaseMetaData getMetaData() throws SQLException + { + return m_conn.getMetaData(); + + } // end getMetaData + + /** + * Puts this connection in read-only mode as a hint to enable + * database optimizations. + * + * @param readOnly true enables read-only mode; false disables read-only mode. + * @exception SQLException if a database access error occurs + */ + public void setReadOnly(boolean readOnly) + { // do nothing + } // end setReadOnly + + /** + * Tests to see if the connection is in read-only mode. + * + * @return true if connection is read-only and false otherwise + * @exception SQLException if a database access error occurs + */ + public boolean isReadOnly() + { + return false; + + } // end isReadOnly + + /** + * Sets a catalog name in order to select + * a subspace of this Connection's database in which to work. + * If the driver does not support catalogs, it will + * silently ignore this request. + * + * @exception SQLException if a database access error occurs + */ + public void setCatalog(String catalog) + { // do nothing + } // end setCatalog + + /** + * Returns the Connection's current catalog name. + * + * @return the current catalog name or null + * @exception SQLException if a database access error occurs + */ + public String getCatalog() throws SQLException + { + return m_conn.getCatalog(); + + } // end getCatalog + + /** + * Attempts to change the transaction + * isolation level to the one given. + * The constants defined in the interface Connection + * are the possible transaction isolation levels. + * + * @param level one of the TRANSACTION_* isolation values with the exception of TRANSACTION_NONE; + * some databases may not support other values + * @exception SQLException if a database access error occurs + * @see DatabaseMetaData#supportsTransactionIsolationLevel + */ + public void setTransactionIsolation(int level) + { // do nothing + } // end setTransactionIsolation + + /** + * Gets this Connection's current transaction isolation level. + * + * @return the current TRANSACTION_* mode value + * @exception SQLException if a database access error occurs + */ + public int getTransactionIsolation() throws SQLException + { + return m_conn.getTransactionIsolation(); + + } // end getTransactionIsolation + + /** + * Returns the first warning reported by calls on this Connection. + * + * @return the first SQLWarning or null + * @exception SQLException if a database access error occurs + */ + public SQLWarning getWarnings() throws SQLException + { + return m_conn.getWarnings(); + + } // end getWarnings + + /** + * Clears all warnings reported for this Connection object. + * After a call to this method, the method getWarnings + * returns null until a new warning is reported for this Connection. + * + * @exception SQLException if a database access error occurs + */ + public void clearWarnings() throws SQLException + { + m_conn.clearWarnings(); + + } // end clearWarnings + + /** + * Creates a Statement object that will generate + * ResultSet objects with the given type and concurrency. + * + * @param resultSetType a result set type; see ResultSet.TYPE_XXX + * @param resultSetConcurrency a concurrency type; see ResultSet.CONCUR_XXX + * @return a new Statement object + * @exception SQLException if a database access error occurs + * @since 1.2 + * @see What Is in the JDBC 2.0 API + */ + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException + { + return m_conn.createStatement(resultSetType,resultSetConcurrency); + + } // end createStatement + + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException + { + return m_conn.createStatement(resultSetType,resultSetConcurrency,resultSetHoldability); + + } // end createStatement + + /** + * Creates a PreparedStatement object that will generate + * ResultSet objects with the given type and concurrency. + * This method is the same as the prepareStatement method + * above, but it allows the default result set + * type and result set concurrency type to be overridden. + * + * @param resultSetType a result set type; see ResultSet.TYPE_XXX + * @param resultSetConcurrency a concurrency type; see ResultSet.CONCUR_XXX + * @return a new PreparedStatement object containing the pre-compiled SQL statement + * @exception SQLException if a database access error occurs + * @since 1.2 + * @see What Is in the JDBC 2.0 API + */ + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException + { + return m_conn.prepareStatement(sql,resultSetType,resultSetConcurrency); + + } // end prepareStatement + + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException + { + return m_conn.prepareStatement(sql,resultSetType,resultSetConcurrency,resultSetHoldability); + + } // end prepareStatement + + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException + { + return m_conn.prepareStatement(sql,autoGeneratedKeys); + + } // end prepareStatement + + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException + { + return m_conn.prepareStatement(sql,columnIndexes); + + } // end prepareStatement + + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException + { + return m_conn.prepareStatement(sql,columnNames); + + } // end prepareStatement + + /** + * Creates a CallableStatement object that will generate + * ResultSet objects with the given type and concurrency. + * This method is the same as the prepareCall method + * above, but it allows the default result set + * type and result set concurrency type to be overridden. + * + * @param resultSetType a result set type; see ResultSet.TYPE_XXX + * @param resultSetConcurrency a concurrency type; see ResultSet.CONCUR_XXX + * @return a new CallableStatement object containing the pre-compiled SQL statement + * @exception SQLException if a database access error occurs + * @since 1.2 + * @see What Is in the JDBC 2.0 API + */ + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException + { + return m_conn.prepareCall(sql,resultSetType,resultSetConcurrency); + + } // end prepareCall + + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException + { + return m_conn.prepareCall(sql,resultSetType,resultSetConcurrency,resultSetHoldability); + + } // end prepareCall + + /** + * Gets the type map object associated with this connection. + * Unless the application has added an entry to the type map, + * the map returned will be empty. + * + * @return the java.util.Map object associated with this Connection object + * @since 1.2 + * @see What Is in the JDBC 2.0 API + */ + public java.util.Map getTypeMap() throws SQLException + { + return m_conn.getTypeMap(); + + } // end getTypeMap + + /** + * Installs the given type map as the type map for + * this connection. The type map will be used for the + * custom mapping of SQL structured types and distinct types. + * + * @param the java.util.Map object to install + * as the replacement for this Connection + * object's default type map + * @since 1.2 + * @see What Is in the JDBC 2.0 API + */ + public void setTypeMap(java.util.Map map) throws SQLException + { + m_conn.setTypeMap(map); + + } // end setTypeMap + + public int getHoldability() throws SQLException + { + return m_conn.getHoldability(); + + } // end getHoldability + + public void setHoldability(int holdability) throws SQLException + { // do nothing + } // end setHoldability + + public Savepoint setSavepoint() throws SQLException + { + return m_conn.setSavepoint(); + + } // end setSavepont + + public Savepoint setSavepoint(String name) throws SQLException + { + return m_conn.setSavepoint(name); + + } // end setSavepoint + + public void rollback(Savepoint savepoint) throws SQLException + { + m_conn.rollback(savepoint); + + } // end rollback + + public void releaseSavepoint(Savepoint savepoint) throws SQLException + { + m_conn.releaseSavepoint(savepoint); + + } // end releaseSavepoint + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + Connection getRealConnection() + { + return m_conn; + + } // end getRealConnection + +} // end class WrappedConnection diff --git a/src/dynamo-framework/com/silverwrist/dynamo/dialog/BaseDialogField.java b/src/dynamo-framework/com/silverwrist/dynamo/dialog/BaseDialogField.java new file mode 100644 index 0000000..270b0bc --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/dialog/BaseDialogField.java @@ -0,0 +1,229 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.dialog; + +import java.io.*; +import java.util.*; +import org.w3c.dom.*; +import com.silverwrist.util.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; + +public abstract class BaseDialogField implements DialogField +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private boolean m_reverse; // if true, field is on left, false = right + private String m_name; // field name (parameter name) + private String m_caption; // primary caption + private String m_caption2; // secondary caption + private boolean m_required; // is this field required? + private boolean m_default_enabled; // are we enabled by default? + private boolean m_enabled; // are we currently enabled? + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + protected BaseDialogField(boolean reverse, Element element) throws DialogException + { + m_reverse = reverse; + XMLLoader loader = XMLLoader.get(); + try + { // get the base class stuff + m_name = loader.getAttribute(element,"name"); + m_caption = loader.getAttribute(element,"caption"); + m_caption2 = element.getAttribute("caption2"); + m_required = loader.getAttributeBoolean(element,"required",false); + m_default_enabled = loader.getAttributeBoolean(element,"enabled",true); + + } // end try + catch (XMLLoadException e) + { // translate the exception and return it + throw new DialogException(e); + + } // end catch + + m_enabled = m_default_enabled; + + } // end constructor + + protected BaseDialogField(BaseDialogField other) + { + m_reverse = other.m_reverse; + m_name = other.m_name; + m_caption = other.m_caption; + m_caption2 = other.m_caption2; + m_required = other.m_required; + m_default_enabled = other.m_default_enabled; + m_enabled = m_default_enabled; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private final void renderCaption(TextRenderControl control, Map render_params) + throws IOException, RenderingException + { + PrintWriter wr = control.getWriter(); + if (!m_enabled) + wr.write(""); + wr.write(StringUtils.encodeHTML(StringUtils.replaceAllVariables(m_caption,render_params))); + if (StringUtils.isNotEmpty(m_caption2)) + wr.write(" " + StringUtils.encodeHTML(StringUtils.replaceAllVariables(m_caption2,render_params))); + if (!m_reverse) + wr.write(":"); + if (!m_enabled) + wr.write(""); + if (m_required) + wr.write("*"); + + } // end renderCaption + + protected final String getCaption() + { + return m_caption; + + } // end getCaption + + protected final void setCaption2(String s) + { + m_caption2 = s; + + } // end setCaption2 + + protected boolean isNull(Object value) + { + return (value==null); + + } // end isNull + + /*-------------------------------------------------------------------------------- + * Abstract operations + *-------------------------------------------------------------------------------- + */ + + protected abstract void renderField(TextRenderControl control, Map render_params) + throws IOException, RenderingException; + + protected abstract void validateContents(Request r, Object data) throws ValidationException; + + /*-------------------------------------------------------------------------------- + * Implementations from interface NamedObject + *-------------------------------------------------------------------------------- + */ + + public String getName() + { + return m_name; + + } // end getName + + /*-------------------------------------------------------------------------------- + * Abstract methods from interface DialogItem + *-------------------------------------------------------------------------------- + */ + + public abstract Object clone(); + + /*-------------------------------------------------------------------------------- + * Implementations from interface DialogItem + *-------------------------------------------------------------------------------- + */ + + public void render(TextRenderControl control, Map render_params) throws IOException, RenderingException + { + PrintWriter wr = control.getWriter(); + wr.write("\n"); + if (m_reverse) + renderField(control,render_params); + else + renderCaption(control,render_params); + wr.write("\n"); + if (m_reverse) + renderCaption(control,render_params); + else + renderField(control,render_params); + wr.write("\n\n"); + + } // end render + + public boolean isEnabled() + { + return m_enabled; + + } // end isEnabled + + public void setEnabled(boolean flag) + { + m_enabled = flag; + + } // end setEnabled + + /*-------------------------------------------------------------------------------- + * Abstract methods from interface DialogField + *-------------------------------------------------------------------------------- + */ + + public abstract Object getValue(); + + public abstract boolean containsValue(); + + public abstract void setValue(Object obj); + + public abstract void setValueFrom(Request r); + + public abstract void reset(); + + /*-------------------------------------------------------------------------------- + * Implementations from interface DialogField + *-------------------------------------------------------------------------------- + */ + + public void validate(Request r) throws ValidationException + { + Object val = getValue(); + if (m_required && m_enabled && isNull(val)) + { // null field value - we need to bail out + ValidationException ve = new ValidationException(BaseDialogField.class,"DialogMessages", + "required.field"); + ve.setParameter(0,m_caption); + throw ve; + + } // end if + + if (m_enabled) + validateContents(r,val); + + } // end validate + + public int getFlags() + { + return (m_required ? FLAG_REQUIRED : 0); + + } // end getFlags + +} // end class BaseDialogField diff --git a/src/dynamo-framework/com/silverwrist/dynamo/dialog/ButtonCaptions.properties b/src/dynamo-framework/com/silverwrist/dynamo/dialog/ButtonCaptions.properties new file mode 100644 index 0000000..bcbb1c0 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/dialog/ButtonCaptions.properties @@ -0,0 +1,21 @@ +# The contents of this file are subject to the Mozilla Public License Version 1.1 +# (the "License"); you may not use this file except in compliance with the License. +# You may obtain a copy of the License at . +# +# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT +# WARRANTY OF ANY KIND, either express or implied. See the License for the specific +# language governing rights and limitations under the License. +# +# The Original Code is the Venice Web Communities System. +# +# The Initial Developer of the Original Code is Eric J. Bowersox , +# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are +# Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +# +# Contributor(s): +# --------------------------------------------------------------------------------- +# This file has been localized for the en_US locale +cancel=Cancel +login=Log In +ok=OK +reminder=Reminder diff --git a/src/dynamo-framework/com/silverwrist/dynamo/dialog/CheckBoxField.java b/src/dynamo-framework/com/silverwrist/dynamo/dialog/CheckBoxField.java new file mode 100644 index 0000000..776871e --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/dialog/CheckBoxField.java @@ -0,0 +1,187 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.dialog; + +import java.io.*; +import java.util.*; +import org.w3c.dom.*; +import com.silverwrist.util.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +class CheckBoxField extends BaseDialogField +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final String YES = "Y"; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String m_value; + private boolean m_default_checked; + private boolean m_checked; + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + CheckBoxField(Element elt) throws DialogException + { + super(true,elt); + XMLLoader loader = XMLLoader.get(); + try + { // get the checkbox value + m_value = loader.getAttribute(elt,"value",YES); + m_default_checked = loader.getAttributeBoolean(elt,"checked",false); + + } // end try + catch (XMLLoadException e) + { // translate into DialogException + throw new DialogException(e); + + } // end catch + + m_checked = m_default_checked; + + } // end constructor + + protected CheckBoxField(CheckBoxField other) + { + super(other); + m_value = other.m_value; + m_default_checked = other.m_default_checked; + m_checked = m_default_checked; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class BaseDialogField + *-------------------------------------------------------------------------------- + */ + + protected boolean isNull(Object value) + { + return false; + + } // end isNull + + public int getFlags() + { + return 0; + + } // end getFlags + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class BaseDialogField + *-------------------------------------------------------------------------------- + */ + + protected void renderField(TextRenderControl control, Map render_params) + throws IOException, RenderingException + { + PrintWriter wr = control.getWriter(); + wr.write(""); + + } // end renderField + + protected void validateContents(Request r, Object data) throws ValidationException + { // do nothing + } // end validateContents + + public Object clone() + { + return new CheckBoxField(this); + + } // end clone + + public Object getValue() + { + return Boolean.valueOf(m_checked); + + } // end getValue + + public boolean containsValue() + { + return true; + + } // end containsValue + + public void setValue(Object obj) + { + if (obj==null) + m_checked = m_default_checked; + else if (obj instanceof Boolean) + m_checked = ((Boolean)obj).booleanValue(); + else if (obj instanceof Number) + m_checked = (((Number)obj).intValue()!=0); + else + { // look at the string equivalent + String s = obj.toString(); + if (StringUtils.isBooleanTrue(s)) + m_checked = true; + else if (StringUtils.isBooleanFalse(s)) + m_checked = false; + + } // end else + + } // end setValue + + public void setValueFrom(Request r) + { + RequestHelper rh = new RequestHelper(r); + String[] vals = rh.getStringParameterValues(getName()); + if (vals!=null) + { // if no values are set, we're definitely NOT checked + for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.dialog; + +import java.io.*; +import java.util.*; +import org.w3c.dom.*; +import com.silverwrist.util.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.util.*; + +abstract class CommonTextField extends BaseDialogField +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final int MINSIZE = 2; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String m_tagname; + private String m_value = null; + private int m_size; + private int m_maxlength; + private int m_real_maxlength; + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + protected CommonTextField(String tagname, Element elt) throws DialogException + { + super(false,elt); + m_tagname = tagname; + XMLLoader loader = XMLLoader.get(); + try + { // load the "size" attributes for the text field + int my_size = loader.getAttributeInt(elt,"size"); + DOMElementHelper h = new DOMElementHelper(elt); + if (h.hasAttribute("maxlength")) + { // get the maxlength and figure it in... + m_real_maxlength = loader.getAttributeInt(elt,"maxlength"); + m_maxlength = Math.max(m_real_maxlength,MINSIZE); + m_size = Math.max(my_size,MINSIZE); + + } // end if + else + { // "size" is all we got - maxlength is equal to it + m_real_maxlength = my_size; + m_maxlength = m_size = Math.max(my_size,MINSIZE); + + } // end else + + } // end try + catch (XMLLoadException e) + { // translate exception here + throw new DialogException(e); + + } // end catch + + } // end constructor + + protected CommonTextField(String tagname, int width, Element elt) throws DialogException + { + super(false,elt); + m_tagname = tagname; + m_real_maxlength = width; + m_maxlength = m_size = Math.max(width,MINSIZE); + + } // end constructor + + protected CommonTextField(CommonTextField other) + { + super(other); + m_tagname = other.m_tagname; + m_size = other.m_size; + m_maxlength = other.m_maxlength; + m_real_maxlength = other.m_real_maxlength; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class BaseDialogField + *-------------------------------------------------------------------------------- + */ + + protected boolean isNull(Object value) + { + return StringUtils.isEmpty((String)value); + + } // end isNull + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class BaseDialogField + *-------------------------------------------------------------------------------- + */ + + protected void renderField(TextRenderControl control, Map render_params) + throws IOException, RenderingException + { + PrintWriter wr = control.getWriter(); + wr.write(""); + + } // end renderField + + protected void validateContents(Request r, Object data) throws ValidationException + { + if ((data!=null) && (data.toString().length()>m_real_maxlength)) + { // this value is too long + ValidationException ve = new ValidationException(CommonTextField.class,"DialogMessages","text.tooLong"); + ve.setParameter(0,getCaption()); + ve.setParameter(1,String.valueOf(m_real_maxlength)); + throw ve; + + } // end if + + } // end validateContents + + public Object getValue() + { + return m_value; + + } // end getValue + + public boolean containsValue() + { + return StringUtils.isNotEmpty(m_value); + + } // end containsValue + + public void setValue(Object obj) + { + if (obj==null) + m_value = null; + else + m_value = obj.toString(); + if ((m_value!=null) && StringUtils.isEmpty(m_value)) + m_value = null; + + } // end setValue + + public void setValueFrom(Request r) + { + RequestHelper rh = new RequestHelper(r); + m_value = rh.getParameterString(getName()); + if ((m_value!=null) && StringUtils.isEmpty(m_value)) + m_value = null; + + } // end setValueFrom + + public void reset() + { + m_value = null; + + } // end reset + +} // end class CommonTextField diff --git a/src/dynamo-framework/com/silverwrist/dynamo/dialog/CountryListField.java b/src/dynamo-framework/com/silverwrist/dynamo/dialog/CountryListField.java new file mode 100644 index 0000000..a892fd3 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/dialog/CountryListField.java @@ -0,0 +1,123 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.dialog; + +import java.util.*; +import org.w3c.dom.Element; +import com.silverwrist.util.*; +import com.silverwrist.dynamo.except.DialogException; + +class CountryListField extends PickListField +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Country UNKNOWN_COUNTRY = International.get().getCountryForCode("XX"); + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + CountryListField(Element elt) throws DialogException + { + super(elt); + + } // end constructor + + protected CountryListField(CountryListField other) + { + super(other); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class BaseDialogField + *-------------------------------------------------------------------------------- + */ + + public Object clone() + { + return new CountryListField(this); + + } // end clone + + /*-------------------------------------------------------------------------------- + * Overrides from class BaseDialogField + *-------------------------------------------------------------------------------- + */ + + protected boolean isNull(Object value) + { + return ((value==null) || UNKNOWN_COUNTRY.equals(value)); + + } // end isNull + + /*-------------------------------------------------------------------------------- + * Abstract implementations from class PickListField + *-------------------------------------------------------------------------------- + */ + + protected Iterator getChoices() + { + return International.get().getCountryList().iterator(); + + } // end getChoices + + protected String getChoiceName(Object choice) + { + return ((Country)choice).getCode(); + + } // end getChoiceName + + protected String getChoiceDisplay(Object choice) + { + return ((Country)choice).getName(); + + } // end getChoiceDisplay + + protected Object getChoiceForName(String name) + { + return International.get().getCountryForCode(name); + + } // end getChoiceForName + + protected boolean isValidChoice(Object choice) + { + if (!(choice instanceof Country)) + return false; + Country x = International.get().getCountryForCode(((Country)choice).getCode()); + return x.equals(choice); + + } // end isValidChoice + + /*-------------------------------------------------------------------------------- + * Overrides from class PickListField + *-------------------------------------------------------------------------------- + */ + + public boolean containsValue() + { + Object v = getValue(); + return ((v!=null) && !UNKNOWN_COUNTRY.equals(v)); + + } // end containsValue + +} // end class CountryListField diff --git a/src/dynamo-framework/com/silverwrist/dynamo/dialog/DefaultDialogLAF.java b/src/dynamo-framework/com/silverwrist/dynamo/dialog/DefaultDialogLAF.java new file mode 100644 index 0000000..b32947a --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/dialog/DefaultDialogLAF.java @@ -0,0 +1,85 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.dialog; + +import java.util.*; +import com.silverwrist.dynamo.iface.*; + +class DefaultDialogLAF implements DialogPLAF +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private ResourceBundle m_captions; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + DefaultDialogLAF() + { + m_captions = ResourceBundle.getBundle("com.silverwrist.dynamo.dialog.ButtonCaptions",Locale.getDefault()); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface DialogPLAF + *-------------------------------------------------------------------------------- + */ + + public Object getButtonRendering(String button_name) + { + String caption; + try + { // get the default caption + caption = m_captions.getString(button_name); + + } // end try + catch (MissingResourceException e) + { // default to just using the button name + caption = button_name; + + } // end catch + + StringBuffer buf = new StringBuffer(""); + return buf.toString(); + + } // end getButtonRendering + + public boolean isButtonClicked(Request r, String button_name) + { + return r.getParameters().containsKey(button_name); + + } // end isButtonClicked + + public Object getContentHeader(String title, String subtitle) + { + StringBuffer buf = new StringBuffer(""); + buf.append(title).append("\n"); + if (subtitle!=null) + buf.append("  ").append(subtitle).append("\n"); + buf.append("


\n"); + return buf.toString(); + + } // end getContentHeader + +} // end class DefaultDialogLAF diff --git a/src/dynamo-framework/com/silverwrist/dynamo/dialog/DialogImpl.java b/src/dynamo-framework/com/silverwrist/dynamo/dialog/DialogImpl.java new file mode 100644 index 0000000..0a70ec2 --- /dev/null +++ b/src/dynamo-framework/com/silverwrist/dynamo/dialog/DialogImpl.java @@ -0,0 +1,643 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.dynamo.dialog; + +import java.io.*; +import java.util.*; +import org.w3c.dom.*; +import com.silverwrist.util.*; +import com.silverwrist.util.xml.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.except.*; + +class DialogImpl implements Dialog +{ + /*-------------------------------------------------------------------------------- + * Internal class to "peel off" certain dialog items that are tags + *-------------------------------------------------------------------------------- + */ + + private class InternalFilter implements DialogItemFactory + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private DialogItemFactory m_inner; + private HashMap m_rp = new HashMap(); + + /*==================================================================== + * Constructor + *==================================================================== + */ + + InternalFilter(DialogItemFactory inner) + { + m_inner = inner; + + } // end constructor + + /*==================================================================== + * Implementations from interface DialogItemFactory + *==================================================================== + */ + + public DialogItem createDialogItem(Element elt, DialogPLAF plaf) throws DialogException + { + try + { // strip out certain items we need from the element stream + XMLLoader loader = XMLLoader.get(); + String tagname = elt.getTagName(); + if (tagname.equals("title")) + { // get title + m_default_title = loader.getText(elt); + if (m_default_title!=null) + m_default_title = m_default_title.trim(); + + } // end if + else if (tagname.equals("subtitle")) + { // get subtitle (not required) + DOMElementHelper h = new DOMElementHelper(elt); + m_default_subtitle = h.getElementText(); + if (m_default_subtitle!=null) + m_default_subtitle = m_default_subtitle.trim(); + + } // end else if + else if (tagname.equals("action")) + { // get action and action type + m_action = loader.getText(elt); + if (m_action!=null) + m_action = m_action.trim(); + m_action_type = loader.getAttribute(elt,"type","SERVLET"); + + } // end else if + else if (tagname.equals("render-param")) + { // get a rendering parameter + String name = loader.getAttribute(elt,"name"); + DOMElementHelper h = new DOMElementHelper(elt); + String value = h.getElementText(); + if (value!=null) + value = value.trim(); + else + value = ""; + m_rp.put(name,value); + + } // end else if + else if (tagname.equals("instructions")) + { // get instructions (not required) + DOMElementHelper h = new DOMElementHelper(elt); + m_default_instructions = h.getElementText(); + if (m_default_instructions!=null) + m_default_instructions = m_default_instructions.trim(); + + } // end else if + else // go create a dialog item + return m_inner.createDialogItem(elt,plaf); + + } // end try + catch (XMLLoadException e) + { // translate XML Load exception to dialog exception + throw new DialogException(e); + + } // end catch + + return null; + + } // end createDialogItem + + /*==================================================================== + * External operations + *==================================================================== + */ + + Map renderParams() + { + if (m_rp.isEmpty()) + return Collections.EMPTY_MAP; + else + return Collections.unmodifiableMap(m_rp); + + } // end renderParams + + } // end class InternalFilter + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private DialogPLAF m_plaf; + private String m_name; + private String m_default_button = null; + private String m_default_title = null; + private String m_default_subtitle = null; + private String m_action = null; + private String m_action_type = null; + private String m_default_instructions = null; + private boolean m_any_required; + private boolean m_need_multipart; + private List m_field_order; + private Map m_field_map; + private List m_button_order; + private Map m_button_map; + private List m_hidden_order; + private Map m_hidden_map; + private String m_title = null; + private String m_subtitle = null; + private String m_instructions = null; + private String m_error_message = null; + private Map m_default_render_params; + private HashMap m_render_params; + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + DialogImpl(Element dialog_element, DialogItemFactory item_factory, DialogPLAF plaf) throws DialogException + { + // Copy the look-and-feel object reference. + m_plaf = plaf; + + // Get the basic stuff from the root tag itself. + XMLLoader loader = XMLLoader.get(); + try + { // get the dialog name + m_name = loader.getAttribute(dialog_element,"name"); + m_default_button = dialog_element.getAttribute("defaultbutton"); + + } // end try + catch (XMLLoadException e) + { // translate to DialogException + throw new DialogException(e); + + } // end catch + + // Load the fields. + ArrayList field_order = new ArrayList(); + HashMap field_map = new HashMap(); + ArrayList button_order = new ArrayList(); + HashMap button_map = new HashMap(); + ArrayList hidden_order = new ArrayList(); + HashMap hidden_map = new HashMap(); + int global_flags = 0; + InternalFilter factory = new InternalFilter(item_factory); + NodeList nl = dialog_element.getChildNodes(); + for (int i=0; i