diff --git a/.gitignore b/.gitignore index 9c9c8ab..421a8fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -build -/nbproject/private/ -/JavaApplication1/nbproject/private/ +target/ +.idea/ +xquery-versioning-module.iml diff --git a/GPL1-template.txt b/GPL1-template.txt new file mode 100644 index 0000000..b946a8e --- /dev/null +++ b/GPL1-template.txt @@ -0,0 +1,17 @@ +${project.description} +Copyright (C) ${project.inceptionYear} ${organisation} <${email}> +${url} + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 1, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0f48181 --- /dev/null +++ b/LICENSE @@ -0,0 +1,190 @@ + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/License.md b/License.md deleted file mode 100644 index 0671f06..0000000 --- a/License.md +++ /dev/null @@ -1,264 +0,0 @@ -The GNU General Public License, Version 2, June 1991 (GPLv2) -============================================================ - -> Copyright (C) 1989, 1991 Free Software Foundation, Inc. -> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - -Everyone is permitted to copy and distribute verbatim copies of this license -document, but changing it is not allowed. - - -Preamble --------- - -The licenses for most software are designed to take away your freedom to share -and change it. By contrast, the GNU General Public License is intended to -guarantee your freedom to share and change free software--to make sure the -software is free for all its users. This General Public License applies to most -of the Free Software Foundation's software and to any other program whose -authors commit to using it. (Some other Free Software Foundation software is -covered by the GNU Library General Public License instead.) You can apply it to -your programs, too. - -When we speak of free software, we are referring to freedom, not price. Our -General Public Licenses are designed to make sure that you have the freedom to -distribute copies of free software (and charge for this service if you wish), -that you receive source code or can get it if you want it, that you can change -the software or use pieces of it in new free programs; and that you know you can -do these things. - -To protect your rights, we need to make restrictions that forbid anyone to deny -you these rights or to ask you to surrender the rights. These restrictions -translate to certain responsibilities for you if you distribute copies of the -software, or if you modify it. - -For example, if you distribute copies of such a program, whether gratis or for a -fee, you must give the recipients all the rights that you have. You must make -sure that they, too, receive or can get the source code. And you must show them -these terms so they know their rights. - -We protect your rights with two steps: (1) copyright the software, and (2) offer -you this license which gives you legal permission to copy, distribute and/or -modify the software. - -Also, for each author's protection and ours, we want to make certain that -everyone understands that there is no warranty for this free software. If the -software is modified by someone else and passed on, we want its recipients to -know that what they have is not the original, so that any problems introduced by -others will not reflect on the original authors' reputations. - -Finally, any free program is threatened constantly by software patents. We wish -to avoid the danger that redistributors of a free program will individually -obtain patent licenses, in effect making the program proprietary. To prevent -this, we have made it clear that any patent must be licensed for everyone's free -use or not licensed at all. - -The precise terms and conditions for copying, distribution and modification -follow. - - -Terms And Conditions For Copying, Distribution And Modification ---------------------------------------------------------------- - -**0.** This License applies to any program or other work which contains a notice -placed by the copyright holder saying it may be distributed under the terms of -this General Public License. The "Program", below, refers to any such program or -work, and a "work based on the Program" means either the Program or any -derivative work under copyright law: that is to say, a work containing the -Program or a portion of it, either verbatim or with modifications and/or -translated into another language. (Hereinafter, translation is included without -limitation in the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not covered by -this License; they are outside its scope. The act of running the Program is not -restricted, and the output from the Program is covered only if its contents -constitute a work based on the Program (independent of having been made by -running the Program). Whether that is true depends on what the Program does. - -**1.** You may copy and distribute verbatim copies of the Program's source code -as you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice and -disclaimer of warranty; keep intact all the notices that refer to this License -and to the absence of any warranty; and give any other recipients of the Program -a copy of this License along with the Program. - -You may charge a fee for the physical act of transferring a copy, and you may at -your option offer warranty protection in exchange for a fee. - -**2.** You may modify your copy or copies of the Program or any portion of it, -thus forming a work based on the Program, and copy and distribute such -modifications or work under the terms of Section 1 above, provided that you also -meet all of these conditions: - -* **a)** You must cause the modified files to carry prominent notices stating - that you changed the files and the date of any change. - -* **b)** You must cause any work that you distribute or publish, that in whole - or in part contains or is derived from the Program or any part thereof, to - be licensed as a whole at no charge to all third parties under the terms of - this License. - -* **c)** If the modified program normally reads commands interactively when - run, you must cause it, when started running for such interactive use in the - most ordinary way, to print or display an announcement including an - appropriate copyright notice and a notice that there is no warranty (or - else, saying that you provide a warranty) and that users may redistribute - the program under these conditions, and telling the user how to view a copy - of this License. (Exception: if the Program itself is interactive but does - not normally print such an announcement, your work based on the Program is - not required to print an announcement.) - -These requirements apply to the modified work as a whole. If identifiable -sections of that work are not derived from the Program, and can be reasonably -considered independent and separate works in themselves, then this License, and -its terms, do not apply to those sections when you distribute them as separate -works. But when you distribute the same sections as part of a whole which is a -work based on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the entire whole, -and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest your -rights to work written entirely by you; rather, the intent is to exercise the -right to control the distribution of derivative or collective works based on the -Program. - -In addition, mere aggregation of another work not based on the Program with the -Program (or with a work based on the Program) on a volume of a storage or -distribution medium does not bring the other work under the scope of this -License. - -**3.** You may copy and distribute the Program (or a work based on it, under -Section 2) in object code or executable form under the terms of Sections 1 and 2 -above provided that you also do one of the following: - -* **a)** Accompany it with the complete corresponding machine-readable source - code, which must be distributed under the terms of Sections 1 and 2 above on - a medium customarily used for software interchange; or, - -* **b)** Accompany it with a written offer, valid for at least three years, to - give any third party, for a charge no more than your cost of physically - performing source distribution, a complete machine-readable copy of the - corresponding source code, to be distributed under the terms of Sections 1 - and 2 above on a medium customarily used for software interchange; or, - -* **c)** Accompany it with the information you received as to the offer to - distribute corresponding source code. (This alternative is allowed only for - noncommercial distribution and only if you received the program in object - code or executable form with such an offer, in accord with Subsection b - above.) - -The source code for a work means the preferred form of the work for making -modifications to it. For an executable work, complete source code means all the -source code for all modules it contains, plus any associated interface -definition files, plus the scripts used to control compilation and installation -of the executable. However, as a special exception, the source code distributed -need not include anything that is normally distributed (in either source or -binary form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component itself -accompanies the executable. - -If distribution of executable or object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the source code -from the same place counts as distribution of the source code, even though third -parties are not compelled to copy the source along with the object code. - -**4.** You may not copy, modify, sublicense, or distribute the Program except as -expressly provided under this License. Any attempt otherwise to copy, modify, -sublicense or distribute the Program is void, and will automatically terminate -your rights under this License. However, parties who have received copies, or -rights, from you under this License will not have their licenses terminated so -long as such parties remain in full compliance. - -**5.** You are not required to accept this License, since you have not signed -it. However, nothing else grants you permission to modify or distribute the -Program or its derivative works. These actions are prohibited by law if you do -not accept this License. Therefore, by modifying or distributing the Program (or -any work based on the Program), you indicate your acceptance of this License to -do so, and all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - -**6.** Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the original -licensor to copy, distribute or modify the Program subject to these terms and -conditions. You may not impose any further restrictions on the recipients' -exercise of the rights granted herein. You are not responsible for enforcing -compliance by third parties to this License. - -**7.** If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), conditions -are imposed on you (whether by court order, agreement or otherwise) that -contradict the conditions of this License, they do not excuse you from the -conditions of this License. If you cannot distribute so as to satisfy -simultaneously your obligations under this License and any other pertinent -obligations, then as a consequence you may not distribute the Program at all. -For example, if a patent license would not permit royalty-free redistribution of -the Program by all those who receive copies directly or indirectly through you, -then the only way you could satisfy both it and this License would be to refrain -entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply and the -section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any patents or -other property right claims or to contest validity of any such claims; this -section has the sole purpose of protecting the integrity of the free software -distribution system, which is implemented by public license practices. Many -people have made generous contributions to the wide range of software -distributed through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing to -distribute software through any other system and a licensee cannot impose that -choice. - -This section is intended to make thoroughly clear what is believed to be a -consequence of the rest of this License. - -**8.** If the distribution and/or use of the Program is restricted in certain -countries either by patents or by copyrighted interfaces, the original copyright -holder who places the Program under this License may add an explicit -geographical distribution limitation excluding those countries, so that -distribution is permitted only in or among countries not thus excluded. In such -case, this License incorporates the limitation as if written in the body of this -License. - -**9.** The Free Software Foundation may publish revised and/or new versions of -the General Public License from time to time. Such new versions will be similar -in spirit to the present version, but may differ in detail to address new -problems or concerns. - -Each version is given a distinguishing version number. If the Program specifies -a version number of this License which applies to it and "any later version", -you have the option of following the terms and conditions either of that version -or of any later version published by the Free Software Foundation. If the -Program does not specify a version number of this License, you may choose any -version ever published by the Free Software Foundation. - -**10.** If you wish to incorporate parts of the Program into other free programs -whose distribution conditions are different, write to the author to ask for -permission. For software which is copyrighted by the Free Software Foundation, -write to the Free Software Foundation; we sometimes make exceptions for this. -Our decision will be guided by the two goals of preserving the free status of -all derivatives of our free software and of promoting the sharing and reuse of -software generally. - - -No Warranty ------------ - -**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR -THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE -STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM -"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, -BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - -**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR -INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA -BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER -OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. diff --git a/README.md b/README.md index 1600c1d..4c62ff6 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,101 @@ -# eXistdb Versioning extension expath package # +# Versioning Module for eXist-db XQuery # +[![Java 8](https://img.shields.io/badge/java-8-blue.svg)](http://java.oracle.com) [![License](https://img.shields.io/badge/license-GPL%201.0-blue.svg)](https://www.gnu.org/licenses/gpl-1.0.html) -This repository holds the old code from the eXistdb Versioning extension. +This repository holds the for the eXist-db XQuery Versioning extension module. -### ROADMAP ### +### Building a EXPath Package for eXist-db ### -Turn it into an installable and working xar package. +Building requires that you have Java JDK version 8 and Maven 3 installed. -### LICENSE ### +```bash +$ https://www.github.com/exist-db/xquery-versioning-module.git +$ mvn package +``` -GPL \ No newline at end of file +You will then find a file named similar to `target/xquery-versioning-module-1.0.xar`. + +### Example `collection.xconf` Trigger Configuration +```xml + + + + + + + +``` + + +### API Overview + +Namespace URI: `http://exist-db.org/xquery/versioning` + +Namespace Prefix: `versioning` + +Class: `org.exist.versioning.xquery.VersioningModule` + + +1. To find the differences between two nodes: + ```xquery + versioning:diff($a as node(), $b as node()) as node() + ``` + +2. To apply a patch to a node: + ```xquery + versioning:patch($node as node(), $patch as node()) as item() + ``` + +3. To annotate a node: + ```xquery + versioning:annotate($node as node(), $patch as node()) as item() + ``` + + +### Utility API Overview + +Namespace URI: `http://exist-db.org/versioning` + +Namespace Prefix: `v` + +file: `versioning.xqm` + +1. Return all revisions of the specified document as a sequence of xs:integer revision numbers in ascending order: + ```xquery + v:revisions($doc as node()) as xs:integer* + ``` + +2. Return all version docs, including the full diff, for the specified document: + ```xquery + v:versions($doc as node()) as element(v:version)* + ``` + +3. Restore a certain revision of a document by applying a sequence of diffs and return it as an in-memory node: + ```xquery + v:doc($doc as node(), $rev as xs:integer?) as node()* + ``` + +4. Apply a given patch on a document: + ```xquery + v:apply-patch($doc as node(), $diffs as element(v:version)*) + ``` + +5. For the document passed as first argument, retrieve the revision specified in the second argument. Generate a diff between both version, i.e. **HEAD** and the given revision: + ```xquery + v:diff($doc as node(), $rev as xs:integer) as element(v:version)? + ``` + +6. Return an XML document in which all changes between ``$rev` and ``$rev - 1` are annotated. + ```xquery + v:annotate($doc as node(), $rev as xs:integer) + ``` + +7. Check if there are any revisions in the database which are newer than the version identified by the specified base revision and key: + ```xquery + v:find-newer-revision($doc as node(), $base as xs:integer, $key as xs:string) as element(v:version)? + ``` + +8. Returns an XML fragment showing the version history of the document to which the specified node belongs. All revisions are listed with date and user, but without the detailed diff: + ```xquery + v:history($doc as node()) as element(v:history) + ``` diff --git a/build.properties.xml b/build.properties.xml deleted file mode 100644 index d786449..0000000 --- a/build.properties.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - versioning - 1.0.0 - versioning - - diff --git a/build.xml b/build.xml deleted file mode 100644 index 11003ea..0000000 --- a/build.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/extension.xml b/extension.xml deleted file mode 100644 index 6842dcd..0000000 --- a/extension.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/ivy.xml b/ivy.xml deleted file mode 100644 index 955d008..0000000 --- a/ivy.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/ivysettings.xml b/ivysettings.xml deleted file mode 100644 index 32534fd..0000000 --- a/ivysettings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/nbproject/project.xml b/nbproject/project.xml deleted file mode 100644 index 24c3178..0000000 --- a/nbproject/project.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - org.netbeans.modules.ant.freeform - - - versionig-xar - - - - versionig-xar - - - - - . - UTF-8 - - - - java - test - UTF-8 - - - - java - src/main/java - UTF-8 - - - - - xar - - - clean - - - clean - xar - - - - - - - test - - - - src/main/java - - - build.xml - - - - - - - - - - - - - test - - build/lib/Saxon-HE.jar:build/lib/antlr.jar:build/lib/avalon-framework.jar:build/lib/c3p0.jar:build/lib/commons-codec.jar:build/lib/commons-io.jar:build/lib/commons-logging.jar:build/lib/commons-pool.jar:build/lib/excalibur-cli.jar:build/lib/existdb-core.jar:build/lib/gnu-crypto.jar:build/lib/isorelax.jar:build/lib/jing.jar:build/lib/junit.jar:build/lib/log4j-api.jar:build/lib/log4j-core.jar:build/lib/log4j.jar:build/lib/logkit.jar:build/lib/pkg-repo.jar:build/lib/quartz.jar:build/lib/servlet-api.jar:build/lib/slf4j-api.jar:build/lib/ws-commons-util.jar:build/lib/xercesImpl.jar:build/lib/xml-apis.jar:build/lib/xml-resolver.jar:build/lib/xmldb-api.jar:build/lib/xmlrpc-client.jar:build/lib/xmlrpc-common.jar:build/lib/xmlrpc-server.jar - 1.8 - - - src/main/java - 1.8 - - - - diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..36d75d1 --- /dev/null +++ b/pom.xml @@ -0,0 +1,258 @@ + + + + 4.0.0 + + + org.sonatype.oss + oss-parent + 7 + + + + org.exist-db.xquery.extensions + xquery-versioning-module + 1.0 + + Versioning Module + Versioning Module for eXist-db XQuery + https://www.github.com/exist-db/xquery-versioning-module + 2008 + + + eXist-db + http://exist-db.org + + + + + >GNU General Public License, version 1 + https://opensource.org/licenses/GPL-1.0 + repo + + + + + scm:git:https://www.github.com/exist-db/xquery-versioning-module.git + scm:git:https://www.github.com/exist-db/xquery-versioning-module.git + scm:git:https://www.github.com/exist-db/xquery-versioning-module.git + + + + http://exist-db.org/xquery/versioning + 3.0.RC1 + 1.7 + + 1.7 + UTF-8 + + org.exist.versioning.xquery + VersioningModule + ${project.version} + ${java-package-name} + ${project.name} + ${versioning.module.namespace} + ${project.artifactId} + ${project.artifactId}-${project.version} + + + + + org.exist-db + exist-core + ${exist.version} + provided + + + com.bmsi + gnudiff + ${gnudiff.version} + + + + + + + com.mycila + license-maven-plugin + 3.0 + +
${basedir}/GPL1-template.txt
+ true + true + true + + ${project.organization.name} + exit-open@lists.sourceforge.net + ${project.organization.url} + + + xquery-license-style.xml + + + xquery_style + xquery_style + + + pom.xml + README.md + LICENSE + GPL1-template.txt + xquery-license-style.xml + xar-assembly.xml + src/test/resources/** + docs/** + collection.sample.xconf + + +
+
+ + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + compile + + compile + + + + + + com.code54.mojo + buildversion-plugin + 1.0.3 + + + validate + + set-properties + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + + + ${java-package-name}.${java-package-main-class-name} + ${java-package-name} + + + + ${versioning.module.namespace} + + ${build-tag} + ${build-commit} + ${build-commit-abbrev} + ${build-version} + ${build-tstamp} + ${project.scm.connection} + ${project.description} + ${project.url} + + + + + + ro.kuberam.maven.plugins + kuberam-expath-plugin + 0.4.8 + + + create-xar + package + + make-xar + + + xar-assembly.xml + ${package-final-name} + + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + + true + true + + + ${build-tag} + ${build-commit} + ${build-commit-abbrev} + ${build-version} + ${build-tstamp} + ${project.scm.connection} + ${project.description} + ${project.url} + + + + + + attach-sources + verify + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + true + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + forked-path + true + @{project.version} + + + +
+
+ + + + exist + https://raw.github.com/eXist-db/mvn-repo/master/ + + + + + + clojars.org + http://clojars.org/repo + + +
diff --git a/src/main/java/bmsi/util/Diff.java b/src/main/java/bmsi/util/Diff.java deleted file mode 100644 index c3602ab..0000000 --- a/src/main/java/bmsi/util/Diff.java +++ /dev/null @@ -1,890 +0,0 @@ -/* - * $Log: Diff.java,v $ - * Revision 1.6 2003/03/06 22:51:32 stuart - * Convert to CVS - * - * Revision 1.5 2002/07/19 19:14:40 stuart - * fix reverseScript, make change ctor public, update docs - * - * Revision 1.4 2002/04/09 17:53:39 stuart - * More flexible interface for diff() function. - * - * Revision 1.3 2000/03/03 21:58:03 stuart - * move discard_confusing_lines and shift_boundaries to class file_data - * - * Revision 1.2 2000/03/02 16:37:38 stuart - * Add GPL and copyright - * - */ -package bmsi.util; - -import java.util.Hashtable; - -/** A class to compare vectors of objects. The result of comparison - is a list of change objects which form an - edit script. The objects compared are traditionally lines - of text from two files. Comparison options such as "ignore - whitespace" are implemented by modifying the equals - and hashcode methods for the objects compared. -

- The basic algorithm is described in:
- "An O(ND) Difference Algorithm and its Variations", Eugene Myers, - Algorithmica Vol. 1 No. 2, 1986, p 251. -

- This class outputs different results from GNU diff 1.15 on some - inputs. Our results are actually better (smaller change list, smaller - total size of changes), but it would be nice to know why. Perhaps - there is a memory overwrite bug in GNU diff 1.15. - - @author Stuart D. Gathman, translated from GNU diff 1.15 - Copyright (C) 2000 Business Management Systems, Inc. -

- This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) - any later version. -

- This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -

- You should have received a copy of the - GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - */ - -public class Diff { - - /** Prepare to find differences between two arrays. Each element of - the arrays is translated to an "equivalence number" based on - the result of equals. The original Object arrays - are no longer needed for computing the differences. They will - be needed again later to print the results of the comparison as - an edit script, if desired. - */ - public Diff(Object[] a,Object[] b) { - Hashtable h = new Hashtable(a.length + b.length); - filevec[0] = new file_data(a,h); - filevec[1] = new file_data(b,h); - } - - /** 1 more than the maximum equivalence value used for this or its - sibling file. */ - private int equiv_max = 1; - - /** When set to true, the comparison uses a heuristic to speed it up. - With this heuristic, for files with a constant small density - of changes, the algorithm is linear in the file size. */ - public boolean heuristic = false; - - /** When set to true, the algorithm returns a guarranteed minimal - set of changes. This makes things slower, sometimes much slower. */ - public boolean no_discards = false; - - private int[] xvec, yvec; /* Vectors being compared. */ - private int[] fdiag; /* Vector, indexed by diagonal, containing - the X coordinate of the point furthest - along the given diagonal in the forward - search of the edit matrix. */ - private int[] bdiag; /* Vector, indexed by diagonal, containing - the X coordinate of the point furthest - along the given diagonal in the backward - search of the edit matrix. */ - private int fdiagoff, bdiagoff; - private final file_data[] filevec = new file_data[2]; - private int cost; - - /** Find the midpoint of the shortest edit script for a specified - portion of the two files. - - We scan from the beginnings of the files, and simultaneously from the ends, - doing a breadth-first search through the space of edit-sequence. - When the two searches meet, we have found the midpoint of the shortest - edit sequence. - - The value returned is the number of the diagonal on which the midpoint lies. - The diagonal number equals the number of inserted lines minus the number - of deleted lines (counting only lines before the midpoint). - The edit cost is stored into COST; this is the total number of - lines inserted or deleted (counting only lines before the midpoint). - - This function assumes that the first lines of the specified portions - of the two files do not match, and likewise that the last lines do not - match. The caller must trim matching lines from the beginning and end - of the portions it is going to specify. - - Note that if we return the "wrong" diagonal value, or if - the value of bdiag at that diagonal is "wrong", - the worst this can do is cause suboptimal diff output. - It cannot cause incorrect diff output. */ - - private int diag (int xoff, int xlim, int yoff, int ylim) { - final int[] fd = fdiag; // Give the compiler a chance. - final int[] bd = bdiag; // Additional help for the compiler. - final int[] xv = xvec; // Still more help for the compiler. - final int[] yv = yvec; // And more and more . . . - final int dmin = xoff - ylim; // Minimum valid diagonal. - final int dmax = xlim - yoff; // Maximum valid diagonal. - final int fmid = xoff - yoff; // Center diagonal of top-down search. - final int bmid = xlim - ylim; // Center diagonal of bottom-up search. - int fmin = fmid, fmax = fmid; // Limits of top-down search. - int bmin = bmid, bmax = bmid; // Limits of bottom-up search. - /* True if southeast corner is on an odd - diagonal with respect to the northwest. */ - final boolean odd = (fmid - bmid & 1) != 0; - - fd[fdiagoff + fmid] = xoff; - bd[bdiagoff + bmid] = xlim; - - for (int c = 1;; ++c) - { - int d; /* Active diagonal. */ - boolean big_snake = false; - - /* Extend the top-down search by an edit step in each diagonal. */ - if (fmin > dmin) - fd[fdiagoff + --fmin - 1] = -1; - else - ++fmin; - if (fmax < dmax) - fd[fdiagoff + ++fmax + 1] = -1; - else - --fmax; - for (d = fmax; d >= fmin; d -= 2) - { - int x, y, oldx, tlo = fd[fdiagoff + d - 1], thi = fd[fdiagoff + d + 1]; - - if (tlo >= thi) - x = tlo + 1; - else - x = thi; - oldx = x; - y = x - d; - while (x < xlim && y < ylim && xv[x] == yv[y]) { - ++x; ++y; - } - if (x - oldx > 20) - big_snake = true; - fd[fdiagoff + d] = x; - if (odd && bmin <= d && d <= bmax && bd[bdiagoff + d] <= fd[fdiagoff + d]) - { - cost = 2 * c - 1; - return d; - } - } - - /* Similar extend the bottom-up search. */ - if (bmin > dmin) - bd[bdiagoff + --bmin - 1] = Integer.MAX_VALUE; - else - ++bmin; - if (bmax < dmax) - bd[bdiagoff + ++bmax + 1] = Integer.MAX_VALUE; - else - --bmax; - for (d = bmax; d >= bmin; d -= 2) - { - int x, y, oldx, tlo = bd[bdiagoff + d - 1], thi = bd[bdiagoff + d + 1]; - - if (tlo < thi) - x = tlo; - else - x = thi - 1; - oldx = x; - y = x - d; - while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) { - --x; --y; - } - if (oldx - x > 20) - big_snake = true; - bd[bdiagoff + d] = x; - if (!odd && fmin <= d && d <= fmax && bd[bdiagoff + d] <= fd[fdiagoff + d]) - { - cost = 2 * c; - return d; - } - } - - /* Heuristic: check occasionally for a diagonal that has made - lots of progress compared with the edit distance. - If we have any such, find the one that has made the most - progress and return it as if it had succeeded. - - With this heuristic, for files with a constant small density - of changes, the algorithm is linear in the file size. */ - - if (c > 200 && big_snake && heuristic) - { - int best = 0; - int bestpos = -1; - - for (d = fmax; d >= fmin; d -= 2) - { - int dd = d - fmid; - if ((fd[fdiagoff + d] - xoff)*2 - dd > 12 * (c + (dd > 0 ? dd : -dd))) - { - if (fd[fdiagoff + d] * 2 - dd > best - && fd[fdiagoff + d] - xoff > 20 - && fd[fdiagoff + d] - d - yoff > 20) - { - int k; - int x = fd[fdiagoff + d]; - - /* We have a good enough best diagonal; - now insist that it end with a significant snake. */ - for (k = 1; k <= 20; k++) - if (xvec[x - k] != yvec[x - d - k]) - break; - - if (k == 21) - { - best = fd[fdiagoff + d] * 2 - dd; - bestpos = d; - } - } - } - } - if (best > 0) - { - cost = 2 * c - 1; - return bestpos; - } - - best = 0; - for (d = bmax; d >= bmin; d -= 2) - { - int dd = d - bmid; - if ((xlim - bd[bdiagoff + d])*2 + dd > 12 * (c + (dd > 0 ? dd : -dd))) - { - if ((xlim - bd[bdiagoff + d]) * 2 + dd > best - && xlim - bd[bdiagoff + d] > 20 - && ylim - (bd[bdiagoff + d] - d) > 20) - { - /* We have a good enough best diagonal; - now insist that it end with a significant snake. */ - int k; - int x = bd[bdiagoff + d]; - - for (k = 0; k < 20; k++) - if (xvec[x + k] != yvec[x - d + k]) - break; - if (k == 20) - { - best = (xlim - bd[bdiagoff + d]) * 2 + dd; - bestpos = d; - } - } - } - } - if (best > 0) - { - cost = 2 * c - 1; - return bestpos; - } - } - } - } - - /** Compare in detail contiguous subsequences of the two files - which are known, as a whole, to match each other. - - The results are recorded in the vectors filevec[N].changed_flag, by - storing a 1 in the element for each line that is an insertion or deletion. - - The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1. - - Note that XLIM, YLIM are exclusive bounds. - All line numbers are origin-0 and discarded lines are not counted. */ - - private void compareseq (int xoff, int xlim, int yoff, int ylim) { - /* Slide down the bottom initial diagonal. */ - while (xoff < xlim && yoff < ylim && xvec[xoff] == yvec[yoff]) { - ++xoff; ++yoff; - } - /* Slide up the top initial diagonal. */ - while (xlim > xoff && ylim > yoff && xvec[xlim - 1] == yvec[ylim - 1]) { - --xlim; --ylim; - } - - /* Handle simple cases. */ - if (xoff == xlim) - while (yoff < ylim) - filevec[1].changed_flag[1+filevec[1].realindexes[yoff++]] = true; - else if (yoff == ylim) - while (xoff < xlim) - filevec[0].changed_flag[1+filevec[0].realindexes[xoff++]] = true; - else - { - /* Find a point of correspondence in the middle of the files. */ - - int d = diag (xoff, xlim, yoff, ylim); - int c = cost; - int f = fdiag[fdiagoff + d]; - int b = bdiag[bdiagoff + d]; - - if (c == 1) - { - /* This should be impossible, because it implies that - one of the two subsequences is empty, - and that case was handled above without calling `diag'. - Let's verify that this is true. */ - throw new IllegalArgumentException("Empty subsequence"); - } - else - { - /* Use that point to split this problem into two subproblems. */ - compareseq (xoff, b, yoff, b - d); - /* This used to use f instead of b, - but that is incorrect! - It is not necessarily the case that diagonal d - has a snake from b to f. */ - compareseq (b, xlim, b - d, ylim); - } - } - } - - /** Discard lines from one file that have no matches in the other file. - */ - - private void discard_confusing_lines() { - filevec[0].discard_confusing_lines(filevec[1]); - filevec[1].discard_confusing_lines(filevec[0]); - } - - private boolean inhibit = false; - - /** Adjust inserts/deletes of blank lines to join changes - as much as possible. - */ - - private void shift_boundaries() { - if (inhibit) - return; - filevec[0].shift_boundaries(filevec[1]); - filevec[1].shift_boundaries(filevec[0]); - } - - public interface ScriptBuilder { - /** Scan the tables of which lines are inserted and deleted, - producing an edit script. - @param changed0 true for lines in first file which do not match 2nd - @param len0 number of lines in first file - @param changed1 true for lines in 2nd file which do not match 1st - @param len1 number of lines in 2nd file - @return a linked list of changes - or null - */ - public change build_script( - boolean[] changed0,int len0, - boolean[] changed1,int len1 - ); - } - - /** Scan the tables of which lines are inserted and deleted, - producing an edit script in reverse order. */ - - static class ReverseScript implements ScriptBuilder { - public change build_script( - final boolean[] changed0,int len0, - final boolean[] changed1,int len1) - { - change script = null; - int i0 = 0, i1 = 0; - while (i0 < len0 || i1 < len1) { - if (changed0[1+i0] || changed1[1+i1]) { - int line0 = i0, line1 = i1; - - /* Find # lines changed here in each file. */ - while (changed0[1+i0]) ++i0; - while (changed1[1+i1]) ++i1; - - /* Record this change. */ - script = new change(line0, line1, i0 - line0, i1 - line1, script); - } - - /* We have reached lines in the two files that match each other. */ - i0++; i1++; - } - - return script; - } - } - - static class ForwardScript implements ScriptBuilder { - /** Scan the tables of which lines are inserted and deleted, - producing an edit script in forward order. */ - public change build_script( - final boolean[] changed0,int len0, - final boolean[] changed1,int len1) - { - change script = null; - int i0 = len0, i1 = len1; - - while (i0 >= 0 || i1 >= 0) - { - if (changed0[i0] || changed1[i1]) - { - int line0 = i0, line1 = i1; - - /* Find # lines changed here in each file. */ - while (changed0[i0]) --i0; - while (changed1[i1]) --i1; - - /* Record this change. */ - script = new change(i0, i1, line0 - i0, line1 - i1, script); - } - - /* We have reached lines in the two files that match each other. */ - i0--; i1--; - } - - return script; - } - } - - /** Standard ScriptBuilders. */ - public final static ScriptBuilder - forwardScript = new ForwardScript(), - reverseScript = new ReverseScript(); - - /* Report the differences of two files. DEPTH is the current directory - depth. */ - public final change diff_2(final boolean reverse) { - return diff(reverse ? reverseScript : forwardScript); - } - - /** Get the results of comparison as an edit script. The script - is described by a list of changes. The standard ScriptBuilder - implementations provide for forward and reverse edit scripts. - Alternate implementations could, for instance, list common elements - instead of differences. - @param bld an object to build the script from change flags - @return the head of a list of changes - */ - public change diff(final ScriptBuilder bld) { - - /* Some lines are obviously insertions or deletions - because they don't match anything. Detect them now, - and avoid even thinking about them in the main comparison algorithm. */ - - discard_confusing_lines (); - - /* Now do the main comparison algorithm, considering just the - undiscarded lines. */ - - xvec = filevec[0].undiscarded; - yvec = filevec[1].undiscarded; - - int diags = - filevec[0].nondiscarded_lines + filevec[1].nondiscarded_lines + 3; - fdiag = new int[diags]; - fdiagoff = filevec[1].nondiscarded_lines + 1; - bdiag = new int[diags]; - bdiagoff = filevec[1].nondiscarded_lines + 1; - - compareseq (0, filevec[0].nondiscarded_lines, - 0, filevec[1].nondiscarded_lines); - fdiag = null; - bdiag = null; - - /* Modify the results slightly to make them prettier - in cases where that can validly be done. */ - - shift_boundaries (); - - /* Get the results of comparison in the form of a chain - of `struct change's -- an edit script. */ - return bld.build_script( - filevec[0].changed_flag, - filevec[0].buffered_lines, - filevec[1].changed_flag, - filevec[1].buffered_lines - ); - - } - - /** The result of comparison is an "edit script": a chain of change objects. - Each change represents one place where some lines are deleted - and some are inserted. - - LINE0 and LINE1 are the first affected lines in the two files (origin 0). - DELETED is the number of lines deleted here from file 0. - INSERTED is the number of lines inserted here in file 1. - - If DELETED is 0 then LINE0 is the number of the line before - which the insertion was done; vice versa for INSERTED and LINE1. */ - - public static class change { - /** Previous or next edit command. */ - public change link; - /** # lines of file 1 changed here. */ - public final int inserted; - /** # lines of file 0 changed here. */ - public final int deleted; - /** Line number of 1st deleted line. */ - public final int line0; - /** Line number of 1st inserted line. */ - public final int line1; - - /** Cons an additional entry onto the front of an edit script OLD. - LINE0 and LINE1 are the first affected lines in the two files (origin 0). - DELETED is the number of lines deleted here from file 0. - INSERTED is the number of lines inserted here in file 1. - - If DELETED is 0 then LINE0 is the number of the line before - which the insertion was done; vice versa for INSERTED and LINE1. */ - public change(int line0, int line1, int deleted, int inserted, change old) { - this.line0 = line0; - this.line1 = line1; - this.inserted = inserted; - this.deleted = deleted; - this.link = old; - //System.err.println(line0+","+line1+","+inserted+","+deleted); - } - } - - /** Data on one input file being compared. - */ - - class file_data { - - /** Allocate changed array for the results of comparison. */ - void clear() { - /* Allocate a flag for each line of each file, saying whether that line - is an insertion or deletion. - Allocate an extra element, always zero, at each end of each vector. - */ - changed_flag = new boolean[buffered_lines + 2]; - } - - /** Return equiv_count[I] as the number of lines in this file - that fall in equivalence class I. - @return the array of equivalence class counts. - */ - int[] equivCount() { - int[] equiv_count = new int[equiv_max]; - for (int i = 0; i < buffered_lines; ++i) - ++equiv_count[equivs[i]]; - return equiv_count; - } - - /** Discard lines that have no matches in another file. - - A line which is discarded will not be considered by the actual - comparison algorithm; it will be as if that line were not in the file. - The file's `realindexes' table maps virtual line numbers - (which don't count the discarded lines) into real line numbers; - this is how the actual comparison algorithm produces results - that are comprehensible when the discarded lines are counted. -

- When we discard a line, we also mark it as a deletion or insertion - so that it will be printed in the output. - @param f the other file - */ - void discard_confusing_lines(file_data f) { - clear(); - /* Set up table of which lines are going to be discarded. */ - final byte[] discarded = discardable(f.equivCount()); - - /* Don't really discard the provisional lines except when they occur - in a run of discardables, with nonprovisionals at the beginning - and end. */ - filterDiscards(discarded); - - /* Actually discard the lines. */ - discard(discarded); - } - - /** Mark to be discarded each line that matches no line of another file. - If a line matches many lines, mark it as provisionally discardable. - @see equivCount() - @param counts The count of each equivalence number for the other file. - @return 0=nondiscardable, 1=discardable or 2=provisionally discardable - for each line - */ - - private byte[] discardable(final int[] counts) { - final int end = buffered_lines; - final byte[] discards = new byte[end]; - final int[] equivs = this.equivs; - int many = 5; - int tem = end / 64; - - /* Multiply MANY by approximate square root of number of lines. - That is the threshold for provisionally discardable lines. */ - while ((tem = tem >> 2) > 0) - many *= 2; - - for (int i = 0; i < end; i++) - { - int nmatch; - if (equivs[i] == 0) - continue; - nmatch = counts[equivs[i]]; - if (nmatch == 0) - discards[i] = 1; - else if (nmatch > many) - discards[i] = 2; - } - return discards; - } - - /** Don't really discard the provisional lines except when they occur - in a run of discardables, with nonprovisionals at the beginning - and end. */ - - private void filterDiscards(final byte[] discards) { - final int end = buffered_lines; - - for (int i = 0; i < end; i++) - { - /* Cancel provisional discards not in middle of run of discards. */ - if (discards[i] == 2) - discards[i] = 0; - else if (discards[i] != 0) - { - /* We have found a nonprovisional discard. */ - int j; - int length; - int provisional = 0; - - /* Find end of this run of discardable lines. - Count how many are provisionally discardable. */ - for (j = i; j < end; j++) - { - if (discards[j] == 0) - break; - if (discards[j] == 2) - ++provisional; - } - - /* Cancel provisional discards at end, and shrink the run. */ - while (j > i && discards[j - 1] == 2) { - discards[--j] = 0; --provisional; - } - - /* Now we have the length of a run of discardable lines - whose first and last are not provisional. */ - length = j - i; - - /* If 1/4 of the lines in the run are provisional, - cancel discarding of all provisional lines in the run. */ - if (provisional * 4 > length) - { - while (j > i) - if (discards[--j] == 2) - discards[j] = 0; - } - else - { - int consec; - int minimum = 1; - int tem = length / 4; - - /* MINIMUM is approximate square root of LENGTH/4. - A subrun of two or more provisionals can stand - when LENGTH is at least 16. - A subrun of 4 or more can stand when LENGTH >= 64. */ - while ((tem = tem >> 2) > 0) - minimum *= 2; - minimum++; - - /* Cancel any subrun of MINIMUM or more provisionals - within the larger run. */ - for (j = 0, consec = 0; j < length; j++) - if (discards[i + j] != 2) - consec = 0; - else if (minimum == ++consec) - /* Back up to start of subrun, to cancel it all. */ - j -= consec; - else if (minimum < consec) - discards[i + j] = 0; - - /* Scan from beginning of run - until we find 3 or more nonprovisionals in a row - or until the first nonprovisional at least 8 lines in. - Until that point, cancel any provisionals. */ - for (j = 0, consec = 0; j < length; j++) - { - if (j >= 8 && discards[i + j] == 1) - break; - if (discards[i + j] == 2) { - consec = 0; discards[i + j] = 0; - } - else if (discards[i + j] == 0) - consec = 0; - else - consec++; - if (consec == 3) - break; - } - - /* I advances to the last line of the run. */ - i += length - 1; - - /* Same thing, from end. */ - for (j = 0, consec = 0; j < length; j++) - { - if (j >= 8 && discards[i - j] == 1) - break; - if (discards[i - j] == 2) { - consec = 0; discards[i - j] = 0; - } - else if (discards[i - j] == 0) - consec = 0; - else - consec++; - if (consec == 3) - break; - } - } - } - } - } - - /** Actually discard the lines. - @param discards flags lines to be discarded - */ - private void discard(final byte[] discards) { - final int end = buffered_lines; - int j = 0; - for (int i = 0; i < end; ++i) - if (no_discards || discards[i] == 0) - { - undiscarded[j] = equivs[i]; - realindexes[j++] = i; - } - else - changed_flag[1+i] = true; - nondiscarded_lines = j; - } - - file_data(Object[] data,Hashtable h) { - buffered_lines = data.length; - - equivs = new int[buffered_lines]; - undiscarded = new int[buffered_lines]; - realindexes = new int[buffered_lines]; - - for (int i = 0; i < data.length; ++i) { - Integer ir = (Integer)h.get(data[i]); - if (ir == null) - h.put(data[i],new Integer(equivs[i] = equiv_max++)); - else - equivs[i] = ir.intValue(); - } - } - - /** Adjust inserts/deletes of blank lines to join changes - as much as possible. - - We do something when a run of changed lines include a blank - line at one end and have an excluded blank line at the other. - We are free to choose which blank line is included. - `compareseq' always chooses the one at the beginning, - but usually it is cleaner to consider the following blank line - to be the "change". The only exception is if the preceding blank line - would join this change to other changes. - @param f the file being compared against - */ - - void shift_boundaries(file_data f) { - final boolean[] changed = changed_flag; - final boolean[] other_changed = f.changed_flag; - int i = 0; - int j = 0; - int i_end = buffered_lines; - int preceding = -1; - int other_preceding = -1; - - for (;;) - { - int start, end, other_start; - - /* Scan forwards to find beginning of another run of changes. - Also keep track of the corresponding point in the other file. */ - - while (i < i_end && !changed[1+i]) - { - while (other_changed[1+j++]) - /* Non-corresponding lines in the other file - will count as the preceding batch of changes. */ - other_preceding = j; - i++; - } - - if (i == i_end) - break; - - start = i; - other_start = j; - - for (;;) - { - /* Now find the end of this run of changes. */ - - while (i < i_end && changed[1+i]) i++; - end = i; - - /* If the first changed line matches the following unchanged one, - and this run does not follow right after a previous run, - and there are no lines deleted from the other file here, - then classify the first changed line as unchanged - and the following line as changed in its place. */ - - /* You might ask, how could this run follow right after another? - Only because the previous run was shifted here. */ - - if (end != i_end - && equivs[start] == equivs[end] - && !other_changed[1+j] - && end != i_end - && !((preceding >= 0 && start == preceding) - || (other_preceding >= 0 - && other_start == other_preceding))) - { - changed[1+end++] = true; - changed[1+start++] = false; - ++i; - /* Since one line-that-matches is now before this run - instead of after, we must advance in the other file - to keep in synch. */ - ++j; - } - else - break; - } - - preceding = i; - other_preceding = j; - } - } - - /** Number of elements (lines) in this file. */ - final int buffered_lines; - - /** Vector, indexed by line number, containing an equivalence code for - each line. It is this vector that is actually compared with that - of another file to generate differences. */ - private final int[] equivs; - - /** Vector, like the previous one except that - the elements for discarded lines have been squeezed out. */ - final int[] undiscarded; - - /** Vector mapping virtual line numbers (not counting discarded lines) - to real ones (counting those lines). Both are origin-0. */ - final int[] realindexes; - - /** Total number of nondiscarded lines. */ - int nondiscarded_lines; - - /** Array, indexed by real origin-1 line number, - containing true for a line that is an insertion or a deletion. - The results of comparison are stored here. */ - boolean[] changed_flag; - - } -} diff --git a/src/main/java/org/exist/versioning/Diff.java b/src/main/java/org/exist/versioning/Diff.java index 4981a08..dc16e3b 100644 --- a/src/main/java/org/exist/versioning/Diff.java +++ b/src/main/java/org/exist/versioning/Diff.java @@ -1,27 +1,26 @@ -package org.exist.versioning; - -import org.exist.dom.persistent.DocumentImpl; -import org.exist.util.serializer.Receiver;/* - * eXist Open Source Native XML Database - * Copyright (C) 2001-07 The eXist Project - * http://exist-db.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * \$Id\$ + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +package org.exist.versioning; + +import org.exist.dom.persistent.DocumentImpl; +import org.exist.util.serializer.Receiver; public interface Diff { void diff(DocumentImpl docA, DocumentImpl docB) diff --git a/src/main/java/org/exist/versioning/DiffException.java b/src/main/java/org/exist/versioning/DiffException.java index 27813e7..a0b2863 100644 --- a/src/main/java/org/exist/versioning/DiffException.java +++ b/src/main/java/org/exist/versioning/DiffException.java @@ -1,23 +1,21 @@ -/* - * eXist Open Source Native XML Database - * Copyright (C) 2001-07 The eXist Project - * http://exist-db.org +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * $Id$ + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.exist.versioning; @@ -25,11 +23,11 @@ public class DiffException extends Exception { private static final long serialVersionUID = 2294067063976070362L; - public DiffException(String message) { + public DiffException(final String message) { super(message); } - public DiffException(String message, Throwable cause) { + public DiffException(final String message, final Throwable cause) { super(message, cause); } } diff --git a/src/main/java/org/exist/versioning/DiffNode.java b/src/main/java/org/exist/versioning/DiffNode.java index 396d42c..d7b8fcb 100644 --- a/src/main/java/org/exist/versioning/DiffNode.java +++ b/src/main/java/org/exist/versioning/DiffNode.java @@ -1,3 +1,22 @@ +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ package org.exist.versioning; import org.exist.numbering.NodeId; @@ -12,48 +31,55 @@ public class DiffNode { protected int status = UNCHANGED; - protected NodeId nodeId; - protected int nodeType; + protected final NodeId nodeId; + protected final int nodeType; protected String value = null; protected QName qname = null; - public DiffNode(NodeId nodeId, int nodeType, String value) { + public DiffNode(final NodeId nodeId, final int nodeType, final String value) { this.nodeId = nodeId; this.nodeType = nodeType; this.value = value; } - public DiffNode(NodeId nodeId, int nodeType, QName qname) { + public DiffNode(final NodeId nodeId, final int nodeType, final QName qname) { this.nodeId = nodeId; this.nodeType = nodeType; this.qname = qname; } - public void setStatus(int status) { + public void setStatus(final int status) { this.status = status; } - public boolean equals(Object obj) { - DiffNode other = (DiffNode) obj; - if (nodeType != other.nodeType) + @Override + public boolean equals(final Object obj) { + final DiffNode other = (DiffNode) obj; + if (nodeType != other.nodeType) { return false; - if (qname != null) + } + if (qname != null) { return qname.equals(other.qname); - else + } else { return value.equals(other.value); + } } + @Override public int hashCode() { - if (qname == null) + if (qname == null) { return (value.hashCode() << 1) + nodeType; - else + } else { return (qname.hashCode() << 1) + nodeType; + } } + @Override public String toString() { - if (qname == null) + if (qname == null) { return nodeType + " " + nodeId.toString() + " " + value; - else + } else { return nodeType + " " + nodeId.toString() + " " + qname; + } } } \ No newline at end of file diff --git a/src/main/java/org/exist/versioning/Difference.java b/src/main/java/org/exist/versioning/Difference.java index 7cae9e8..962f6bc 100644 --- a/src/main/java/org/exist/versioning/Difference.java +++ b/src/main/java/org/exist/versioning/Difference.java @@ -1,3 +1,22 @@ +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ package org.exist.versioning; import org.exist.dom.persistent.NodeProxy; @@ -32,70 +51,73 @@ public abstract class Difference implements Comparable { public final static QName ELEMENT_APPEND = new QName("append", StandardDiff.NAMESPACE, StandardDiff.PREFIX); public final static QName ELEMENT_DELETE = new QName("delete", StandardDiff.NAMESPACE, StandardDiff.PREFIX); - protected int type; - protected NodeProxy refChild; + protected final int type; + protected final NodeProxy refChild; - public Difference(int type, NodeProxy reference) { + public Difference(final int type, final NodeProxy refChild) { this.type = type; - this.refChild = reference; + this.refChild = refChild; } - public abstract void serialize(DBBroker broker, Receiver handler); + public abstract void serialize(final DBBroker broker, final Receiver handler); - public boolean equals(Object obj) { - Difference other = (Difference) obj; + @Override + public boolean equals(final Object obj) { + final Difference other = (Difference) obj; return refChild.getNodeId().equals(other.refChild.getNodeId()); } - public int compareTo(Difference other) { + @Override + public int compareTo(final Difference other) { return refChild.getNodeId().compareTo(other.refChild.getNodeId()); } public static class Insert extends Difference { - protected DocumentImpl otherDoc; + protected final DocumentImpl otherDoc; protected DiffNode[] nodes; - public Insert(NodeProxy reference, DocumentImpl otherDoc) { + public Insert(final NodeProxy reference, final DocumentImpl otherDoc) { super(INSERT, reference); this.otherDoc = otherDoc; } - public Insert(int type, NodeProxy reference, DocumentImpl otherDoc) { + public Insert(final int type, final NodeProxy reference, final DocumentImpl otherDoc) { super(type, reference); this.otherDoc = otherDoc; } - protected void addNodes(DiffNode[] nodesToAdd) { - if (nodes == null) + protected void addNodes(final DiffNode[] nodesToAdd) { + if (nodes == null) { nodes = nodesToAdd; - else { - DiffNode n[] = new DiffNode[nodes.length + nodesToAdd.length]; + } else { + final DiffNode n[] = new DiffNode[nodes.length + nodesToAdd.length]; System.arraycopy(nodes, 0, n, 0, nodes.length); System.arraycopy(nodesToAdd, 0, n, nodes.length, nodesToAdd.length); nodes = n; } } - public void serialize(DBBroker broker, Receiver handler) { + @Override + public void serialize(final DBBroker broker, final Receiver handler) { try { - AttrList attribs = new AttrList(); + final AttrList attribs = new AttrList(); attribs.addAttribute(ATTR_REF, refChild.getNodeId().toString()); handler.startElement(ELEMENT_INSERT, attribs); serializeChildren(broker, handler); handler.endElement(ELEMENT_INSERT); - } catch (SAXException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (final SAXException e) { + e.printStackTrace(); } } - protected void serializeChildren(DBBroker broker, Receiver handler) throws SAXException { + protected void serializeChildren(final DBBroker broker, final Receiver handler) throws SAXException { AttrList attribs; for (int i = 0; i < nodes.length; i++) { switch (nodes[i].nodeType) { case XMLStreamReader.ATTRIBUTE: attribs = new AttrList(); - AttrImpl attr = (AttrImpl) broker.objectWith(otherDoc, nodes[i].nodeId); + final AttrImpl attr = (AttrImpl) broker.objectWith(otherDoc, nodes[i].nodeId); attribs.addAttribute(new QName(attr.getLocalName(), attr.getNamespaceURI(), attr.getPrefix()), attr.getValue(), attr.getType()); handler.startElement(ELEMENT_ATTRIBUTE, attribs); @@ -105,13 +127,13 @@ protected void serializeChildren(DBBroker broker, Receiver handler) throws SAXEx // check if there's a complete element to write, not just a start or end tag // if yes, just copy the element, if no, write a start-tag node boolean isClosed = false; - NodeId nodeId = nodes[i].nodeId; + final NodeId nodeId = nodes[i].nodeId; for (int j = i; j < nodes.length; j++) { if (nodes[j].nodeType == XMLStreamReader.END_ELEMENT && nodes[j].nodeId.equals(nodeId)) { isClosed = true; - NodeProxy proxy = new NodeProxy(otherDoc, nodes[i].nodeId); - Serializer serializer = broker.getSerializer(); + final NodeProxy proxy = new NodeProxy(otherDoc, nodes[i].nodeId); + final Serializer serializer = broker.getSerializer(); serializer.reset(); serializer.setProperty(Serializer.GENERATE_DOC_EVENTS, "false"); serializer.setReceiver(handler); @@ -144,8 +166,8 @@ protected void serializeChildren(DBBroker broker, Receiver handler) throws SAXEx handler.endElement(ELEMENT_COMMENT); break; default: - NodeProxy proxy = new NodeProxy(otherDoc, nodes[i].nodeId); - Serializer serializer = broker.getSerializer(); + final NodeProxy proxy = new NodeProxy(otherDoc, nodes[i].nodeId); + final Serializer serializer = broker.getSerializer(); serializer.reset(); serializer.setProperty(Serializer.GENERATE_DOC_EVENTS, "false"); serializer.setReceiver(handler); @@ -158,39 +180,41 @@ protected void serializeChildren(DBBroker broker, Receiver handler) throws SAXEx public final static class Append extends Insert { - public Append(NodeProxy reference, DocumentImpl otherDoc) { + public Append(final NodeProxy reference, final DocumentImpl otherDoc) { super(APPEND, reference, otherDoc); } - public void serialize(DBBroker broker, Receiver handler) { + @Override + public void serialize(final DBBroker broker, final Receiver handler) { try { - AttrList attribs = new AttrList(); + final AttrList attribs = new AttrList(); attribs.addAttribute(ATTR_REF, refChild.getNodeId().toString()); handler.startElement(ELEMENT_APPEND, attribs); serializeChildren(broker, handler); handler.endElement(ELEMENT_APPEND); - } catch (SAXException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (final SAXException e) { + e.printStackTrace(); } } } public final static class Delete extends Difference { - protected int event = -1; + protected final int event; - public Delete(NodeProxy reference) { + public Delete(final NodeProxy reference) { this(-1, reference); } - public Delete(int event, NodeProxy reference) { + public Delete(final int event, final NodeProxy reference) { super(DELETE, reference); this.event = event; } - public void serialize(DBBroker broker, Receiver handler) { + @Override + public void serialize(final DBBroker broker, final Receiver handler) { try { - AttrList attribs = new AttrList(); + final AttrList attribs = new AttrList(); if (event == XMLStreamReader.START_ELEMENT || event == XMLStreamReader.END_ELEMENT) { String ev = event == XMLStreamReader.START_ELEMENT ? "start" : "end"; attribs.addAttribute(ATTR_EVENT, ev); @@ -198,9 +222,9 @@ public void serialize(DBBroker broker, Receiver handler) { attribs.addAttribute(ATTR_REF, refChild.getNodeId().toString()); handler.startElement(ELEMENT_DELETE, attribs); handler.endElement(ELEMENT_DELETE); - } catch (SAXException e) { + } catch (final SAXException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } } -} \ No newline at end of file +} diff --git a/src/main/java/org/exist/versioning/Patch.java b/src/main/java/org/exist/versioning/Patch.java index 8904041..82d84c3 100644 --- a/src/main/java/org/exist/versioning/Patch.java +++ b/src/main/java/org/exist/versioning/Patch.java @@ -1,23 +1,21 @@ -/* - * eXist Open Source Native XML Database - * Copyright (C) 2001-07 The eXist Project - * http://exist-db.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * $Id$ + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.exist.versioning; @@ -49,9 +47,7 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import java.io.IOException; -import java.util.Map; -import java.util.TreeMap; -import java.util.Stack; +import java.util.*; /** * Patch a given source document by applying a diff in eXist's diff format. @@ -77,7 +73,7 @@ public class Patch { private Map appendedNodes = null; private boolean annotate = false; - private Stack elementStack = null; + private Deque elementStack = null; private NewArrayNodeSet changeSet = null; private DocumentImpl diffDoc; @@ -148,7 +144,7 @@ public void patch(ExtendedXMLStreamReader reader, Receiver receiver) throws Diff public void annotate(ExtendedXMLStreamReader reader, Receiver receiver) throws DiffException { annotate = true; - elementStack = new Stack(); + elementStack = new ArrayDeque<>(); buildChangeSet(); try { NodeId skipSubtree = null; @@ -212,7 +208,7 @@ private void insertNode(StoredNode insertedNode, Receiver receiver, String chang receiver.attribute(qname, reader.getAttributeValue(i)); } } else if ("comment".equals(reader.getLocalName())) { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); while (reader.hasNext()) { status = reader.next(); if (status == XMLStreamReader.END_ELEMENT && @@ -338,14 +334,14 @@ private void copyNode(ExtendedXMLStreamReader reader, Receiver receiver, int sta } } - private void parseDiff(DBBroker broker, DocumentImpl doc) throws XPathException { - deletedNodes = new TreeMap(); - insertedNodes = new TreeMap(); - appendedNodes = new TreeMap(); - XQuery service = broker.getXQueryService(); + private void parseDiff(final DBBroker broker, final DocumentImpl doc) throws XPathException { + deletedNodes = new TreeMap<>(); + insertedNodes = new TreeMap<>(); + appendedNodes = new TreeMap<>(); + XQuery service = broker.getBrokerPool().getXQueryService(); Sequence changes; try { - changes = service.execute("declare namespace v=\"http://exist-db.org/versioning\";" + + changes = service.execute(broker, "declare namespace v=\"http://exist-db.org/versioning\";" + "doc('" + doc.getURI().toString() + "')/v:version/v:diff/*", Sequence.EMPTY_SEQUENCE, AccessContext.TEST); } catch (PermissionDeniedException e) { diff --git a/src/main/java/org/exist/versioning/StandardDiff.java b/src/main/java/org/exist/versioning/StandardDiff.java index 41de200..a1012f0 100644 --- a/src/main/java/org/exist/versioning/StandardDiff.java +++ b/src/main/java/org/exist/versioning/StandardDiff.java @@ -1,3 +1,22 @@ +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ package org.exist.versioning; import bmsi.util.Diff; @@ -34,19 +53,19 @@ public class StandardDiff implements org.exist.versioning.Diff { private final static QName DIFF_ELEMENT = new QName("diff", NAMESPACE, PREFIX); - private DBBroker broker; + private final DBBroker broker; private List changes = null; - public StandardDiff(DBBroker broker) { + public StandardDiff(final DBBroker broker) { this.broker = broker; } - public void diff(DocumentImpl docA, DocumentImpl docB) - throws DiffException { + @Override + public void diff(final DocumentImpl docA, final DocumentImpl docB) throws DiffException { try { - DiffNode[] nodesA = getNodes(broker, docA); - DiffNode[] nodesB = getNodes(broker, docB); + final DiffNode[] nodesA = getNodes(broker, docA); + final DiffNode[] nodesB = getNodes(broker, docB); if (LOG.isTraceEnabled()) { LOG.trace("Source:"); @@ -55,32 +74,30 @@ public void diff(DocumentImpl docA, DocumentImpl docB) debugNodes(nodesB); } - Diff diff = new Diff(nodesA, nodesB); - Diff.change script = diff.diff_2(false); - changes = getChanges(script, docA, docB, nodesA, nodesB); - } catch (XMLStreamException e) { - throw new DiffException(e.getMessage(), e); - } catch (IOException e) { + final Diff diff = new Diff(nodesA, nodesB); + final Diff.change script = diff.diff_2(false); + this.changes = getChanges(script, docA, docB, nodesA, nodesB); + } catch (final XMLStreamException | IOException e) { throw new DiffException(e.getMessage(), e); } } - private void debugNodes(DiffNode[] nodes) { - StringBuffer buf = new StringBuffer(); + private void debugNodes(final DiffNode[] nodes) { + final StringBuilder buf = new StringBuilder(); buf.append('\n'); for (int i = 0; i < nodes.length; i++) { - DiffNode node = nodes[i]; + final DiffNode node = nodes[i]; buf.append(Integer.toString(i)).append(' ').append(node.toString()).append('\n'); } LOG.trace(buf.toString()); } + @Override public String diff2XML() throws DiffException { - try { - StringWriter writer = new StringWriter(); - SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject( + try(final StringWriter writer = new StringWriter()) { + final SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject( SAXSerializer.class); - Properties outputProperties = new Properties(); + final Properties outputProperties = new Properties(); outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); outputProperties.setProperty(OutputKeys.INDENT, "no"); sax.setOutput(writer, outputProperties); @@ -88,7 +105,7 @@ public String diff2XML() throws DiffException { diff2XML(sax); sax.endDocument(); return writer.toString(); - } catch (SAXException e) { + } catch (final IOException | SAXException e) { throw new DiffException("error while serializing diff: " + e.getMessage(), e); } } diff --git a/src/main/java/org/exist/versioning/VersioningFilter.java b/src/main/java/org/exist/versioning/VersioningFilter.java index 323cad8..63d500a 100644 --- a/src/main/java/org/exist/versioning/VersioningFilter.java +++ b/src/main/java/org/exist/versioning/VersioningFilter.java @@ -1,3 +1,22 @@ +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ package org.exist.versioning; import org.exist.dom.persistent.DocumentImpl; @@ -24,33 +43,26 @@ public class VersioningFilter extends CustomMatchListener { private int elementStack = 0; - public VersioningFilter() { - } - @Override - public void startElement(QName qname, AttrList attribs) throws SAXException { + public void startElement(final QName qname, final AttrList attribs) throws SAXException { if (elementStack == 0) { final NodeHandle node = getCurrentNode(); if (node != null) { final DocumentImpl doc = node.getOwnerDocument(); - XmldbURI uri = doc.getURI(); + final XmldbURI uri = doc.getURI(); if (!uri.startsWith(XmldbURI.SYSTEM_COLLECTION_URI)) { if (doc.getCollection().getConfiguration(getBroker()).triggerRegistered(VersioningTrigger.class)) { try { - long rev = VersioningHelper.getCurrentRevision(getBroker(), doc.getURI()); - long time = System.currentTimeMillis(); - String key = Long.toHexString(time) + Long.toHexString(rev); + final long rev = VersioningHelper.getCurrentRevision(getBroker(), doc.getURI()); + final long time = System.currentTimeMillis(); + final String key = Long.toHexString(time) + Long.toHexString(rev); attribs.addAttribute(ATTR_REVISION, rev == 0 ? "0" : Long.toString(rev)); attribs.addAttribute(ATTR_KEY, key); attribs.addAttribute(ATTR_PATH, doc.getURI().toString()); - } catch (XPathException e) { - LOG.error("Exception while retrieving versioning info: " + e.getMessage(), e); - } catch (IOException e) { + } catch (XPathException | IOException | PermissionDeniedException e) { LOG.error("Exception while retrieving versioning info: " + e.getMessage(), e); - } catch (PermissionDeniedException e) { - LOG.error("Exception while retrieving versioning info: " + e.getMessage(), e); - } + } } } } @@ -59,7 +71,8 @@ public void startElement(QName qname, AttrList attribs) throws SAXException { nextListener.startElement(qname, attribs); } - public void endElement(QName qname) throws SAXException { + @Override + public void endElement(final QName qname) throws SAXException { --elementStack; nextListener.endElement(qname); } diff --git a/src/main/java/org/exist/versioning/VersioningHelper.java b/src/main/java/org/exist/versioning/VersioningHelper.java index be9c2f3..398c024 100644 --- a/src/main/java/org/exist/versioning/VersioningHelper.java +++ b/src/main/java/org/exist/versioning/VersioningHelper.java @@ -1,29 +1,28 @@ -/* - * eXist Open Source Native XML Database - * Copyright (C) 2001-07 The eXist Project - * http://exist-db.org +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * $Id$ + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.exist.versioning; import org.exist.security.PermissionDeniedException; import org.exist.security.xacml.AccessContext; import org.exist.source.StringSource; +import org.exist.storage.BrokerPool; import org.exist.storage.DBBroker; import org.exist.storage.XQueryPool; import org.exist.xmldb.XmldbURI; @@ -77,87 +76,116 @@ public class VersioningHelper { private final static StringSource GET_BASE_REV_FOR_KEY_SOURCE = new StringSource(GET_BASE_REV_FOR_KEY); - public static long getCurrentRevision(DBBroker broker, XmldbURI docPath) throws XPathException, IOException, PermissionDeniedException { - String docName = docPath.lastSegment().toString(); - XmldbURI collectionPath = docPath.removeLastSegment(); - XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath); - XQuery xquery = broker.getXQueryService(); - XQueryPool pool = xquery.getXQueryPool(); - XQueryContext context; - CompiledXQuery compiled = pool.borrowCompiledXQuery(broker, GET_CURRENT_REV_SOURCE); - if(compiled == null) - context = xquery.newContext(AccessContext.VALIDATION_INTERNAL); - else - context = compiled.getContext(); + public static long getCurrentRevision(final DBBroker broker, final XmldbURI docPath) + throws XPathException, IOException, PermissionDeniedException { + final String docName = docPath.lastSegment().toString(); + final XmldbURI collectionPath = docPath.removeLastSegment(); + final XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath); + + final BrokerPool brokerPool = broker.getBrokerPool(); + final XQuery xquery = brokerPool.getXQueryService(); + final XQueryPool xqueryPool = brokerPool.getXQueryPool(); + CompiledXQuery compiled = xqueryPool.borrowCompiledXQuery(broker, GET_CURRENT_REV_SOURCE); + final XQueryContext context; + if(compiled == null) { + context = new XQueryContext(brokerPool, AccessContext.VALIDATION_INTERNAL); + } else { + context = compiled.getContext(); + } context.declareVariable("collection", path.toString()); context.declareVariable("document", docName); - if(compiled == null) - compiled = xquery.compile(context, GET_CURRENT_REV_SOURCE); + if(compiled == null) { + compiled = xquery.compile(broker, context, GET_CURRENT_REV_SOURCE); + } else { + compiled.getContext().updateContext(context); + context.getWatchDog().reset(); + } + try { - Sequence s = xquery.execute(compiled, Sequence.EMPTY_SEQUENCE); - if (s.isEmpty()) + final Sequence s = xquery.execute(broker, compiled, Sequence.EMPTY_SEQUENCE); + if (s.isEmpty()) { return 0; - IntegerValue iv = (IntegerValue) s.itemAt(0); + } + final IntegerValue iv = (IntegerValue) s.itemAt(0); return iv.getLong(); } finally { - pool.returnCompiledXQuery(GET_CURRENT_REV_SOURCE, compiled); + xqueryPool.returnCompiledXQuery(GET_CURRENT_REV_SOURCE, compiled); } } - public static boolean newerRevisionExists(DBBroker broker, XmldbURI docPath, long baseRev, String key) throws XPathException, IOException, PermissionDeniedException { - String docName = docPath.lastSegment().toString(); - XmldbURI collectionPath = docPath.removeLastSegment(); - XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath); - XQuery xquery = broker.getXQueryService(); - XQueryPool pool = xquery.getXQueryPool(); - XQueryContext context; - CompiledXQuery compiled = pool.borrowCompiledXQuery(broker, GET_CONFLICTING_REV_SOURCE); - if(compiled == null) - context = xquery.newContext(AccessContext.VALIDATION_INTERNAL); - else + public static boolean newerRevisionExists(final DBBroker broker, final XmldbURI docPath, final long baseRev, + final String key) throws XPathException, IOException, PermissionDeniedException { + final String docName = docPath.lastSegment().toString(); + final XmldbURI collectionPath = docPath.removeLastSegment(); + final XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath); + + final BrokerPool brokerPool = broker.getBrokerPool(); + final XQuery xquery = brokerPool.getXQueryService(); + final XQueryPool xqueryPool = brokerPool.getXQueryPool(); + final XQueryContext context; + CompiledXQuery compiled = xqueryPool.borrowCompiledXQuery(broker, GET_CONFLICTING_REV_SOURCE); + if(compiled == null) { + context = new XQueryContext(brokerPool, AccessContext.VALIDATION_INTERNAL); + } else { context = compiled.getContext(); + } context.declareVariable("collection", path.toString()); context.declareVariable("document", docName); context.declareVariable("base", new IntegerValue(baseRev)); context.declareVariable("key", key); - if(compiled == null) - compiled = xquery.compile(context, GET_CONFLICTING_REV_SOURCE); + if(compiled == null) { + compiled = xquery.compile(broker, context, GET_CONFLICTING_REV_SOURCE); + } else { + compiled.getContext().updateContext(context); + context.getWatchDog().reset(); + } + try { - Sequence s = xquery.execute(compiled, Sequence.EMPTY_SEQUENCE); + final Sequence s = xquery.execute(broker, compiled, Sequence.EMPTY_SEQUENCE); return !s.isEmpty(); } finally { - pool.returnCompiledXQuery(GET_CONFLICTING_REV_SOURCE, compiled); + xqueryPool.returnCompiledXQuery(GET_CONFLICTING_REV_SOURCE, compiled); } } - public static long getBaseRevision(DBBroker broker, XmldbURI docPath, long baseRev, String sessionKey) throws XPathException, IOException, PermissionDeniedException { - String docName = docPath.lastSegment().toString(); - XmldbURI collectionPath = docPath.removeLastSegment(); - XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath); - XQuery xquery = broker.getXQueryService(); - XQueryPool pool = xquery.getXQueryPool(); - XQueryContext context; - CompiledXQuery compiled = pool.borrowCompiledXQuery(broker, GET_BASE_REV_FOR_KEY_SOURCE); - if(compiled == null) - context = xquery.newContext(AccessContext.VALIDATION_INTERNAL); - else + public static long getBaseRevision(final DBBroker broker, final XmldbURI docPath, final long baseRev, + final String sessionKey) throws XPathException, IOException, PermissionDeniedException { + final String docName = docPath.lastSegment().toString(); + final XmldbURI collectionPath = docPath.removeLastSegment(); + final XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath); + + final BrokerPool brokerPool = broker.getBrokerPool(); + final XQuery xquery = brokerPool.getXQueryService(); + final XQueryPool xqueryPool = brokerPool.getXQueryPool(); + final XQueryContext context; + CompiledXQuery compiled = xqueryPool.borrowCompiledXQuery(broker, GET_BASE_REV_FOR_KEY_SOURCE); + if (compiled == null) { + context = new XQueryContext(brokerPool, AccessContext.VALIDATION_INTERNAL); + } else { context = compiled.getContext(); + } context.declareVariable("collection", path.toString()); context.declareVariable("document", docName); context.declareVariable("base", new IntegerValue(baseRev)); context.declareVariable("key", sessionKey); - if(compiled == null) - compiled = xquery.compile(context, GET_BASE_REV_FOR_KEY_SOURCE); + if (compiled == null) { + compiled = xquery.compile(broker, context, GET_BASE_REV_FOR_KEY_SOURCE); + } else { + compiled.getContext().updateContext(context); + context.getWatchDog().reset(); + } + try { - Sequence s = xquery.execute(compiled, Sequence.EMPTY_SEQUENCE); - if (s.isEmpty()) + final Sequence s = xquery.execute(broker, compiled, Sequence.EMPTY_SEQUENCE); + if (s.isEmpty()) { return 0; - - IntegerValue iv = (IntegerValue) s.itemAt(0); - return iv.getLong(); + } else { + final IntegerValue iv = (IntegerValue) s.itemAt(0); + return iv.getLong(); + } } finally { - pool.returnCompiledXQuery(GET_BASE_REV_FOR_KEY_SOURCE, compiled); + xqueryPool.returnCompiledXQuery(GET_BASE_REV_FOR_KEY_SOURCE, compiled); } } } diff --git a/src/main/java/org/exist/versioning/VersioningTrigger.java b/src/main/java/org/exist/versioning/VersioningTrigger.java index b9e34cd..10e2a9b 100644 --- a/src/main/java/org/exist/versioning/VersioningTrigger.java +++ b/src/main/java/org/exist/versioning/VersioningTrigger.java @@ -1,34 +1,31 @@ -/* - * eXist Open Source Native XML Database - * Copyright (C) 2001-2010 The eXist Project - * http://exist-db.org +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * $Id$ + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.exist.versioning; import java.io.DataInputStream; import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Date; import java.util.List; import java.util.Map; @@ -101,28 +98,32 @@ public class VersioningTrigger extends FilteringTrigger { private boolean checkForConflicts = false; @Override - public void configure(DBBroker broker, Collection parent, Map> parameters) + public void configure(final DBBroker broker, final Collection parent, final Map> parameters) throws TriggerException { super.configure(broker, parent, parameters); if (parameters != null) { - String allowOverwrite = (String) parameters.get(PARAM_OVERWRITE).get(0); - if (allowOverwrite != null) - checkForConflicts = allowOverwrite.equals("false") || allowOverwrite.equals("no"); + final String allowOverwrite = (String) parameters.get(PARAM_OVERWRITE).get(0); + if (allowOverwrite != null) { + checkForConflicts = allowOverwrite.equals("false") || allowOverwrite.equals("no"); + } } - - LOG.debug("checkForConflicts: " + checkForConflicts); + + if(LOG.isDebugEnabled()) { + LOG.debug("checkForConflicts: " + checkForConflicts); + } } //XXX: is it safe to delete? @Deprecated - public void finish(int event, DBBroker broker, Txn transaction, XmldbURI documentPath, DocumentImpl document) { - - if (documentPath == null || documentPath.startsWith(VERSIONS_COLLECTION)) - return; + public void finish(final int event, final DBBroker broker, final Txn transaction, XmldbURI documentPath, + final DocumentImpl document) { - Subject activeSubject = broker.getSubject(); + if (documentPath == null || documentPath.startsWith(VERSIONS_COLLECTION)) { + return; + } + final Subject activeSubject = broker.getSubject(); try { broker.setSubject(broker.getBrokerPool().getSecurityManager().getSystemSubject()); @@ -132,13 +133,10 @@ public void finish(int event, DBBroker broker, Txn transaction, XmldbURI documen vDoc.getUpdateLock().acquire(Lock.WRITE_LOCK); vCollection.addDocument(transaction, broker, vDoc); broker.storeXMLResource(transaction, vDoc); - } catch (LockException e) { + } catch (LockException | PermissionDeniedException e) { LOG.warn("Versioning trigger could not store base document: " + vDoc.getFileURI() + e.getMessage(), e); - } catch (PermissionDeniedException e) { - LOG.warn("Versioning trigger could not store base document: " + vDoc.getFileURI() + - e.getMessage(), e); - } finally { + } finally { vDoc.getUpdateLock().release(Lock.WRITE_LOCK); } } @@ -148,92 +146,93 @@ public void finish(int event, DBBroker broker, Txn transaction, XmldbURI documen try { vCollection = getVersionsCollection(broker, transaction, documentPath.removeLastSegment()); - String existingURI = document.getFileURI().toString(); - XmldbURI deletedURI = XmldbURI.create(existingURI + DELETED_SUFFIX); + final String existingURI = document.getFileURI().toString(); + final XmldbURI deletedURI = XmldbURI.create(existingURI + DELETED_SUFFIX); lastRev = vCollection.getDocument(broker, deletedURI); if (lastRev == null) { lastRev = vCollection.getDocument(broker, XmldbURI.create(existingURI + BASE_SUFFIX)); removeLast = false; - } else - removeLast = true; - } catch (IOException e) { + } else { + removeLast = true; + } + } catch (IOException | TriggerException e) { LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e); } catch (PermissionDeniedException e) { LOG.warn("Permission denied in VersioningTrigger: " + e.getMessage(), e); - } catch (TriggerException e) { - LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e); } - } + } if (lastRev != null || event == REMOVE_DOCUMENT_EVENT) { try { - long revision = newRevision(broker.getBrokerPool()); - if (documentPath.isCollectionPathAbsolute()) - documentPath = documentPath.lastSegment(); - XmldbURI diffUri = XmldbURI.createInternal(documentPath.toString() + '.' + revision); + final long revision = newRevision(broker.getBrokerPool()); + if (documentPath.isCollectionPathAbsolute()) { + documentPath = documentPath.lastSegment(); + } + final XmldbURI diffUri = XmldbURI.createInternal(documentPath.toString() + '.' + revision); vCollection.setTriggersEnabled(false); - StringWriter writer = new StringWriter(); - SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject( - SAXSerializer.class); - Properties outputProperties = new Properties(); - outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); - outputProperties.setProperty(OutputKeys.INDENT, "no"); - sax.setOutput(writer, outputProperties); - - sax.startDocument(); - sax.startElement(ELEMENT_VERSION, null); - writeProperties(sax, getVersionProperties(revision, documentPath, activeSubject)); - - if(event == REMOVE_DOCUMENT_EVENT) { - sax.startElement(ELEMENT_REMOVED, null); - sax.endElement(ELEMENT_REMOVED); - } else { - - //Diff - if(document instanceof BinaryDocument) { - //create a copy of the last Binary revision - XmldbURI binUri = XmldbURI.create(diffUri.toString() + BINARY_SUFFIX); - broker.copyResource(transaction, document, vCollection, binUri); - - //Create metadata about the last Binary Version - sax.startElement(ELEMENT_REPLACED_BINARY, null); - sax.attribute(ATTRIBUTE_REF, binUri.toString()); - sax.endElement(ELEMENT_REPLACED_BINARY); - } else if(lastRev instanceof BinaryDocument) { - //create a copy of the last XML revision - XmldbURI xmlUri = XmldbURI.create(diffUri.toString() + XML_SUFFIX); - broker.copyResource(transaction, document, vCollection, xmlUri); - - //Create metadata about the last Binary Version - sax.startElement(ELEMENT_REPLACED_XML, null); - sax.attribute(ATTRIBUTE_REF, xmlUri.toString()); - sax.endElement(ELEMENT_REPLACED_BINARY); - } else { - //Diff the XML versions - Diff diff = new StandardDiff(broker); - diff.diff(lastRev, document); - diff.diff2XML(sax); - } - - sax.endElement(ELEMENT_VERSION); - - sax.endDocument(); - String editscript = writer.toString(); - - if (removeLast) { - if(lastRev instanceof BinaryDocument) { - vCollection.removeBinaryResource(transaction, broker, lastRev.getFileURI()); - } else { - vCollection.removeXMLResource(transaction, broker, lastRev.getFileURI()); - } - } - - IndexInfo info = vCollection.validateXMLResource(transaction, broker, diffUri, editscript); - vCollection.store(transaction, broker, info, editscript, false); - } - } catch (Exception e) { + try(StringWriter writer = new StringWriter()) { + final SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject( + SAXSerializer.class); + final Properties outputProperties = new Properties(); + outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); + outputProperties.setProperty(OutputKeys.INDENT, "no"); + sax.setOutput(writer, outputProperties); + + sax.startDocument(); + sax.startElement(ELEMENT_VERSION, null); + writeProperties(sax, getVersionProperties(revision, documentPath, activeSubject)); + + if (event == REMOVE_DOCUMENT_EVENT) { + sax.startElement(ELEMENT_REMOVED, null); + sax.endElement(ELEMENT_REMOVED); + } else { + + //Diff + if (document instanceof BinaryDocument) { + //create a copy of the last Binary revision + final XmldbURI binUri = XmldbURI.create(diffUri.toString() + BINARY_SUFFIX); + broker.copyResource(transaction, document, vCollection, binUri); + + //Create metadata about the last Binary Version + sax.startElement(ELEMENT_REPLACED_BINARY, null); + sax.attribute(ATTRIBUTE_REF, binUri.toString()); + sax.endElement(ELEMENT_REPLACED_BINARY); + } else if (lastRev instanceof BinaryDocument) { + //create a copy of the last XML revision + final XmldbURI xmlUri = XmldbURI.create(diffUri.toString() + XML_SUFFIX); + broker.copyResource(transaction, document, vCollection, xmlUri); + + //Create metadata about the last Binary Version + sax.startElement(ELEMENT_REPLACED_XML, null); + sax.attribute(ATTRIBUTE_REF, xmlUri.toString()); + sax.endElement(ELEMENT_REPLACED_BINARY); + } else { + //Diff the XML versions + final Diff diff = new StandardDiff(broker); + diff.diff(lastRev, document); + diff.diff2XML(sax); + } + + sax.endElement(ELEMENT_VERSION); + + sax.endDocument(); + final String editscript = writer.toString(); + + if (removeLast) { + if (lastRev instanceof BinaryDocument) { + vCollection.removeBinaryResource(transaction, broker, lastRev.getFileURI()); + } else { + vCollection.removeXMLResource(transaction, broker, lastRev.getFileURI()); + } + } + + final IndexInfo info = vCollection.validateXMLResource(transaction, broker, diffUri, editscript); + vCollection.store(transaction, broker, info, editscript, false); + } + } + } catch (final Exception e) { LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e); } finally { vCollection.setTriggersEnabled(true); @@ -244,30 +243,31 @@ public void finish(int event, DBBroker broker, Txn transaction, XmldbURI documen } } - private void before(DBBroker broker, Txn transaction, DocumentImpl document, boolean remove) - throws TriggerException { + private void before(final DBBroker broker, final Txn transaction, final DocumentImpl document, final boolean remove) + throws TriggerException { this.documentPath = document.getURI(); - if (documentPath.startsWith(VERSIONS_COLLECTION)) - return; + if (documentPath.startsWith(VERSIONS_COLLECTION)) { + return; + } this.broker = broker; - Subject activeSubject = broker.getSubject(); + final Subject activeSubject = broker.getSubject(); try { broker.setSubject(broker.getBrokerPool().getSecurityManager().getSystemSubject()); - Collection collection = document.getCollection(); - if (collection.getURI().startsWith(VERSIONS_COLLECTION)) - return; + final Collection collection = document.getCollection(); + if (collection.getURI().startsWith(VERSIONS_COLLECTION)) { + return; + } vCollection = getVersionsCollection(broker, transaction, documentPath.removeLastSegment()); - String existingURI = document.getFileURI().toString(); - XmldbURI baseURI = XmldbURI.create(existingURI + BASE_SUFFIX); - DocumentImpl baseRev = vCollection.getDocument(broker, baseURI); - - String vFileName; + final String existingURI = document.getFileURI().toString(); + final XmldbURI baseURI = XmldbURI.create(existingURI + BASE_SUFFIX); + final DocumentImpl baseRev = vCollection.getDocument(broker, baseURI); + final String vFileName; if (baseRev == null) { vFileName = baseURI.toString(); removeLast = false; @@ -283,12 +283,12 @@ private void before(DBBroker broker, Txn transaction, DocumentImpl document, boo // setReferenced(true) will tell the broker that the document // data is referenced from another document and should not be - // deleted when the orignal document is removed. + // deleted when the original document is removed. document.getMetadata().setReferenced(true); if(document instanceof BinaryDocument) { - XmldbURI binUri = XmldbURI.createInternal(vFileName); + final XmldbURI binUri = XmldbURI.createInternal(vFileName); broker.copyResource(transaction, document, vCollection, binUri); vDoc = vCollection.getDocument(broker, binUri); } else { @@ -301,21 +301,22 @@ private void before(DBBroker broker, Txn transaction, DocumentImpl document, boo lastRev = vDoc; } - } catch (PermissionDeniedException e) { + } catch (final PermissionDeniedException e) { throw new TriggerException("Permission denied in VersioningTrigger: " + e.getMessage(), e); - } catch (Exception e) { + } catch (final Exception e) { LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e); } finally { broker.setSubject(activeSubject); } } - private void after(DBBroker broker, Txn transaction, DocumentImpl document, boolean remove) { - if (documentPath == null || documentPath.startsWith(VERSIONS_COLLECTION)) - return; - - Subject activeSubject = broker.getSubject(); + private void after(final DBBroker broker, final Txn transaction, final DocumentImpl document, + final boolean remove) { + if (documentPath == null || documentPath.startsWith(VERSIONS_COLLECTION)) { + return; + } + final Subject activeSubject = broker.getSubject(); try { broker.setSubject(broker.getBrokerPool().getSecurityManager().getSystemSubject()); @@ -323,94 +324,94 @@ private void after(DBBroker broker, Txn transaction, DocumentImpl document, bool try { vCollection = getVersionsCollection(broker, transaction, documentPath.removeLastSegment()); - String existingURI = document.getFileURI().toString(); - XmldbURI deletedURI = XmldbURI.create(existingURI + DELETED_SUFFIX); + final String existingURI = document.getFileURI().toString(); + final XmldbURI deletedURI = XmldbURI.create(existingURI + DELETED_SUFFIX); lastRev = vCollection.getDocument(broker, deletedURI); if (lastRev == null) { lastRev = vCollection.getDocument(broker, XmldbURI.create(existingURI + BASE_SUFFIX)); removeLast = false; - } else - removeLast = true; - } catch (IOException e) { + } else { + removeLast = true; + } + } catch (final IOException | TriggerException e) { LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e); - } catch (PermissionDeniedException e) { + } catch (final PermissionDeniedException e) { LOG.warn("Permission denied in VersioningTrigger: " + e.getMessage(), e); - } catch (TriggerException e) { - LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e); } - } + } if (lastRev != null || remove) { try { - long revision = newRevision(broker.getBrokerPool()); + final long revision = newRevision(broker.getBrokerPool()); if (documentPath.isCollectionPathAbsolute()) { documentPath = documentPath.lastSegment(); } - XmldbURI diffUri = XmldbURI.createInternal(documentPath.toString() + '.' + revision); + final XmldbURI diffUri = XmldbURI.createInternal(documentPath.toString() + '.' + revision); vCollection.setTriggersEnabled(false); - StringWriter writer = new StringWriter(); - SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject( - SAXSerializer.class); - Properties outputProperties = new Properties(); - outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); - outputProperties.setProperty(OutputKeys.INDENT, "no"); - sax.setOutput(writer, outputProperties); - - sax.startDocument(); - sax.startElement(ELEMENT_VERSION, null); - writeProperties(sax, getVersionProperties(revision, documentPath, activeSubject)); - - if (remove) { - sax.startElement(ELEMENT_REMOVED, null); - sax.endElement(ELEMENT_REMOVED); - } else { - - //Diff - if(document instanceof BinaryDocument) { - //create a copy of the last Binary revision - XmldbURI binUri = XmldbURI.create(diffUri.toString() + BINARY_SUFFIX); - broker.copyResource(transaction, document, vCollection, binUri); - - //Create metadata about the last Binary Version - sax.startElement(ELEMENT_REPLACED_BINARY, null); - sax.attribute(ATTRIBUTE_REF, binUri.toString()); - sax.endElement(ELEMENT_REPLACED_BINARY); - } else if(lastRev instanceof BinaryDocument) { - //create a copy of the last XML revision - XmldbURI xmlUri = XmldbURI.create(diffUri.toString() + XML_SUFFIX); - broker.copyResource(transaction, document, vCollection, xmlUri); - - //Create metadata about the last Binary Version - sax.startElement(ELEMENT_REPLACED_XML, null); - sax.attribute(ATTRIBUTE_REF, xmlUri.toString()); - sax.endElement(ELEMENT_REPLACED_XML); - } else { - //Diff the XML versions - Diff diff = new StandardDiff(broker); - diff.diff(lastRev, document); - diff.diff2XML(sax); - } - - sax.endElement(ELEMENT_VERSION); - - sax.endDocument(); - String editscript = writer.toString(); - - if (removeLast) { - if(lastRev instanceof BinaryDocument) { - vCollection.removeBinaryResource(transaction, broker, lastRev.getFileURI()); - } else { - vCollection.removeXMLResource(transaction, broker, lastRev.getFileURI()); - } - } - - IndexInfo info = vCollection.validateXMLResource(transaction, broker, diffUri, editscript); - vCollection.store(transaction, broker, info, editscript, false); - } - } catch (Exception e) { + try(final StringWriter writer = new StringWriter()) { + final SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject( + SAXSerializer.class); + final Properties outputProperties = new Properties(); + outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); + outputProperties.setProperty(OutputKeys.INDENT, "no"); + sax.setOutput(writer, outputProperties); + + sax.startDocument(); + sax.startElement(ELEMENT_VERSION, null); + writeProperties(sax, getVersionProperties(revision, documentPath, activeSubject)); + + if (remove) { + sax.startElement(ELEMENT_REMOVED, null); + sax.endElement(ELEMENT_REMOVED); + } else { + + //Diff + if (document instanceof BinaryDocument) { + //create a copy of the last Binary revision + final XmldbURI binUri = XmldbURI.create(diffUri.toString() + BINARY_SUFFIX); + broker.copyResource(transaction, document, vCollection, binUri); + + //Create metadata about the last Binary Version + sax.startElement(ELEMENT_REPLACED_BINARY, null); + sax.attribute(ATTRIBUTE_REF, binUri.toString()); + sax.endElement(ELEMENT_REPLACED_BINARY); + } else if (lastRev instanceof BinaryDocument) { + //create a copy of the last XML revision + final XmldbURI xmlUri = XmldbURI.create(diffUri.toString() + XML_SUFFIX); + broker.copyResource(transaction, document, vCollection, xmlUri); + + //Create metadata about the last Binary Version + sax.startElement(ELEMENT_REPLACED_XML, null); + sax.attribute(ATTRIBUTE_REF, xmlUri.toString()); + sax.endElement(ELEMENT_REPLACED_XML); + } else { + //Diff the XML versions + final Diff diff = new StandardDiff(broker); + diff.diff(lastRev, document); + diff.diff2XML(sax); + } + + sax.endElement(ELEMENT_VERSION); + + sax.endDocument(); + final String editscript = writer.toString(); + + if (removeLast) { + if (lastRev instanceof BinaryDocument) { + vCollection.removeBinaryResource(transaction, broker, lastRev.getFileURI()); + } else { + vCollection.removeXMLResource(transaction, broker, lastRev.getFileURI()); + } + } + + final IndexInfo info = vCollection.validateXMLResource(transaction, broker, diffUri, editscript); + vCollection.store(transaction, broker, info, editscript, false); + } + } + } catch (final Exception e) { LOG.warn("Caught exception in VersioningTrigger: " + e.getMessage(), e); } finally { vCollection.setTriggersEnabled(true); @@ -421,10 +422,9 @@ private void after(DBBroker broker, Txn transaction, DocumentImpl document, bool } } - private Properties getVersionProperties(long revision, XmldbURI documentPath, Account commitAccount) - throws XPathException { - Properties properties = new Properties(); - + private Properties getVersionProperties(final long revision, final XmldbURI documentPath, + final Account commitAccount) throws XPathException { + final Properties properties = new Properties(); properties.setProperty("document", documentPath.toString()); properties.setProperty("revision", Long.toString(revision)); properties.setProperty("date", new DateTimeValue(new Date()).getStringValue()); @@ -432,32 +432,29 @@ private Properties getVersionProperties(long revision, XmldbURI documentPath, Ac if (documentKey != null) { properties.setProperty("key", documentKey); } - return properties; } - public static void writeProperties(Receiver receiver, Properties properties) - throws SAXException { + public static void writeProperties(final Receiver receiver, final Properties properties) throws SAXException { receiver.startElement(PROPERTIES_ELEMENT, null); - - for (Entry entry : properties.entrySet()) { - QName qn = new QName((String)entry.getKey(), StandardDiff.NAMESPACE, StandardDiff.PREFIX); + for (final Entry entry : properties.entrySet()) { + final QName qn = new QName((String)entry.getKey(), StandardDiff.NAMESPACE, StandardDiff.PREFIX); receiver.startElement(qn, null); receiver.characters(entry.getValue().toString()); receiver.endElement(qn); } - receiver.endElement(PROPERTIES_ELEMENT); } - private Collection getVersionsCollection(DBBroker broker, Txn transaction, XmldbURI collectionPath) - throws IOException, PermissionDeniedException, TriggerException { - XmldbURI path = VERSIONS_COLLECTION.append(collectionPath); + private Collection getVersionsCollection(final DBBroker broker, final Txn transaction, + final XmldbURI collectionPath) throws IOException, PermissionDeniedException, TriggerException { + final XmldbURI path = VERSIONS_COLLECTION.append(collectionPath); Collection collection = broker.openCollection(path, Lock.WRITE_LOCK); if (collection == null) { - if(LOG.isDebugEnabled()) - LOG.debug("Creating versioning collection: " + path); + if(LOG.isDebugEnabled()) { + LOG.debug("Creating versioning collection: " + path); + } collection = broker.getOrCreateCollection(transaction, path); broker.saveCollection(transaction, collection); } else { @@ -467,99 +464,78 @@ private Collection getVersionsCollection(DBBroker broker, Txn transaction, Xmldb return collection; } - private long newRevision(BrokerPool pool) { - String dataDir = (String) pool.getConfiguration().getProperty(BrokerPool.PROPERTY_DATA_DIR); + private long newRevision(final BrokerPool pool) { + final String dataDir = (String) pool.getConfiguration().getProperty(BrokerPool.PROPERTY_DATA_DIR); synchronized (latch) { - File f = new File(dataDir, "versions.dbx"); + final Path f = Paths.get(dataDir, "versions.dbx"); long rev = 0; - if (f.canRead()) { - DataInputStream is = null; - try { - is = new DataInputStream(new FileInputStream(f)); + if (Files.isReadable(f)) { + try(final DataInputStream is = new DataInputStream(Files.newInputStream(f))) { rev = is.readLong(); - } catch (FileNotFoundException e) { + } catch (final IOException e) { LOG.warn("Failed to read versions.dbx: " + e.getMessage(), e); - } catch (IOException e) { - LOG.warn("Failed to read versions.dbx: " + e.getMessage(), e); - } finally { - if(is != null) { - try { - is.close(); - } catch(IOException ioe) { - LOG.warn("Failed to close InputStream for versions.dbx: " + ioe.getMessage(), ioe); - } - } } } ++rev; - - DataOutputStream os = null; - try { - os = new DataOutputStream(new FileOutputStream(f)); + try(final DataOutputStream os = new DataOutputStream(Files.newOutputStream(f))) { os.writeLong(rev); - } catch (FileNotFoundException e) { - LOG.warn("Failed to write versions.dbx: " + e.getMessage(), e); } catch (IOException e) { LOG.warn("Failed to write versions.dbx: " + e.getMessage(), e); - } finally { - if(os != null) { - try { - os.close(); - } catch(IOException ioe) { - LOG.warn("Failed to close OutputStream for versions.dbx: " + ioe.getMessage(), ioe); - } - } } - + return rev; } } - public void startElement(String namespaceURI, String localName, String qname, Attributes attributes) - throws SAXException { + @Override + public void startElement(final String namespaceURI, final String localName, final String qname, + Attributes attributes) throws SAXException { if (checkForConflicts && isValidating() && elementStack == 0) { for (int i = 0; i < attributes.getLength(); i++) { if (StandardDiff.NAMESPACE.equals(attributes.getURI(i))) { - String attrName = attributes.getLocalName(i); - if (VersioningFilter.ATTR_KEY.getLocalPart().equals(attrName)) - documentKey = attributes.getValue(i); - else if (VersioningFilter.ATTR_REVISION.getLocalPart().equals(attrName)) - documentRev = attributes.getValue(i); + final String attrName = attributes.getLocalName(i); + if (VersioningFilter.ATTR_KEY.getLocalPart().equals(attrName)) { + documentKey = attributes.getValue(i); + } else if (VersioningFilter.ATTR_REVISION.getLocalPart().equals(attrName)) { + documentRev = attributes.getValue(i); + } } } if (documentKey != null && documentRev != null) { - LOG.debug("v:key = " + documentKey + "; v:revision = " + documentRev); + if(LOG.isDebugEnabled()) { + LOG.debug("v:key = " + documentKey + "; v:revision = " + documentRev); + } + try { - long rev = Long.parseLong(documentRev); + final long rev = Long.parseLong(documentRev); if (VersioningHelper.newerRevisionExists(broker, documentPath, rev, documentKey)) { - long baseRev = VersioningHelper.getBaseRevision(broker, documentPath, rev, documentKey); - LOG.debug("base revision: " + baseRev); + final long baseRev = VersioningHelper.getBaseRevision(broker, documentPath, rev, documentKey); + if(LOG.isDebugEnabled()) { + LOG.debug("base revision: " + baseRev); + } throw new TriggerException("Possible version conflict detected for document: " + documentPath); } - } catch (XPathException e) { - LOG.warn("Internal error in VersioningTrigger: " + e.getMessage(), e); - } catch (IOException e) { + } catch (final XPathException | IOException | PermissionDeniedException e) { LOG.warn("Internal error in VersioningTrigger: " + e.getMessage(), e); - } catch (NumberFormatException e) { + } catch (final NumberFormatException e) { LOG.warn("Illegal revision number in VersioningTrigger: " + documentRev); - } catch (PermissionDeniedException e) { - LOG.warn("Internal error in VersioningTrigger: " + e.getMessage(), e); - } - } + } + } } if (elementStack == 0) { // Remove the versioning attributes which were inserted during serialization. We don't want // to store them in the db - AttributesImpl nattrs = new AttributesImpl(); + final AttributesImpl nattrs = new AttributesImpl(); for (int i = 0; i < attributes.getLength(); i++) { - if (!StandardDiff.NAMESPACE.equals(attributes.getURI(i))) - nattrs.addAttribute(attributes.getURI(i), attributes.getLocalName(i), - attributes.getQName(i), attributes.getType(i), attributes.getValue(i)); + if (!StandardDiff.NAMESPACE.equals(attributes.getURI(i))) { + nattrs.addAttribute(attributes.getURI(i), attributes.getLocalName(i), + attributes.getQName(i), attributes.getType(i), attributes.getValue(i)); + } } attributes = nattrs; } @@ -568,82 +544,86 @@ else if (VersioningFilter.ATTR_REVISION.getLocalPart().equals(attrName)) super.startElement(namespaceURI, localName, qname, attributes); } - public void endElement(String namespaceURI, String localName, String qname) - throws SAXException { + @Override + public void endElement(final String namespaceURI, final String localName, final String qname) throws SAXException { elementStack--; super.endElement(namespaceURI, localName, qname); } - public void startPrefixMapping(String prefix, String namespaceURI) - throws SAXException { - if (StandardDiff.NAMESPACE.equals(namespaceURI)) - return; + @Override + public void startPrefixMapping(final String prefix, final String namespaceURI) throws SAXException { + if (StandardDiff.NAMESPACE.equals(namespaceURI)) { + return; + } super.startPrefixMapping(prefix, namespaceURI); } @Override - public void beforeCreateDocument(DBBroker broker, Txn transaction, XmldbURI uri) throws TriggerException { + public void beforeCreateDocument(final DBBroker broker, final Txn transaction, final XmldbURI uri) + throws TriggerException { this.documentPath = uri; } @Override - public void afterCreateDocument(DBBroker broker, Txn transaction, DocumentImpl document) + public void afterCreateDocument(final DBBroker broker, final Txn transaction, final DocumentImpl document) throws TriggerException { after(broker, transaction, document, false); } @Override - public void beforeUpdateDocument(DBBroker broker, Txn transaction, DocumentImpl document) + public void beforeUpdateDocument(final DBBroker broker, final Txn transaction, final DocumentImpl document) throws TriggerException { before(broker, transaction, document, false); } @Override - public void afterUpdateDocument(DBBroker broker, Txn transaction, DocumentImpl document) + public void afterUpdateDocument(final DBBroker broker, final Txn transaction, final DocumentImpl document) throws TriggerException { after(broker, transaction, document, false); } @Override - public void beforeCopyDocument(DBBroker broker, Txn transaction, DocumentImpl document, XmldbURI newUri) - throws TriggerException { + public void beforeCopyDocument(final DBBroker broker, final Txn transaction, final DocumentImpl document, + final XmldbURI newUri) throws TriggerException { } @Override - public void afterCopyDocument(DBBroker broker, Txn transaction, DocumentImpl document, XmldbURI newUri) - throws TriggerException { + public void afterCopyDocument(final DBBroker broker, final Txn transaction, final DocumentImpl document, + final XmldbURI newUri) throws TriggerException { after(broker, transaction, document, false); } @Override - public void beforeMoveDocument(DBBroker broker, Txn transaction, DocumentImpl document, XmldbURI newUri) - throws TriggerException { + public void beforeMoveDocument(final DBBroker broker, final Txn transaction, final DocumentImpl document, + final XmldbURI newUri) throws TriggerException { before(broker, transaction, document, true); } @Override - public void afterMoveDocument(DBBroker broker, Txn transaction, DocumentImpl document, XmldbURI oldUri) - throws TriggerException { - after(broker, transaction, null, true); //TODO: check + public void afterMoveDocument(final DBBroker broker, final Txn transaction, final DocumentImpl document, + final XmldbURI oldUri) throws TriggerException { + after(broker, transaction, null, true); } @Override - public void beforeDeleteDocument(DBBroker broker, Txn transaction, DocumentImpl document) - throws TriggerException { + public void beforeDeleteDocument(final DBBroker broker, final Txn transaction, final DocumentImpl document) + throws TriggerException { before(broker, transaction, document, true); } @Override - public void afterDeleteDocument(DBBroker broker, Txn transaction, XmldbURI uri) - throws TriggerException { - after(broker, transaction, null, true); //TODO: check + public void afterDeleteDocument(final DBBroker broker, final Txn transaction, final XmldbURI uri) + throws TriggerException { + after(broker, transaction, null, true); } @Override - public void beforeUpdateDocumentMetadata(DBBroker broker, Txn txn, DocumentImpl document) throws TriggerException { + public void beforeUpdateDocumentMetadata(final DBBroker broker, final Txn txn, final DocumentImpl document) + throws TriggerException { } @Override - public void afterUpdateDocumentMetadata(DBBroker broker, Txn txn, DocumentImpl document) throws TriggerException { + public void afterUpdateDocumentMetadata(final DBBroker broker, final Txn txn, final DocumentImpl document) + throws TriggerException { } } \ No newline at end of file diff --git a/src/main/java/org/exist/versioning/xquery/DiffFunction.java b/src/main/java/org/exist/versioning/xquery/DiffFunction.java index 6cd5d9e..efa50af 100644 --- a/src/main/java/org/exist/versioning/xquery/DiffFunction.java +++ b/src/main/java/org/exist/versioning/xquery/DiffFunction.java @@ -1,23 +1,21 @@ -/* - * eXist Open Source Native XML Database - * Copyright (C) 2001-07 The eXist Project - * http://exist-db.org +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * $Id$ + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.exist.versioning.xquery; @@ -61,41 +59,41 @@ public class DiffFunction extends BasicFunction { new SequenceType( Type.NODE, Cardinality.EXACTLY_ONE ) ); - public DiffFunction(XQueryContext context) { + public DiffFunction(final XQueryContext context) { super(context, signature); } - public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException { - NodeValue nv1 = (NodeValue) args[0].itemAt(0); - NodeValue nv2 = (NodeValue) args[1].itemAt(0); + @Override + public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException { + final NodeValue nv1 = (NodeValue) args[0].itemAt(0); + final NodeValue nv2 = (NodeValue) args[1].itemAt(0); if (nv1.getImplementationType() != NodeValue.PERSISTENT_NODE || - nv2.getImplementationType() != NodeValue.PERSISTENT_NODE) + nv2.getImplementationType() != NodeValue.PERSISTENT_NODE) { throw new XPathException(this, "diff function only works on persistent documents stored in the db"); - DocumentImpl doc1 = ((NodeProxy)nv1).getOwnerDocument(); - DocumentImpl doc2 = ((NodeProxy)nv2).getOwnerDocument(); + } + final DocumentImpl doc1 = ((NodeProxy)nv1).getOwnerDocument(); + final DocumentImpl doc2 = ((NodeProxy)nv2).getOwnerDocument(); context.pushDocumentContext(); try { - MemTreeBuilder builder = context.getDocumentBuilder(); - DocumentBuilderReceiver receiver = new DocumentBuilderReceiver(builder); - Properties properties = new Properties(); + final MemTreeBuilder builder = context.getDocumentBuilder(); + final DocumentBuilderReceiver receiver = new DocumentBuilderReceiver(builder); + final Properties properties = new Properties(); properties.setProperty("document", doc1.getURI().toString()); properties.setProperty("revision", ""); properties.setProperty("date", new DateTimeValue(new Date()).getStringValue()); properties.setProperty("user", context.getUser().getName()); - int nodeNr = builder.startElement(VersioningTrigger.ELEMENT_VERSION, null); + final int nodeNr = builder.startElement(VersioningTrigger.ELEMENT_VERSION, null); VersioningTrigger.writeProperties(receiver, properties); - Diff diff = new StandardDiff(context.getBroker()); + final Diff diff = new StandardDiff(context.getBroker()); diff.diff(doc1, doc2); diff.diff2XML(receiver); builder.endElement(); return builder.getDocument().getNode(nodeNr); - } catch (SAXException e) { - throw new XPathException(this, "Caugt error while generating diff: " + e.getMessage(), e); - } catch (DiffException e) { + } catch (final SAXException | DiffException e) { throw new XPathException(this, "Caugt error while generating diff: " + e.getMessage(), e); } finally { context.popDocumentContext(); diff --git a/src/main/java/org/exist/versioning/xquery/PatchFunction.java b/src/main/java/org/exist/versioning/xquery/PatchFunction.java index dbd07e2..b9c70dc 100644 --- a/src/main/java/org/exist/versioning/xquery/PatchFunction.java +++ b/src/main/java/org/exist/versioning/xquery/PatchFunction.java @@ -1,23 +1,21 @@ -/* - * eXist Open Source Native XML Database - * Copyright (C) 2001-07 The eXist Project - * http://exist-db.org +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * $Id$ + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.exist.versioning.xquery; @@ -74,43 +72,48 @@ public class PatchFunction extends BasicFunction { ) }; - public PatchFunction(XQueryContext context, FunctionSignature signature) { + public PatchFunction(final XQueryContext context, final FunctionSignature signature) { super(context, signature); } - public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException { + @Override + public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException { context.pushDocumentContext(); try { - ExtendedXMLStreamReader reader; NodeValue nv = (NodeValue) args[0].itemAt(0); - if (nv.getImplementationType() == NodeValue.IN_MEMORY_NODE) { - NodeImpl node = (NodeImpl) nv; - reader = new InMemoryXMLStreamReader(node.getOwnerDocument(), node.getOwnerDocument()); - } else { - NodeProxy proxy = (NodeProxy) nv; - reader = context.getBroker().newXMLStreamReader(new NodeProxy(proxy.getOwnerDocument(), NodeId.DOCUMENT_NODE, proxy.getOwnerDocument().getFirstChildAddress()), false); - } + ExtendedXMLStreamReader reader = null; + try { + if (nv.getImplementationType() == NodeValue.IN_MEMORY_NODE) { + final NodeImpl node = (NodeImpl) nv; + reader = new InMemoryXMLStreamReader(node.getOwnerDocument(), node.getOwnerDocument()); + } else { + final NodeProxy proxy = (NodeProxy) nv; + reader = context.getBroker().newXMLStreamReader(new NodeProxy(proxy.getOwnerDocument(), NodeId.DOCUMENT_NODE, proxy.getOwnerDocument().getFirstChildAddress()), false); + } - nv = (NodeValue) args[1].itemAt(0); - if (nv.getImplementationType() == NodeValue.IN_MEMORY_NODE) - throw new XPathException("patch cannot be applied to in-memory documents"); - NodeProxy diffProxy = (NodeProxy) nv; - DocumentImpl diff = diffProxy.getOwnerDocument(); - - MemTreeBuilder builder = context.getDocumentBuilder(); - DocumentBuilderReceiver receiver = new DocumentBuilderReceiver(builder); - Patch patch = new Patch(context.getBroker(), diff); - if (isCalledAs("annotate")) - patch.annotate(reader, receiver); - else - patch.patch(reader, receiver); - NodeValue result = (NodeValue) builder.getDocument().getDocumentElement(); - return result == null ? Sequence.EMPTY_SEQUENCE : result; - } catch (IOException e) { - throw new XPathException(this, e.getMessage(), e); - } catch (XMLStreamException e) { - throw new XPathException(this, e.getMessage(), e); - } catch (DiffException e) { + nv = (NodeValue) args[1].itemAt(0); + if (nv.getImplementationType() == NodeValue.IN_MEMORY_NODE) { + throw new XPathException("patch cannot be applied to in-memory documents"); + } + final NodeProxy diffProxy = (NodeProxy) nv; + final DocumentImpl diff = diffProxy.getOwnerDocument(); + + final MemTreeBuilder builder = context.getDocumentBuilder(); + final DocumentBuilderReceiver receiver = new DocumentBuilderReceiver(builder); + final Patch patch = new Patch(context.getBroker(), diff); + if (isCalledAs("annotate")) { + patch.annotate(reader, receiver); + } else { + patch.patch(reader, receiver); + } + final NodeValue result = (NodeValue) builder.getDocument().getDocumentElement(); + return result == null ? Sequence.EMPTY_SEQUENCE : result; + } finally { + if(reader != null) { + reader.close(); + } + } + } catch (IOException | XMLStreamException | DiffException e) { throw new XPathException(this, e.getMessage(), e); } finally { context.popDocumentContext(); diff --git a/src/main/java/org/exist/versioning/xquery/VersioningModule.java b/src/main/java/org/exist/versioning/xquery/VersioningModule.java index a97b4e6..9b3ada9 100644 --- a/src/main/java/org/exist/versioning/xquery/VersioningModule.java +++ b/src/main/java/org/exist/versioning/xquery/VersioningModule.java @@ -1,23 +1,21 @@ -/* - * eXist Open Source Native XML Database - * Copyright (C) 2008-2009 The eXist Project - * http://exist-db.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. +/** + * Versioning Module for eXist-db XQuery + * Copyright (C) 2008 eXist-db + * http://exist-db.org * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * $Id$ + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.exist.versioning.xquery; @@ -49,24 +47,27 @@ public class VersioningModule extends AbstractInternalModule { new FunctionDef(DiffFunction.signature, DiffFunction.class) }; - public VersioningModule(Map> parameters) { + public VersioningModule(final Map> parameters) { super(functions, parameters); } + @Override public String getNamespaceURI() { return NAMESPACE_URI; } + @Override public String getDefaultPrefix() { return PREFIX; } + @Override public String getDescription() { return "A module for versioning of XML documents."; } - public String getReleaseVersion() { + @Override + public String getReleaseVersion() { return RELEASED_IN_VERSION; } - } diff --git a/src/main/resources/exist.xml b/src/main/resources/exist.xml deleted file mode 100644 index 409d2f3..0000000 --- a/src/main/resources/exist.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - @app.name@-@app.version@.jar - - http://exist-db.org/xquery/versioning - org.exist.versioning.xquery.VersioningModule - - - diff --git a/src/main/resources/expath-pkg.xml b/src/main/resources/expath-pkg.xml deleted file mode 100644 index 0f7ba5c..0000000 --- a/src/main/resources/expath-pkg.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - @app.title@ - - diff --git a/src/main/resources/repo.xml b/src/main/resources/repo.xml deleted file mode 100644 index 03e9e3b..0000000 --- a/src/main/resources/repo.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - @app.title@ - tobias AT existsolutions.com - - http://www.exist-db.com - alpha - GPL - true - libary - \ No newline at end of file diff --git a/src/main/java/org/exist/versioning/xquery/versioning.xqm b/src/main/xquery/versioning.xqm similarity index 90% rename from src/main/java/org/exist/versioning/xquery/versioning.xqm rename to src/main/xquery/versioning.xqm index 5876f37..7a6ebd3 100644 --- a/src/main/java/org/exist/versioning/xquery/versioning.xqm +++ b/src/main/xquery/versioning.xqm @@ -1,3 +1,22 @@ +(: + : Versioning Module for eXist-db XQuery + : Copyright (C) 2008 eXist-db + : http://exist-db.org + : + : This program is free software; you can redistribute it and/or modify + : it under the terms of the GNU General Public License as published by + : the Free Software Foundation; either version 1, or (at your option) + : any later version. + : + : This program is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + : GNU General Public License for more details. + : + : You should have received a copy of the GNU General Public License + : along with this program; if not, write to the Free Software + : Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + :) module namespace v="http://exist-db.org/versioning"; import module namespace version="http://exist-db.org/xquery/versioning" diff --git a/test/test.xml b/src/test/resources/test.xml similarity index 100% rename from test/test.xml rename to src/test/resources/test.xml diff --git a/test/test.xq b/src/test/xquery/test.xq similarity index 72% rename from test/test.xq rename to src/test/xquery/test.xq index 84e1b11..a349c97 100644 --- a/test/test.xq +++ b/src/test/xquery/test.xq @@ -1,3 +1,22 @@ +(: + : Versioning Module for eXist-db XQuery + : Copyright (C) 2008 eXist-db + : http://exist-db.org + : + : This program is free software; you can redistribute it and/or modify + : it under the terms of the GNU General Public License as published by + : the Free Software Foundation; either version 1, or (at your option) + : any later version. + : + : This program is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + : GNU General Public License for more details. + : + : You should have received a copy of the GNU General Public License + : along with this program; if not, write to the Free Software + : Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + :) xquery version "1.0"; import module namespace xdb="http://exist-db.org/xquery/xmldb"; diff --git a/xar-assembly.xml b/xar-assembly.xml new file mode 100644 index 0000000..c802547 --- /dev/null +++ b/xar-assembly.xml @@ -0,0 +1,38 @@ + + + ${package-title} + eXist-db + ${project.url} + GNU General Public License, version 1 + true + library + stable + ${project.artifactId} + library + versioning + Libraries + eXist extensions + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + com.bmsi + gnudiff + ${gnudiff.version} + + + + + ${basedir}/src/main/xquery + + versioning.xqm + + content + + + diff --git a/xquery-license-style.xml b/xquery-license-style.xml new file mode 100644 index 0000000..5db109a --- /dev/null +++ b/xquery-license-style.xml @@ -0,0 +1,15 @@ + + + + (: + : + :) + EOL + + "(\\s|\\t)*/\\*.*$" + ".*\\*/(\\s|\\t)*$" + false + true + false + + \ No newline at end of file