summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberto Ruiz <alberto.ruiz@sun.com>2007-10-30 17:21:07 +0000
committerAlberto Ruiz <alberto.ruiz@sun.com>2007-10-30 17:21:07 +0000
commitaadeffb3f0716ffd231d1146d050847e3be355ee (patch)
tree9f2ed61a84a37fce5f154498023b28d6bfbf69bf
2007-30-10 Alberto Ruiz <alberto.ruiz@sun.com>
* Initial commit.
-rw-r--r--AUTHORS0
-rw-r--r--COPYING680
-rw-r--r--ChangeLog2
-rw-r--r--INSTALL44
-rw-r--r--Makefile.am16
-rw-r--r--NEWS0
-rw-r--r--README0
-rw-r--r--apocd/Makefile.am16
-rw-r--r--apocd/apocd.c659
-rw-r--r--apocd/apocd.h97
-rw-r--r--apocd/config.h.in40
-rw-r--r--apocd/linux.c178
-rw-r--r--apocd/solaris.c178
-rw-r--r--apocd/win32/apocdctl.c1393
-rwxr-xr-xautogen.sh84
-rw-r--r--configure.ac287
-rwxr-xr-xinitd/apocd.in65
-rw-r--r--libapoc.pc.in13
-rw-r--r--libapoc/Makefile.am39
-rw-r--r--libapoc/config.h.in41
-rw-r--r--libapoc/papi.c128
-rw-r--r--libapoc/papi.h146
-rw-r--r--libapoc/papiConnection.c747
-rw-r--r--libapoc/papiConnection.h117
-rw-r--r--libapoc/papiDaemon.c516
-rw-r--r--libapoc/papiDaemon.h91
-rw-r--r--libapoc/papiDatabase.c285
-rw-r--r--libapoc/papiDatabase.h88
-rw-r--r--libapoc/papiEntityList.c92
-rw-r--r--libapoc/papiEntityList.h56
-rw-r--r--libapoc/papiInternal.c227
-rw-r--r--libapoc/papiInternal.h81
-rw-r--r--libapoc/papiLayerList.c104
-rw-r--r--libapoc/papiLayerList.h55
-rw-r--r--libapoc/papiListenerList.c131
-rw-r--r--libapoc/papiListenerList.h66
-rw-r--r--libapoc/papiMessage.c293
-rw-r--r--libapoc/papiMessage.h125
-rw-r--r--libapoc/papiPort.c457
-rw-r--r--libapoc/papiSAXParserContext.c182
-rw-r--r--libapoc/papiSAXParserContext.h74
-rw-r--r--libapoc/papiStringList.c176
-rw-r--r--libapoc/papiStringList.h61
-rw-r--r--libapoc/papiTypes.h96
-rw-r--r--libapoc/papiUtils.c662
-rw-r--r--libapoc/papiUtils.h167
-rw-r--r--libapoc/papitool.c521
-rw-r--r--libapoc/w32/Makefile55
-rw-r--r--libapoc/w32/Makefile.old110
-rwxr-xr-xlibapoc/w32/papiPort.c624
-rw-r--r--libfileaccess/FileAccess.c493
-rw-r--r--libfileaccess/FileAccess.h63
-rw-r--r--libfileaccess/Makefile.am7
-rw-r--r--m4/ac_check_class.m4107
-rw-r--r--m4/ac_check_classpath.m423
-rw-r--r--m4/ac_check_junit.m454
-rw-r--r--m4/ac_check_rqrd_class.m426
-rw-r--r--m4/ac_expand.m48
-rw-r--r--m4/ac_java_options.m432
-rw-r--r--m4/ac_jni_include_dirs.m4114
-rw-r--r--m4/ac_prog_jar.m436
-rw-r--r--m4/ac_prog_java.m479
-rw-r--r--m4/ac_prog_java_works.m497
-rw-r--r--m4/ac_prog_javac.m443
-rw-r--r--m4/ac_prog_javac_works.m435
-rw-r--r--m4/ac_prog_javadoc.m437
-rw-r--r--m4/ac_prog_javah.m426
-rw-r--r--m4/ac_try_compile_java.m439
-rw-r--r--m4/ac_try_run_javac.m440
-rwxr-xr-xsmf/apocd.xml.in75
-rw-r--r--src/Makefile.am1
-rw-r--r--src/com/Makefile.am1
-rw-r--r--src/com/sun/Makefile.am1
-rw-r--r--src/com/sun/apoc/Makefile.am1
-rw-r--r--src/com/sun/apoc/daemon/Makefile.am5
-rw-r--r--src/com/sun/apoc/daemon/admin/AdminManager.java286
-rw-r--r--src/com/sun/apoc/daemon/admin/AdminOpHandler.java43
-rw-r--r--src/com/sun/apoc/daemon/admin/PortMapper.java100
-rwxr-xr-xsrc/com/sun/apoc/daemon/apocd/Cache.java927
-rwxr-xr-xsrc/com/sun/apoc/daemon/apocd/CacheFactory.java151
-rwxr-xr-xsrc/com/sun/apoc/daemon/apocd/CacheReadResult.java47
-rw-r--r--src/com/sun/apoc/daemon/apocd/ChangeDetectEventHandler.java93
-rw-r--r--src/com/sun/apoc/daemon/apocd/Client.java148
-rw-r--r--src/com/sun/apoc/daemon/apocd/ClientEventHandler.java79
-rw-r--r--src/com/sun/apoc/daemon/apocd/ClientManager.java311
-rw-r--r--src/com/sun/apoc/daemon/apocd/Daemon.java209
-rw-r--r--src/com/sun/apoc/daemon/apocd/EventHandler.java42
-rw-r--r--src/com/sun/apoc/daemon/apocd/EventQueue.java100
-rw-r--r--src/com/sun/apoc/daemon/apocd/EventWorkerThread.java122
-rw-r--r--src/com/sun/apoc/daemon/apocd/EventWorkerThreadPool.java191
-rw-r--r--src/com/sun/apoc/daemon/apocd/GarbageCollectEventHandler.java56
-rw-r--r--src/com/sun/apoc/daemon/apocd/PolicyBackend.java366
-rw-r--r--src/com/sun/apoc/daemon/apocd/PolicyBackendFactory.java235
-rw-r--r--src/com/sun/apoc/daemon/apocd/SaslAuthCallbackHandler.java221
-rw-r--r--src/com/sun/apoc/daemon/apocd/Session.java335
-rw-r--r--src/com/sun/apoc/daemon/apocd/SessionListener.java42
-rw-r--r--src/com/sun/apoc/daemon/apocd/UpdateAggregator.java92
-rw-r--r--src/com/sun/apoc/daemon/build.xml.in87
-rw-r--r--src/com/sun/apoc/daemon/config/ConfigEventListener.java40
-rw-r--r--src/com/sun/apoc/daemon/config/DaemonConfig.java418
-rw-r--r--src/com/sun/apoc/daemon/config/LocalConfig.java79
-rw-r--r--src/com/sun/apoc/daemon/config/RemoteConfig.java198
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/Database.java365
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/LocalDatabase.java200
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/LocalDatabaseFactory.java460
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/SetDbt.java96
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/StringDbt.java70
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/Timestamp.java108
-rwxr-xr-xsrc/com/sun/apoc/daemon/localdatabase/UpdateItem.java75
-rw-r--r--src/com/sun/apoc/daemon/localdatabase/VectorStringDbt.java109
-rw-r--r--src/com/sun/apoc/daemon/messaging/AddListenerMessage.java133
-rw-r--r--src/com/sun/apoc/daemon/messaging/CreateSessionExtMessage.java111
-rw-r--r--src/com/sun/apoc/daemon/messaging/CreateSessionMessage.java134
-rw-r--r--src/com/sun/apoc/daemon/messaging/CredentialsProviderMessage.java41
-rw-r--r--src/com/sun/apoc/daemon/messaging/DestroySessionMessage.java65
-rw-r--r--src/com/sun/apoc/daemon/messaging/ListMessage.java65
-rw-r--r--src/com/sun/apoc/daemon/messaging/Message.java80
-rw-r--r--src/com/sun/apoc/daemon/messaging/MessageFactory.java113
-rw-r--r--src/com/sun/apoc/daemon/messaging/Messenger.java91
-rw-r--r--src/com/sun/apoc/daemon/messaging/Notification.java119
-rw-r--r--src/com/sun/apoc/daemon/messaging/ProtocolDeserialiser.java72
-rw-r--r--src/com/sun/apoc/daemon/messaging/ProtocolHandler.java103
-rw-r--r--src/com/sun/apoc/daemon/messaging/ProtocolUnbinder.java206
-rw-r--r--src/com/sun/apoc/daemon/messaging/ReadMessage.java109
-rw-r--r--src/com/sun/apoc/daemon/messaging/RemoveListenerMessage.java109
-rw-r--r--src/com/sun/apoc/daemon/messaging/RequestReceiver.java92
-rw-r--r--src/com/sun/apoc/daemon/messaging/Response.java109
-rw-r--r--src/com/sun/apoc/daemon/misc/APOCAuthenticator.java169
-rw-r--r--src/com/sun/apoc/daemon/misc/APOCException.java98
-rw-r--r--src/com/sun/apoc/daemon/misc/APOCLogger.java227
-rw-r--r--src/com/sun/apoc/daemon/misc/APOCSymbols.java246
-rw-r--r--src/com/sun/apoc/daemon/misc/ConfigurableLogger.java72
-rw-r--r--src/com/sun/apoc/daemon/misc/DaemonTimerTask.java110
-rw-r--r--src/com/sun/apoc/daemon/misc/FileAccess.java42
-rw-r--r--src/com/sun/apoc/daemon/misc/Name.java128
-rw-r--r--src/com/sun/apoc/daemon/properties/apocd.properties66
-rw-r--r--src/com/sun/apoc/daemon/properties/daemon.properties82
-rw-r--r--src/com/sun/apoc/daemon/properties/defaults.properties83
-rw-r--r--src/com/sun/apoc/daemon/properties/os.properties.in4
-rw-r--r--src/com/sun/apoc/daemon/properties/policymgr.properties9
-rw-r--r--src/com/sun/apoc/daemon/transaction/AddListenerTransaction.java58
-rw-r--r--src/com/sun/apoc/daemon/transaction/ChangeDetectTransaction.java128
-rw-r--r--src/com/sun/apoc/daemon/transaction/CreateSessionExtTransaction.java76
-rw-r--r--src/com/sun/apoc/daemon/transaction/CreateSessionTransaction.java81
-rw-r--r--src/com/sun/apoc/daemon/transaction/DestroySessionTransaction.java56
-rw-r--r--src/com/sun/apoc/daemon/transaction/GarbageCollectTransaction.java79
-rw-r--r--src/com/sun/apoc/daemon/transaction/ListTransaction.java82
-rw-r--r--src/com/sun/apoc/daemon/transaction/ReadTransaction.java86
-rw-r--r--src/com/sun/apoc/daemon/transaction/RemoveListenerTransaction.java57
-rw-r--r--src/com/sun/apoc/daemon/transaction/Transaction.java148
-rw-r--r--src/com/sun/apoc/daemon/transaction/TransactionFactory.java181
-rw-r--r--src/com/sun/apoc/daemon/transport/ChannelManager.java414
-rw-r--r--src/com/sun/apoc/daemon/transport/ClientChannel.java150
-rw-r--r--src/com/sun/apoc/daemon/transport/ClientChannelEventListener.java41
154 files changed, 23034 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/AUTHORS
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..b8a9e57
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,680 @@
+COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+
+1. Definitions.
+
+1.1. Contributor means each individual or entity that creates or
+contributes to the creation of Modifications.
+
+1.2. Contributor Version means the combination of the Original
+Software, prior Modifications used by a Contributor (if any),
+and the Modifications made by that particular Contributor.
+
+1.3. Covered Software means (a) the Original Software, or (b)
+Modifications, or (c) the combination of files containing
+Original Software with files containing Modifications, in each
+case including portions thereof.
+
+1.4. Executable means the Covered Software in any form other
+than Source Code.
+
+1.5. Initial Developer means the individual or entity that first
+makes Original Software available under this License.
+
+1.6. Larger Workmeans a work which combines Covered Software or
+portions thereof with code not governed by the terms of this
+License.
+
+1.7. License means this document.
+
+1.8. Licensable means having the right to grant, to the maximum
+extent possible, whether at the time of the initial grant or
+subsequently acquired, any and all of the rights conveyed herein.
+
+1.9. Modifications means the Source Code and Executable form of
+any of the following: A. Any file that results from an addition
+to, deletion from or modification of the contents of a file
+containing Original Software or previous Modifications; B. Any
+new file that contains any part of the Original Software or
+previous Modification; or C. Any new file that is contributed or
+otherwise made available under the terms of this License.
+
+1.10. Original Software means the Source Code and Executable
+form of computer software code that is originally released under
+this License.
+
+1.11. Patent Claims means any patent claim(s), now owned or
+hereafter acquired, including without limitation, method,
+process, and apparatus claims, in any patent Licensable by
+grantor.
+
+1.12. Source Code means (a) the common form of computer software
+code in which modifications are made and (b) associated
+documentation included in or with such code.
+
+1.13. You (or Your) means an individual or a legal entity
+exercising rights under, and complying with all of the terms of,
+this License. For legal entities, You includes any entity which
+controls, is controlled by, or is under common control with You.
+For purposes of this definition, control means (a) the power,
+direct or indirect, to cause the direction or management of such
+entity, whether by contract or otherwise, or (b) ownership of
+more than fifty percent (50%) of the outstanding shares or
+beneficial ownership of such entity.
+
+2. License Grants.
+
+2.1. The Initial Developer Grant. Conditioned upon Your
+compliance with Section 3.1 below and subject to third party
+intellectual property claims, the Initial Developer hereby
+grants You a world-wide, royalty-free, non-exclusive license:
+
+(a) under intellectual property rights (other than patent or
+trademark) Licensable by Initial Developer, to use, reproduce,
+modify, display, perform, sublicense and distribute the Original
+Software (or portions thereof), with or without Modifications,
+and/or as part of a Larger Work; and
+
+(b) under Patent Claims infringed by the making, using or
+selling of Original Software, to make, have made, use, practice,
+sell, and offer for sale, and/or otherwise dispose of the
+Original Software (or portions thereof);
+
+(c) The licenses granted in Sections 2.1(a) and (b) are
+effective on the date Initial Developer first distributes or
+otherwise makes the Original Software available to a third party
+under the terms of this License;
+
+(d) Notwithstanding Section 2.1(b) above, no patent license is
+granted: (1) for code that You delete from the Original
+Software, or (2) for infringements caused by: (i) the
+modification of the Original Software, or (ii) the combination
+of the Original Software with other software or devices.
+
+2.2. Contributor Grant. Conditioned upon Your compliance with
+Section 3.1 below and subject to third party intellectual
+property claims, each Contributor hereby grants You a
+world-wide, royalty-free, non-exclusive license:
+
+(a) under intellectual property rights (other than patent or
+trademark) Licensable by Contributor to use, reproduce, modify,
+display, perform, sublicense and distribute the Modifications
+created by such Contributor (or portions thereof), either on an
+unmodified basis, with other Modifications, as Covered Software
+and/or as part of a Larger Work; and
+
+(b) under Patent Claims infringed by the making, using, or
+selling of Modifications made by that Contributor either alone
+and/or in combination with its Contributor Version (or portions
+of such combination), to make, use, sell, offer for sale, have
+made, and/or otherwise dispose of: (1) Modifications made by
+that Contributor (or portions thereof); and (2) the combination
+of Modifications made by that Contributor with its Contributor
+Version (or portions of such combination).
+
+(c) The licenses granted in Sections 2.2(a) and 2.2(b)
+areeffective on the date Contributor first distributes or
+otherwise makes the Modifications available to a third party.
+
+(d) Notwithstanding Section 2.2(b) above, no patent license is
+granted: (1) for any code that Contributor has deleted from the
+Contributor Version; (2) for infringements caused by: (i) third
+party modifications of Contributor Version, or (ii) the
+combination of Modifications made by that Contributor with other
+software (except as part of the Contributor Version) or other
+devices; or (3) under Patent Claims infringed by Covered
+Software in the absence of Modifications made by that
+Contributor.
+
+3. Distribution Obligations.
+
+3.1. Availability of Source Code. Any Covered Software that You
+distribute or otherwise make available in Executable form must
+also be made available in Source Code form and that Source Code
+form must be distributed only under the terms of this License.
+You must include a copy of this License with every copy of the
+Source Code form of the Covered Software You distribute or
+otherwise make available. You must inform recipients of any such
+Covered Software in Executable form as to how they can obtain
+such Covered Software in Source Code form in a reasonable manner
+on or through a medium customarily used for software exchange.
+
+3.2. Modifications. The Modifications that You create or to
+which You contribute are governed by the terms of this License.
+You represent that You believe Your Modifications are Your
+original creation(s) and/or You have sufficient rights to grant
+the rights conveyed by this License.
+
+3.3. Required Notices. You must include a notice in each of Your
+Modifications that identifies You as the Contributor of the
+Modification. You may not remove or alter any copyright, patent
+or trademark notices contained within the Covered Software, or
+any notices of licensing or any descriptive text giving
+attribution to any Contributor or the Initial Developer.
+
+3.4. Application of Additional Terms. You may not offer or
+impose any terms on any Covered Software in Source Code form
+that alters or restricts the applicable version of this License
+or the recipients rights hereunder. You may choose to offer, and
+to charge a fee for, warranty, support, indemnity or liability
+obligations to one or more recipients of Covered
+Software. However, you may do so only on Your own behalf, and
+not on behalf of the Initial Developer or any Contributor. You
+must make it absolutely clear that any such warranty, support,
+indemnity or liability obligation is offered by You alone, and
+You hereby agree to indemnify the Initial Developer and every
+Contributor for any liability incurred by the Initial Developer
+or such Contributor as a result of warranty, support, indemnity
+or liability terms You offer.
+
+3.5. Distribution of Executable Versions. You may distribute the
+Executable form of the Covered Software under the terms of this
+License or under the terms of a license of Your choice, which
+may contain terms different from this License, provided that You
+are in compliance with the terms of this License and that the
+license for the Executable form does not attempt to limit or
+alter the recipients rights in the Source Code form from the
+rights set forth in this License. If You distribute the Covered
+Software in Executable form under a different license, You must
+make it absolutely clear that any terms which differ from this
+License are offered by You alone, not by the Initial Developer
+or Contributor. You hereby agree to indemnify the Initial
+Developer and every Contributor for any liability incurred by
+the Initial Developer or such Contributor as a result of any
+such terms You offer.
+
+3.6. Larger Works. You may create a Larger Work by combining
+Covered Software with other code not governed by the terms of
+this License and distribute the Larger Work as a single product.
+In such a case, You must make sure the requirements of this
+License are fulfilled for the Covered Software.
+
+4. Versions of the License.
+
+4.1. New Versions. Sun Microsystems, Inc. is the initial license
+steward and may publish revised and/or new versions of this
+License from time to time. Each version will be given a
+distinguishing version number. Except as provided in Section
+4.3, no one other than the license steward has the right to
+modify this License.
+
+4.2. Effect of New Versions. You may always continue to use,
+distribute or otherwise make the Covered Software available
+under the terms of the version of the License under which You
+originally received the Covered Software. If the Initial
+Developer includes a notice in the Original Software prohibiting
+it from being distributed or otherwise made available under any
+subsequent version of the License, You must distribute and make
+the Covered Software available under the terms of the version of
+the License under which You originally received the Covered
+Software. Otherwise, You may also choose to use, distribute or
+otherwise make the Covered Software available under the terms of
+any subsequent version of the License published by the license
+steward.
+
+4.3. Modified Versions. When You are an Initial Developer and
+You want to create a new license for Your Original Software, You
+may create and use a modified version of this License if You:
+(a) rename the license and remove any references to the name of
+the license steward (except to note that the license differs
+from this License); and (b) otherwise make it clear that the
+license contains terms which differ from this License.
+
+5. DISCLAIMER OF WARRANTY. COVERED SOFTWARE IS PROVIDED UNDER
+THIS LICENSE ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY KIND,
+EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
+WARRANTIES THAT THE COVERED SOFTWARE IS FREE OF DEFECTS,
+MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE
+DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY
+OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING,
+REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN
+ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE
+IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+6. TERMINATION.
+
+6.1. This License and the rights granted hereunder will
+terminate automatically if You fail to comply with terms herein
+and fail to cure such breach within 30 days of becoming aware of
+the breach. Provisions which, by their nature, must remain in
+effect beyond the termination of this License shall survive.
+
+6.2. If You assert a patent infringement claim (excluding
+declaratory judgment actions) against Initial Developer or a
+Contributor (the Initial Developer or Contributor against whom
+You assert such claim is referred to as Participant) alleging
+that the Participant Software (meaning the Contributor Version
+where the Participant is a Contributor or the Original Software
+where the Participant is the Initial Developer) directly or
+indirectly infringes any patent, then any and all rights granted
+directly or indirectly to You by such Participant, the Initial
+Developer (if the Initial Developer is not the Participant) and
+all Contributors under Sections 2.1 and/or 2.2 of this License
+shall, upon 60 days notice from Participant terminate
+prospectively and automatically at the expiration of such 60 day
+notice period, unless if within such 60 day period You withdraw
+Your claim with respect to the Participant Software against such
+Participant either unilaterally or pursuant to a written
+agreement with Participant.
+
+6.3. In the event of termination under Sections 6.1 or 6.2
+above, all end user licenses that have been validly granted by
+You or any distributor hereunder prior to termination (excluding
+licenses granted to You by any distributor) shall survive
+termination.
+
+7. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO
+LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR
+OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER
+CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED SOFTWARE, OR ANY
+SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY
+INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOST
+PROFITS, LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR
+MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES,
+EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY
+OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO
+LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH
+PARTYS NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH
+LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR
+LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS
+EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+8. U.S. GOVERNMENT END USERS. The Covered Software is a
+commercial item, as that term is defined in 48 C.F.R. 2.101
+(Oct. 1995), consisting of commercial computer software (as that
+term is defined at 48 C.F.R. 252.227-7014(a)(1)) and commercial
+computer software documentation as such terms are used in 48
+C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and
+48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all
+U.S. Government End Users acquire Covered Software with only
+those rights set forth herein. This U.S. Government Rights
+clause is in lieu of, and supersedes, any other FAR, DFAR, or
+other clause or provision that addresses Government rights in
+computer software under this License.
+
+9. MISCELLANEOUS. This License represents the complete agreement
+concerning subject matter hereof. If any provision of this
+License is held to be unenforceable, such provision shall be
+reformed only to the extent necessary to make it enforceable.
+This License shall be governed by the law of the jurisdiction
+specified in a notice contained within the Original Software
+(except to the extent applicable law, if any, provides
+otherwise), excluding such jurisdictions conflict-of-law
+provisions. Any litigation relating to this License shall be
+subject to the jurisdiction of the courts located in the
+jurisdiction and venue specified in a notice contained within
+the Original Software, with the losing party responsible for
+costs, including, without limitation, court costs and reasonable
+attorneys fees and expenses. The application of the United
+Nations Convention on Contracts for the International Sale of
+Goods is expressly excluded. Any law or regulation which
+provides that the language of a contract shall be construed
+against the drafter shall not apply to this License. You agree
+that You alone are responsible for compliance with the United
+States export administration regulations (and the export control
+laws and regulation of any other countries) when You use,
+distribute or otherwise make available any Covered Software.
+
+10. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and
+the Contributors, each party is responsible for claims and
+damages arising, directly or indirectly, out of its utilization
+of rights under this License and You agree to work with Initial
+Developer and Contributors to distribute such responsibility on
+an equitable basis. Nothing herein is intended or shall be
+deemed to constitute any admission of liability.
+
+----------------------------------------------------------------
+
+NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND
+DISTRIBUTION LICENSE (CDDL): This code is released under the
+CDDL and shall be governed by the laws of the State of
+California (excluding conflict-of-law provisions). Any
+litigation relating to this License shall be subject to the
+jurisdiction of the Federal Courts of the Northern District of
+California and the state courts of the State of California, with
+venue lying in Santa Clara County, California.
+
+----------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
+
+ GNU GENERAL PUBLIC LICENSE
+ 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.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 2 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..7c0a25a
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,2 @@
+2007-30-10 Alberto Ruiz <alberto.ruiz@sun.com>
+ * Initial commit.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..d294c00
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,44 @@
+-------------------
+- Desktop Agent -
+-------------------
+
+The following steps should be completed in the agent sub directory of the root path of the source code.
+
+Before to continue, make sure you have all the dependencies requeried by this package:
+
+ * The APOC SPI
+ * Berkeley DB (v4.2) library Java bindings
+ * Heimdall Generic Security Service libraries and headers
+ * LibXML2 libraries and headers
+
+ Step 1: Generating the configure script
+-----------------------------------------
+
+NOTE: Tarball releases already include a configure script so this step is unnecessary in that case.
+
+Type this to generate the configure script:
+
+$ ./autogen.sh --help
+
+ Step 2: Calling the configure script
+--------------------------------------
+
+In the root path of the source code, you should execute the configure script. For more information on changing the default paths, execute configure with the --help option.
+
+$ ./configure --prefix=/usr --with-bdb-path=/path/to/db.jar
+
+NOTE: You should use the same prefix than the SPI. The db.jar would be looked by default on /usr/share/lib/apoc/db.jar, it can be located elsewhere, use the --with-bdb-path option used in the example for any other location.
+
+ Step 3: Building the sources
+------------------------------
+
+If the configuration ends successfully, then you should build and install the sources:
+
+$ make
+$ make install
+
+
+ Post Installation
+-------------------
+
+To start the daemon the build generates an init.d script (initd/apocd) that should be installed manually. An SMF manifest for SOLARIS is generated and installed under the prefix directory as svc/manifest/network/apocd.xml, the SMF database should be updated manually.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..315abd7
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,16 @@
+SUBDIRS = libfileaccess libapoc apocd src
+
+apocddir=$(APOCDIR)
+apocd_DATA=build/class/apocd.jar
+
+configdir=$(sysconfdir)
+config_DATA= \
+ src/com/sun/apoc/daemon/properties/apocd.properties \
+ src/com/sun/apoc/daemon/properties/os.properties \
+ src/com/sun/apoc/daemon/properties/policymgr.properties
+
+
+if SOLARIS
+smfdir=$(localstatedir)/svc/manifest/network
+smf_DATA=smf/apocd.xml
+endif
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README
diff --git a/apocd/Makefile.am b/apocd/Makefile.am
new file mode 100644
index 0000000..cd07fc2
--- /dev/null
+++ b/apocd/Makefile.am
@@ -0,0 +1,16 @@
+INCLUDES = \
+ -I${top_builddir}/libapoc/
+
+apocd_LDADD = ${top_builddir}/libapoc/libapoc.la -lapoc
+
+bindir = $(APOCD_DIR)
+bin_PROGRAMS = apocd
+
+apocd_SOURCES = apocd.c
+
+if SOLARIS
+apocd_SOURCES += solaris.c
+else
+apocd_SOURCES += linux.c
+endif
+
diff --git a/apocd/apocd.c b/apocd/apocd.c
new file mode 100644
index 0000000..f6c6505
--- /dev/null
+++ b/apocd/apocd.c
@@ -0,0 +1,659 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#include "apocd.h"
+#include "config.h"
+
+#include <papiUtils.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+static int authenticate( PAPISocket inSocket );
+static Status daemonChangeDetect( void );
+static Status daemonReload( void );
+static Status daemonRequest( DaemonOp inOp, int inQuiet );
+static Status daemonRestart( void );
+static Status doOp( DaemonOp inOp );
+static int getDaemonAdminPort( void );
+static int getResponse( int inSocket, char * outResponse );
+static void invalidArg( const char * inArg );
+static Status javaStart( int inWait );
+static void putEnv( void );
+static int sendRequest( int inSocket, const unsigned char * inRequest );
+static DaemonOp stringToDaemonOp( const char * inString );
+static void usage( void );
+
+static const char * sArgChangeDetect = "change-detect";
+static const char * sArgDisable = "disable";
+static const char * sArgEnable = "enable";
+static const char * sArgIsEnabled = "is-enabled";
+static const char * sArgReload = "reload";
+static const char * sArgRestart = "restart";
+static const char * sArgStart = "start";
+static const char * sArgStatus = "status";
+static const char * sArgStop = "stop";
+static const char * sArgsvcStart = "svcStart";
+static const char * sArgsvcStop = "svcStop";
+
+int main( int inArgc, char ** inArgv )
+{
+ Status theRC;
+
+ if ( inArgc == 2 )
+ {
+ DaemonOp theOp = stringToDaemonOp( inArgv[ 1 ] );
+ if ( theOp == sOpUndefined )
+ {
+ invalidArg( inArgv[ 1 ] );
+ theRC = sErrorInvalidArg;
+ }
+ else
+ {
+ theRC = doOp( theOp );
+ }
+ }
+ else
+ {
+ usage();
+ theRC = sErrorInvalidArg;
+ }
+ return theRC;
+}
+
+Status daemonStart( void )
+{
+ Status theRC = daemonStatus( 1 );
+ writeInitialMessage( sOpStart );
+ if ( theRC == sStatusNotRunning )
+ {
+#ifndef LINUX
+ theRC = javaStart( 0 );
+ if ( theRC == sStatusOK )
+ {
+ theRC = daemonWaitStatus( sStatusOK, 30 );
+ }
+#else
+ if ( fork() == 0 )
+ {
+ while ( 1 )
+ {
+ theRC = javaStart( 1 );
+ if ( theRC == sStatusOK )
+ {
+ break;
+ }
+ if ( osDaemonShouldRestart() == 0 )
+ {
+ theRC = sErrorGeneric;
+ break;
+ }
+ }
+ return theRC;
+ }
+ else
+ {
+ theRC = daemonWaitStatus( sStatusOK, 30 );
+ }
+#endif
+ }
+ writeFinalMessage( sOpStart, theRC );
+ return theRC;
+}
+
+Status daemonStatus( int inQuiet )
+{
+ return daemonRequest( sOpStatus, inQuiet ) == sStatusOK ?
+ sStatusOK : sStatusNotRunning;
+}
+
+Status daemonStop( void )
+{
+ Status theRC;
+ writeInitialMessage( sOpStop );
+ daemonRequest( sOpStop, 1 );
+ theRC =
+ daemonWaitStatus( sStatusNotRunning, 20 ) == sStatusNotRunning ?
+ sStatusOK : sErrorGeneric;
+ writeFinalMessage( sOpStop, theRC );
+ return theRC;
+}
+
+Status daemonWaitStatus( Status inStatus, int inMaxIterations )
+{
+ Status theRC;
+ int theIteration = 0;
+
+ while ( ( theRC = daemonStatus( 1 ) ) != inStatus &&
+ ++ theIteration <= inMaxIterations )
+ {
+ papiSleep( 1 );
+ }
+ return theRC;
+}
+
+void writeInitialMessage( DaemonOp inOp )
+{
+ if ( inOp == sOpChangeDetect )
+ {
+ printf( "Requesting a Configuration Agent change detection ... " );
+ }
+ else if ( inOp == sOpDisable )
+ {
+ printf( "Disabling Configuration Agent ... ");
+ }
+ else if ( inOp == sOpEnable )
+ {
+ printf( "Enabling Configuration Agent ... ");
+ }
+ else if ( inOp == sOpIsEnabled )
+ {
+ printf( "Checking Configuration Agent enabled status ... " );
+ }
+ else if ( inOp == sOpReload )
+ {
+ printf( "Reloading Configuration Agent ... " );
+ }
+ else if ( inOp == sOpStatus )
+ {
+ printf( "Checking Configuration Agent status ... " );
+ }
+ else if ( inOp == sOpStart )
+ {
+ printf( "Starting Configuration Agent ... " );
+ }
+ else if ( inOp == sOpStop )
+ {
+ printf( "Stopping Configuration Agent ... " );
+ }
+ fflush( stdout );
+}
+
+void writeAlreadyMessage(DaemonOp inOp)
+{
+ const char *theMessage = NULL ;
+
+ switch (inOp) {
+ case sOpStart:
+ theMessage = "Already started" ;
+ break ;
+ case sOpStop:
+ theMessage = "Already stopped" ;
+ break ;
+ case sOpEnable:
+ theMessage = "Already enabled" ;
+ break ;
+ case sOpDisable:
+ theMessage = "Already disabled" ;
+ break ;
+ default:
+ break ;
+ }
+ if (theMessage != NULL) {
+ printf("%s\n", theMessage) ;
+ }
+}
+
+void writeFinalMessage( DaemonOp inOp, Status inStatus )
+{
+ if ( inStatus == sErrorAuthentication )
+ {
+ printf( "Failed\n" );
+ }
+ else if ( inOp == sOpIsEnabled )
+ {
+ printf( "%s\n", inStatus == sStatusEnabled ? "Enabled" : "Not enabled");
+ }
+ else if ( inOp == sOpStatus )
+ {
+ printf( "%s\n", inStatus == sStatusOK ? "Running" : "Not running" );
+ }
+ else if ( inOp == sOpStop )
+ {
+ printf( inStatus == sStatusOK || inStatus == sErrorNotRunning ?
+ "OK\n" : "Failed\n" );
+ }
+ else
+ {
+ printf( inStatus == sStatusOK ? "OK\n" : "Failed\n" );
+ }
+ fflush( stdout );
+}
+
+int authenticate( PAPISocket inSocket )
+{
+ static int sLocalCredentialsBufferSize = 21;
+
+ int theRC = sErrorAuthentication;
+ char theChallenge[ BUFSIZ ];
+ int theIndex = 0;
+
+ theChallenge[ 0 ] = 0;
+ while ( recv( inSocket, &theChallenge[ theIndex ++ ], 1, 0 ) != -1 )
+ {
+ if ( theChallenge[ theIndex - 1 ] == 0 )
+ {
+ if ( theChallenge[ 0 ] != 0 )
+ {
+ FILE * theFile = fopen( theChallenge, "r" );
+ if ( theFile != 0 )
+ {
+ char * theCredentials =
+ ( char * )malloc( sLocalCredentialsBufferSize );
+ if ( theCredentials != 0 )
+ {
+ if ( fgets( theCredentials,
+ sLocalCredentialsBufferSize,
+ theFile ) != 0 )
+ {
+ if ( send( inSocket,
+ theCredentials,
+ sLocalCredentialsBufferSize - 1,
+ 0 ) == ( sLocalCredentialsBufferSize - 1 ) )
+ {
+ char theResponse;
+ if ( getResponse(inSocket,&theResponse)!= -1 &&
+ theResponse == 0 )
+ {
+ theRC = sStatusOK;
+ }
+ }
+ }
+ free( ( void * )theCredentials );
+ }
+ fclose( theFile );
+ }
+ }
+ break;
+ }
+ }
+ return theRC;
+}
+
+Status daemonChangeDetect( void )
+{
+ return daemonRequest( sOpChangeDetect, 0 );
+}
+
+Status daemonReload( void )
+{
+ return daemonRequest( sOpReload, 0 );
+}
+
+Status daemonRequest( DaemonOp inOp, int inQuiet )
+{
+ Status theRC = sErrorNotRunning;
+ PAPISocket theSocket;
+ PAPIConnectResult theConnectResult =
+ getConnectedSocket( getDaemonAdminPort(), SOCK_STREAM, 0, &theSocket );
+ if ( inQuiet == 0 )
+ {
+ writeInitialMessage( inOp );
+ }
+ if ( theConnectResult == PAPIConnectSuccess )
+ {
+ if ( ( theRC = authenticate( theSocket ) ) == sStatusOK )
+ {
+ unsigned char theOp = ( unsigned char )inOp;
+ if ( sendRequest( theSocket, &theOp ) != -1 )
+ {
+ char theResponse;
+ if ( getResponse( theSocket, &theResponse ) == -1 )
+ {
+ theRC = sErrorNotRunning;
+ }
+ else if ( theResponse == 0 )
+ {
+ theRC = sStatusOK;
+ }
+ else
+ {
+ theRC = sErrorGeneric;
+ }
+ }
+ }
+ papiClose( theSocket );
+ }
+ if ( inQuiet == 0 )
+ {
+ writeFinalMessage( inOp, theRC );
+ }
+ return theRC;
+}
+
+Status daemonRestart( void )
+{
+ Status theRC = osDaemonStop();
+ if ( theRC == sStatusOK )
+ {
+ theRC = osDaemonStart();
+ }
+ return theRC;
+}
+
+static int checkAlreadyDone(DaemonOp inOp)
+{
+ int retCode = 0 ;
+
+ switch (inOp) {
+ case sOpStart:
+ if (daemonStatus(1) == sStatusRunning) { retCode = 1 ; }
+ break ;
+ case sOpStop:
+ if (daemonStatus(1) == sStatusNotRunning) { retCode = 1 ; }
+ break ;
+ case sOpEnable:
+ if (osDaemonIsEnabled(1) == sStatusEnabled) { retCode = 1 ; }
+ break ;
+ case sOpDisable:
+ if (osDaemonIsEnabled(1) == sStatusNotEnabled) { retCode = 1 ; }
+ break ;
+ default:
+ break ;
+ }
+ return retCode ;
+}
+
+Status doOp( DaemonOp inOp )
+{
+ Status theStatus = sErrorGeneric;
+
+ if (checkAlreadyDone(inOp)) {
+ writeInitialMessage(inOp) ;
+ writeAlreadyMessage(inOp) ;
+ return sStatusOK ;
+ }
+ /*
+ * Non os specific operations
+ */
+ if ( inOp == sOpChangeDetect )
+ {
+ theStatus = daemonChangeDetect();
+ }
+ else if ( inOp == sOpReload )
+ {
+ theStatus = daemonReload();
+ }
+ else if ( inOp == sOpRestart )
+ {
+ theStatus = daemonRestart();
+ }
+ else if ( inOp == sOpStatus )
+ {
+ theStatus = daemonStatus( 0 );
+ }
+
+ /*
+ * os specific operations
+ */
+ else if ( inOp == sOpDisable )
+ {
+ theStatus = osDaemonDisable();
+ }
+ else if ( inOp == sOpEnable )
+ {
+ theStatus = osDaemonEnable();
+ }
+ else if ( inOp == sOpIsEnabled )
+ {
+ theStatus = osDaemonIsEnabled(0);
+ }
+ else if ( inOp == sOpStart )
+ {
+ theStatus = osDaemonStart();
+ }
+ else if ( inOp == sOpStop )
+ {
+ theStatus = osDaemonStop();
+ }
+ else if ( inOp == sOpSvcStart )
+ {
+ theStatus = osDaemonSvcStart();
+ }
+ else if ( inOp == sOpSvcStop )
+ {
+ theStatus = osDaemonSvcStop();
+ }
+ return theStatus;
+}
+
+/*
+ * 6417539 - Need to use IANA registered port
+ *
+ * IANA has registered 3809 for us. We use a udp connection on this port to
+ * the daemon to ask what port is currently set as the admin port
+ */
+int getDaemonAdminPort( void )
+{
+ static char sByte = 1;
+ static const char * sLocalHostName = "127.0.0.1";
+
+ int thePort = -1;
+ PAPISocket theSocket;
+ char thePortString[ 6 ];
+ struct sockaddr_in theDaemonAddr;
+ struct hostent * theHostEnt;
+ int theCount;
+
+ theHostEnt = gethostbyname( sLocalHostName );
+ theDaemonAddr.sin_family = AF_INET;
+ theDaemonAddr.sin_port = htons( getDaemonPort() );
+ theDaemonAddr.sin_addr = *( (struct in_addr * )theHostEnt->h_addr );
+ memset( ( void * )&( theDaemonAddr.sin_zero ), 0, 8 );
+ if ( ( theSocket = socket( AF_INET, SOCK_DGRAM, 0 ) ) != INVALID_SOCKET &&
+ connect( theSocket,
+ ( struct sockaddr * )&theDaemonAddr,
+ sizeof( struct sockaddr ) ) == 0 &&
+ send( theSocket, &sByte, 1, 0 ) == 1 &&
+ ( theCount = recv( theSocket, thePortString, 6, 0 ) ) > 1 &&
+ thePortString[ theCount - 1 ] == 0 )
+ {
+ thePort = atoi( thePortString );
+ }
+ papiClose( theSocket );
+ return thePort;
+}
+
+int getResponse( int inSocket, char * outResponse )
+{
+ return recv( inSocket,
+ outResponse,
+ 1,
+ 0 );
+}
+
+void invalidArg( const char * inOp )
+{
+ if ( inOp != 0 )
+ {
+ fprintf( stderr, "Invalid argument '%s'\n", inOp );
+ }
+ usage();
+}
+
+Status javaStart( int inWait )
+{
+ static char * theFormat =
+ "java -Djava.library.path=%s%s%s -cp %s%sapocd.jar com.sun.apoc.daemon.apocd.Daemon %s %s";
+ static char * theCommand = 0;
+ Status theRC = sStatusOK;
+
+ putEnv();
+ if ( theCommand == 0 )
+ {
+ const char * theDaemonInstallDir = getDaemonInstallDir();
+ const char * theDaemonLibraryDir = getDaemonLibraryDir();
+ const char * theDaemonPropertiesDir = getDaemonPropertiesDir();
+ theCommand =
+ ( char * )malloc( ( strlen( theDaemonInstallDir ) * 2 ) +
+ strlen( theDaemonLibraryDir ) +
+ strlen( PATHSEP ) +
+ strlen( DBJAVA_LIBDIR ) +
+ strlen( theDaemonPropertiesDir ) +
+ strlen( FILESEP ) +
+ ( strlen( theFormat ) + 6 ));
+
+ if ( theCommand != 0 )
+ {
+ sprintf( theCommand,
+ theFormat,
+ theDaemonLibraryDir, PATHSEP,
+ DBJAVA_LIBDIR,
+ theDaemonInstallDir, FILESEP,
+ theDaemonInstallDir,
+ theDaemonPropertiesDir );
+ }
+ }
+ if ( theCommand != 0 )
+ {
+ FILE * theStream = papiPopen( theCommand, "r" );
+ if ( theStream == 0 )
+ {
+ theRC = sErrorGeneric;
+ }
+ else if ( inWait == 1 )
+ {
+ theRC = papiPclose( theStream ) == 0 ? sStatusOK : sErrorGeneric;
+ }
+ }
+ else
+ {
+ theRC = sErrorGeneric;
+ }
+ return theRC;
+}
+
+void putEnv( void )
+{
+ char * theJavaHome = getenv( "JAVA_HOME" );
+
+ if ( theJavaHome != 0 )
+ {
+ char * theJavaPath = ( char * )malloc( strlen( theJavaHome ) +
+ 4 +
+ strlen( FILESEP ) );
+ if ( theJavaPath != 0 )
+ {
+ char * thePath = getenv( "PATH" );
+ char * theNewPath;
+ sprintf( theJavaPath, "%s%sbin", theJavaHome, FILESEP );
+ theNewPath = ( char * )malloc( strlen( theJavaPath ) +
+ strlen( PATHSEP ) +
+ strlen( thePath ) +
+ 6 );
+ if ( theNewPath != 0 )
+ {
+ sprintf( theNewPath,
+ "PATH=%s%s%s",
+ theJavaPath,
+ PATHSEP,
+ thePath );
+ putenv( theNewPath );
+ free( ( void * )theJavaPath );
+ }
+ }
+ }
+ papiUmask( 022 );
+}
+
+int sendRequest( int inSocket,
+ const unsigned char * inRequest )
+{
+ return send( inSocket, inRequest, 1, 0 );
+}
+
+DaemonOp stringToDaemonOp( const char * inString )
+{
+ DaemonOp theDaemonOp = sOpUndefined;
+ if ( strcmp( inString, sArgChangeDetect ) == 0 )
+ {
+ theDaemonOp = sOpChangeDetect;
+ }
+ else if ( strcmp( inString, sArgDisable ) == 0 )
+ {
+ theDaemonOp = sOpDisable;
+ }
+ else if ( strcmp( inString, sArgEnable ) == 0 )
+ {
+ theDaemonOp = sOpEnable;
+ }
+ else if ( strcmp( inString, sArgIsEnabled ) == 0 )
+ {
+ theDaemonOp = sOpIsEnabled;
+ }
+ else if ( strcmp( inString, sArgReload ) == 0 )
+ {
+ theDaemonOp = sOpReload;
+ }
+ else if ( strcmp( inString, sArgRestart ) == 0 )
+ {
+ theDaemonOp = sOpRestart;
+ }
+ else if ( strcmp( inString, sArgStart ) == 0 )
+ {
+ theDaemonOp = sOpStart;
+ }
+ else if ( strcmp( inString, sArgStatus ) == 0 )
+ {
+ theDaemonOp = sOpStatus;
+ }
+ else if ( strcmp( inString, sArgStop ) == 0 )
+ {
+ theDaemonOp = sOpStop;
+ }
+ else if ( strcmp( inString, sArgsvcStart ) == 0 )
+ {
+ theDaemonOp = sOpSvcStart;
+ }
+ else if ( strcmp( inString, sArgsvcStop ) == 0 )
+ {
+ theDaemonOp = sOpSvcStop;
+ }
+ return theDaemonOp;
+}
+
+void usage( void )
+{
+ fprintf( stderr,
+ "%s",
+ "Usage: apocd change-detect | disable | enable | is-enabled | reload | restart | start | status | stop\n" );
+}
diff --git a/apocd/apocd.h b/apocd/apocd.h
new file mode 100644
index 0000000..7f9747e
--- /dev/null
+++ b/apocd/apocd.h
@@ -0,0 +1,97 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#ifndef _APOCD_H_
+#define _APOCD_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+ sOpUndefined,
+ sOpChangeDetect,
+ sOpDisable,
+ sOpEnable,
+ sDEPRECATED_OpInetdStart,
+ sOpIsEnabled,
+ sOpReload,
+ sOpRestart,
+ sOpStart,
+ sOpStatus,
+ sOpStop,
+ sOpSvcStart,
+ sOpSvcStop
+} DaemonOp;
+
+typedef enum
+{
+ sStatusOK = 0,
+ sStatusEnabled = 0,
+ sStatusRunning = 0,
+ sErrorGeneric = 1,
+ sStatusNotEnabled = 1,
+ sErrorInvalidArg,
+ sStatusNotRunning,
+ sErrorNotRunning,
+ sErrorAuthentication
+} Status;
+
+extern Status daemonStart( void );
+extern Status daemonStatus( int inQuiet );
+extern Status daemonStop( void );
+extern Status daemonWaitStatus( Status inStatus, int inMaxIterations );
+
+extern Status osDaemonDisable( void );
+extern Status osDaemonEnable( void );
+extern Status osDaemonIsEnabled( int inQuiet );
+extern Status osDaemonStart( void );
+extern Status osDaemonStop( void );
+extern Status osDaemonSvcStart( void );
+extern Status osDaemonSvcStop( void );
+#ifdef LINUX
+extern int osDaemonShouldRestart( void );
+#endif
+
+extern void writeInitialMessage( DaemonOp inOp );
+extern void writeFinalMessage( DaemonOp inOp, Status inStatus );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APOCD_H_ */
diff --git a/apocd/config.h.in b/apocd/config.h.in
new file mode 100644
index 0000000..e6c6da3
--- /dev/null
+++ b/apocd/config.h.in
@@ -0,0 +1,40 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#ifndef _HAVE_CONFIG_H
+#define _HAVE_CONFIG_H
+#define BDBJDK "@BDBJDK@"
+#define DBJAVA_LIBDIR "@DBJAVA_LIBDIR@"
+#endif
diff --git a/apocd/linux.c b/apocd/linux.c
new file mode 100644
index 0000000..f3b7752
--- /dev/null
+++ b/apocd/linux.c
@@ -0,0 +1,178 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#include "apocd.h"
+
+#include <papiUtils.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <time.h>
+#include <syslog.h>
+
+#define SCRIPT_DISABLE "#!/bin/sh\n \
+/sbin/chkconfig apocd off\n \
+exit $?\n"
+
+#define SCRIPT_ENABLE "#!/bin/sh\n \
+/sbin/chkconfig apocd on\n \
+exit $?\n"
+
+#define SCRIPT_ISENABLED "#!/bin/sh\n \
+/sbin/chkconfig -c apocd\n \
+exit $?\n"
+
+static int execute( const char * inCommand );
+
+Status osDaemonDisable( void )
+{
+ Status theRC;
+ writeInitialMessage( sOpDisable );
+ theRC = execute( SCRIPT_DISABLE ) == 0 ? sStatusOK : sErrorGeneric;
+ writeFinalMessage( sOpDisable, theRC );
+ if ( theRC == sStatusOK && daemonStatus( 1 ) == sStatusOK )
+ {
+ theRC = daemonStop();
+ }
+ return theRC;
+}
+
+Status osDaemonEnable( void )
+{
+ Status theRC;
+ writeInitialMessage( sOpEnable );
+ theRC = execute( SCRIPT_ENABLE ) == 0 ? sStatusOK : sErrorGeneric;
+ writeFinalMessage( sOpEnable, theRC );
+ if ( theRC == sStatusOK && daemonStatus( 1 ) != sStatusOK )
+ {
+ theRC = daemonStart();
+ }
+ return theRC;
+}
+
+Status osDaemonIsEnabled( inQuiet )
+{
+ Status theRC;
+ if (inQuiet == 0) { writeInitialMessage( sOpIsEnabled ); }
+ theRC = execute( SCRIPT_ISENABLED ) == 0 ?
+ sStatusEnabled : sStatusNotEnabled;
+ if (inQuiet == 0) { writeFinalMessage( sOpIsEnabled, theRC ); }
+ return theRC;
+}
+
+int osDaemonShouldRestart( void )
+{
+ static int sFailureIndex = 0;
+ static time_t sFailureTimes[ 4 ];
+ time_t theFailureTime = time( 0 );
+ int bShouldRestart = 1;
+
+ if ( sFailureIndex == 4 )
+ {
+ if ( theFailureTime - sFailureTimes[ 0 ] < 60 )
+ {
+ bShouldRestart = 0;
+ }
+ else
+ {
+ sFailureTimes[ 0 ] = sFailureTimes[ 1 ];
+ sFailureTimes[ 1 ] = sFailureTimes[ 2 ];
+ sFailureTimes[ 2 ] = sFailureTimes[ 3 ];
+ sFailureTimes[ 3 ] = theFailureTime;
+ }
+ }
+ else
+ {
+ sFailureTimes[ sFailureIndex ++ ] = theFailureTime;
+ }
+ if ( bShouldRestart == 0 )
+ {
+ syslog( LOG_WARNING, "Too many Configuration Agent failures in the last 60 seconds. Not restarting." );
+ }
+ return bShouldRestart;
+}
+
+Status osDaemonStart( void )
+{
+ return daemonStart();
+}
+
+Status osDaemonStop( void )
+{
+ return daemonStop();
+}
+
+Status osDaemonSvcStart( void )
+{
+ close( 0 ); close( 1 ); close( 2 );
+ return daemonStart();
+}
+
+Status osDaemonSvcStop( void )
+{
+ return daemonStop();
+}
+
+
+int execute( const char * inCommand )
+{
+ int theRC = -1;
+ char * theFileName = tmpnam( 0 );
+ FILE * theFile = fopen( theFileName, "w" );
+
+ if ( theFile != 0 )
+ {
+ char theBuf[ BUFSIZ ];
+
+ fprintf( theFile, "%s", inCommand );
+ fclose( theFile );
+ chmod( theFileName, 0700 );
+
+ theFile = papiPopen( theFileName, "r" );
+ if ( theFile != 0 )
+ {
+ while ( 1 )
+ {
+ if ( fgets( theBuf, BUFSIZ, theFile ) == 0 )
+ {
+ break;
+ }
+ }
+ theRC = papiPclose( theFile );
+ unlink( theFileName );
+ }
+ }
+ return theRC;
+}
diff --git a/apocd/solaris.c b/apocd/solaris.c
new file mode 100644
index 0000000..4552a49
--- /dev/null
+++ b/apocd/solaris.c
@@ -0,0 +1,178 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#include "apocd.h"
+
+#include <libscf.h>
+#include <stdlib.h>
+#include <string.h>
+
+static const char * sInstanceName = "svc:/network/apocd/udp:default";
+
+static Status osEnabler( int inEnable, int inOneTime, int inQuiet );
+
+Status osDaemonDisable( void )
+{
+ return osEnabler( 0, 0, 0 );
+}
+
+Status osDaemonEnable( void )
+{
+ return osEnabler( 1, 0, 0 );
+}
+
+Status osDaemonIsEnabled( int inQuiet )
+{
+ Status isEnabled = sStatusNotEnabled;
+ scf_handle_t * theHandle = scf_handle_create( SCF_VERSION );
+ if (inQuiet == 0) { writeInitialMessage( sOpIsEnabled ); }
+ if ( theHandle != 0 )
+ {
+ if ( scf_handle_bind( theHandle ) == 0 )
+ {
+ scf_instance_t * theInstance = scf_instance_create( theHandle );
+ if ( theInstance != 0 )
+ {
+ if ( scf_handle_decode_fmri(
+ theHandle,
+ sInstanceName,
+ 0,
+ 0,
+ theInstance,
+ 0,
+ 0,
+ SCF_DECODE_FMRI_EXACT ) != -1 )
+ {
+ scf_handle_t * theInstanceHandle =
+ scf_instance_handle( theInstance );
+ if ( theInstanceHandle != 0 )
+ {
+ uint8_t theEnabled;
+ scf_propertygroup_t * theGroup =
+ scf_pg_create( theInstanceHandle );
+ scf_property_t * theProp =
+ scf_property_create( theInstanceHandle );
+ scf_value_t * theValue =
+ scf_value_create( theInstanceHandle );
+ if ( theGroup != 0 && theProp != 0 && theValue != 0 )
+ {
+ if ( scf_instance_get_pg( theInstance,
+ SCF_PG_GENERAL,
+ theGroup ) == 0 &&
+ scf_pg_get_property( theGroup,
+ SCF_PROPERTY_ENABLED,
+ theProp ) == 0 &&
+ scf_property_get_value( theProp,
+ theValue ) == 0 &&
+ scf_value_get_boolean( theValue,
+ &theEnabled ) == 0 )
+ {
+ isEnabled = theEnabled == 1 ?
+ sStatusEnabled : sStatusNotEnabled;
+ }
+ }
+ scf_pg_destroy( theGroup );
+ scf_property_destroy( theProp );
+ scf_value_destroy( theValue );
+ }
+ }
+ scf_instance_destroy( theInstance );
+ }
+ }
+ scf_handle_destroy( theHandle );
+ }
+ if (inQuiet == 0) { writeFinalMessage( sOpIsEnabled, isEnabled ); }
+ return isEnabled;
+}
+
+Status osDaemonStart( void )
+{
+ Status theRC;
+ writeInitialMessage( sOpStart );
+ osEnabler( 1, 1, 1 );
+ theRC = daemonWaitStatus( sStatusOK, 30 );
+ writeFinalMessage( sOpStart, theRC );
+ return theRC;
+}
+
+Status osDaemonStop( void )
+{
+ Status theRC;
+ writeInitialMessage( sOpStop );
+ osEnabler( 0, 1, 1 );
+ theRC = daemonWaitStatus( sStatusNotRunning, 20 ) == sStatusNotRunning ?
+ sStatusOK : sErrorGeneric;
+ writeFinalMessage( sOpStop, theRC );
+ return theRC;
+}
+
+Status osDaemonSvcStart( void )
+{
+ return daemonStart();
+}
+
+Status osDaemonSvcStop( void )
+{
+ return daemonStop();
+}
+
+Status osEnabler( int inEnable, int inOneTime, int inQuiet )
+{
+ Status theStatus;
+ DaemonOp theOp = inEnable == 1 ? sOpEnable : sOpDisable;
+ int theFlags = inOneTime == 1 ? SMF_TEMPORARY : 0;
+
+ if ( inQuiet == 0 )
+ {
+ writeInitialMessage( theOp );
+ }
+ if ( theOp == sOpEnable )
+ {
+ theStatus =
+ smf_enable_instance( sInstanceName, theFlags ) == SCF_SUCCESS ?
+ sStatusOK : sErrorGeneric;
+ }
+ else
+ {
+ theStatus =
+ smf_disable_instance( sInstanceName, theFlags ) == SCF_SUCCESS ?
+ sStatusOK : sErrorGeneric;
+ }
+ if ( inQuiet == 0 )
+ {
+ writeFinalMessage( theOp, theStatus );
+ }
+ return theStatus;
+}
diff --git a/apocd/win32/apocdctl.c b/apocd/win32/apocdctl.c
new file mode 100644
index 0000000..3081284
--- /dev/null
+++ b/apocd/win32/apocdctl.c
@@ -0,0 +1,1393 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#include <papi/papiUtils.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifndef WNT
+#include <sys/socket.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+#include <strings.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/stat.h>
+#endif
+
+typedef unsigned char daemonOp;
+
+static int authenticate( PAPISocket inSocket );
+
+static int doDisable( int inQuite );
+
+static int doEnable( void );
+
+static int doGeneric( daemonOp inOp, int inQuiet );
+
+static int doIsEnabled( void );
+
+static int doOp( daemonOp inOp );
+
+static int doServiceOp( void * inService, int inOp );
+
+#ifndef WNT
+static int doStart( int inQuite );
+#else
+static int doStart( int inQuite, HANDLE * outHandle );
+#endif
+
+static int doStop( void );
+
+static int doRestart( void );
+
+static void * getService( void );
+
+static int getResponse( int inSocket, char * outResponse );
+
+static void invalidArg( const char * inArg );
+
+static void putEnv( void );
+
+static int sendRequest( int inSocket,
+ const unsigned char * inRequest );
+
+static daemonOp stringToDaemonOp( const char * inString );
+
+static void usage( void );
+
+static void writeInitialMessage( daemonOp inOp );
+
+static void writeFinalMessage( daemonOp inOp, int inStatus );
+
+#ifndef WNT
+
+static int doInetdDisable( void );
+
+static int doInetdEnable( void );
+
+static int doInetdStart( void );
+
+static pid_t getPid( void );
+
+static const char * getPidFile( void );
+
+static int isInetdRunning( void );
+
+static void killPid( void );
+
+static void putPid( void );
+
+static const char * sPidFile = ".pid";
+
+#ifdef LINUX
+
+#define SCRIPT_DISABLE "#!/bin/sh\n \
+if [ -f /etc/inetd.conf ] ; then\n \
+ grep -v apocd /etc/inetd.conf > /tmp/inetd.conf\n \
+ cp /tmp/inetd.conf /etc/inetd.conf\n \
+ rm -f /tmp/inetd.conf\n \
+ /etc/init.d/inetd status > /dev/null 2>&1\n \
+ if [ $? -eq 0 ] ; then\n \
+ /etc/init.d/inetd restart\n \
+ fi\n \
+fi\n \
+exit 0\n"
+
+#define SCRIPT_ENABLE "#!/bin/sh\n \
+if [ -f /etc/inetd.conf ] ; then\n \
+ grep -v apocd /etc/inetd.conf > /tmp/inetd.conf\n \
+ cp /tmp/inetd.conf /etc/inetd.conf\n \
+ rm -f /tmp/inetd.conf\n \
+ echo \"apocd dgram udp wait root /usr/lib/apoc/apocd apocd inetdStart\" >> /etc/inetd.conf\n\
+ /etc/init.d/inetd status > /dev/null 2>&1\n \
+ if [ $? -eq 0 ] ; then\n \
+ /etc/init.d/inetd restart\n \
+ fi\n \
+fi\n \
+exit 0\n"
+
+#else
+
+#define SCRIPT_DISABLE "#!/bin/sh\n \
+if [ -f /etc/inetd.conf ] ; then\n \
+ grep -v apocd /etc/inetd.conf > /tmp/inetd.conf\n \
+ cp /tmp/inetd.conf /etc/inetd.conf\n \
+ rm -f /tmp/inetd.conf\n \
+ pkill -HUP inetd > /dev/null 2>&1\n \
+fi\n \
+exit 0\n"
+
+#define SCRIPT_ENABLE "#!/bin/sh\n \
+if [ -f /etc/inetd.conf ] ; then\n \
+ grep -v apocd /etc/inetd.conf > /tmp/inetd.conf\n \
+ cp /tmp/inetd.conf /etc/inetd.conf\n \
+ rm -f /tmp/inetd.conf\n \
+ echo \"apocd dgram udp wait root /usr/lib/apoc/apocd apocd inetdStart\" >> /etc/inetd.conf\n\
+ pkill -HUP inetd > /dev/null 2>&1\n \
+fi\n \
+exit 0\n"
+
+#endif
+
+#else
+
+#include <windows.h>
+
+typedef WINADVAPI BOOL ( WINAPI *ChangeServiceConfig2Func )( SC_HANDLE, DWORD, LPVOID );
+
+typedef WINADVAPI BOOL ( WINAPI *CloseServiceHandleFunc )( SC_HANDLE );
+
+typedef WINADVAPI BOOL ( WINAPI *ControlServiceFunc )( SC_HANDLE, DWORD, LPSERVICE_STATUS );
+
+typedef WINADVAPI SC_HANDLE ( WINAPI *CreateServiceFunc )( SC_HANDLE,
+ LPCTSTR,
+ LPCTSTR,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ LPCTSTR,
+ LPCTSTR,
+ LPDWORD,
+ LPCTSTR,
+ LPCTSTR,
+ LPCTSTR );
+
+typedef WINADVAPI BOOL ( WINAPI *DeleteServiceFunc )( SC_HANDLE );
+
+typedef WINADVAPI SC_HANDLE ( WINAPI *OpenSCManagerFunc )( LPCTSTR, LPCTSTR, DWORD );
+
+typedef WINADVAPI SC_HANDLE ( WINAPI *OpenServiceFunc )( SC_HANDLE, LPCTSTR, DWORD );
+
+typedef WINADVAPI BOOL ( WINAPI *SetServiceStatusFunc )( SERVICE_STATUS_HANDLE, LPSERVICE_STATUS );
+
+typedef WINADVAPI SERVICE_STATUS_HANDLE ( WINAPI *RegisterServiceCtrlHandlerFunc )( LPCTSTR, LPHANDLER_FUNCTION );
+
+typedef WINADVAPI BOOL ( WINAPI *StartServiceFunc )( SC_HANDLE, DWORD, LPCTSTR * );
+
+typedef WINADVAPI BOOL ( WINAPI *StartServiceCtrlDispatcherFunc )( CONST LPSERVICE_TABLE_ENTRY );
+
+ChangeServiceConfig2Func fChangeServiceConfig2;
+CloseServiceHandleFunc fCloseServiceHandle;
+ControlServiceFunc fControlService;
+CreateServiceFunc fCreateService;
+DeleteServiceFunc fDeleteService;
+OpenSCManagerFunc fOpenSCManager;
+OpenServiceFunc fOpenService;
+RegisterServiceCtrlHandlerFunc fRegisterServiceCtrlHandler;
+SetServiceStatusFunc fSetServiceStatus;
+StartServiceFunc fStartService;
+StartServiceCtrlDispatcherFunc fStartServiceCtrlDispatcher;
+
+static int doRegistryDisable( void );
+
+static int doRegistryEnable( void );
+
+static int doServiceDisable( void );
+
+static int doServiceEnable( void );
+
+static DWORD getServiceStatus( void );
+
+static int loadServiceFuncs( void );
+
+static void serviceCtrlHandler( DWORD inOpCode );
+
+static void serviceMain( DWORD inArgc, LPTSTR * inArgv );
+
+static void serviceRestartLoop( HANDLE inHandle );
+
+static void setServiceStatus( DWORD inStatus );
+
+static const char * sServiceProgram = "apocd.exe";
+
+static const char * sServiceName = "apocd";
+
+static const char * sServiceDisplayName = "Configuration Agent";
+
+static const char * sServiceDescription = "Maintains locally cached policy data";
+
+SERVICE_STATUS_HANDLE gServiceStatusHandle;
+
+SERVICE_STATUS gServiceStatus;
+
+PAPIMutex * gServiceStatusMutex;
+
+#endif
+
+static const char * sArgChangeDetect = "change-detect";
+static const char * sArgDisable = "disable";
+static const char * sArgEnable = "enable";
+static const char * sArgInetdStart = "inetdStart";
+static const char * sArgIsEnabled = "is-enabled";
+static const char * sArgReload = "reload";
+static const char * sArgRestart = "restart";
+static const char * sArgStart = "start";
+static const char * sArgStatus = "status";
+static const char * sArgStop = "stop";
+
+static unsigned char sOpUndefined = 0;
+static unsigned char sOpChangeDetect = 1;
+static unsigned char sOpDisable = 2;
+static unsigned char sOpEnable = 3;
+static unsigned char sOpInetdStart = 4;
+static unsigned char sOpIsEnabled = 5;
+static unsigned char sOpReload = 6;
+static unsigned char sOpRestart = 7;
+static unsigned char sOpStart = 8;
+static unsigned char sOpStatus = 9;
+static unsigned char sOpStop = 10;
+
+static int sStatusOK = 0;
+static int sStatusEnabled = 0;
+static int sErrorGeneric = 1;
+static int sStatusNotEnabled = 1;
+static int sErrorInvalidArg = 2;
+static int sStatusNotRunning = 3;
+static int sStatusEnabledWithWarning = 4;
+static int sErrorNotRunning = 7;
+static int sErrorAuthentication = 8;
+
+static int sLocalCredentialsBufferSize = 21;
+
+int main( int inArgc, char ** inArgv )
+{
+ int theRC;
+ int newerThanWindows98 = 0;
+
+#ifdef WNT
+ if ( isNewerThanWindows98() == 1 )
+ {
+ newerThanWindows98 = 1;
+ loadServiceFuncs();
+ gServiceStatusMutex = newMutex();
+ }
+ if ( inArgc == 1 && newerThanWindows98 == 1 )
+ {
+ SERVICE_TABLE_ENTRY theServiceTable[] =
+ {
+ { ( char *)sServiceName, ( LPSERVICE_MAIN_FUNCTION )serviceMain },
+ { NULL, NULL }
+ };
+ fStartServiceCtrlDispatcher( theServiceTable );
+ }
+#endif
+
+ if ( inArgc == 2 )
+ {
+ daemonOp theOp = stringToDaemonOp( inArgv[ 1 ] );
+ if ( theOp == sOpUndefined )
+ {
+ invalidArg( inArgv[ 1 ] );
+ theRC = sErrorInvalidArg;
+ }
+ else
+ {
+ theRC = doOp( theOp );
+ }
+ }
+ else
+ {
+ usage();
+ theRC = sErrorInvalidArg;
+ }
+ return theRC;
+}
+
+int authenticate( PAPISocket inSocket )
+{
+ int theRC = sErrorAuthentication;
+ char theChallenge[ BUFSIZ ];
+ int theIndex = 0;
+
+ theChallenge[ 0 ] = 0;
+ while ( recv( inSocket, &theChallenge[ theIndex ++ ], 1, 0 ) != -1 )
+ {
+ if ( theChallenge[ theIndex - 1 ] == 0 )
+ {
+ if ( theChallenge[ 0 ] != 0 )
+ {
+ FILE * theFile = fopen( theChallenge, "r" );
+ if ( theFile != 0 )
+ {
+ char * theCredentials =
+ ( char * )malloc( sLocalCredentialsBufferSize );
+ if ( theCredentials != 0 )
+ {
+ if ( fgets( theCredentials,
+ sLocalCredentialsBufferSize,
+ theFile ) != 0 )
+ {
+ if ( send( inSocket,
+ theCredentials,
+ sLocalCredentialsBufferSize - 1,
+ 0 ) == ( sLocalCredentialsBufferSize - 1 ) )
+ {
+ char theResponse;
+ if ( getResponse(inSocket,&theResponse)!= -1 &&
+ theResponse == 0 )
+ {
+ theRC = sStatusOK;
+ }
+ }
+ }
+ free( ( void * )theCredentials );
+ }
+ fclose( theFile );
+#ifdef WNT
+ remove( theChallenge );
+#endif
+ }
+ }
+ break;
+ }
+ }
+ return theRC;
+}
+
+int doGeneric( daemonOp inOp, int inQuiet )
+{
+ int theRC;
+ PAPISocket theSocket;
+ PAPIConnectResult theConnectResult =
+ getConnectedSocket( getDaemonAdminPort(), SOCK_STREAM, 0, &theSocket );
+
+ if ( inQuiet != 1 )
+ {
+ writeInitialMessage( inOp );
+ }
+ if ( theConnectResult == PAPIConnectSuccess )
+ {
+ if ( ( theRC = authenticate( theSocket ) ) == sStatusOK )
+ {
+ if ( ( theRC = sendRequest( theSocket, &inOp ) ) != -1 )
+ {
+ char theResponse;
+ theRC = getResponse( theSocket, &theResponse );
+ }
+ if ( theRC == -1 )
+ {
+ theRC = inOp == sOpStatus ?
+ sStatusNotRunning : sErrorNotRunning;
+ }
+ else
+ {
+ theRC = sStatusOK;
+ }
+ }
+ papiClose( theSocket );
+ }
+ else
+ {
+ theRC = sStatusNotRunning;
+ }
+ if ( inQuiet != 1 )
+ {
+ writeFinalMessage( inOp, theRC );
+ }
+ return theRC;
+}
+
+int doIsEnabled()
+{
+ int theRC = isDaemonEnabled() == 1 ? sStatusEnabled : sStatusNotEnabled;
+ writeInitialMessage( sOpIsEnabled );
+ writeFinalMessage( sOpIsEnabled, theRC );
+ return theRC;
+}
+
+int doOp( daemonOp inOp )
+{
+ int theRC;
+
+ if ( inOp == sOpDisable )
+ {
+ theRC = doDisable( 0 );
+ }
+ else if ( inOp == sOpEnable )
+ {
+ theRC = doEnable();
+ }
+#ifndef WNT
+ else if ( inOp == sOpInetdStart )
+ {
+ theRC = doInetdStart();
+ }
+#endif
+ else if ( inOp == sOpIsEnabled )
+ {
+ theRC = doIsEnabled();
+ }
+ else if ( inOp == sOpStart || inOp == sOpStop || inOp == sOpRestart )
+ {
+ void * theService = getService();
+ if ( theService != 0 )
+ {
+ theRC = doServiceOp( theService, inOp );
+ }
+ else
+ {
+ if ( inOp == sOpStart )
+ {
+#ifndef WNT
+ theRC = doStart( 0 );
+#else
+ theRC = doStart( 0, 0 );
+#endif
+ }
+ else if ( inOp == sOpStop )
+ {
+ theRC = doStop();
+ }
+ else if ( inOp == sOpRestart )
+ {
+ theRC = doRestart();
+ }
+ }
+ }
+ else
+ {
+ theRC = doGeneric( inOp, 0 );
+ }
+ return theRC;
+}
+
+int doServiceOp( void * inService, int inOp )
+{
+ int theRC = sStatusOK;
+#ifdef WNT
+ if ( inOp == sOpStop || inOp == sOpRestart )
+ {
+ SERVICE_STATUS theServiceStatus;
+ BOOL theStatus;
+
+ writeInitialMessage( sOpStop );
+ theStatus =
+ fControlService( inService, SERVICE_CONTROL_STOP, &theServiceStatus );
+ if ( theStatus == 0 &&
+ GetLastError() != ERROR_SERVICE_NOT_ACTIVE )
+ {
+ theRC = sErrorGeneric;
+ }
+ writeFinalMessage( sOpStop, theRC );
+ }
+ if ( inOp == sOpStart || ( inOp == sOpRestart && theRC == sStatusOK ) )
+ {
+ BOOL theStatus;
+
+ writeInitialMessage( sOpStart );
+ theStatus = fStartService( inService, 0, NULL );
+ if ( theStatus == 0 &&
+ GetLastError() != ERROR_SERVICE_ALREADY_RUNNING )
+ {
+ theRC = sErrorGeneric;
+ }
+ writeFinalMessage( sOpStart, theRC );
+ }
+#endif
+ return theRC;
+}
+
+#ifndef WNT
+int doStart( int inQuiet )
+#else
+int doStart( int inQuiet, HANDLE * outHandle )
+#endif
+{
+ static char * theFormat =
+ "java -Djava.library.path=%s -cp %s%sapocd.jar%s%s%sdb.jar%s%s%sldapjdk.jar%s%s%sspi.jar com.sun.apoc.daemon.apocd.Daemon %s %s";
+ static char * theCommand = 0;
+ int theRC = sStatusOK;
+
+ if ( inQuiet != 1 )
+ {
+ writeInitialMessage( sOpStart );
+ }
+ if ( isDaemonEnabled() == 1 )
+ {
+ putEnv();
+ if ( theCommand == 0 )
+ {
+ const char * theDaemonInstallDir = getDaemonInstallDir();
+ const char * theDaemonLibraryDir = getDaemonLibraryDir();
+ const char * theDaemonPropertiesDir = getDaemonPropertiesDir();
+ theCommand =
+ ( char * )malloc( ( strlen( theDaemonInstallDir ) * 5 ) +
+ strlen( theDaemonLibraryDir ) +
+ strlen( theDaemonPropertiesDir ) +
+ ( strlen( FILESEP ) * 4 ) +
+ ( strlen( PATHSEP ) * 3 ) +
+ strlen( theFormat ) + 1 );
+ if ( theCommand != 0 )
+ {
+ sprintf( theCommand,
+ theFormat,
+ theDaemonLibraryDir,
+ theDaemonInstallDir, FILESEP, PATHSEP,
+ theDaemonInstallDir, FILESEP, PATHSEP,
+ theDaemonInstallDir, FILESEP, PATHSEP,
+ theDaemonInstallDir, FILESEP,
+ theDaemonInstallDir,
+ theDaemonPropertiesDir );
+ }
+ }
+ if ( theCommand != 0 )
+ {
+#ifndef WNT
+ if ( papiPopen( theCommand, "w" ) == 0 )
+ {
+ theRC = sErrorGeneric;
+ }
+#else
+ STARTUPINFO theStartupInfo;
+ PROCESS_INFORMATION theProcessInfo;
+
+
+ ZeroMemory( &theStartupInfo, sizeof( theStartupInfo ) );
+ theStartupInfo.dwFlags = STARTF_USESHOWWINDOW;
+ theStartupInfo.wShowWindow = SW_HIDE;
+ theStartupInfo.cb = sizeof( theStartupInfo );
+ ZeroMemory( &theProcessInfo, sizeof( theProcessInfo ) );
+ if ( CreateProcess( 0,
+ theCommand,
+ 0,
+ 0,
+ FALSE,
+ 0,
+ 0,
+ 0,
+ &theStartupInfo,
+ &theProcessInfo ) == 0 )
+ {
+ theRC = sErrorGeneric;
+ }
+ else if ( outHandle != 0 )
+ {
+ *outHandle = theProcessInfo.hProcess;
+ }
+#endif
+ }
+ else
+ {
+ theRC = sErrorGeneric;
+ }
+ }
+ else
+ {
+ theRC = sErrorGeneric;
+ }
+ if ( inQuiet != 1 )
+ {
+ writeFinalMessage( sOpStart, theRC );
+ }
+ return theRC;
+}
+
+int doStop( void )
+{
+ int theRC;
+ writeInitialMessage( sOpStop );
+ theRC = doGeneric( sOpStatus, 1 );
+ if ( theRC != sErrorAuthentication )
+ {
+ if ( theRC == sStatusNotRunning )
+ {
+ theRC = sStatusOK;
+ }
+ else
+ {
+ theRC = doGeneric( sOpStop, 1 );
+ }
+ }
+ writeFinalMessage( sOpStop, theRC );
+#ifndef WNT
+ if ( theRC == sStatusOK )
+ {
+ killPid();
+ }
+#endif
+ return theRC;
+}
+
+void * getService( void )
+{
+#ifndef WNT
+ return 0;
+#else
+ if ( isNewerThanWindows98() == 0 )
+ {
+ return 0;
+ }
+ else
+ {
+ SC_HANDLE theService = NULL;
+ SC_HANDLE theServiceManager =
+ fOpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS );
+ if ( theServiceManager != NULL )
+ {
+ theService = fOpenService( theServiceManager,
+ sServiceName,
+ GENERIC_EXECUTE );
+ }
+ return theService;
+ }
+#endif
+}
+
+int doRestart( void )
+{
+ doGeneric( sOpStop, 0 );
+#ifndef WNT
+ return doStart( 0 );
+#else
+ return doStart( 0, 0 );
+#endif
+}
+
+int getResponse( int inSocket, char * outResponse )
+{
+ return recv( inSocket,
+ outResponse,
+ 1,
+ 0 );
+}
+
+void invalidArg( const char * inOp )
+{
+ if ( inOp != 0 )
+ {
+ fprintf( stderr, "Invalid argument '%s'\n", inOp );
+ }
+ usage();
+}
+
+void putEnv( void )
+{
+ char * theJavaHome = getenv( "JAVA_HOME" );
+
+ if ( theJavaHome != 0 )
+ {
+ char * theJavaPath = ( char * )malloc( strlen( theJavaHome ) +
+ 4 +
+ strlen( FILESEP ) );
+ if ( theJavaPath != 0 )
+ {
+ char * thePath = getenv( "PATH" );
+ char * theNewPath;
+ sprintf( theJavaPath, "%s%sbin", theJavaHome, FILESEP );
+ theNewPath = ( char * )malloc( strlen( theJavaPath ) +
+ strlen( PATHSEP ) +
+ strlen( thePath ) +
+ 6 );
+ if ( theNewPath != 0 )
+ {
+ sprintf( theNewPath,
+ "PATH=%s%s%s",
+ theJavaPath,
+ PATHSEP,
+ thePath );
+ putenv( theNewPath );
+ free( ( void * )theJavaPath );
+ }
+ }
+ }
+ papiUmask( 022 );
+}
+
+int sendRequest( int inSocket,
+ const unsigned char * inRequest )
+{
+ return send( inSocket, inRequest, 1, 0 );
+}
+
+daemonOp stringToDaemonOp( const char * inString )
+{
+ daemonOp theDaemonOp = sOpUndefined;
+ if ( strcmp( inString, sArgChangeDetect ) == 0 )
+ {
+ theDaemonOp = sOpChangeDetect;
+ }
+ else if ( strcmp( inString, sArgDisable ) == 0 )
+ {
+ theDaemonOp = sOpDisable;
+ }
+ else if ( strcmp( inString, sArgEnable ) == 0 )
+ {
+ theDaemonOp = sOpEnable;
+ }
+ else if ( strcmp( inString, sArgInetdStart ) == 0 )
+ {
+ theDaemonOp = sOpInetdStart;
+ }
+ else if ( strcmp( inString, sArgIsEnabled ) == 0 )
+ {
+ theDaemonOp = sOpIsEnabled;
+ }
+ else if ( strcmp( inString, sArgReload ) == 0 )
+ {
+ theDaemonOp = sOpReload;
+ }
+ else
+ if ( strcmp( inString, sArgRestart ) == 0 )
+ {
+ theDaemonOp = sOpRestart;
+ }
+ else
+ if ( strcmp( inString, sArgStart ) == 0 )
+ {
+ theDaemonOp = sOpStart;
+ }
+ else if ( strcmp( inString, sArgStatus ) == 0 )
+ {
+ theDaemonOp = sOpStatus;
+ }
+ else
+ if ( strcmp( inString, sArgStop ) == 0 )
+ {
+ theDaemonOp = sOpStop;
+ }
+ return theDaemonOp;
+}
+
+void usage( void )
+{
+ fprintf( stderr,
+ "%s",
+ "Usage: apocdctl change-detect | disable | enable | is-enabled | reload | restart | start | status | stop\n" );
+}
+
+void writeInitialMessage( daemonOp inOp )
+{
+ if ( inOp == sOpChangeDetect )
+ {
+ printf( "Requesting a Configuration Agent change detection ... " );
+ }
+ else if ( inOp == sOpDisable )
+ {
+ printf( "Disabling Configuration Agent ... ");
+ }
+ else if ( inOp == sOpEnable )
+ {
+ printf( "Enabling Configuration Agent ... ");
+ }
+ else if ( inOp == sOpIsEnabled )
+ {
+ printf( "Checking Configuration Agent enabled status ... " );
+ }
+ else if ( inOp == sOpReload )
+ {
+ printf( "Reloading Configuration Agent ... " );
+ }
+ else if ( inOp == sOpStatus )
+ {
+ printf( "Checking Configuration Agent status ... " );
+ }
+ else if ( inOp == sOpStart )
+ {
+ printf( "Starting Configuration Agent ... " );
+ }
+ else if ( inOp == sOpStop )
+ {
+ printf( "Stopping Configuration Agent ... " );
+ }
+}
+
+void writeFinalMessage( daemonOp inOp, int inStatus )
+{
+ if ( inStatus == sErrorAuthentication )
+ {
+ printf( "Failed\n" );
+ }
+ else if ( inOp == sOpIsEnabled )
+ {
+ printf( "%s\n", inStatus == sStatusEnabled ? "Enabled" : "Not enabled");
+ }
+ else if ( inOp == sOpStatus )
+ {
+ printf( "%s\n", inStatus == sStatusOK ? "Running" : "Not running" );
+ }
+ else if ( inOp == sOpStop )
+ {
+ printf( inStatus == sStatusOK || inStatus == sErrorNotRunning ?
+ "OK\n" : "Failed\n" );
+ }
+ else
+ {
+ printf( inStatus == sStatusOK ? "OK\n" : "Failed\n" );
+ }
+}
+
+#ifndef WNT
+
+int doDisable( int inQuite )
+{
+ int theRC;
+ if ( inQuite != 1 )
+ {
+ writeInitialMessage( sOpDisable );
+ }
+#ifdef SOLARIS
+ if ( haveService() != 0 )
+ {
+ theRC = doServiceDisable();
+ }
+ else
+ {
+ theRC = doInetdDisable();
+ }
+#else
+ theRC = doInetdDisable();
+#endif
+ if ( inQuite != 1 )
+ {
+ writeFinalMessage( sOpDisable, theRC );
+ }
+ doStop();
+ return theRC;
+}
+
+int doInetdDisable()
+{
+ char * theFileName = tmpnam( 0 );
+ FILE * theFile;
+ int theRC = sErrorGeneric;
+
+ theFile = fopen( theFileName, "w" );
+ if ( theFile != 0 )
+ {
+ FILE * theStream;
+ char theBuf[ BUFSIZ ];
+
+ fprintf( theFile, "%s", SCRIPT_DISABLE );
+ fclose( theFile );
+ chmod( theFileName, 0700 );
+ theStream = papiPopen( theFileName, "r" );
+ if ( theStream != 0 )
+ {
+ while ( 1 )
+ {
+ if ( fgets( theBuf, BUFSIZ, theStream ) == 0 )
+ {
+ break;
+ }
+ }
+ theRC = papiPclose( theStream );
+ }
+ unlink( theFileName );
+ }
+ return theRC;
+}
+
+int doEnable( void )
+{
+ int theRC;
+
+ writeInitialMessage( sOpEnable );
+#ifdef SOLARIS
+ if ( haveService() != 0 )
+ {
+ theRC = doServiceEnable();
+ }
+ else
+ {
+ theRC = doInetdEnable();
+ }
+#else
+ theRC = doInetdEnable();
+#endif
+ writeFinalMessage( sOpEnable, theRC );
+ if ( theRC == sStatusOK && isInetdRunning() != 1 )
+ {
+ fprintf( stderr,
+ "%s\n",
+ "Warning: inetd is not running and must be started if you want the" );
+ fprintf( stderr,
+ "%s\n",
+ " Configuration Agent to start automatically." );
+ theRC = sStatusEnabledWithWarning;
+ }
+ return theRC;
+}
+
+int doInetdEnable( void )
+{
+ char * theFileName = tmpnam( 0 );
+ FILE * theFile;
+ int theRC = sErrorGeneric;
+
+ theFile = fopen( theFileName, "w" );
+ if ( theFile != 0 )
+ {
+ FILE * theStream;
+ char theBuf[ BUFSIZ ];
+
+ fprintf( theFile, "%s", SCRIPT_ENABLE );
+ fclose( theFile );
+ chmod( theFileName, 0700 );
+ theStream = papiPopen( theFileName, "r" );
+ if ( theStream != 0 )
+ {
+ while ( 1 )
+ {
+ if ( fgets( theBuf, BUFSIZ, theStream ) == 0 )
+ {
+ break;
+ }
+ }
+ theRC = papiPclose( theStream );
+ }
+ unlink( theFileName );
+ }
+ return theRC;
+}
+
+int doInetdStart( void )
+{
+ if ( doStart( 1 ) == sStatusOK )
+ {
+ putPid();
+ while ( 1 )
+ {
+ getchar();
+ }
+ }
+ return 0;
+}
+
+pid_t getPid( void )
+{
+ pid_t thePid = 0;
+ const char * thePidFile = getPidFile();
+ if ( thePidFile != 0 )
+ {
+ FILE * thePidStream = fopen( thePidFile, "r" );
+ if ( thePidStream != 0 )
+ {
+ fscanf( thePidStream, "%d", &thePid );
+ fclose( thePidStream );
+ }
+ free( ( void * )thePidFile );
+ }
+ return thePid;
+}
+
+const char * getPidFile( void )
+{
+ const char * thePidDir = getDaemonInstallDir();
+ char * thePidFile =
+ ( char * )malloc( strlen( thePidDir ) +
+ ( 2 * strlen( FILESEP ) ) +
+ strlen( sPidFile ) +
+ 4 );
+ if ( thePidFile != 0 )
+ {
+ sprintf( thePidFile,
+ "%s%s%s",
+ thePidDir,
+ FILESEP,
+ sPidFile );
+ }
+ return thePidFile;
+}
+
+int isInetdRunning( void )
+{
+ int theRC = 0;
+ static const char * theCommand = "/bin/ps -e | /bin/grep inetd ";
+ FILE * theStream = papiPopen( theCommand, "r" );
+
+ if ( theStream != 0 )
+ {
+ char theBuffer[ BUFSIZ ];
+
+ while ( fgets( theBuffer, BUFSIZ, theStream ) != 0 ){}
+ theRC = papiPclose( theStream ) == 0 ? 1 : 0;
+ }
+ return theRC;
+}
+
+void killPid( void )
+{
+ pid_t thePid = getPid();
+ if ( thePid > 0 )
+ {
+ kill( thePid, SIGINT );
+ }
+ unlink( getPidFile() );
+}
+
+void putPid( void )
+{
+ const char * thePidFile = getPidFile();
+ if ( thePidFile != 0 )
+ {
+ FILE * thePidStream = fopen( thePidFile, "w" );
+ if ( thePidStream != 0 )
+ {
+ chmod( thePidFile, 0600 );
+ fprintf( thePidStream, "%d", getpid() );
+ fclose( thePidStream );
+ }
+ free( ( void * )thePidFile );
+ }
+}
+
+#else
+
+int doDisable( int inQuiet )
+{
+ int theRC;
+ int newerThanWindows98 = isNewerThanWindows98();
+
+ if ( newerThanWindows98 == 1 )
+ {
+ doServiceOp( getService(), sOpStop );
+ theRC = doServiceDisable();
+ }
+ else
+ {
+ theRC = doRegistryDisable();
+ doStop();
+ }
+ return theRC;
+}
+
+int doRegistryDisable( void )
+{
+ int theRC;
+ LONG theStatus;
+
+ writeInitialMessage( sOpDisable );
+ theStatus = RegDeleteKey( HKEY_LOCAL_MACHINE, APOCENABLEDKEY );
+ theRC = theStatus == ERROR_SUCCESS || theStatus == ERROR_FILE_NOT_FOUND ?
+ sStatusOK : sErrorGeneric;
+ writeFinalMessage( sOpDisable, theRC );
+ return theRC;
+}
+
+int doServiceDisable( void )
+{
+ int theRC = sErrorGeneric;
+ SC_HANDLE theServiceManager;
+
+ if ( isNewerThanWindows98() == 1 )
+ {
+ theServiceManager = fOpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS );
+ writeInitialMessage( sOpDisable );
+ if ( theServiceManager != 0 )
+ {
+ SC_HANDLE theService = fOpenService( theServiceManager,
+ sServiceName,
+ DELETE );
+ if ( theService != 0 )
+ {
+ if ( fDeleteService( theService ) == TRUE ||
+ GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE )
+ {
+ theRC = sStatusOK;
+ }
+ fCloseServiceHandle( theService );
+ }
+ else
+ {
+ if ( GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST )
+ {
+ theRC = sStatusOK;
+ }
+ }
+ fCloseServiceHandle( theServiceManager );
+ }
+ else
+ {
+ theRC = sStatusOK;
+ }
+ }
+ writeFinalMessage( sOpDisable, theRC );
+ return theRC;
+}
+
+int doEnable( void )
+{
+ int theRC;
+ int newerThanWindows98 = isNewerThanWindows98();
+
+ writeInitialMessage( sOpEnable );
+ theRC = newerThanWindows98 == 1 ?
+ doServiceEnable() : doRegistryEnable();
+ writeFinalMessage( sOpEnable, theRC );
+
+ if ( newerThanWindows98 == 1 && theRC == sStatusOK )
+ {
+ theRC = doServiceOp( getService(), sOpStart );
+ }
+ return theRC;
+}
+
+int doServiceEnable( void )
+{
+ int theRC = sErrorGeneric;
+ char * theDaemonInstallDir = getDaemonInstallDir();
+ char * theServiceProgram =
+ ( char * )malloc( strlen( theDaemonInstallDir ) +
+ strlen( FILESEP ) +
+ strlen( sServiceProgram ) +
+ 1 );
+ if ( theServiceProgram != 0 )
+ {
+ SC_HANDLE theServiceManager;
+ char * theCP = ( char * )theDaemonInstallDir +
+ strlen( theDaemonInstallDir ) - 1;
+ while ( theCP-- != theDaemonInstallDir )
+ {
+ if ( *theCP == '\\' )
+ {
+ *( ++theCP ) = 0;
+ break;
+ }
+ }
+ sprintf( theServiceProgram,
+ "%sbin%s%s",
+ theDaemonInstallDir,
+ FILESEP,
+ sServiceProgram );
+ theServiceManager = fOpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS );
+ if ( theServiceManager != 0 )
+ {
+ SC_HANDLE theService =
+ fCreateService( theServiceManager,
+ sServiceName,
+ sServiceDisplayName,
+ SERVICE_ALL_ACCESS,
+ SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_AUTO_START,
+ SERVICE_ERROR_NORMAL,
+ theServiceProgram,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0 );
+ if ( theService != 0 )
+ {
+ fChangeServiceConfig2( theService,
+ SERVICE_CONFIG_DESCRIPTION,
+ ( LPVOID )&sServiceDescription );
+ theRC = sStatusOK;
+ fCloseServiceHandle( theService );
+ }
+ else
+ {
+ if ( GetLastError() == ERROR_SERVICE_EXISTS )
+ {
+ theRC = sStatusOK;
+ }
+ }
+ fCloseServiceHandle( theServiceManager );
+ }
+ free( ( void * )theServiceProgram );
+ }
+ return theRC;
+}
+
+int doRegistryEnable( void )
+{
+ int theRC = sErrorGeneric;
+ HKEY theKey;
+ DWORD theDisposition;
+
+ if ( RegCreateKeyEx( HKEY_LOCAL_MACHINE,
+ APOCENABLEDKEY,
+ 0,
+ 0,
+ 0,
+ KEY_WRITE,
+ 0,
+ &theKey,
+ &theDisposition ) == ERROR_SUCCESS )
+ {
+ RegCloseKey( theKey );
+ theRC = sStatusOK;
+ }
+ return theRC;
+}
+
+DWORD getServiceStatus( void )
+{
+ DWORD theStatus = -1;
+ if ( lockMutex( gServiceStatusMutex ) == 0 )
+ {
+ theStatus = gServiceStatus.dwCurrentState;
+ unlockMutex( gServiceStatusMutex );
+ }
+ return theStatus;
+}
+
+int loadServiceFuncs( void )
+{
+ HMODULE theModule = GetModuleHandle( "advapi32" );
+ if ( theModule != NULL )
+ {
+ fChangeServiceConfig2 =
+ ( ChangeServiceConfig2Func )GetProcAddress(
+ theModule, "ChangeServiceConfig2A" );
+ fCloseServiceHandle =
+ ( CloseServiceHandleFunc )GetProcAddress(
+ theModule, "CloseServiceHandle" );
+ fControlService =
+ ( ControlServiceFunc )GetProcAddress(
+ theModule, "ControlService" );
+ fCreateService =
+ ( CreateServiceFunc )GetProcAddress(
+ theModule, "CreateServiceA" );
+ fDeleteService =
+ ( DeleteServiceFunc )GetProcAddress(
+ theModule, "DeleteService" );
+ fOpenSCManager =
+ ( OpenSCManagerFunc )GetProcAddress(
+ theModule, "OpenSCManagerA" );
+ fOpenService =
+ ( OpenServiceFunc )GetProcAddress(
+ theModule, "OpenServiceA" );
+ fRegisterServiceCtrlHandler =
+ ( RegisterServiceCtrlHandlerFunc )GetProcAddress(
+ theModule, "RegisterServiceCtrlHandlerA" );
+ fSetServiceStatus =
+ ( SetServiceStatusFunc )GetProcAddress(
+ theModule, "SetServiceStatus" );
+ fStartService =
+ ( StartServiceFunc )GetProcAddress(
+ theModule, "StartServiceA" );
+ fStartServiceCtrlDispatcher =
+ ( StartServiceCtrlDispatcherFunc )GetProcAddress(
+ theModule, "StartServiceCtrlDispatcherA" );
+ }
+ return 1;
+}
+
+void serviceCtrlHandler( DWORD inOpcode )
+{
+ switch( inOpcode )
+ {
+ case SERVICE_CONTROL_STOP:
+ case SERVICE_CONTROL_SHUTDOWN:
+ setServiceStatus( SERVICE_STOPPED );
+ doGeneric( sOpStop, 1 );
+ break;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ setServiceStatus( doGeneric( sOpStatus, 1 ) == 0 ?
+ SERVICE_RUNNING : SERVICE_STOPPED );
+ break;
+
+ default:
+ break;
+ }
+ gServiceStatus.dwWin32ExitCode = NO_ERROR;
+ gServiceStatus.dwCheckPoint = 0;
+ gServiceStatus.dwWaitHint = 0;
+ fSetServiceStatus( gServiceStatusHandle, &gServiceStatus );
+}
+
+void serviceMain( DWORD inArgc, LPTSTR * inArgv )
+{
+ HANDLE theHandle;
+ gServiceStatusHandle =
+ fRegisterServiceCtrlHandler(
+ sServiceName,
+ ( LPHANDLER_FUNCTION )serviceCtrlHandler );
+
+ gServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ setServiceStatus( SERVICE_START_PENDING );
+ gServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
+ SERVICE_ACCEPT_SHUTDOWN;
+ gServiceStatus.dwWin32ExitCode = 0;
+ gServiceStatus.dwServiceSpecificExitCode = 0;
+ gServiceStatus.dwCheckPoint = 0;
+ gServiceStatus.dwWaitHint = 0;
+ fSetServiceStatus( gServiceStatusHandle, &gServiceStatus );
+
+ if ( doStart( 1, &theHandle ) == 0 )
+ {
+ setServiceStatus( SERVICE_RUNNING );
+ gServiceStatus.dwWin32ExitCode = NO_ERROR;
+ gServiceStatus.dwCheckPoint = 0;
+ gServiceStatus.dwWaitHint = 0;
+ fSetServiceStatus( gServiceStatusHandle, &gServiceStatus );
+ serviceRestartLoop( theHandle );
+ }
+ else
+ {
+ setServiceStatus( SERVICE_STOPPED );
+ gServiceStatus.dwWin32ExitCode = ERROR_GEN_FAILURE;
+ gServiceStatus.dwCheckPoint = 0;
+ gServiceStatus.dwWaitHint = 0;
+ fSetServiceStatus( gServiceStatusHandle, &gServiceStatus );
+ }
+}
+
+void serviceRestartLoop( HANDLE inHandle )
+{
+ while ( 1 )
+ {
+ WaitForSingleObject( inHandle, INFINITE );
+ Sleep( 5000 );
+ if ( getServiceStatus() == SERVICE_RUNNING )
+ {
+ doStart( 1, &inHandle );
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+void setServiceStatus( DWORD inStatus )
+{
+ if ( lockMutex( gServiceStatusMutex ) == 0 )
+ {
+ gServiceStatus.dwCurrentState = inStatus;
+ unlockMutex( gServiceStatusMutex );
+ }
+}
+
+#endif
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..7893731
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+PROJECT=AGENT
+TEST_TYPE=-f
+FILE=apocd/apocd.c
+
+DIE=0
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have autoconf installed to compile $PROJECT."
+ echo "Install the appropriate package for your distribution,"
+ echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+ DIE=1
+}
+
+
+if test -x "`which automake-1.9`"
+then
+ AUTOMAKE=`which automake-1.9`
+ ACLOCAL=`which aclocal-1.9`
+ ACLOCAL_FLAGS="-I m4"
+elif test -x "`which automake-1.10`"
+then
+ AUTOMAKE=`which automake-1.10`
+ ACLOCAL=`which aclocal-1.10`
+ ACLOCAL_FLAGS="-I m4"
+else
+ echo
+ echo "You must have automake 1.10.x or 1.9.x installed to compile $PROJECT."
+ echo "Install the appropriate package for your distribution,"
+ echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+ DIE=1
+fi
+
+if test -x "`which libtoolize`"
+then
+ LIBTOOLIZE=`which libtoolize`
+ LIBTOOLIZEFLAGS="--force"
+else
+ echo
+ echo "You must have libtoolize installed to comopile $PROJECT."
+ echo "Install the appropriate package for your operating system."
+ DIE=1
+fi
+
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+ echo "You must run this script in the top-level $PROJECT directory"
+ exit 1
+}
+
+if test -z "$AUTOGEN_SUBDIR_MODE"; then
+ if test -z "$*"; then
+ echo "I am going to run ./configure with no arguments - if you wish "
+ echo "to pass any to it, please specify them on the $0 command line."
+ fi
+fi
+
+rm -rf autom4te.cache
+
+
+$ACLOCAL $ACLOCAL_FLAGS || exit $?
+$LIBTOOLIZE $LIBTOOLIZEFLAGS || exit $?
+$AUTOMAKE --add-missing || exit $?
+autoconf || exit $?
+cd $ORIGDIR || exit $?
+
+if test -z "$AUTOGEN_SUBDIR_MODE"; then
+ $srcdir/configure --enable-maintainer-mode $AUTOGEN_CONFIGURE_ARGS "$@" || exit $?
+
+ echo
+ echo "Now type 'make' to compile $PROJECT."
+fi
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..293cf7d
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,287 @@
+AC_INIT(apoc-desktop-agent, 1.0)
+
+AM_INIT_AUTOMAKE
+AC_JAVA_OPTIONS
+
+AC_PROG_CC
+AC_PROG_LIBTOOL
+
+#Checking and including libXML2
+PKG_CHECK_MODULES(LIBXML2, libxml-2.0)
+CFLAGS="$CFLAGS $LIBXML2_CFLAGS"
+LDFLAGS="$LDFLAGS $LIBXML2_LIBS"
+LIBS="$LIBS $LIBXML2_LIBS"
+
+# Setting APOC Daemon dir
+AC_EXPAND(libdir,NONE,EXPANDED_LIBDIR)
+
+APOCD_DIR="$EXPANDED_LIBDIR/apoc"
+
+AC_ARG_WITH(daemon-dir,
+AC_HELP_STRING( [--with-daemon-dir=DIR],
+ [specify the APOC daemon installation path (default=LIBDIR/apoc)]),
+[
+ if test "$withval" != "no"
+ then
+ APOCD_DIR=$withval
+ fi
+])
+
+#Java DB 4.2 library directory
+DBJAVA_DIR="/usr"
+AC_ARG_WITH(db-java-prefix,
+AC_HELP_STRING( [--with-db-java-prefix=DIR],
+ [specify the DB JAVA 4.2 installation prefix (default=/usr)]),
+[
+ if test "$withval" != "no"
+ then
+ BDBJAVA_DIR=$withval
+ fi
+])
+
+DBJAVA_LIBDIR=$DBJAVA_DIR/lib
+AC_ARG_WITH(db-java-libdir,
+AC_HELP_STRING( [--with-db-java-libdir=DIR],
+ [specify the BDB JAVA 4.2 library installation prefix (default=DBJAVA_DIR/usr)]),
+[
+ if test "$withval" != "no"
+ then
+ DBJAVA_LIBDIR=$withval
+ fi
+])
+
+# Check only for the presence of the library, it's only needed
+# in runtime by the java bindings. No need to add compiler flags.
+TMP_LIBS=$LIBS
+TMP_CFLAGS=$CFLAGS
+TMP_LDFLAGS=$LDFLAGS
+LDFLAGS=-L$DBJAVA_LIBDIR
+AC_CHECK_LIB(db_java-4.2, DbEnv_get_version_major,
+ [],
+ AC_MSG_ERROR(DB JAVA 4.2 library not found. Check your DBJAVA prefix option.
+If it is already installed please use --with-db-java-prefix=DIR or --with-db-java-libdir=DIR options to point to the DB JAVA 4.2 installation prefix or library dir.))
+LDFLAGS=$TMP_LDFLAGS
+CFLAGS=$CFLAGS
+LIBS=$TMP_LIBS
+
+# Checking for the GSSAPI
+GSSAPI_DIR=/usr
+GSSAPI_LIBDIR="$GSSAPI_DIR/lib"
+GSSAPI_INCLUDEDIR="$GSSAPI_DIR/include"
+
+AC_ARG_WITH(gss-prefix,
+AC_HELP_STRING( [--with-gss-prefix=DIR],
+ [specify the GSS API installation prefix (default=/usr)]),
+[
+ if test "$withval" != "no"
+ then
+ GSSAPI_DIR=$withval
+ fi
+])
+
+AC_ARG_WITH(gss-libdir,
+AC_HELP_STRING( [--with-gss-libdir=DIR],
+ [specify the GSS API library path (default=GSS_PREFIX/lib)]),
+[
+ if test "$withval" != "no"
+ then
+ GSSAPI_LIBDIR=$withval
+ fi
+])
+
+AC_ARG_WITH(gss-includedir,
+AC_HELP_STRING( [--with-gss-includedir=DIR],
+ [specify the GSS API include path (default=GSS_PREFIX/include)]),
+[
+ if test "$withval" != "no"
+ then
+ GSSAPI_INCLUDEDIR=$withval
+ fi
+])
+
+
+CFLAGS="$CFLAGS -I$GSSAPI_INCLUDEDIR"
+LDFLAGS="$LDFLAGS -L$GSSAPI_LIBDIR"
+
+AC_CHECK_HEADERS(gssapi/gssapi.h,
+ [GSSAPI_INCLUDES="-I$GSSAPI_INCLUDEDIR/gssapi"])
+
+if test -z "$GSSAPI_INCLUDES"
+then
+AC_CHECK_HEADERS(gssapi.h,
+ [GSSAPI_INCLUDES="-I$GSSAPI_INCLUDEDIR"])
+fi
+
+if test -z "$GSSAPI_INCLUDES"
+then
+ AC_MSG_ERROR(GSSAPI development headers not found.
+If it is already installed please use --with-gss-prefix=DIR to point to the GSSAPI installation prefix.)
+fi
+
+#Checking the gssapi presence
+AC_CHECK_LIB(gss, gss_init_sec_context,
+ [GSSAPI_LIBS="-L$GSSAPI_LIBDIR -lgss"],)
+
+if test -z "$GSSAPI_LIBS"
+then
+AC_CHECK_LIB(gssapi, gss_init_sec_context,
+ [GSSAPI_LIBS="-L$GSSAPI_LIBDIR -lgssapi"],)
+fi
+
+if test -z "$GSSAPI_LIBS"
+then
+AC_CHECK_LIB(gssapi_krb5, gss_init_sec_context,
+ [GSSAPI_LIBS="-L$GSSAPI_LIBDIR -lgssapi_krb5"],)
+fi
+
+if test -z "$GSSAPI_LIBS"
+then
+AC_MSG_ERROR(GSSAPI library not found. Check your GSSAPI prefix option.
+If it is already installed please use --with-gss-prefix=DIR to point to the GSSAPI installation prefix.)
+fi
+
+
+CFLAGS="$CFLAGS $GSSAPI_INCLUDES"
+LDFLAGS="$LDFLAGS $GSSAPI_LIBS"
+LIBS="$LIBS $GSSAPI_LIBS"
+
+
+# Setting APOC class path
+AC_EXPAND(datadir, NONE, EXPANDED_DATADIR)
+
+APOCDIR=$EXPANDED_DATADIR'/lib/apoc'
+
+AC_ARG_WITH(apoc-path,
+AC_HELP_STRING( [--with-apoc-path=DIR],
+ [specify a path to install the apoc libraries (DATADIR/lib/apoc)]),
+[
+ if test "$withval" != "no"
+ then
+ APOCDIR=$withval
+ fi
+])
+
+SPIJDK=$APOCDIR/spi.jar
+
+#Setting Oracle/Sleepycat's BerkeleyDB JDK
+BDBJDK=$APOCDIR/db.jar
+
+AC_ARG_WITH(bdb-path,
+AC_HELP_STRING( [--with-bdb-path=DIR],
+ [specify the Sleepycat's BerkeleyDB JDK path or jar file (APOCDIR/db.jar)]),
+[
+ if test "$withval" != "no"
+ then
+ BDBJDK=$withval
+ fi
+])
+
+AC_ARG_ENABLE(debug,
+AC_HELP_STRING( [--enable-debug],
+ [enable debugging symbols]),
+ [debug="yes"])
+
+if test "$debug" == "yes"
+then
+ CFLAGS="$CFLAGS -g "
+fi
+
+
+_SAVE_CLASSPATH=$CLASSPATH
+export CLASSPATH=$CLASPATH:$SPIJDK:$BDBJDK
+
+AC_PROG_JAVAC
+AC_PROG_JAVA
+AC_PROG_JAR
+
+AC_CHECK_CLASS(com.sleepycat.db.Db, [], [
+echo
+AC_MSG_ERROR(Sleepycat's BerkeleyDB JDK
+If it is already installed please use --with-bdb-path=DIR to point to the path or jar file.)
+])
+
+AC_CHECK_CLASS(com.sun.apoc.spi.PolicyManager, [], [
+echo
+AC_MSG_ERROR(APOC SPI not found.
+If it is already installed please use --with-apoc-path=DIR to point to the path wher the spi.jar file is stored.)
+])
+
+AC_JNI_INCLUDE_DIR
+
+if test -z "$JNI_INCLUDE_DIRS"
+then
+ AC_MSG_ERROR(Java Native Interface (JNI) headers not found.)
+fi
+
+for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS
+do
+ CFLAGS="$CFLAGS -I$JNI_INCLUDE_DIR"
+done
+
+AC_CHECK_PROG(ANT, ant, ant, no)
+if test $ANT == "no"
+then
+ AC_MSG_ERROR(Apache's Ant was not found in path.)
+fi
+
+case "${host}" in
+ *-*solaris*) PLATFORM=UNX
+ OS=SOLARIS
+ CFLAGS="$CFLAGS -xarch=v8 -xspace -xO3"
+ LIBS="$LIBS -lpthread -lnsl -lsocket -lm -lc -lrt -lscf"
+ LDFLAGS="-mt -z combreloc -z text -Bdirect -z defs"
+ ;;
+ *-*linux*) PLATFORM=UNX
+ OS=LINUX
+ ;;
+esac
+
+CFLAGS="$CFLAGS -D$PLATFORM -D$OS"
+
+AM_CONDITIONAL([SOLARIS], [test "$OS" = "SOLARIS"])
+
+#APOC data dir
+AC_EXPAND(localstatedir, NONE, EXPANDED_LOCALSTATEDIR)
+
+APOC_DATADIR="$EXPANDED_LOCALSTATEDIR/apoc"
+
+AC_ARG_WITH(apoc-datadir,
+AC_HELP_STRING( [--with-apoc-data=DIR],
+ [specify the APOC data dir (default=LOCALSTATEDIR/apoc)]),
+[
+ if test "$withval" != "no"
+ then
+ APOCD_DIR=$withval
+ fi
+])
+
+AC_EXPAND(sysconfdir, NONE, EXPANDED_SYSCONFDIR)
+AC_EXPAND(libdir, NONE, EXPANDED_LIBDIR)
+
+AC_SUBST(APOCDIR)
+AC_SUBST(SPIJDK)
+AC_SUBST(BDBJDK)
+AC_SUBST(APOCD_DIR)
+AC_SUBST(APOC_DATADIR)
+AC_SUBST(EXPANDED_SYSCONFDIR)
+AC_SUBST(EXPANDED_LIBDIR)
+AC_SUBST(DBJAVA_LIBDIR)
+
+AC_OUTPUT([
+Makefile
+libapoc.pc
+libapoc/Makefile
+libapoc/config.h
+libfileaccess/Makefile
+apocd/Makefile
+apocd/config.h
+smf/apocd.xml
+initd/apocd
+src/Makefile
+src/com/Makefile
+src/com/sun/Makefile
+src/com/sun/apoc/Makefile
+src/com/sun/apoc/daemon/Makefile
+src/com/sun/apoc/daemon/build.xml
+src/com/sun/apoc/daemon/properties/os.properties
+])
diff --git a/initd/apocd.in b/initd/apocd.in
new file mode 100755
index 0000000..97b59bd
--- /dev/null
+++ b/initd/apocd.in
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# Copyright (c) 2004 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# /etc/init.d/apocd
+#
+### BEGIN INIT INFO
+# Provides: apocd
+# Required-Start: $network $local_fs
+# Required-Stop: $network $local_fs
+# Default-Start: 3 5
+# Default-Stop: 0 1 2 6
+# Description: Configuration Agent
+### END INIT INFO
+
+APOCD_BIN=@APOCD_DIR@/apocd
+test -x $APOCD_BIN || exit 5
+
+. /etc/rc.status
+rc_reset
+
+case "$1" in
+ start)
+ echo -n "Starting Configuration Agent"
+ $APOCD_BIN svcStart > /dev/null
+ rc_status -v
+ ;;
+
+ stop)
+ echo -n "Stopping Configuration Agent"
+ $APOCD_BIN svcStop > /dev/null
+ rc_status -v
+ ;;
+
+ try-restart)
+ $0 status >/dev/null && $0 restart
+ rc_status
+ ;;
+
+ restart)
+ $0 stop
+ $0 start
+ rc_status
+ ;;
+
+ force-reload|reload)
+ echo -n "Reloading Configuration Agent"
+ $APOCD_BIN reload > /dev/null
+ rc_status -v
+ ;;
+
+ status)
+ echo -n "Checking Configuration Agent status"
+ $APOCD_BIN status > /dev/null
+ rc_status -v
+ ;;
+
+ *)
+ echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload}"
+ exit 1
+ ;;
+esac
+rc_exit
+
diff --git a/libapoc.pc.in b/libapoc.pc.in
new file mode 100644
index 0000000..d38e32b
--- /dev/null
+++ b/libapoc.pc.in
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+gssapilibs=@GSSAPI_LIBS@
+gssapiincludes=@GSSAPI_INCLUDES@
+
+Name: libapoc
+Description: library that provides an interface to the APOC desktop agent for applications
+Version: @VERSION@
+Requires: libxml-2.0
+Libs: -L${libdir} -lapoc ${gssapilibs}
+Cflags: -I${includedir}/apoc ${gssapiincludes}
diff --git a/libapoc/Makefile.am b/libapoc/Makefile.am
new file mode 100644
index 0000000..1da0d20
--- /dev/null
+++ b/libapoc/Makefile.am
@@ -0,0 +1,39 @@
+lib_LTLIBRARIES = libapoc.la
+
+libapocdir = $(includedir)/apoc/papi
+
+libapoc_HEADERS = \
+ papi.h \
+ papiTypes.h
+
+libapoc_la_LDFLAGS = -version-info "1:0:0"
+
+libapoc_la_SOURCES = \
+ papi.c \
+ papi.h \
+ papiConnection.h \
+ papiConnection.c \
+ papiDaemon.h \
+ papiDaemon.c \
+ papiDatabase.c \
+ papiDatabase.h \
+ papiInternal.c \
+ papiInternal.h \
+ papiLayerList.c \
+ papiLayerList.h \
+ papiListenerList.c \
+ papiListenerList.h \
+ papiMessage.c \
+ papiMessage.h \
+ papiSAXParserContext.c \
+ papiSAXParserContext.h \
+ papiStringList.c \
+ papiStringList.h \
+ papiEntityList.c \
+ papiEntityList.h \
+ papiUtils.c \
+ papiUtils.h \
+ papiPort.c \
+ papiTypes.h
+
+
diff --git a/libapoc/config.h.in b/libapoc/config.h.in
new file mode 100644
index 0000000..74120a7
--- /dev/null
+++ b/libapoc/config.h.in
@@ -0,0 +1,41 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#ifndef _HAVE_CONFIG_H
+#define _HAVE_CONFIG_H
+#define APOC_INSTALLDIR "@APOCDIR@"
+#define APOC_LIBRARYDIR "@EXPANDED_LIBDIR@"
+#define APOC_PROPDIR "@EXPANDED_SYSCONFDIR@"
+#endif
diff --git a/libapoc/papi.c b/libapoc/papi.c
new file mode 100644
index 0000000..23e4c8f
--- /dev/null
+++ b/libapoc/papi.c
@@ -0,0 +1,128 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papi.h"
+#include "papiInternal.h"
+
+
+PAPI * papiInitialise( const char * inEntityId,
+ PAPIStatus * outStatus )
+{
+ return papiInitialiseWithListener( inEntityId, 0, 0, outStatus );
+}
+
+PAPI * papiInitialiseWithListener( const char * inEntityId,
+ PAPIConnectionListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIEntityList theEntity ;
+
+ theEntity.entityType = PAPIEntityUser;
+ theEntity.entityId = inEntityId;
+ theEntity.next = 0;
+ return initialise( &theEntity, inListener, inUserData, outStatus);
+}
+
+void papiDeinitialise( PAPI * inPAPI, PAPIStatus * outStatus )
+{
+ deinitialise( inPAPI, outStatus );
+}
+
+PAPILayerList * papiReadComponentLayers( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIStatus * outStatus )
+{
+ return readComponentLayers( inPAPI, inComponentName, outStatus );
+}
+
+PAPIStringList * papiListComponentNames( const PAPI * inPAPI,
+ const char * inFilter,
+ PAPIStatus * outStatus )
+{
+ return listComponentNames( inPAPI, inFilter, outStatus );
+}
+
+void papiSetOffline( const PAPI * inPAPI,
+ const char * inComponentName,
+ int inOffline,
+ PAPIStatus * outStatus )
+{
+ if ( outStatus != 0 )
+ {
+ *outStatus = PAPISuccess;
+ }
+}
+
+int papiIsOffline( const PAPI * inPAPI,
+ const char * inComponentName,
+ int * outIsOffline,
+ PAPIStatus * outStatus )
+{
+ if ( outStatus != 0 )
+ {
+ *outStatus = PAPISuccess;
+ }
+ return 0;
+}
+
+PAPIListenerId papiAddListener( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ return addListener( inPAPI,
+ inComponentName,
+ inListener,
+ inUserData,
+ outStatus );
+}
+
+void papiRemoveListener( const PAPI * inPAPI,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus )
+{
+ removeListener( inPAPI, inListenerId, outStatus );
+}
+
+void papiFreeLayerList( PAPILayerList * inList )
+{
+ deleteLayerList( inList );
+}
+
+void papiFreeStringList( PAPIStringList * inList )
+{
+ deleteStringList( inList );
+}
diff --git a/libapoc/papi.h b/libapoc/papi.h
new file mode 100644
index 0000000..0addec9
--- /dev/null
+++ b/libapoc/papi.h
@@ -0,0 +1,146 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+/* papi.h - Policy Access API */
+
+#ifndef PAPI_H_
+#define PAPI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "papiTypes.h"
+
+#ifdef WIN32
+#ifdef PAPI_EXPORTS
+#define PAPI_API __declspec(dllexport)
+#else
+#define PAPI_API __declspec(dllimport)
+#endif
+#else
+#define PAPI_API
+#endif
+
+/* Main PAPI functions */
+
+/*
+ * Obtain a new PAPI handle for the specified entity
+ * Specifying inEntityId=NULL will result in the entity id being calculated
+ * from the current user id.
+ */
+PAPI_API PAPI * papiInitialise( const char * inEntityId,
+ PAPIStatus * outStatus );
+
+/*
+ * Same as papiInitialise with the additional possibility of specifying
+ * a listener function which will be called in the event of a daemon connect or
+ * disconnect.
+ */
+PAPI_API PAPI * papiInitialiseWithListener( const char * inEntityId,
+ PAPIConnectionListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+/*
+ * Invalidate and free all resoures associated with a PAPI handle
+ * previously returned by papiInitialise()
+ */
+PAPI_API void papiDeinitialise( PAPI * inPAPI, PAPIStatus * outStatus );
+
+/*
+ * Retrieve all layers for a specified component
+ * Returns a PAPILayerList ( See papiTypes.h ) ordered according to mergepath
+ *
+ * The caller must "free" the returned PAPILayerList using papiFreeLayerList()
+ */
+PAPI_API PAPILayerList * papiReadComponentLayers( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIStatus * outStatus );
+
+/*
+ * List all available components which comply with the specified filter
+ * Returns a PAPIStringList ( See papiTypes.h )
+ *
+ * The caller must "free" the returned PAPIStringList using papiFreeStringList()
+ *
+ * TBD: specify the supported filter syntax
+ */
+PAPI_API PAPIStringList * papiListComponentNames( const PAPI * inPAPI,
+ const char * inFilter,
+ PAPIStatus * outStatus );
+
+/*
+ * Mark the specified component as offline or online
+ */
+PAPI_API void papiSetOffline( const PAPI * inPAPI,
+ const char * inComponentName,
+ int inOffline,
+ PAPIStatus * outStatus );
+
+/*
+ * Query the online/offline status of a specified component
+ */
+PAPI_API int papiIsOffline( const PAPI * inPAPI,
+ const char * inComponentName,
+ int * outIsOffline,
+ PAPIStatus * outStatus );
+
+/*
+ * Add a listener for changes to the specified component
+ */
+PAPI_API PAPIListenerId papiAddListener( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+/*
+ * Remove a listener previously added by papiAddListener()
+ */
+PAPI_API void papiRemoveListener( const PAPI * inPAPI,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus );
+
+/*
+ * Free all resources associated with the specified list
+ */
+PAPI_API void papiFreeLayerList( PAPILayerList * inList );
+PAPI_API void papiFreeStringList( PAPIStringList * inList );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPI_H_ */
diff --git a/libapoc/papiConnection.c b/libapoc/papiConnection.c
new file mode 100644
index 0000000..7eb4b6e
--- /dev/null
+++ b/libapoc/papiConnection.c
@@ -0,0 +1,747 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papiConnection.h"
+#include "papiSAXParserContext.h"
+#include "papiStringList.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#ifndef WNT
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+typedef struct NotificationThreadArg
+{
+ PAPIListener mListener;
+ PAPIEvent * mEvent;
+ void * mUserData;
+} NotificationThreadArg;
+
+static PAPIConnection * allocConnection (
+ PAPIConnectionListener inListener,
+ void * inUserDat,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPISocket inFD,
+ PAPIStatus * outStatus );
+
+static int daemonConnect( int inRetryCount );
+
+static void createNotificationThread( PAPIListener inListener,
+ PAPIEventType inType,
+ const char * inComponentName,
+ void * inUserData );
+
+static PAPIListenerThreadStatus getListenerThreadStatus(
+ PAPIConnection *inConnection );
+
+static PAPIMessage * getResponse( PAPIConnection *inConnection,
+ PAPIStatus * outStatus );
+
+static PAPIMessage * getResponseMessage( PAPIConnection *inConnection,
+ PAPIStatus * outStatus );
+
+static void handleSASLAuth( PAPIConnection *inConnection,
+ PAPIMessage * inChallenge );
+
+static int haveMessage( PAPIConnection *inConnection );
+
+static void * listener( void * inConnection );
+
+static void * notifier( void * inNotificationThreadArg );
+
+static void sendInternalNotification( PAPIConnection *inConnection,
+ PAPIMessage * inMessage );
+
+static void sendNotification( PAPIConnection *inConnection,
+ PAPIMessage * theMessage );
+
+static void setListenerThreadStatus( PAPIConnection *inConnection,
+ PAPIListenerThreadStatus inStatus );
+
+static void startListeningThread( PAPIConnection *inConnection,
+ PAPIStatus * outStatus );
+
+static void stopListeningThread( PAPIConnection *inConnection,
+ PAPIStatus * outStatus );
+
+static void takeFive( void );
+
+static int sDefaultDaemonPort = 38900;
+
+PAPIListenerId connectionAddListener( PAPIConnection * inConnection,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIListenerId theListenerId = 0;
+ *outStatus = PAPISuccess;
+ if ( lockMutex( inConnection->mListenersMutex ) == 0 )
+ {
+ theListenerId = addListenerList( &( inConnection->mListeners ),
+ inComponentName,
+ inListener,
+ inUserData );
+ *outStatus = theListenerId == 0 ?
+ PAPIOutOfMemoryFailure :
+ PAPISuccess;
+ unlockMutex( inConnection->mListenersMutex );
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+ return theListenerId;
+}
+
+void connectionRemoveListener( PAPIConnection * inConnection,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus )
+{
+ *outStatus = PAPISuccess;
+ if ( lockMutex( inConnection->mListenersMutex ) == 0 )
+ {
+ removeListenerList( & ( inConnection->mListeners ),
+ ( PAPIListenerList * )inListenerId );
+ unlockMutex( inConnection->mListenersMutex );
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+}
+
+void connectionSetSASLAuthHandler( PAPIConnection * inConnection,
+ PAPIAuthHandler inHandler,
+ void * inHandlerUserData )
+{
+ inConnection->mAuthHandler = inHandler;
+ inConnection->mAuthHandlerUserData->mUserData = inHandlerUserData;
+}
+
+void deleteConnection( PAPIConnection * inConnection )
+{
+ if ( inConnection != 0 )
+ {
+ PAPIStatus theStatus;
+ stopListeningThread( inConnection, &theStatus );
+ deleteListenerList( inConnection->mListeners );
+ deleteMutex( inConnection->mListenersMutex );
+ deleteMutex( inConnection->mSavedMessageMutex );
+ deleteMutex( inConnection->mListenerThreadStatusMutex );
+ deleteMutex( inConnection->mConnectionStateChangeMutex );
+ if ( inConnection->mAuthHandlerUserData != 0 )
+ {
+ free( ( void * )inConnection->mAuthHandlerUserData );
+ }
+ free( ( void * )inConnection );
+ }
+}
+
+PAPIConnection * newConnection( PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPIConnection * theConnection = 0;
+ int theSocket = daemonConnect( 10 );
+
+ if ( theSocket == INVALID_SOCKET )
+ {
+ *outStatus = PAPIConnectionFailure;
+ }
+ else
+ {
+ *outStatus = PAPISuccess;
+ }
+ if ( *outStatus == PAPISuccess || isDaemonEnabled() == 1 )
+ {
+ theConnection = allocConnection( inConnectionListener,
+ inUserData,
+ inInternalListener,
+ inInternalListenerData,
+ theSocket,
+ &theStatus );
+ if ( theStatus == PAPISuccess )
+ {
+ startListeningThread( theConnection, &theStatus );
+ }
+ if ( theStatus != PAPISuccess )
+ {
+ deleteConnection( theConnection );
+ theConnection = 0;
+ *outStatus = theStatus;
+ }
+ }
+ return theConnection;
+}
+
+int readBytes( PAPIConnection * inConnection, char * inBuffer, int inLen )
+{
+ int theTotalByteCount = 0;
+ while ( inLen > 0 )
+ {
+ int theByteCount = -1;
+ if ( haveMessage( inConnection ) != -1 )
+ {
+ theByteCount =
+ recv(inConnection->mFD, inBuffer + theTotalByteCount, inLen, 0);
+ if ( theByteCount == -1 && errno == EINTR )
+ {
+ theByteCount = 0;
+ }
+ }
+ if ( theByteCount == SOCKET_ERROR )
+ {
+ theTotalByteCount = -1;
+ break;
+ }
+ else
+ {
+ inLen -= theByteCount;
+ theTotalByteCount += theByteCount;
+ }
+ }
+ return theTotalByteCount;
+}
+
+int readContentLength( PAPIConnection * inConnection )
+{
+ char theBuffer[ 15 ];
+ int theIndex;
+ int theContentLength = -1;
+ if ( readBytes( inConnection, theBuffer, 15 ) != 15 )
+ {
+ return -1;
+ }
+ if ( strncmp( theBuffer,
+ CONTENTLENGTH,
+ sizeof( CONTENTLENGTH ) - 1 ) != 0)
+ {
+ return -1;
+ }
+ theIndex = 0;
+ while ( readBytes( inConnection, theBuffer + theIndex, 1 ) == 1 )
+ {
+ if ( theBuffer[ theIndex ] == '\n' )
+ {
+ theBuffer[ theIndex - 1 ] = 0;
+ theContentLength = atoi( theBuffer );
+ break;
+ }
+ theIndex ++;
+ }
+ return theContentLength;
+}
+
+PAPIMessage * sendRequest( PAPIConnection * inConnection,
+ PAPIMessage * inRequestMessage,
+ PAPIStatus * outStatus )
+{
+ int theContentLength;
+ char theContentLengthString[ MAX_CONTENT_LENGTH_SIZE ];
+ char * theRequest;
+ PAPIMessage * theResponse = 0;
+
+ *outStatus = PAPISuccess;
+
+ if ( inConnection == 0 || inConnection->mFD == INVALID_SOCKET )
+ {
+ *outStatus = PAPIConnectionFailure;
+ return 0;
+ }
+
+ theRequest = messageToString( inRequestMessage );
+ if ( theRequest != 0 && ( theContentLength = strlen( theRequest ) ) > 0 )
+ {
+ char * theBuf;
+ int theSize;
+ snprintf( theContentLengthString,
+ MAX_CONTENT_LENGTH_SIZE,
+ "%s%d\r\n",
+ CONTENTLENGTH,
+ theContentLength );
+
+ deleteMessage( inConnection->mSavedMessage );
+ inConnection->mSavedMessage = 0;
+ theSize = strlen( theContentLengthString ) + theContentLength + 1;
+ theBuf = ( char * )malloc( theSize );
+ if ( theBuf == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ free( ( void * )theRequest );
+ return 0;
+ }
+ snprintf( theBuf, theSize, "%s%s", theContentLengthString, theRequest );
+ if ( send( inConnection->mFD,
+ ( void * )theBuf,
+ theSize - 1,
+ 0 ) == SOCKET_ERROR )
+ {
+ *outStatus = PAPIConnectionFailure;
+ free( ( void * )theBuf );
+ free( ( void * )theRequest );
+ return 0;
+ }
+ free( ( void * )theBuf );
+ free( ( void * )theRequest );
+ theResponse = getResponse( inConnection, outStatus );
+ }
+ else
+ {
+ free( ( void * )theRequest );
+ }
+ return theResponse;
+}
+
+void setBlocking( PAPIConnection * inConnection, int inIsBlocking )
+{
+ inConnection->mFDPollTimeout = inIsBlocking == 1 ?
+ -1 : getTransactionTimeout();
+}
+
+PAPIConnection* allocConnection( PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPISocket inSocket,
+ PAPIStatus * outStatus )
+{
+ PAPIConnection * theConnection =
+ ( PAPIConnection * )malloc( sizeof( PAPIConnection ) );
+ if ( theConnection != 0 )
+ {
+ theConnection->mFD = inSocket;
+ theConnection->mFDPollTimeout = getTransactionTimeout();
+ theConnection->mListeners = 0;
+ theConnection->mSavedMessage = 0;
+ theConnection->mListenerThreadStatus = NOT_RUNNING;
+ theConnection->mConnectionListener = inConnectionListener;
+ theConnection->mUserData = inUserData;
+ theConnection->mListenersMutex = newMutex();
+ theConnection->mSavedMessageMutex = newMutex();
+ theConnection->mListenerThreadStatusMutex= newMutex();
+ theConnection->mConnectionStateChangeMutex= newMutex();
+ theConnection->mInternalListener = inInternalListener;
+ theConnection->mInternalListenerData = inInternalListenerData;
+ theConnection->mAuthHandler = 0;
+ theConnection->mAuthHandlerUserData =
+ ( PAPIAuthHandlerData * )malloc( sizeof( PAPIAuthHandlerData ) );
+ *outStatus = PAPISuccess;
+ }
+ else
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ }
+ return theConnection;
+}
+
+PAPISocket daemonConnect( int inRetryCount )
+{
+ int thePort = getDaemonPort();
+ PAPISocket theSocket;
+ PAPIConnectResult theRC =
+ getConnectedSocket( thePort, SOCK_STREAM, 0, &theSocket );
+
+ if ( theRC == PAPIConnectRejected ||
+ ( theRC == PAPIConnectFailed && startDaemon() == 0 ) )
+ {
+ theRC =
+ getConnectedSocket( thePort, SOCK_STREAM, inRetryCount, &theSocket);
+ }
+ return theSocket;
+}
+
+void createNotificationThread( PAPIListener inListener,
+ PAPIEventType inType,
+ const char * inComponentName,
+ void * inUserData )
+{
+ NotificationThreadArg * theArg =
+ ( NotificationThreadArg * )malloc( sizeof( NotificationThreadArg ) );
+ if ( theArg != 0 )
+ {
+ theArg->mEvent = ( PAPIEvent * )malloc( sizeof( PAPIEvent ) );
+ if ( theArg->mEvent != 0 )
+ {
+ theArg->mEvent->eventType = inType;
+ theArg->mEvent->componentName = strdup( inComponentName );
+ theArg->mListener = inListener;
+ theArg->mUserData = inUserData;
+
+ createThread( notifier, ( void *)theArg );
+ }
+ }
+}
+
+PAPIListenerThreadStatus getListenerThreadStatus(
+ PAPIConnection * inConnection )
+{
+ PAPIListenerThreadStatus theListenerThreadStatus = NOT_RUNNING;
+ if ( lockMutex( inConnection->mListenerThreadStatusMutex ) == 0 )
+ {
+ theListenerThreadStatus = inConnection->mListenerThreadStatus;
+ unlockMutex( inConnection->mListenerThreadStatusMutex );
+ }
+ return theListenerThreadStatus;
+}
+
+PAPIMessage * getResponse( PAPIConnection * inConnection,
+ PAPIStatus * outStatus )
+{
+ PAPIMessage * theResponse = 0;
+ *outStatus = PAPISuccess;
+ while ( theResponse == 0 && inConnection->mFD != INVALID_SOCKET )
+ {
+ if ( lockMutex( inConnection->mSavedMessageMutex ) == 0 )
+ {
+ theResponse = inConnection->mSavedMessage;
+ inConnection->mSavedMessage = 0;
+ unlockMutex( inConnection->mSavedMessageMutex );
+ }
+ takeFive();
+ }
+ if ( theResponse == 0 || inConnection->mFD == INVALID_SOCKET )
+ {
+ *outStatus = PAPIConnectionFailure;
+ }
+ return theResponse;
+}
+
+PAPIMessage * getResponseMessage( PAPIConnection * inConnection,
+ PAPIStatus * outStatus )
+{
+ PAPISAXUserData theUserData;
+ PAPISAXParserContext theSAXParserContext;
+ PAPIMessage * theResponse = 0;
+
+ theUserData.mMessage = 0;
+ theSAXParserContext =
+ newSAXParserContext( inConnection, &theUserData );
+ if ( parse( theSAXParserContext ) != 0 )
+ {
+ if ( inConnection->mFD == INVALID_SOCKET )
+ {
+ *outStatus = PAPIConnectionFailure;
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+ }
+ deleteSAXParserContext( theSAXParserContext );
+ return theUserData.mMessage;
+}
+
+void handleSASLAuth( PAPIConnection * inConnection, PAPIMessage * inChallenge )
+{
+ PAPIAuthHandler theHandler = inConnection->mAuthHandler;
+ PAPIAuthHandlerData * theData = inConnection->mAuthHandlerUserData;
+ theData->mChallenge = inChallenge;
+ /* avoid calling handler repeatedly during sasl auth */
+ inConnection->mAuthHandler = 0;
+ createThread( theHandler, theData );
+}
+
+int haveMessage( PAPIConnection * inConnection )
+{
+ int bHaveMessage = 0;
+ int theRC;
+
+ theRC = socketPoll( inConnection->mFD, inConnection->mFDPollTimeout );
+ if ( theRC == 1 )
+ {
+ char theByte;
+ if ( recv( inConnection->mFD, &theByte, 1, MSG_PEEK ) != 1 )
+ {
+ if ( errno != EINTR )
+ {
+ bHaveMessage = -1;
+ }
+ }
+ else
+ {
+ bHaveMessage = 1;
+ }
+ }
+ else
+ {
+ bHaveMessage = -1;
+ }
+ return bHaveMessage;
+}
+
+void * listener( void * inConnection )
+{
+#ifndef WNT
+ sigset_t theSigset;
+#endif
+ PAPIConnection * theConnection = ( PAPIConnection * )inConnection;
+
+#ifndef WNT
+ sigemptyset( &theSigset );
+ sigaddset( &theSigset, SIGHUP );
+ pthread_sigmask( SIG_BLOCK, &theSigset, 0 );
+#endif
+ setListenerThreadStatus( inConnection, RUNNING );
+ while ( getListenerThreadStatus( inConnection ) == RUNNING )
+ {
+ PAPIStatus theStatus;
+ PAPIMessage * theMessage;
+ if ( theConnection->mFD != INVALID_SOCKET )
+ {
+ int bHaveMessage = haveMessage( theConnection );
+ if ( bHaveMessage == 0 )
+ {
+ continue;
+ }
+ else if ( bHaveMessage == -1 )
+ {
+ papiClose( theConnection->mFD );
+ theConnection->mFD = INVALID_SOCKET;
+ if ( lockMutex( theConnection->mConnectionStateChangeMutex )
+ == 0 )
+ {
+ theConnection->mConnectionListener( PAPIDisconnected,
+ theConnection->mUserData );
+ unlockMutex( theConnection->mConnectionStateChangeMutex );
+ }
+ if ( isDaemonEnabled() != 1 )
+ {
+ break;
+ }
+ continue;
+ }
+ theMessage = getResponseMessage( theConnection, &theStatus );
+ if ( theMessage != 0 )
+ {
+ if ( theMessage->mName == PAPImodifyNotification ||
+ theMessage->mName == PAPIaddNotification ||
+ theMessage->mName == PAPIremoveNotification )
+ {
+ sendInternalNotification( theConnection, theMessage );
+ sendNotification( theConnection, theMessage );
+ deleteMessage( theMessage );
+ }
+ else if ( theMessage->mName == PAPIRespSuccessContinueSASLAuth&&
+ theConnection->mAuthHandler != 0 )
+ {
+ handleSASLAuth( theConnection, theMessage );
+ }
+ else
+ {
+ if ( lockMutex( theConnection->mSavedMessageMutex ) == 0 )
+ {
+ theConnection->mSavedMessage = theMessage;
+ unlockMutex( theConnection->mSavedMessageMutex );
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( lockMutex( theConnection->mConnectionStateChangeMutex ) == 0 )
+ {
+ theConnection->mFD = daemonConnect( 1 );
+ setBlocking( theConnection, 0 );
+ if ( theConnection->mFD != INVALID_SOCKET )
+ {
+ theConnection->mConnectionListener( PAPIConnected,
+ theConnection->mUserData );
+ }
+ unlockMutex( theConnection->mConnectionStateChangeMutex );
+ if ( theConnection->mFD == INVALID_SOCKET )
+ {
+ papiSleep( 10 );
+ }
+ }
+ }
+ }
+ setListenerThreadStatus( inConnection, NOT_RUNNING );
+ return 0;
+}
+
+void * notifier( void * inArg )
+{
+ NotificationThreadArg * theArg = ( NotificationThreadArg * )inArg;
+ theArg->mListener( theArg->mEvent, theArg->mUserData );
+ free( ( void *)theArg->mEvent->componentName );
+ free( ( void *)theArg->mEvent );
+ free( ( void *)theArg );
+ return 0;
+}
+
+void sendInternalNotification( PAPIConnection * inConnection,
+ PAPIMessage * inMessage )
+{
+ PAPIMessageName theName = inMessage->mName;
+ if ( theName == PAPIaddNotification || theName == PAPIremoveNotification )
+ {
+ PAPIStringList * theComponentNames =
+ getParamValue( inMessage, PAPIParamComponentName );
+ PAPIStringList * theTmpList = theComponentNames;
+ while ( theTmpList != 0 )
+ {
+ PAPIEvent theEvent;
+ theEvent.eventType =
+ theName == PAPIaddNotification ?
+ PAPIComponentAdd : PAPIComponentRemove;
+ theEvent.componentName = theTmpList->data;
+ inConnection->mInternalListener(
+ &theEvent,
+ inConnection->mInternalListenerData );
+ theTmpList = theTmpList->next;
+ }
+ deleteStringList( theComponentNames );
+ }
+}
+
+void sendNotification( PAPIConnection * inConnection, PAPIMessage * inMessage )
+{
+ PAPIStringList * theComponentNames =
+ getParamValue( inMessage, PAPIParamComponentName );
+ PAPIStringList * theTmpList = theComponentNames;
+ while ( theComponentNames != 0 )
+ {
+ PAPIListenerList * theListenerList;
+
+ if ( lockMutex( inConnection->mListenersMutex ) == 0 )
+ {
+ theListenerList = inConnection->mListeners;
+ while ( theListenerList != 0 )
+ {
+ int theLen = strlen( theListenerList->mComponentName );
+ if ( strcmp( theListenerList->mComponentName,
+ theComponentNames->data ) == 0 ||
+ ( theListenerList->mComponentName[ theLen - 1 ] == '.' &&
+ strncmp( theListenerList->mComponentName,
+ theComponentNames->data,
+ theLen ) == 0 ) )
+ {
+ PAPIEventType theEventType;
+ switch( inMessage->mName )
+ {
+ case PAPImodifyNotification:
+ theEventType = PAPIComponentModify;
+ break;
+
+ case PAPIaddNotification:
+ theEventType = PAPIComponentAdd;
+ break;
+
+ case PAPIremoveNotification:
+ theEventType = PAPIComponentRemove;
+ break;
+ }
+ createNotificationThread( theListenerList->mListener,
+ theEventType,
+ theComponentNames->data,
+ theListenerList->mUserData);
+ }
+ theListenerList = theListenerList->mNext;
+ }
+ theComponentNames = theComponentNames->next;
+ unlockMutex( inConnection->mListenersMutex );
+ }
+ }
+ deleteStringList( theTmpList );
+}
+
+void setListenerThreadStatus( PAPIConnection * inConnection,
+ PAPIListenerThreadStatus inStatus )
+{
+ if ( lockMutex(inConnection->mListenerThreadStatusMutex ) == 0 )
+ {
+ inConnection->mListenerThreadStatus = inStatus;
+ unlockMutex( inConnection->mListenerThreadStatusMutex );
+ }
+}
+
+void startListeningThread( PAPIConnection * inConnection,
+ PAPIStatus * outStatus )
+{
+ inConnection->mListenerThread = createThread( listener, inConnection );
+ if ( inConnection->mListenerThread != 0 )
+ {
+ *outStatus = PAPISuccess;
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+}
+
+void stopListeningThread( PAPIConnection * inConnection, PAPIStatus * outStatus)
+{
+ *outStatus = PAPISuccess;
+ if ( getListenerThreadStatus( inConnection ) == RUNNING )
+ {
+ if ( lockMutex( inConnection->mListenersMutex ) == 0 )
+ {
+ destroyThread( inConnection->mListenerThread );
+ papiClose( inConnection->mFD );
+ unlockMutex( inConnection->mListenersMutex );
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+ }
+}
+
+void takeFive( void )
+{
+#ifndef WNT
+
+ struct timespec theTimeout;
+
+ theTimeout.tv_sec = 0;
+ theTimeout.tv_nsec = 5000000;
+ nanosleep( &theTimeout, NULL);
+
+#else
+
+ Sleep( 50 );
+
+#endif
+}
diff --git a/libapoc/papiConnection.h b/libapoc/papiConnection.h
new file mode 100644
index 0000000..b973806
--- /dev/null
+++ b/libapoc/papiConnection.h
@@ -0,0 +1,117 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#ifndef PAPICONNECTION_H_
+#define PAPICONNECTION_H_
+
+#include "papiListenerList.h"
+#include "papiMessage.h"
+#include "papiUtils.h"
+#include "papiTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum { NOT_RUNNING, EXITING, RUNNING } PAPIListenerThreadStatus;
+
+typedef struct PAPIAuthHandlerData
+{
+ void * mUserData;
+ PAPIMessage * mChallenge;
+} PAPIAuthHandlerData;
+
+typedef void * ( *PAPIAuthHandler )( void * inAuthData );
+
+typedef struct PAPIConnection
+{
+ PAPISocket mFD;
+ int mFDPollTimeout;
+ PAPIListenerList * mListeners;
+ PAPIMutex * mListenersMutex;
+ PAPIMessage * mSavedMessage;
+ PAPIMutex * mSavedMessageMutex;
+ PAPIThread mListenerThread;
+ PAPIListenerThreadStatus mListenerThreadStatus;
+ PAPIMutex * mListenerThreadStatusMutex;
+ PAPIConnectionListener mConnectionListener;
+ PAPIMutex * mConnectionStateChangeMutex;
+ void * mUserData;
+ PAPIListener mInternalListener;
+ void * mInternalListenerData;
+ PAPIAuthHandler mAuthHandler;
+ PAPIAuthHandlerData * mAuthHandlerUserData;
+} PAPIConnection;
+
+PAPIListenerId connectionAddListener( PAPIConnection * inConnection,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+void connectionRemoveListener( PAPIConnection * inConnection,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus );
+
+void connectionSetSASLAuthHandler( PAPIConnection * inConnection,
+ PAPIAuthHandler inAuthHandler,
+ void * inUserData );
+
+void deleteConnection ( PAPIConnection * inConnection );
+
+
+PAPIConnection * newConnection( PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPIStatus * outStatus );
+
+int readBytes( PAPIConnection * inConnection,
+ char * inBuffer,
+ int inLen );
+
+int readContentLength( PAPIConnection * inConnection );
+
+PAPIMessage * sendRequest( PAPIConnection * inConnection,
+ PAPIMessage * inRequest,
+ PAPIStatus * outStatus );
+
+void setBlocking( PAPIConnection * inConnection,
+ int inIsBlocking );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPICONNECTION_H_ */
diff --git a/libapoc/papiDaemon.c b/libapoc/papiDaemon.c
new file mode 100644
index 0000000..841ee19
--- /dev/null
+++ b/libapoc/papiDaemon.c
@@ -0,0 +1,516 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papiDaemon.h"
+#include "papiMessage.h"
+#include "papiUtils.h"
+#include "papiEntityList.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static PAPIMessage * createCreateSessionRequest(
+ const char * inUserId,
+ const PAPIEntityList * inEntityId,
+ const char * inCredentials );
+
+static void createSession( PAPIDaemon * inDaemon,
+ PAPIStatus * outStatus );
+
+static void daemonReaddListener( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIStatus * outStatus );
+
+static void destroySession( PAPIDaemon * inDaemon );
+
+static const char * getLocalCreds( const char * inLocalChallengeFile,
+ PAPIStatus * outStatus );
+
+static void * saslAuthHandler( void * inData );
+
+static int sLocalCredentialsBufferSize = 21;
+
+PAPIListenerId daemonAddListener( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIListenerId theListenerId = 0;
+ daemonReaddListener( inDaemon, inComponentName, outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ theListenerId = connectionAddListener( inDaemon->mConnection,
+ inComponentName,
+ inListener,
+ inUserData,
+ outStatus );
+ }
+ return theListenerId;
+}
+
+PAPIStringList * daemonList( PAPIDaemon * inDaemon, PAPIStatus * outStatus )
+{
+ PAPIStringList * theList = 0;
+ if ( inDaemon->mSessionId != 0 )
+ {
+ PAPIMessage * theRequest;
+ PAPIMessage * theResponse;
+
+ theRequest = newMessage( PAPIReqList );
+ if ( theRequest == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return 0;
+ }
+ addParam( theRequest, PAPIParamSessionId, inDaemon->mSessionId );
+ theResponse = sendRequest( inDaemon->mConnection,theRequest,outStatus );
+ if ( theResponse != 0 )
+ {
+ theList = getParamValue( theResponse, PAPIParamComponentName );
+ }
+
+ deleteMessage( theRequest );
+ deleteMessage( theResponse );
+ }
+ return theList;
+}
+
+PAPIStringList * daemonRead( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIStatus * outStatus )
+{
+ PAPIStringList * theLayers = 0;
+ if ( inDaemon->mSessionId != 0 )
+ {
+ PAPIMessage * theRequest;
+ PAPIMessage * theResponse;
+
+ theRequest = newMessage( PAPIReqRead );
+ if ( theRequest == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return 0;
+ }
+ addParam( theRequest, PAPIParamSessionId, inDaemon->mSessionId );
+ addParam( theRequest, PAPIParamComponentName, inComponentName );
+ theResponse = sendRequest( inDaemon->mConnection,theRequest,outStatus );
+ if ( theResponse != 0 )
+ {
+ theLayers = getParamValue( theResponse, PAPIParamLayer );
+ }
+
+ deleteMessage( theRequest );
+ deleteMessage( theResponse );
+ }
+ return theLayers;
+}
+
+void daemonReconnect( PAPIDaemon * inDaemon,
+ PAPIStatus * outStatus )
+{
+ setBlocking( inDaemon->mConnection, 0 );
+ createSession( inDaemon, outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ PAPIListenerList * theList = inDaemon->mConnection->mListeners;
+ setBlocking( inDaemon->mConnection, 1 );
+ while ( theList != 0 )
+ {
+ daemonReaddListener( inDaemon, theList->mComponentName, outStatus);
+ theList = theList->mNext;
+ }
+ }
+}
+
+void daemonRemoveListener( PAPIDaemon * inDaemon,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus )
+{
+ *outStatus = PAPISuccess;
+ if ( inDaemon->mSessionId != 0 && inListenerId != 0 )
+ {
+ PAPIMessage * theRequest;
+ PAPIMessage * theResponse;
+ PAPIListenerList * theListenerList =
+ ( PAPIListenerList * )inListenerId;
+ const char * theComponentName = theListenerList->mComponentName;
+
+ if ( theComponentName == 0 )
+ {
+ return;
+ }
+
+ theRequest = newMessage( PAPIReqRemoveListener );
+ if ( theRequest == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return;
+ }
+ addParam( theRequest, PAPIParamSessionId, inDaemon->mSessionId );
+ addParam( theRequest, PAPIParamComponentName, theComponentName );
+ theResponse = sendRequest( inDaemon->mConnection,theRequest,outStatus );
+ deleteMessage( theRequest );
+ deleteMessage( theResponse );
+
+ if ( *outStatus == PAPISuccess )
+ {
+ connectionRemoveListener( inDaemon->mConnection,
+ inListenerId,
+ outStatus );
+ }
+ }
+}
+
+void deleteDaemon( PAPIDaemon * inDaemon )
+{
+ if ( inDaemon != 0 )
+ {
+ if ( inDaemon->mUserId != 0 )
+ {
+ free( ( void *)inDaemon->mUserId );
+ }
+ if ( inDaemon->mEntities != 0 )
+ {
+ papiFreeEntityList( inDaemon->mEntities );
+ }
+ if ( inDaemon->mSessionId != 0 )
+ {
+ destroySession( inDaemon );
+ free( ( void * )inDaemon->mSessionId );
+ }
+ deleteConnection( inDaemon->mConnection );
+ free( inDaemon );
+ }
+}
+
+static void fillDaemonEntities( PAPIDaemon * inDaemon )
+{
+ PAPIEntityList *theEntity = inDaemon->mEntities;
+
+ while ( theEntity != 0 )
+ {
+ switch ( theEntity->entityType )
+ {
+ case PAPIEntityUser:
+ if ( theEntity->entityId == 0 )
+ {
+ theEntity->entityId = strdup(inDaemon->mUserId);
+ }
+ break ;
+ default:
+ break ;
+ }
+ theEntity = theEntity->next;
+ }
+}
+
+PAPIDaemon * newDaemon( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inListener,
+ void * inUserData,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPIStatus * outStatus )
+{
+ PAPIDaemon * theDaemon = ( PAPIDaemon *)malloc( sizeof( PAPIDaemon ) );
+ if ( theDaemon == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return 0;
+ }
+ memset( theDaemon, 0, sizeof( PAPIDaemon ) );
+ theDaemon->mUserId = getUserName();
+ if ( theDaemon->mUserId == 0 )
+ {
+ *outStatus = PAPIUnknownFailure;
+ deleteDaemon( theDaemon );
+ return 0;
+ }
+ if ( inEntities != 0 )
+ {
+ theDaemon->mEntities = papiCopyEntityList( inEntities );
+ if ( theDaemon->mEntities == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ deleteDaemon( theDaemon );
+ return 0;
+ }
+ fillDaemonEntities( theDaemon );
+ }
+
+
+ theDaemon->mConnection = newConnection( inListener,
+ inUserData,
+ inInternalListener,
+ inInternalListenerData,
+ outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ daemonReconnect( theDaemon, outStatus );
+ }
+ if ( *outStatus != PAPISuccess && *outStatus != PAPIConnectionFailure )
+ {
+ deleteDaemon( theDaemon );
+ theDaemon = 0;
+ }
+ return theDaemon;
+}
+
+PAPIMessage * createCreateSessionRequest( const char * inUserId,
+ const PAPIEntityList * inEntities,
+ const char * inCredentials )
+{
+ PAPIMessage * theRequest = newMessage( PAPIReqCreateSessionExt );
+ if ( theRequest != 0 )
+ {
+ const PAPIEntityList * entity = inEntities;
+
+ addParam( theRequest, PAPIParamUserId, inUserId );
+ addParam( theRequest, PAPIParamCredentials, inCredentials );
+ while ( entity != 0 )
+ {
+ addParam( theRequest, PAPIParamEntityType,
+ getEntityTypeString( entity->entityType ) );
+ addParam( theRequest, PAPIParamEntityId, entity->entityId );
+ entity = entity->next;
+ }
+ }
+ return theRequest;
+}
+
+void createSession( PAPIDaemon * inDaemon,
+ PAPIStatus * outStatus )
+{
+ int shouldContinue = 1;
+ char * theCreds = 0;
+ void * theSASLContext = 0;
+
+ connectionSetSASLAuthHandler( inDaemon->mConnection, 0, 0 );
+ while ( shouldContinue == 1 )
+ {
+ PAPIMessage * theResponse;
+ PAPIMessage * theRequest =
+ createCreateSessionRequest( inDaemon->mUserId,
+ inDaemon->mEntities,
+ theCreds );
+ if ( theCreds != 0 )
+ {
+ free( ( void * )theCreds );
+ }
+ if ( theRequest == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ connectionSetSASLAuthHandler( inDaemon->mConnection,
+ saslAuthHandler,
+ inDaemon );
+ return;
+ }
+ theResponse = sendRequest(inDaemon->mConnection, theRequest, outStatus);
+ deleteMessage( theRequest );
+ if ( *outStatus == PAPISuccess )
+ {
+ PAPIStringList * theValues;
+ switch( theResponse->mName )
+ {
+ case PAPIRespSuccess:
+ theValues = getParamValue( theResponse, PAPIParamSessionId);
+ if ( theValues != 0 )
+ {
+ inDaemon->mSessionId = strdup( theValues->data );
+ deleteStringList( theValues );
+ }
+ shouldContinue = 0;
+ break;
+
+ case PAPIRespSuccessContinueLocalAuth:
+ case PAPIRespSuccessContinueSASLAuth:
+ theValues = getParamValue( theResponse, PAPIParamMessage );
+ if ( theValues != 0 )
+ {
+ theCreds =
+ theResponse->mName == PAPIRespSuccessContinueLocalAuth?
+ ( char * )getLocalCreds( theValues->data,
+ outStatus ) :
+ ( char * )getSASLCreds( theValues->data,
+ outStatus );
+ if ( *outStatus != PAPISuccess )
+ {
+ theCreds = 0;
+ *outStatus = PAPISuccess;
+ }
+ deleteStringList( theValues );
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ shouldContinue = 0;
+ }
+ break;
+
+ case PAPIRespConnectionFailure:
+ case PAPIRespAuthenticationFailure:
+ *outStatus = PAPISuccess;
+ shouldContinue = 0;
+ break;
+
+ default:
+ *outStatus = PAPIUnknownFailure;
+ shouldContinue = 0;
+ break;
+ }
+ }
+ else
+ {
+ shouldContinue = 0;
+ }
+ deleteMessage( theResponse );
+ }
+ connectionSetSASLAuthHandler( inDaemon->mConnection,
+ saslAuthHandler,
+ inDaemon );
+}
+
+void daemonReaddListener( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIStatus * outStatus )
+{
+ if ( inDaemon->mSessionId != 0 )
+ {
+ PAPIMessage * theRequest;
+ PAPIMessage * theResponse;
+
+ theRequest = newMessage( PAPIReqAddListener );
+ if ( theRequest == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return;
+ }
+ addParam( theRequest, PAPIParamSessionId, inDaemon->mSessionId );
+ addParam( theRequest, PAPIParamComponentName, inComponentName );
+ theResponse = sendRequest( inDaemon->mConnection,theRequest,outStatus );
+ deleteMessage( theRequest );
+ deleteMessage( theResponse );
+ }
+ else
+ {
+ *outStatus = PAPIAuthenticationFailure;
+ }
+}
+
+void destroySession( PAPIDaemon * inDaemon )
+{
+ if ( inDaemon->mSessionId != 0 )
+ {
+ PAPIMessage * theRequest;
+ PAPIMessage * theResponse;
+ PAPIStatus theStatus;
+
+ theRequest = newMessage( PAPIReqDestroySession );
+ if ( theRequest == 0 )
+ {
+ return;
+ }
+ addParam( theRequest, PAPIParamSessionId, inDaemon->mSessionId );
+ theResponse = sendRequest( inDaemon->mConnection,theRequest,&theStatus);
+ deleteMessage( theRequest );
+ deleteMessage( theResponse );
+ }
+}
+
+const char * getLocalCreds( const char * inLocalChallengeFile,
+ PAPIStatus * outStatus )
+{
+ char * theCredentials = ( char * )malloc( sLocalCredentialsBufferSize );
+ if ( theCredentials == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return theCredentials;
+ }
+ if ( inLocalChallengeFile != 0 )
+ {
+ FILE * theFile = fopen( inLocalChallengeFile, "r" );
+ if ( theFile != 0 )
+ {
+ fgets( theCredentials,
+ sLocalCredentialsBufferSize,
+ theFile );
+ fclose( theFile );
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+ return theCredentials;
+}
+
+void * saslAuthHandler( void * inData )
+{
+ PAPIAuthHandlerData * theData = ( PAPIAuthHandlerData * )inData;
+ PAPIDaemon * theDaemon = ( PAPIDaemon * )theData->mUserData;
+ PAPIStringList * theValues = getParamValue( theData->mChallenge,
+ PAPIParamMessage );
+ deleteMessage( theData->mChallenge );
+ if ( theValues != 0 )
+ {
+ PAPIStatus theStatus;
+ const char * theCreds =
+ getSASLCreds( theValues->data, &theStatus );
+ PAPIMessage * theRequest =
+ createCreateSessionRequest( theDaemon->mUserId,
+ theDaemon->mEntities,
+ theCreds );
+ deleteStringList( theValues );
+ if ( theCreds != 0 )
+ {
+ free( ( void * )theCreds );
+ }
+ if ( theRequest != 0 )
+ {
+ PAPIMessage * theResponse =
+ sendRequest( theDaemon->mConnection, theRequest,&theStatus);
+ deleteMessage( theResponse );
+ deleteMessage( theRequest );
+ }
+ }
+ connectionSetSASLAuthHandler( theDaemon->mConnection,
+ saslAuthHandler,
+ theDaemon );
+ return 0;
+}
diff --git a/libapoc/papiDaemon.h b/libapoc/papiDaemon.h
new file mode 100644
index 0000000..b7732b8
--- /dev/null
+++ b/libapoc/papiDaemon.h
@@ -0,0 +1,91 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+/* papiDaemon.h */
+
+#ifndef PAPIDAEMON_H_
+#define PAPIDAEMON_H_
+
+#include "papiConnection.h"
+#include "papiTypes.h"
+#include "papiInternal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct PAPIDaemon
+{
+ const char * mUserId;
+ PAPIEntityList * mEntities;
+ PAPIConnection * mConnection;
+ const char * mSessionId;
+ PAPIConnectionListener mConnectionListener;
+ void * mUserData;
+} PAPIDaemon;
+
+PAPIListenerId daemonAddListener( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+PAPIStringList *daemonList( PAPIDaemon * inDaemon,
+ PAPIStatus * outStatus );
+
+PAPIStringList *daemonRead( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIStatus * outStatus );
+
+void daemonReconnect( PAPIDaemon * inDaemon,
+ PAPIStatus * outStatus );
+
+void daemonRemoveListener( PAPIDaemon * inDaemon,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus );
+
+void deleteDaemon( PAPIDaemon * inDaemon );
+
+PAPIDaemon * newDaemon( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inListener,
+ void * inUserData,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPIStatus * outStatus );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPIDAEMON_H_ */
diff --git a/libapoc/papiDatabase.c b/libapoc/papiDatabase.c
new file mode 100644
index 0000000..dad61e6
--- /dev/null
+++ b/libapoc/papiDatabase.c
@@ -0,0 +1,285 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papiDatabase.h"
+#include "papiInternal.h"
+#include "papiUtils.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void connectionListener( PAPIConnectionState inState,
+ void * inUserData);
+
+static int componentExists( PAPIDatabase * inDatabase,
+ const char * inComponentName );
+
+static void componentsListener( const PAPIEvent * inEvent,
+ void * inUserData );
+
+static void * onConnect( void * inDatabase );
+
+static void * onDisconnect( void * inDatabase );
+
+#define TIMESTAMPSIZE 16
+
+
+PAPIListenerId addListenerToDatabase( PAPIDatabase * inDatabase,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ return daemonAddListener( inDatabase->mDaemon,
+ inComponentName,
+ inListener,
+ inUserData,
+ outStatus );
+}
+
+void deleteDatabase( PAPIDatabase * inDatabase )
+{
+ if ( inDatabase != 0 )
+ {
+ deleteStringList( inDatabase->mComponents );
+ deleteMutex( inDatabase->mComponentsMutex );
+ if ( inDatabase->mDaemon != 0 )
+ {
+ deleteDaemon( inDatabase->mDaemon );
+ }
+ deleteMutex( inDatabase->mConnectionStateMutex );
+ free( ( void *)inDatabase );
+ }
+}
+
+PAPIConnectionState getConnectionState( PAPIDatabase * inDatabase )
+{
+ PAPIConnectionState theState = PAPIDisconnected;
+ if ( lockMutex( inDatabase->mConnectionStateMutex ) == 0 )
+ {
+ theState = inDatabase->mConnectionState;
+ unlockMutex( inDatabase->mConnectionStateMutex );
+ }
+ return theState;
+}
+
+PAPILayerList * readLayersFromDatabase( PAPIDatabase * inDatabase,
+ const char * inComponentName,
+ PAPIStatus * outStatus )
+{
+ PAPILayerList * theLayerList = 0;
+ if ( componentExists( inDatabase, inComponentName ) != 0 )
+ {
+ PAPIStringList * theTmpList =
+ daemonRead( inDatabase->mDaemon, inComponentName, outStatus );
+ PAPIStringList * theList = theTmpList;
+ while ( theTmpList != 0 )
+ {
+ if ( theTmpList->data != 0 &&
+ strlen( theTmpList->data ) >= TIMESTAMPSIZE )
+ {
+ char theTimestamp[ TIMESTAMPSIZE ];
+ snprintf( theTimestamp, TIMESTAMPSIZE, "%s", theTmpList->data);
+#ifdef WNT
+ theTimestamp[ TIMESTAMPSIZE - 1 ] = 0;
+#endif
+ addLayerList( &theLayerList,
+ theTmpList->data + TIMESTAMPSIZE - 1,
+ theTimestamp );
+ theTmpList = theTmpList->next;
+ }
+ }
+ deleteStringList( theList );
+ }
+ else
+ {
+ *outStatus = PAPINoSuchComponentFailure;
+ }
+ return theLayerList;
+}
+
+PAPIStringList * readNamesFromDatabase( PAPIDatabase * inDatabase,
+ const char * inFilter )
+{
+ PAPIStringList * theList = 0;
+ if ( lockMutex( inDatabase->mComponentsMutex ) == 0 )
+ {
+ theList = copyStringList( inDatabase->mComponents );
+ unlockMutex( inDatabase->mComponentsMutex );
+ }
+ return theList;
+}
+
+void removeListenerFromDatabase( PAPIDatabase * inDatabase,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus )
+{
+ daemonRemoveListener( inDatabase->mDaemon, inListenerId, outStatus );
+}
+
+PAPIDatabase * newDatabase( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIDatabase * theDatabase =
+ ( PAPIDatabase *)malloc( sizeof( PAPIDatabase ) );
+
+ if ( theDatabase == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return 0;
+ }
+ memset( theDatabase, 0, sizeof( PAPIDatabase ) );
+ theDatabase->mConnectionListener = inConnectionListener;
+ theDatabase->mUserData = inUserData;
+ theDatabase->mConnectionState = PAPIDisconnected;
+ theDatabase->mConnectionStateMutex = newMutex();
+ if ( lockMutex( theDatabase->mConnectionStateMutex ) == 0 )
+ {
+ theDatabase->mDaemon = newDaemon( inEntities,
+ connectionListener,
+ theDatabase,
+ componentsListener,
+ theDatabase,
+ outStatus );
+ if ( *outStatus != PAPISuccess &&
+ ( *outStatus != PAPIConnectionFailure || isDaemonEnabled() == 0 ) )
+ {
+ unlockMutex( theDatabase->mConnectionStateMutex );
+ deleteDatabase( theDatabase );
+ theDatabase = 0;
+ }
+ else
+ {
+ if ( *outStatus == PAPISuccess )
+ {
+ theDatabase->mComponents =
+ daemonList( theDatabase->mDaemon, outStatus );
+ theDatabase->mConnectionState = PAPIConnected;
+ }
+ theDatabase->mComponentsMutex = newMutex();
+ unlockMutex( theDatabase->mConnectionStateMutex );
+ }
+ }
+ return theDatabase;
+}
+
+void connectionListener( PAPIConnectionState inState, void * inUserData )
+{
+ createThread( inState == PAPIConnected ? onConnect : onDisconnect,
+ inUserData );
+}
+
+int componentExists( PAPIDatabase * inDatabase, const char * inComponentName )
+{
+ int haveComponent = 0;
+ if ( lockMutex( inDatabase->mComponentsMutex ) == 0 )
+ {
+ haveComponent =
+ containsString( inDatabase->mComponents, inComponentName );
+ unlockMutex( inDatabase->mComponentsMutex );
+ }
+ return haveComponent;
+}
+
+void componentsListener( const PAPIEvent * inEvent, void * inUserData )
+{
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inUserData;
+ if ( lockMutex( theDatabase->mComponentsMutex ) == 0 )
+ {
+ if ( inEvent->eventType == PAPIComponentAdd )
+ {
+ addStringList( &theDatabase->mComponents,
+ ( const char * )inEvent->componentName );
+ }
+ else
+ {
+ deleteStringList(
+ removeStringList( &theDatabase->mComponents,
+ ( const char * )inEvent->componentName ) );
+ }
+ unlockMutex( theDatabase->mComponentsMutex );
+ }
+}
+
+void * onConnect( void * inDatabase )
+{
+ PAPIStatus theStatus;
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inDatabase;
+ if ( lockMutex( theDatabase->mConnectionStateMutex ) == 0 )
+ {
+ daemonReconnect( theDatabase->mDaemon,
+ &theStatus );
+ if ( theStatus == PAPISuccess )
+ {
+ theDatabase->mConnectionState = PAPIConnected;
+ if ( lockMutex( theDatabase->mComponentsMutex ) == 0 )
+ {
+ deleteStringList( theDatabase->mComponents );
+ theDatabase->mComponents =
+ daemonList( theDatabase->mDaemon, &theStatus );
+ unlockMutex( theDatabase->mComponentsMutex );
+ }
+ unlockMutex( theDatabase->mConnectionStateMutex );
+ if ( theDatabase->mConnectionListener != 0 )
+ {
+ theDatabase->mConnectionListener( PAPIConnected,
+ theDatabase->mUserData );
+ }
+ }
+ else
+ {
+ unlockMutex( theDatabase->mConnectionStateMutex );
+ }
+ }
+ return 0;
+}
+
+void * onDisconnect( void * inDatabase )
+{
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inDatabase;
+ if ( lockMutex( theDatabase->mConnectionStateMutex ) == 0 )
+ {
+ theDatabase->mConnectionState = PAPIDisconnected;
+ unlockMutex( theDatabase->mConnectionStateMutex );
+ if ( theDatabase->mConnectionListener != 0 )
+ {
+ theDatabase->mConnectionListener( PAPIDisconnected,
+ theDatabase->mUserData );
+ }
+ }
+ return 0;
+}
diff --git a/libapoc/papiDatabase.h b/libapoc/papiDatabase.h
new file mode 100644
index 0000000..e8e3b86
--- /dev/null
+++ b/libapoc/papiDatabase.h
@@ -0,0 +1,88 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+/* papiDatabase.h */
+
+#ifndef PAPIDATABASE_H_
+#define PAPIDATABASE_H_
+
+#include "papiTypes.h"
+#include "papiDaemon.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct PAPIDatabase
+{
+ PAPIStringList * mComponents;
+ PAPIMutex * mComponentsMutex;
+ PAPIDaemon * mDaemon;
+ PAPIConnectionState mConnectionState;
+ PAPIMutex * mConnectionStateMutex;
+ PAPIConnectionListener mConnectionListener;
+ void * mUserData;
+} PAPIDatabase;
+
+PAPIListenerId addListenerToDatabase( PAPIDatabase * inDatabase,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+void deleteDatabase( PAPIDatabase * inDatabase );
+
+PAPIConnectionState getConnectionState( PAPIDatabase * inDatabase );
+
+PAPILayerList * readLayersFromDatabase( PAPIDatabase * inDatabase,
+ const char * inComponentName,
+ PAPIStatus * outStatus );
+
+PAPIStringList * readNamesFromDatabase( PAPIDatabase * inDatabase,
+ const char * inFilter );
+
+void removeListenerFromDatabase( PAPIDatabase * inDatabase,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus );
+
+PAPIDatabase * newDatabase( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPIDATABASE_H_ */
diff --git a/libapoc/papiEntityList.c b/libapoc/papiEntityList.c
new file mode 100644
index 0000000..3a2249a
--- /dev/null
+++ b/libapoc/papiEntityList.c
@@ -0,0 +1,92 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#include "papiEntityList.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+PAPIEntityList *papiAddEntityItem(PAPIEntityList *aEntities,
+ PAPIEntityType aEntityType,
+ const char *aEntityId)
+{
+ PAPIEntityList *retCode = aEntities ;
+
+ if (aEntityId != NULL)
+ {
+ PAPIEntityList *last = retCode ;
+ PAPIEntityList *newItem = malloc(sizeof(PAPIEntityList)) ;
+
+ newItem->entityType = aEntityType ;
+ newItem->entityId = strdup(aEntityId) ;
+ newItem->next = NULL ;
+ while (last != NULL && last->next != NULL) { last = last->next ; }
+ if (last != NULL) { last->next = newItem ; }
+ else { retCode = newItem ; }
+ }
+ return retCode ;
+}
+
+PAPIEntityList *papiCopyEntityList(const PAPIEntityList *aEntities)
+{
+ PAPIEntityList *retCode = NULL ;
+
+ if (aEntities != NULL)
+ {
+ retCode = malloc(sizeof(PAPIEntityList)) ;
+ retCode->entityType = aEntities->entityType ;
+ if (aEntities->entityId != NULL)
+ {
+ retCode->entityId = strdup(aEntities->entityId) ;
+ }
+ else { retCode->entityId = NULL ; }
+ retCode->next = papiCopyEntityList(aEntities->next) ;
+ }
+ return retCode ;
+}
+
+void papiFreeEntityList(PAPIEntityList *aEntities)
+{
+ if (aEntities != NULL)
+ {
+ if (aEntities->entityId != NULL)
+ {
+ free((void *) aEntities->entityId) ;
+ }
+ if (aEntities->next != NULL) { papiFreeEntityList(aEntities->next) ; }
+ free(aEntities) ;
+ }
+}
+
diff --git a/libapoc/papiEntityList.h b/libapoc/papiEntityList.h
new file mode 100644
index 0000000..6a8b207
--- /dev/null
+++ b/libapoc/papiEntityList.h
@@ -0,0 +1,56 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#ifndef PAPI_ENTITY_LIST_H_
+#define PAPI_ENTITY_LIST_H_
+
+/* Recognised entity types. */
+typedef enum { PAPIEntityHost = 0,
+ PAPIEntityUser } PAPIEntityType;
+
+typedef struct PAPIEntityList
+{
+ PAPIEntityType entityType;
+ const char * entityId;
+ struct PAPIEntityList * next;
+} PAPIEntityList;
+
+PAPIEntityList * papiAddEntityItem( PAPIEntityList * inEntities,
+ PAPIEntityType inEntityType,
+ const char * inEntityId );
+void papiFreeEntityList( PAPIEntityList * inEntities );
+PAPIEntityList *papiCopyEntityList(const PAPIEntityList *aEntities) ;
+
+#endif /* PAPI_ENTITY_LIST_H_ */
diff --git a/libapoc/papiInternal.c b/libapoc/papiInternal.c
new file mode 100644
index 0000000..c2c08e6
--- /dev/null
+++ b/libapoc/papiInternal.c
@@ -0,0 +1,227 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papi.h"
+#include "papiDatabase.h"
+
+static PAPIMutex * gMutex = 0;
+
+static int lock( void )
+{
+ int theRC = -1;
+ if ( gMutex == 0 )
+ {
+ gMutex = newMutex();
+ }
+ if ( gMutex != 0 )
+ {
+ theRC = lockMutex( gMutex );
+ }
+ return theRC;
+}
+
+static int unlock( void )
+{
+ int theRC = -1;
+ if ( gMutex != 0 )
+ {
+ theRC = unlockMutex( gMutex );
+ }
+ return theRC;
+}
+
+PAPIListenerId addListener( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inPAPI;
+ PAPIListenerId theListenerId;
+
+ if ( theDatabase != 0 && inComponentName != 0 && inListener != 0 )
+ {
+ if ( getConnectionState( theDatabase ) == PAPIDisconnected )
+ {
+ theStatus = PAPIConnectionFailure;
+ }
+ else if ( lock() == 0 )
+ {
+ theListenerId = addListenerToDatabase( theDatabase,
+ inComponentName,
+ inListener,
+ inUserData,
+ &theStatus );
+ unlock();
+ }
+ }
+ else
+ {
+ theStatus = PAPIInvalidArg;
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = theStatus;
+ }
+ return theListenerId;
+}
+
+void deinitialise( PAPI * inPAPI, PAPIStatus * outStatus )
+{
+ if ( lock() == 0 )
+ {
+ deleteDatabase( ( PAPIDatabase * )inPAPI );
+ unlock();
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = PAPISuccess;
+ }
+}
+
+PAPI * initialise( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPI * thePAPI = 0;
+ if ( lock() == 0 )
+ {
+ thePAPI = ( PAPI *)newDatabase( inEntities,
+ inConnectionListener,
+ inUserData,
+ &theStatus );
+ unlock();
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = theStatus;
+ }
+ return thePAPI;
+}
+
+PAPIStringList * listComponentNames( const PAPI * inPAPI,
+ const char * inFilter,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inPAPI;
+ PAPIStringList * theNames = 0;
+ if ( theDatabase != 0 )
+ {
+ if ( getConnectionState( theDatabase ) == PAPIDisconnected )
+ {
+ theStatus = PAPIConnectionFailure;
+ }
+ else if ( lock() == 0 )
+ {
+ theNames = readNamesFromDatabase( theDatabase, inFilter );
+ theStatus = PAPISuccess;
+ unlock();
+ }
+ }
+ else
+ {
+ theStatus = PAPIInvalidArg;
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = theStatus;
+ }
+ return theNames;
+}
+
+PAPILayerList * readComponentLayers( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inPAPI;
+ PAPILayerList * theLayers = 0;
+
+ if ( theDatabase != 0 && inComponentName != 0 )
+ {
+ if ( getConnectionState( theDatabase ) == PAPIDisconnected )
+ {
+ theStatus = PAPIConnectionFailure;
+ }
+ else if ( lock() == 0 )
+ {
+ theLayers = readLayersFromDatabase( theDatabase,
+ inComponentName,
+ &theStatus );
+ unlock();
+ }
+ }
+ else
+ {
+ theStatus = PAPIInvalidArg;
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = theStatus;
+ }
+ return theLayers;
+}
+
+void removeListener( const PAPI * inPAPI,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inPAPI;
+
+ if ( theDatabase != 0 && inListenerId != 0 )
+ {
+ if ( getConnectionState( theDatabase ) == PAPIDisconnected )
+ {
+ theStatus = PAPIConnectionFailure;
+ }
+ else if ( lock() == 0 )
+ {
+ removeListenerFromDatabase( theDatabase, inListenerId, &theStatus );
+ unlock();
+ }
+ }
+ else
+ {
+ theStatus = PAPIInvalidArg;
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = theStatus;
+ }
+}
diff --git a/libapoc/papiInternal.h b/libapoc/papiInternal.h
new file mode 100644
index 0000000..0b36c17
--- /dev/null
+++ b/libapoc/papiInternal.h
@@ -0,0 +1,81 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#ifndef PAPIINTERNAL_H_
+#define PAPIINTERNAL_H_
+
+#include "papi.h"
+#include "papiLayerList.h"
+#include "papiStringList.h"
+#include "papiEntityList.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PAPIListenerId addListener( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+void deinitialise( PAPI * inPAPI,
+ PAPIStatus * outStatus );
+
+PAPI * initialise( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+PAPIStringList * listComponentNames( const PAPI * inPAPI,
+ const char * inFilter,
+ PAPIStatus * outStatus );
+
+
+
+PAPILayerList * readComponentLayers( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIStatus * outStatus );
+
+
+
+void removeListener( const PAPI * inPAPI,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPIINTERNAL_H_ */
diff --git a/libapoc/papiLayerList.c b/libapoc/papiLayerList.c
new file mode 100644
index 0000000..3cb6def
--- /dev/null
+++ b/libapoc/papiLayerList.c
@@ -0,0 +1,104 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papiLayerList.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static PAPILayerList * newLayerList( void );
+
+PAPILayerList * addLayerList( PAPILayerList ** ioPrevious,
+ const char * inData,
+ const char * inTimestamp )
+{
+ PAPILayerList * theLayerList = ioPrevious[ 0 ];
+
+ if ( inData != 0 )
+ {
+ if ( ( theLayerList = newLayerList() ) != 0 )
+ {
+ theLayerList->data = ( unsigned char * )strdup( inData );
+ theLayerList->size = strlen( inData );
+ theLayerList->timestamp = strdup( inTimestamp );
+ if ( ioPrevious[ 0 ] == 0 )
+ {
+ ioPrevious[ 0 ] = theLayerList;
+ }
+ else
+ {
+ PAPILayerList * theTmpList = ioPrevious[ 0 ];
+ while ( theTmpList->next != 0 )
+ {
+ theTmpList = theTmpList->next;
+ }
+ theTmpList->next = theLayerList;
+ }
+ }
+ }
+ return theLayerList;
+}
+
+void deleteLayerList( PAPILayerList * inLayerList )
+{
+ if ( inLayerList != 0 )
+ {
+ if ( inLayerList->next != 0 )
+ {
+ deleteLayerList( inLayerList->next );
+ }
+ if ( inLayerList->data != 0 )
+ {
+ free( ( void *)inLayerList->data );
+ }
+ if ( inLayerList->timestamp != 0 )
+ {
+ free( ( void *)inLayerList->timestamp );
+ }
+ free( inLayerList );
+ }
+}
+
+PAPILayerList * newLayerList( void )
+{
+ PAPILayerList * theLayerList =
+ ( PAPILayerList * )malloc( sizeof( PAPILayerList ) );
+ if ( theLayerList != 0 )
+ {
+ theLayerList->data = 0;
+ theLayerList->size = 0;
+ theLayerList->next = 0;
+ }
+ return theLayerList;
+}
diff --git a/libapoc/papiLayerList.h b/libapoc/papiLayerList.h
new file mode 100644
index 0000000..55fb938
--- /dev/null
+++ b/libapoc/papiLayerList.h
@@ -0,0 +1,55 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#ifndef PAPILAYERLIST_H_
+#define PAPILAYERLIST_H_
+
+#include "papiTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PAPILayerList * addLayerList( PAPILayerList ** ioPreviousList,
+ const char * inData,
+ const char * inTimestamp );
+
+void deleteLayerList( PAPILayerList * inLayerList );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPILAYERLIST_H_ */
diff --git a/libapoc/papiListenerList.c b/libapoc/papiListenerList.c
new file mode 100644
index 0000000..d7d6222
--- /dev/null
+++ b/libapoc/papiListenerList.c
@@ -0,0 +1,131 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papiListenerList.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static PAPIListenerList * newListenerList( void );
+
+PAPIListenerList * addListenerList( PAPIListenerList ** ioPrevious,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData )
+{
+ PAPIListenerList * theListenerList = ioPrevious[ 0 ];
+
+ if ( inComponentName != 0 && inListener != 0 )
+ {
+ if ( ( theListenerList = newListenerList() ) != 0 )
+ {
+ theListenerList->mComponentName = strdup( inComponentName );
+ theListenerList->mListener = inListener;
+ theListenerList->mUserData = inUserData;
+ if ( ioPrevious[ 0 ] == 0 )
+ {
+ ioPrevious[ 0 ] = theListenerList;
+ }
+ else
+ {
+ PAPIListenerList * theTmpList = ioPrevious[ 0 ];
+ while ( theTmpList->mNext != 0 )
+ {
+ theTmpList = theTmpList->mNext;
+ }
+ theTmpList->mNext = theListenerList;
+ }
+ }
+ }
+ return theListenerList;
+}
+
+void removeListenerList( PAPIListenerList ** ioPreviousList,
+ PAPIListenerList * inList )
+{
+ if ( inList != 0 && ioPreviousList != 0 )
+ {
+ PAPIListenerList * thePreviousList = 0;
+ PAPIListenerList * theNextList = ioPreviousList[ 0 ];
+ while ( theNextList != 0 )
+ {
+ if ( theNextList == inList )
+ {
+ if ( theNextList == ioPreviousList[ 0 ] )
+ {
+ ioPreviousList[ 0 ] = ioPreviousList[ 0 ]->mNext;
+ }
+ else
+ {
+ thePreviousList->mNext = theNextList->mNext;
+ }
+ inList->mNext = 0;
+ deleteListenerList( inList );
+ break;
+ }
+ thePreviousList = theNextList;
+ theNextList = theNextList->mNext;
+ }
+ }
+}
+
+void deleteListenerList( PAPIListenerList * inListenerList )
+{
+ if ( inListenerList != 0 )
+ {
+ if ( inListenerList->mNext != 0 )
+ {
+ deleteListenerList( inListenerList->mNext );
+ }
+ if ( inListenerList->mComponentName != 0 )
+ {
+ free( ( void *)inListenerList->mComponentName );
+ }
+ free( inListenerList );
+ }
+}
+
+PAPIListenerList * newListenerList( void )
+{
+ PAPIListenerList * theListenerList =
+ ( PAPIListenerList * )malloc( sizeof( PAPIListenerList ) );
+ if ( theListenerList != 0 )
+ {
+ theListenerList->mComponentName = 0;
+ theListenerList->mListener = 0;
+ theListenerList->mUserData = 0;
+ theListenerList->mNext = 0;
+ }
+ return theListenerList;
+}
diff --git a/libapoc/papiListenerList.h b/libapoc/papiListenerList.h
new file mode 100644
index 0000000..120b0c3
--- /dev/null
+++ b/libapoc/papiListenerList.h
@@ -0,0 +1,66 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#ifndef PAPILISTENERLIST_H_
+#define PAPILISTENERLIST_H_
+
+#include "papiTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct PAPIListenerList
+{
+ const char * mComponentName;
+ PAPIListener mListener;
+ void * mUserData;
+ struct PAPIListenerList * mNext;
+} PAPIListenerList;
+
+PAPIListenerList * addListenerList( PAPIListenerList ** ioPreviousList,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData );
+
+void removeListenerList( PAPIListenerList ** ioPreviousList,
+ PAPIListenerList * inList );
+
+void deleteListenerList( PAPIListenerList * inListenerList );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPILISTENERLIST_H_ */
diff --git a/libapoc/papiMessage.c b/libapoc/papiMessage.c
new file mode 100644
index 0000000..da95ef8
--- /dev/null
+++ b/libapoc/papiMessage.c
@@ -0,0 +1,293 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "papiMessage.h"
+#include "papiInternal.h"
+
+static PAPIParamNameList * newParamNameList( PAPIParamName inParamName );
+
+static void deleteParamNameList( PAPIParamNameList * inParamNameList );
+
+static PAPIParamNameList * addParamNameList( PAPIParamNameList **ioPreviousList,
+ PAPIParamName inParamName );
+
+static const char *sMessageNames[] =
+{
+ "success",
+ "invalidRequest",
+ "connectionFailure",
+ "authenticationFailure",
+ "invalidSessionId",
+ "noSuchComponent",
+ "successContinueLocalAuth",
+ "successContinueSASLAuth",
+
+ "addNotification",
+ "removeNotification",
+ "modifyNotification",
+
+ "createSession",
+ "read",
+ "list",
+ "destroySession",
+ "addListener",
+ "removeListener",
+ "createSessionExt"
+};
+
+static const char *sParamNames[] =
+{
+ "sessionId",
+ "userId",
+ "entityId",
+ "credentials",
+ "componentName",
+ "clientData",
+ "message",
+ "layer",
+ "entityType"
+};
+
+/* Must be aligned with PAPIEntityType enumeration in papiTypes.h AND
+ must be the same strings as the SOURCE ones in
+ spi/environment/EnvironmentConstants. */
+static const char *sEntityTypes[] =
+{
+ "HOST",
+ "USER"
+};
+
+PAPIMessage * newMessage( PAPIMessageName inMessageName )
+{
+ PAPIMessage * theMessage = ( PAPIMessage * )malloc( sizeof( PAPIMessage ) );
+ if ( theMessage != 0 )
+ {
+ theMessage->mName = inMessageName;
+ theMessage->mParamNames = 0;
+ theMessage->mParamValues = 0;
+ }
+ return theMessage;
+}
+
+void deleteMessage( PAPIMessage * inMessage )
+{
+ if ( inMessage != 0 )
+ {
+ deleteParamNameList( inMessage->mParamNames );
+ deleteStringList( inMessage->mParamValues );
+ free( ( void * )inMessage );
+ }
+}
+
+void addParam( PAPIMessage * inMessage,
+ PAPIParamName inParamName,
+ const char * inParamValue )
+{
+ if ( inMessage != 0 )
+ {
+ addParamNameList( &inMessage->mParamNames, inParamName );
+ addStringList( &inMessage->mParamValues, inParamValue );
+ }
+}
+
+char * messageToString( PAPIMessage * inMessage )
+{
+ int theStringSize;
+ char * theString = 0;
+ if ( inMessage != 0 )
+ {
+ PAPIParamNameList * theNameList = inMessage->mParamNames;
+ PAPIStringList * theValueList = inMessage->mParamValues;
+ theStringSize =
+ ( 2 * strlen( sMessageNames[ ( int )inMessage->mName ] ) ) + 5;
+ while ( theNameList != 0 )
+ {
+ theStringSize +=
+ ( 2 * strlen( sParamNames[ ( int )theNameList->mName ] ) ) + 5;
+ if ( theValueList->data != 0 )
+ {
+ theStringSize += strlen( theValueList->data );
+ }
+ theNameList = theNameList->mNext;
+ theValueList = theValueList->next;
+ }
+
+
+ if ( theStringSize > 0 )
+ {
+ theNameList = inMessage->mParamNames;
+ theValueList = inMessage->mParamValues;
+ theString = ( char * )malloc( theStringSize + 1 );
+ theString[ 0 ] = 0;
+
+ sprintf( theString, "<%s>", sMessageNames[( int )inMessage->mName]);
+ while ( theNameList != 0 )
+ {
+ strcat( theString, "<" );
+ strcat( theString, sParamNames[ ( int )theNameList->mName ] );
+ strcat( theString, ">" );
+
+ if ( theValueList->data != 0 )
+ {
+ strcat( theString, theValueList->data );
+ }
+
+ strcat( theString, "</" );
+ strcat( theString, sParamNames[ ( int )theNameList->mName] );
+ strcat( theString, ">" );
+
+ theNameList = theNameList->mNext;
+ theValueList = theValueList->next;
+ }
+ strcat( theString, "</" );
+ strcat( theString, sMessageNames[ ( int )inMessage->mName ] );
+ strcat( theString, ">" );
+ }
+ }
+ return theString;
+}
+
+PAPIStringList * getParamValue( PAPIMessage * inMessage,
+ PAPIParamName inParamName )
+{
+ PAPIStringList * theValue = 0;
+ if ( inMessage != 0 )
+ {
+ PAPIParamNameList * theNames = inMessage->mParamNames;
+ PAPIStringList * theValues = inMessage->mParamValues;
+ while ( theNames != 0 )
+ {
+ if ( theNames->mName == inParamName )
+ {
+ addStringList( &theValue, theValues->data );
+ }
+ theNames = theNames->mNext;
+ theValues = theValues->next;
+ }
+ }
+ return theValue;
+}
+
+PAPIParamNameList * newParamNameList( PAPIParamName inParamName )
+{
+ PAPIParamNameList * theList =
+ ( PAPIParamNameList * )malloc( sizeof( PAPIParamNameList ) );
+ if ( theList != 0 )
+ {
+ theList->mName = inParamName;
+ theList->mNext = 0;
+ }
+ return theList;
+}
+
+PAPIMessageName stringToMessageName( const char * inMessageName )
+{
+ PAPIMessageName theName = PAPIMessageNameUnused;
+ if ( inMessageName != 0 )
+ {
+ int theIndex;
+ for ( theIndex = 0; theIndex < PAPIMessageNameUnused; theIndex ++ )
+ {
+ if ( strcmp( inMessageName, sMessageNames[ theIndex ] ) == 0 )
+ {
+ theName = ( PAPIMessageName )theIndex;
+ break;
+ }
+ }
+ }
+ return theName;
+}
+
+PAPIParamName stringToParamName( const char * inParamName )
+{
+ PAPIParamName theName = PAPIParamNameUnused;
+ if ( inParamName != 0 )
+ {
+ int theIndex;
+ for ( theIndex = 0; theIndex < PAPIParamNameUnused; theIndex ++ )
+ {
+ if ( strcmp( inParamName, sParamNames[ theIndex ] ) == 0 )
+ {
+ theName = ( PAPIParamName )theIndex;
+ break;
+ }
+ }
+ }
+ return theName;
+}
+
+static void deleteParamNameList( PAPIParamNameList * inParamNameList )
+{
+ if ( inParamNameList != 0 )
+ {
+ if ( inParamNameList->mNext != 0 )
+ {
+ deleteParamNameList( inParamNameList->mNext );
+ }
+ free( ( void * )inParamNameList );
+ }
+}
+
+static PAPIParamNameList * addParamNameList( PAPIParamNameList **ioPrevious,
+ PAPIParamName inParamName )
+{
+ PAPIParamNameList * theList = newParamNameList( inParamName );
+ if ( theList != 0 )
+ {
+ if ( ioPrevious[ 0 ] == 0 )
+ {
+ ioPrevious[ 0 ] = theList;
+ }
+ else
+ {
+ PAPIParamNameList * theTmpList = ioPrevious[ 0 ];
+ while ( theTmpList->mNext != 0 )
+ {
+ theTmpList = theTmpList->mNext;
+ }
+ theTmpList->mNext = theList;
+ }
+ }
+ return theList;
+}
+
+const char * getEntityTypeString( PAPIEntityType inType )
+{
+ return sEntityTypes[ inType ];
+}
+
diff --git a/libapoc/papiMessage.h b/libapoc/papiMessage.h
new file mode 100644
index 0000000..988ee99
--- /dev/null
+++ b/libapoc/papiMessage.h
@@ -0,0 +1,125 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#ifndef PAPIMESSAGE_H_
+#define PAPIMESSAGE_H_
+
+#include "papiTypes.h"
+#include "papiEntityList.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+ PAPIRespSuccess = 0,
+ PAPIRespInvalidRequest,
+ PAPIRespConnectionFailure,
+ PAPIRespAuthenticationFailure,
+ PAPIRespInvalidSessionId,
+ PAPIRespNoSuchComponent,
+ PAPIRespSuccessContinueLocalAuth,
+ PAPIRespSuccessContinueSASLAuth,
+
+ PAPIaddNotification,
+ PAPIremoveNotification,
+ PAPImodifyNotification,
+
+ PAPIReqCreateSession,
+ PAPIReqRead,
+ PAPIReqList,
+ PAPIReqDestroySession,
+ PAPIReqAddListener,
+ PAPIReqRemoveListener,
+ PAPIReqCreateSessionExt,
+
+ PAPIMessageNameUnused
+
+} PAPIMessageName;
+
+typedef enum
+{
+ PAPIParamSessionId = 0,
+ PAPIParamUserId,
+ PAPIParamEntityId,
+ PAPIParamCredentials,
+ PAPIParamComponentName,
+ PAPIParamClientData,
+ PAPIParamMessage,
+ PAPIParamLayer,
+ PAPIParamEntityType,
+ PAPIParamNameUnused
+} PAPIParamName;
+
+typedef struct PAPIParamNameList
+{
+ PAPIParamName mName;
+ struct PAPIParamNameList * mNext;
+} PAPIParamNameList;
+
+typedef struct PAPIMessage
+{
+ PAPIMessageName mName;
+ PAPIParamNameList * mParamNames;
+ PAPIStringList * mParamValues;
+} PAPIMessage;
+
+PAPIMessage * newMessage( PAPIMessageName inMessageName );
+
+void deleteMessage( PAPIMessage * inMessage );
+
+void addParam( PAPIMessage * inMessage,
+ PAPIParamName inParamName,
+ const char * inParamValue );
+
+PAPIStringList *getParamValue( PAPIMessage * inMessage,
+ PAPIParamName inParamName );
+
+char * messageToString( PAPIMessage * inMessage );
+
+PAPIMessageName stringToMessageName( const char * inMessageName );
+PAPIParamName stringToParamName( const char * inParamName );
+
+const char *getEntityTypeString( PAPIEntityType inType );
+
+#define CONTENTLENGTH "CONTENT-LENGTH:"
+#define MAX_CONTENT_LENGTH_SIZE 23
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPIMESSAGE_H_ */
diff --git a/libapoc/papiPort.c b/libapoc/papiPort.c
new file mode 100644
index 0000000..f19926e
--- /dev/null
+++ b/libapoc/papiPort.c
@@ -0,0 +1,457 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papiUtils.h"
+#include "config.h"
+
+#include <gssapi.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef SOLARIS
+#include <libscf.h>
+#endif
+
+static void initGSSAPIContext( const char * inServiceName,
+ gss_ctx_id_t * outContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus );
+
+static int isDaemonInitdEnabled( void );
+
+static void writeGSSAPIAuthId( gss_ctx_id_t * outContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus );
+
+const char * getGSSAPISrcName( gss_ctx_id_t * inContext );
+
+static void getTargetService( const char * inServiceName,
+ gss_name_t * outService,
+ PAPIStatus * outStatus );
+
+static void encodeGSSAPITokens( gss_buffer_desc * inBuffers,
+ int inBufferCnt,
+ char ** outB64 );
+
+static const char * sInstallDir = APOC_INSTALLDIR;
+static const char * sLibraryDir = APOC_LIBRARYDIR;
+static const char * sPropertiesDir = APOC_PROPDIR;
+
+
+PAPIThread createThread( PAPIThreadFunc inThreadFunc, void * inArg )
+{
+ pthread_attr_t theAttr;
+ pthread_t * theThread = ( pthread_t * )malloc( sizeof( pthread_t ) );
+
+ pthread_attr_init( &theAttr );
+ pthread_attr_setdetachstate( &theAttr, PTHREAD_CREATE_DETACHED );
+ if ( pthread_create( theThread, &theAttr, inThreadFunc, inArg ) != 0 )
+ {
+ free( ( void * )theThread );
+ theThread = 0;
+ }
+ return theThread;
+}
+
+void destroyThread( PAPIThread inThread )
+{
+ pthread_cancel( *inThread );
+}
+
+void deleteMutex( PAPIMutex * inMutex )
+{
+ if ( inMutex != 0 )
+ {
+ pthread_mutex_destroy( inMutex );
+ free( ( void * )inMutex );
+ }
+}
+
+const char * getSASLCreds( const char * inServiceName, PAPIStatus * outStatus )
+{
+ char * theCredentials = 0;
+ gss_ctx_id_t theContextHandle = GSS_C_NO_CONTEXT;
+ gss_buffer_desc theOutputTokens[ 3 ];
+
+ theOutputTokens[ 0 ].length =
+ theOutputTokens[ 1 ].length =
+ theOutputTokens[ 2 ].length = 0;
+ initGSSAPIContext( inServiceName,
+ &theContextHandle,
+ &theOutputTokens[ 0 ],
+ outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ writeGSSAPIAuthId( &theContextHandle, &theOutputTokens[ 2 ],outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ OM_uint32 theMinorStatus;
+ encodeGSSAPITokens( theOutputTokens,
+ 3,
+ &theCredentials );
+ gss_release_buffer( &theMinorStatus, &theOutputTokens[ 0 ] );
+ gss_release_buffer( &theMinorStatus, &theOutputTokens[ 2 ] );
+ gss_delete_sec_context( &theMinorStatus,
+ &theContextHandle,
+ 0 );
+ }
+ }
+ return theCredentials;
+}
+
+const char * getInstallDir( void )
+{
+ return sInstallDir;
+}
+
+const char * getLibraryDir( void )
+{
+ return sLibraryDir;
+}
+
+const char * getPropertiesDir( void )
+{
+ return sPropertiesDir;
+}
+
+const char * getUserName( void )
+{
+/*
+ * no longer using cuserid here as it truncates user name at 8 characters
+ */
+ struct passwd * thePasswd = getpwuid( geteuid() );
+ return thePasswd != 0 && thePasswd->pw_name != 0 ?
+ strdup( thePasswd->pw_name ) : 0;
+}
+
+int isDaemonEnabled( void )
+{
+ int isDaemonEnabled = 0;
+#ifdef SOLARIS
+ isDaemonEnabled = isServiceEnabled();
+#else
+ isDaemonEnabled = isDaemonInitdEnabled();
+#endif
+ return isDaemonEnabled;
+}
+
+#ifdef SOLARIS
+int isServiceEnabled( void )
+{
+ static const char * sInstanceName = "svc:/network/apocd/udp:default";
+ int isServiceEnabled = 0;
+ char * theState = smf_get_state( sInstanceName );
+ if ( theState != 0 )
+ {
+ if ( strcmp( theState, SCF_STATE_STRING_DISABLED ) != 0 )
+ {
+ isServiceEnabled = 1;
+ }
+ free( ( void * )theState );
+ }
+ return isServiceEnabled;
+}
+#else
+int isDaemonInitdEnabled( void )
+{
+ static char * theCommand = "/sbin/chkconfig -c apocd";
+ FILE * theStream;
+ int theRC = 0;
+
+ theStream = papiPopen( theCommand, "w" );
+ if ( theStream != 0 )
+ {
+ theRC = papiPclose( theStream ) == 0 ? 1 : 0;
+ }
+
+ return theRC;
+}
+#endif
+
+int lockMutex( PAPIMutex * inMutex )
+{
+ return pthread_mutex_lock( inMutex );
+}
+
+PAPIMutex * newMutex( void )
+{
+ pthread_mutex_t * theMutex =
+ ( pthread_mutex_t * )malloc( sizeof( pthread_mutex_t ) );
+ if ( theMutex != 0 )
+ {
+ pthread_mutex_init( theMutex, 0 );
+ }
+ return theMutex;
+}
+
+int socketPoll( PAPISocket inSocket, int inMillis )
+{
+ struct pollfd thePollFD;
+ int theRC;
+
+ thePollFD.fd = inSocket;
+ thePollFD.events = POLLIN;
+ theRC = poll( &thePollFD, 1, inMillis );
+ if ( theRC == 1 && thePollFD.revents & POLLIN != POLLIN )
+ {
+ theRC = 0;
+ }
+ else if ( theRC == -1 && thePollFD.revents & POLLHUP == POLLHUP )
+ {
+ theRC = 0;
+ }
+
+ return theRC;
+}
+
+int startDaemon( void )
+{
+ int theRC = 1;
+
+ /*
+ * apoc2.0: daemon startup via inetd no longer supported
+ *
+ if ( isDaemonEnabled() == 1 )
+ {
+ int theSocket = getConnectedSocket( getDaemonPort(), SOCK_DGRAM, 0 );
+ if ( theSocket != INVALID_SOCKET )
+ {
+ if ( send( theSocket, ( void *)"\n", 1, 0 ) != -1 )
+ {
+ theRC = 0;
+ }
+ close( theSocket );
+ }
+ }
+ */
+ return theRC;
+}
+
+int unlockMutex( PAPIMutex * inMutex )
+{
+ return pthread_mutex_unlock( inMutex );
+}
+
+void encodeGSSAPITokens( gss_buffer_desc * inBuffers,
+ int inBufferCnt,
+ char ** outB64Buffer )
+{
+ void * theBuffer;
+ char * theTmpPtr;
+ int theBufferSize = 0;
+ int theIndex;
+
+ for ( theIndex = 0; theIndex < inBufferCnt; ++ theIndex )
+ {
+ theBufferSize += inBuffers[ theIndex ].length + 5;
+ }
+
+ theBuffer = malloc( theBufferSize );
+ theTmpPtr = ( char *)theBuffer;
+ for ( theIndex = 0; theIndex < inBufferCnt; ++ theIndex )
+ {
+ /* Write the token size */
+ snprintf( theTmpPtr, 6, "%05d", inBuffers[ theIndex ].length );
+ theTmpPtr += 5;
+
+ /* Write the token */
+ memcpy( ( void *)theTmpPtr,
+ inBuffers[ theIndex ].value,
+ inBuffers[ theIndex ].length);
+ theTmpPtr += inBuffers[ theIndex ].length;
+ }
+ base64_encode( theBuffer, theBufferSize, outB64Buffer );
+ free( ( void *)theBuffer );
+}
+
+void initGSSAPIContext( const char * inServiceName,
+ gss_ctx_id_t * outContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus )
+{
+ gss_name_t theServiceName;
+
+ getTargetService( inServiceName, &theServiceName, outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_buffer_desc theServiceNameBuf;
+ OM_uint32 theReqFlags = GSS_C_DELEG_FLAG;
+ OM_uint32 theRetFlags;
+ gss_OID theMech;
+#ifdef SOLARIS
+ gss_OID_desc theMechArr =
+ { 9, "\052\206\110\206\367\022\001\002\002"};
+ theMech = &theMechArr;
+#else
+ theMech = GSS_KRB5_MECHANISM;
+#endif
+
+ outToken->length = 0;
+ theMajorStatus = gss_init_sec_context( &theMinorStatus,
+ GSS_C_NO_CREDENTIAL,
+ outContext,
+ theServiceName,
+ GSS_C_NO_OID,
+ 0,
+ 0,
+ NULL,
+ GSS_C_NO_BUFFER,
+ 0,
+ outToken,
+ &theRetFlags,
+ 0 );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ *outStatus = PAPISuccess;
+ }
+ else
+ {
+ *outStatus = PAPIAuthenticationFailure;
+ }
+ }
+}
+
+const char * getGSSAPISrcName( gss_ctx_id_t * inContext )
+{
+ char * theGSSAPISrcName = 0;
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_name_t theSrcName;
+
+ theMajorStatus = gss_inquire_context( &theMinorStatus,
+ *inContext,
+ &theSrcName,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0 );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ gss_buffer_desc theSrcNameBuffer;
+ theMajorStatus = gss_display_name( &theMinorStatus,
+ theSrcName,
+ &theSrcNameBuffer,
+ 0 );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ int theSize = theSrcNameBuffer.length + 1;
+ theGSSAPISrcName = ( char * )malloc( theSize );
+ if ( theGSSAPISrcName != 0 )
+ {
+ snprintf( theGSSAPISrcName,
+ theSize,
+ "%s",
+ ( char *)theSrcNameBuffer.value );
+ }
+ gss_release_buffer( &theMinorStatus, &theSrcNameBuffer );
+ }
+ }
+ return theGSSAPISrcName;
+}
+
+void getTargetService( const char * inServiceName,
+ gss_name_t * outServiceName,
+ PAPIStatus * outStatus )
+{
+ if ( inServiceName != 0 )
+ {
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_buffer_desc theServiceNameBuf;
+ OM_uint32 theReqFlags = GSS_C_DELEG_FLAG;
+ OM_uint32 theRetFlags;
+
+ theServiceNameBuf.length = strlen( inServiceName );
+ theServiceNameBuf.value = ( char * )inServiceName;
+ theMajorStatus =
+ gss_import_name( &theMinorStatus,
+ &theServiceNameBuf,
+ GSS_C_NO_OID,
+ outServiceName );
+ *outStatus = theMajorStatus == GSS_S_COMPLETE ?
+ PAPISuccess : PAPIAuthenticationFailure;
+ }
+}
+
+void writeGSSAPIAuthId( gss_ctx_id_t * inContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus )
+{
+ /*
+ * We no longer write the ldap authorisation id as LDAP servers
+ * can't agree on the format.
+ * See 6275775
+ */
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_buffer_desc theAuthzIdBuffer;
+ int theConfState;
+
+ *outStatus = PAPIAuthenticationFailure;
+ theAuthzIdBuffer.length = 4;
+ theAuthzIdBuffer.value = malloc( theAuthzIdBuffer.length );
+ if ( theAuthzIdBuffer.value != 0 )
+ {
+ char * theCP = ( char *)theAuthzIdBuffer.value;
+ /* security layer */
+ theCP[ 0 ] = ( char )1;
+ /* message size */
+ theCP[ 1 ] = ( char )1;
+ theCP[ 2 ] = theCP[ 3 ] = ( char )0;
+
+ theMajorStatus = gss_wrap( &theMinorStatus,
+ *inContext,
+ 0,
+ GSS_C_QOP_DEFAULT,
+ &theAuthzIdBuffer,
+ &theConfState,
+ outToken );
+ free( theAuthzIdBuffer.value );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ *outStatus = PAPISuccess;
+ }
+ }
+}
diff --git a/libapoc/papiSAXParserContext.c b/libapoc/papiSAXParserContext.c
new file mode 100644
index 0000000..edf60dc
--- /dev/null
+++ b/libapoc/papiSAXParserContext.c
@@ -0,0 +1,182 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include <stdlib.h>
+
+#include "papiSAXParserContext.h"
+
+static int saxReader( void * inIOContext, char * inBuffer, int inLen );
+
+static int saxCloser( void * inIOContext );
+
+static void papiStartElement( void * inUserData,
+ const xmlChar * inName,
+ const xmlChar ** inAttrs );
+static void papiCharacters( void * inUserData,
+ const xmlChar * inChars,
+ int inLen );
+
+static xmlSAXHandler sSAXHandler =
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ papiStartElement,
+ 0,
+ 0,
+ papiCharacters,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1
+ };
+
+PAPISAXParserContext newSAXParserContext( PAPIConnection * inConnection,
+ PAPISAXUserData * inUserData )
+{
+ PAPISAXParserContext theSAXParserContext;
+ PAPISAXIOContext * theIOContext =
+ ( PAPISAXIOContext * )malloc( sizeof( PAPISAXIOContext ) );
+ if ( theIOContext != 0 )
+ {
+ theIOContext->mContentLength = -1;
+ theIOContext->mConnection = inConnection;
+
+ theSAXParserContext =
+ xmlCreateIOParserCtxt( &sSAXHandler,
+ ( void *) inUserData,
+ saxReader,
+ saxCloser,
+ ( void *)theIOContext,
+ XML_CHAR_ENCODING_NONE );
+
+ }
+ return theSAXParserContext;
+}
+
+void deleteSAXParserContext( PAPISAXParserContext inParserContext )
+{
+ xmlFreeParserCtxt( inParserContext );
+}
+
+int parse( PAPISAXParserContext inParserContext )
+{
+ return xmlParseDocument( inParserContext );
+}
+
+void papiStartElement( void * inUserData,
+ const xmlChar * inName,
+ const xmlChar ** inAttrs )
+{
+ PAPISAXUserData * theUserData = ( PAPISAXUserData * )inUserData;
+ if ( theUserData != 0 && theUserData->mMessage == 0 )
+ {
+ theUserData->mMessage = newMessage(
+ stringToMessageName( ( const char * )inName ) );
+ }
+ else
+ {
+ theUserData->mCurrentParamName =
+ stringToParamName( ( const char * )inName );
+ }
+}
+
+void papiCharacters( void * inUserData,
+ const xmlChar * inChars,
+ int inLen )
+{
+ PAPISAXUserData * theUserData = ( PAPISAXUserData * )inUserData;
+ if ( theUserData != 0 && theUserData->mMessage != 0 )
+ {
+ char * theValue = ( char * )malloc( inLen + 1 );
+ if ( theValue != 0 )
+ {
+ snprintf( theValue, inLen + 1, "%s", inChars );
+ theValue[ inLen ] = 0;
+ addParam( theUserData->mMessage,
+ theUserData->mCurrentParamName,
+ theValue );
+ free( ( void *)theValue );
+ theUserData->mCurrentParamName = PAPIParamNameUnused;
+ }
+ }
+}
+
+int saxReader( void * inIOContext, char * inBuffer, int inLen )
+{
+ int theByteCount = EOF;
+ PAPISAXIOContext * theIOContext = ( PAPISAXIOContext * )inIOContext;
+
+ if ( theIOContext->mContentLength == -1 )
+ {
+ theIOContext->mContentLength =
+ readContentLength( theIOContext->mConnection );
+ }
+ if ( theIOContext->mContentLength > 0 )
+ {
+ int theLen = inLen < theIOContext->mContentLength ?
+ inLen : theIOContext->mContentLength;
+ theByteCount = readBytes( theIOContext->mConnection,
+ ( void *)inBuffer,
+ theLen );
+ if ( theByteCount > 0 )
+ {
+ theIOContext->mContentLength -= theByteCount;
+ }
+ }
+ return theByteCount == -1 ? 0 : theByteCount;
+}
+
+int saxCloser( void * inIOContext )
+{
+ free( inIOContext );
+ return 0;
+}
diff --git a/libapoc/papiSAXParserContext.h b/libapoc/papiSAXParserContext.h
new file mode 100644
index 0000000..b36bf99
--- /dev/null
+++ b/libapoc/papiSAXParserContext.h
@@ -0,0 +1,74 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#ifndef PAPISAXPARSERCONTEXT_H_
+#define PAPISAXPARSERCONTEXT_H_
+
+#include <libxml/parser.h>
+
+#include "papiConnection.h"
+#include "papiMessage.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef xmlParserCtxtPtr PAPISAXParserContext;
+
+typedef struct PAPISAXIOContext
+{
+ int mContentLength;
+ PAPIConnection * mConnection;
+} PAPISAXIOContext;
+
+typedef struct PAPISAXUserData
+{
+ PAPIMessage * mMessage;
+ PAPIParamName mCurrentParamName;
+} PAPISAXUserData;
+
+PAPISAXParserContext newSAXParserContext( PAPIConnection * inFD,
+ PAPISAXUserData * inUserData );
+
+void deleteSAXParserContext( PAPISAXParserContext inParserContext );
+
+int parse( PAPISAXParserContext inParserContext );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPISAXPARSERCONTEXT_H_ */
diff --git a/libapoc/papiStringList.c b/libapoc/papiStringList.c
new file mode 100644
index 0000000..d992af6
--- /dev/null
+++ b/libapoc/papiStringList.c
@@ -0,0 +1,176 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papiStringList.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static PAPIStringList * newStringList( void );
+
+PAPIStringList * addStringList( PAPIStringList ** ioPrevious,
+ const char * inData )
+{
+ PAPIStringList * theStringList = newStringList();
+ if ( theStringList != 0 )
+ {
+ theStringList->data = inData == 0 ? 0 : strdup( inData );
+ if ( ioPrevious[ 0 ] == 0 )
+ {
+ ioPrevious[ 0 ] = theStringList;
+ }
+ else
+ {
+ PAPIStringList * theTmpList = ioPrevious[ 0 ];
+ while ( theTmpList->next != 0 )
+ {
+ theTmpList = theTmpList->next;
+ }
+ theTmpList->next = theStringList;
+ }
+ }
+ return theStringList;
+}
+
+int containsString( PAPIStringList * inList, const char * inString )
+{
+ int isContained = 0;
+ if ( inList != 0 && inString != 0 )
+ {
+ while ( inList != 0 )
+ {
+ if ( strcmp( inList->data, inString ) == 0 )
+ {
+ isContained = 1;
+ break;
+ }
+ inList = inList->next;
+ }
+ }
+ return isContained;
+}
+
+PAPIStringList * copyStringList( PAPIStringList * inList )
+{
+ PAPIStringList * theList = 0;
+ while ( inList != 0 )
+ {
+ addStringList( &theList, inList->data );
+ inList = inList->next;
+ }
+ return theList;
+}
+
+void deleteStringList( PAPIStringList * inStringList )
+{
+ if ( inStringList != 0 )
+ {
+ if ( inStringList->next != 0 )
+ {
+ deleteStringList( inStringList->next );
+ }
+ if ( inStringList->data != 0 )
+ {
+ free( ( void *)inStringList->data );
+ }
+ free( inStringList );
+ }
+}
+
+PAPIStringList * removeStringList( PAPIStringList ** ioStringList,
+ const char * inString )
+{
+ PAPIStringList * theList = 0;
+ if ( ioStringList != 0 && inString != 0 )
+ {
+ theList = ioStringList[ 0 ];
+ if ( theList != 0 )
+ {
+ PAPIStringList * thePrevList = theList;
+ while ( theList != 0 )
+ {
+ if ( strcmp( theList->data, inString ) == 0 )
+ {
+ if ( theList == ioStringList[ 0 ] )
+ {
+ ioStringList[ 0 ] = ioStringList[ 0 ]->next;
+ }
+ else
+ {
+ thePrevList->next = theList->next;
+ }
+ theList->next = 0;
+ break;
+ }
+ thePrevList = theList;
+ theList = theList->next;
+ }
+ }
+ }
+ return theList;
+}
+
+PAPIStringList * strToStringList( const char * inString )
+{
+ PAPIStringList * theList = 0;
+ if ( inString != 0 )
+ {
+ PAPIStringList * theTmpList;
+ const char * theString = strdup( inString );
+ char * theToken = strtok( ( char *)theString, " " );
+ while ( theToken != 0 )
+ {
+ theTmpList = addStringList( &theList, theToken );
+ if ( theList == 0 )
+ {
+ theList = theTmpList;
+ }
+ theToken = strtok( NULL, " " );
+ }
+ free( ( void * )theString );
+ }
+ return theList;
+}
+
+PAPIStringList * newStringList( void )
+{
+ PAPIStringList * theStringList =
+ ( PAPIStringList * )malloc( sizeof( PAPIStringList ) );
+ if ( theStringList != 0 )
+ {
+ theStringList->data = 0;
+ theStringList->next = 0;
+ }
+ return theStringList;
+}
diff --git a/libapoc/papiStringList.h b/libapoc/papiStringList.h
new file mode 100644
index 0000000..52f2526
--- /dev/null
+++ b/libapoc/papiStringList.h
@@ -0,0 +1,61 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#ifndef PAPISTRINGLIST_H_
+#define PAPISTRINGLIST_H_
+
+#include "papiTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PAPIStringList * addStringList( PAPIStringList ** ioPreviousList,
+ const char * inData );
+
+int containsString( PAPIStringList * inList, const char * inString );
+
+PAPIStringList * copyStringList( PAPIStringList * inList );
+
+void deleteStringList( PAPIStringList * inStringList );
+
+PAPIStringList * removeStringList( PAPIStringList ** ioStringList, const char * inString );
+
+PAPIStringList * strToStringList( const char * inString );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPISTRINGLIST_H_ */
diff --git a/libapoc/papiTypes.h b/libapoc/papiTypes.h
new file mode 100644
index 0000000..f324476
--- /dev/null
+++ b/libapoc/papiTypes.h
@@ -0,0 +1,96 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+/* papiTypes.h - Policy Access API types */
+
+#ifndef PAPITYPES_H_
+#define PAPITYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* opaque PAPI session handle */
+typedef struct PAPI PAPI;
+
+/* Status returned by PAPI functions */
+typedef enum { PAPISuccess = 0,
+ PAPIConnectionFailure,
+ PAPIAuthenticationFailure,
+ PAPINoSuchComponentFailure,
+ PAPILDBFailure,
+ PAPIInvalidArg,
+ PAPIOutOfMemoryFailure,
+ PAPIUnknownFailure } PAPIStatus;
+
+/* Notification stuff */
+typedef enum { PAPIComponentAdd,
+ PAPIComponentModify,
+ PAPIComponentRemove } PAPIEventType;
+
+typedef struct {
+ PAPIEventType eventType;
+ const char * componentName;
+} PAPIEvent;
+
+typedef void ( *PAPIListener )( const PAPIEvent * inEvent, void * inUserData );
+
+typedef void * PAPIListenerId;
+
+/* Connection state stuff */
+typedef enum { PAPIConnected, PAPIDisconnected } PAPIConnectionState;
+
+typedef void ( *PAPIConnectionListener )( PAPIConnectionState inState,
+ void * inUserData );
+
+/* Layer stuff */
+typedef struct PAPILayerList
+{
+ const unsigned char * data;
+ int size;
+ const char * timestamp;
+ struct PAPILayerList * next;
+} PAPILayerList;
+
+typedef struct PAPIStringList
+{
+ const char * data;
+ struct PAPIStringList * next;
+} PAPIStringList;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPITYPES_H_ */
diff --git a/libapoc/papiUtils.c b/libapoc/papiUtils.c
new file mode 100644
index 0000000..df30a13
--- /dev/null
+++ b/libapoc/papiUtils.c
@@ -0,0 +1,662 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papiUtils.h"
+
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#ifndef WNT
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#endif
+
+typedef struct PAPIConfigList
+{
+ int mName;
+ const char * mValue;
+ struct PAPIConfigList * mNext;
+} PAPIConfigList;
+
+typedef enum
+{
+ PAPIDaemonInstallDir = 0,
+ PAPIDaemonPort,
+ PAPIDaemonDataDir,
+ PAPITransactionTimeout,
+ PAPIUnknown
+} PAPIConfigName;
+
+static PAPIConfigList * addConfigList( PAPIConfigList ** inPrevious,
+ int inName,
+ char * inValue) ;
+
+static void deleteConfigList( PAPIConfigList * inList );
+
+static unsigned char findNextPair( FILE * inFile,
+ int * outName,
+ char ** outValue );
+
+static int mapToName( const char * inName );
+
+static void loadConfig( void );
+
+static void loadConfigFile( const char * inFileName,
+ PAPIConfigList ** inoutList );
+
+static int configLock( void );
+
+static PAPIConfigList * newConfigList( void );
+
+static int skipComments( FILE * inFile );
+
+static int configUnlock( void );
+
+static int papiConnect( PAPISocket inSocket,
+ struct sockaddr * inRemote );
+
+static const char * sDaemonInstallDir = 0;
+static const char * sDaemonLibraryDir = 0;
+static const char * sDaemonPropertiesDir = 0;
+static int sDaemonPort = -1;
+static const char * sDataDir = 0;
+static int sTransactionTimeout = -1;
+
+static int sDefaultDaemonPort = 3809;
+static int sDefaultTransactionTimeout = 10000;
+static int sMinimumTransactionTimeout = 1000;
+
+static PAPIMutex * sConfigMutex = 0;
+
+
+static const char sB64[ 64 ] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+#define ISWHITESPACE(inChar) ((inChar) == ' ' || (inChar) == '\t')
+#define ISRETURN(inChar) ((inChar) == '\r' || (inChar) == '\n')
+
+int base64_encode( const void * inBuffer,
+ int inBufferSize,
+ char ** outB64Buffer )
+{
+ char *s, *p;
+ int i;
+ int c;
+ const unsigned char *q;
+
+ p = s = (char *) malloc( inBufferSize * 4 / 3 + 4);
+ if (p == NULL)
+ return -1;
+ q = (const unsigned char *) inBuffer;
+ i = 0;
+ for (i = 0; i < inBufferSize;) {
+ c = q[i++];
+ c *= 256;
+ if (i < inBufferSize)
+ c += q[i];
+ i++;
+ c *= 256;
+ if (i < inBufferSize)
+ c += q[i];
+ i++;
+ p[0] = ( char )sB64[(c & 0x00fc0000) >> 18];
+ p[1] = ( char )sB64[(c & 0x0003f000) >> 12];
+ p[2] = ( char )sB64[(c & 0x00000fc0) >> 6];
+ p[3] = ( char )sB64[(c & 0x0000003f) >> 0];
+ if (i > inBufferSize)
+ p[3] = '=';
+ if (i > inBufferSize + 1)
+ p[2] = '=';
+ p += 4;
+ }
+ *p = 0;
+ *outB64Buffer = s;
+ return strlen(s);
+}
+
+const char * getDaemonDataDir( void )
+{
+ if ( configLock() == 0 )
+ {
+ if ( sDataDir == 0 )
+ {
+ loadConfig();
+ }
+ configUnlock();
+ }
+ return sDataDir;
+}
+
+const char * getDaemonInstallDir( void )
+{
+ if ( sDaemonInstallDir == 0 )
+ {
+ sDaemonInstallDir = getInstallDir();
+ }
+ return sDaemonInstallDir;
+}
+
+const char * getDaemonLibraryDir( void )
+{
+ if ( sDaemonLibraryDir == 0 )
+ {
+ sDaemonLibraryDir = getLibraryDir();
+ }
+ return sDaemonLibraryDir;
+}
+
+const char * getDaemonPropertiesDir( void )
+{
+ if ( sDaemonPropertiesDir == 0 )
+ {
+ sDaemonPropertiesDir = getPropertiesDir();
+ }
+ return sDaemonPropertiesDir;
+}
+
+int getDaemonPort( void )
+{
+ if ( configLock() == 0 )
+ {
+ if ( sDaemonPort == -1 )
+ {
+ loadConfig();
+ if ( sDaemonPort == -1 )
+ {
+ sDaemonPort = sDefaultDaemonPort;
+ }
+ }
+ configUnlock();
+ }
+ return sDaemonPort;
+}
+
+const char * getTimestamp( void )
+{
+ char * theTimestamp = 0;
+ time_t theTime = time( 0 );
+ struct tm * theGMTime = gmtime( &theTime );
+ if ( theTime != 0 )
+ {
+ theTimestamp = ( char * )malloc( 16 );
+ if ( theTimestamp != 0 )
+ {
+ snprintf( theTimestamp,
+ 16,
+ "%d%.2d%.2d%.2d%.2d%.2dZ",
+ theGMTime->tm_year + 1900,
+ theGMTime->tm_mon + 1,
+ theGMTime->tm_mday,
+ theGMTime->tm_hour,
+ theGMTime->tm_min,
+ theGMTime->tm_sec );
+ }
+ }
+ return theTimestamp;
+}
+
+int getTransactionTimeout( void )
+{
+ if ( configLock() == 0 )
+ {
+ if ( sTransactionTimeout == -1 )
+ {
+ loadConfig();
+ if ( sTransactionTimeout == -1 )
+ {
+ sTransactionTimeout = sDefaultTransactionTimeout;
+ }
+ else
+ if ( sTransactionTimeout < sMinimumTransactionTimeout )
+ {
+ sTransactionTimeout = sMinimumTransactionTimeout;
+ }
+ }
+ configUnlock();
+ }
+ return sTransactionTimeout;
+}
+
+PAPIConfigList * addConfigList( PAPIConfigList ** inPrevious,
+ int inName,
+ char * inValue)
+{
+ PAPIConfigList * theConfigList = newConfigList();
+ if ( theConfigList != 0 )
+ {
+ theConfigList->mName = inName;
+ theConfigList->mValue = inValue ;
+ theConfigList->mNext = 0;
+ if ( inPrevious[ 0 ] == 0 )
+ {
+ inPrevious[ 0 ] = theConfigList;
+ }
+ else
+ {
+ PAPIConfigList * theTmpList = inPrevious[ 0 ];
+ while ( theTmpList->mNext != 0 )
+ {
+ theTmpList = theTmpList->mNext;
+ }
+ theTmpList->mNext = theConfigList;
+ }
+ }
+ return theConfigList;
+}
+
+void deleteConfigList( PAPIConfigList * inList )
+{
+ if ( inList != 0 )
+ {
+ if ( inList->mNext != 0 )
+ {
+ deleteConfigList( inList->mNext );
+ }
+ if ( inList->mValue )
+ {
+ free( ( void * )inList->mValue );
+ }
+ free( inList );
+ }
+}
+
+unsigned char findNextPair(FILE *inFile, int *outName, char **outValue)
+{
+ char theString [1024] ;
+ int theChar = -1 ;
+ int theStringLength = 0 ;
+
+ *outName = PAPIUnknown ;
+ *outValue = 0 ;
+ /* Get rid of comments */
+ theChar = skipComments(inFile) ;
+ /* Find name */
+ while (theChar != EOF)
+ {
+ /* Skip initial whitespace */
+ if (theStringLength == 0 && ISWHITESPACE(theChar)) { continue ; }
+ if (theChar == '\\')
+ { /* Drop escape character */
+ theChar = fgetc(inFile) ;
+ }
+ else if (theChar == '=')
+ { /* Skip initial whitespace for possible value */
+ do { theChar = fgetc(inFile) ; } while (ISWHITESPACE(theChar)) ;
+ break ;
+ }
+ /* If we encounter a line break, something's wrong */
+ if (ISRETURN(theChar))
+ {
+ theStringLength = 0 ;
+ break ;
+ }
+ /* Else copy into the current string */
+ theString [theStringLength ++] = theChar ;
+ theChar = fgetc(inFile) ;
+ }
+ /* Remove trailing whitespace */
+ while (theStringLength != 0 &&
+ ISWHITESPACE(theString [theStringLength - 1]))
+ {
+ -- theStringLength ;
+ }
+ /* Terminate string */
+ theString [theStringLength] = 0 ;
+ *outName = mapToName(theString) ;
+ if (*outName == PAPIUnknown)
+ { /* If uncomprehensible name, move to next line */
+ while (!ISRETURN(theChar) && theChar != EOF)
+ {
+ theChar = fgetc(inFile) ;
+ }
+ return theChar != EOF ;
+ }
+ theStringLength = 0 ;
+ /* Find corresponding value */
+ while (theChar != EOF)
+ {
+ /* Skip initial whitespace */
+ if (theStringLength == 0 && ISWHITESPACE(theChar)) { continue ; }
+ if (theChar == '\\')
+ { /* Drop escape character */
+ theChar = fgetc(inFile) ;
+ }
+ if (ISRETURN(theChar))
+ { /* If end of line is reached, remove trailing whitespace */
+ while (theStringLength != 0 &&
+ ISWHITESPACE(theString [theStringLength - 1]))
+ {
+ -- theStringLength ;
+ }
+ break ;
+ }
+ /* Else copy into the current string */
+ theString [theStringLength ++] = theChar ;
+ theChar = fgetc(inFile) ;
+ }
+ /* Terminate and duplicate value */
+ theString [theStringLength] = 0 ;
+ *outValue = strdup(theString) ;
+ return theChar != EOF ;
+}
+
+PAPIConnectResult getConnectedSocket(
+ int inPort, int inType, int inRetryCount, PAPISocket * outSocket )
+{
+ static char sRejected = 0;
+ static char sAccepted = 1;
+ static const char * sLocalHostName = "127.0.0.1";
+ PAPIConnectResult theResult;
+ PAPISocket theSocket;
+ struct sockaddr_in theDaemonAddr;
+ struct hostent * theHostEnt;
+ int bResue = 1;
+#ifdef WNT
+ static int isWSAInitialised = 0;
+ WSADATA theWSAData;
+
+ if ( isWSAInitialised == 0 )
+ {
+ WSAStartup( MAKEWORD( 2, 2 ), &theWSAData );
+ isWSAInitialised = 1;
+ }
+#endif
+
+ *outSocket = INVALID_SOCKET;
+
+ theHostEnt = gethostbyname( sLocalHostName );
+ theDaemonAddr.sin_family = AF_INET;
+ theDaemonAddr.sin_port = htons( inPort );
+ theDaemonAddr.sin_addr = *( (struct in_addr * )theHostEnt->h_addr );
+
+ do
+ {
+ memset( ( void * )&( theDaemonAddr.sin_zero ), 0, 8 );
+ theResult = PAPIConnectFailed;
+ if ( ( theSocket = socket( AF_INET, inType, 0 ) ) != INVALID_SOCKET &&
+ papiConnect( theSocket,
+ ( struct sockaddr * )&theDaemonAddr ) == 0 )
+ {
+ char theInitialByte;
+ if ( socketPoll( theSocket, getTransactionTimeout() ) != 1 ||
+ recv( theSocket, &theInitialByte, 1, 0 ) != 1 ||
+ ( theInitialByte != sAccepted && theInitialByte != sRejected ))
+ {
+ papiClose( theSocket );
+ theResult = PAPIConnectWrongService;
+ break;
+ }
+ else
+ {
+ theResult = theInitialByte == sAccepted ?
+ PAPIConnectSuccess : PAPIConnectRejected;
+ if ( theResult == PAPIConnectSuccess )
+ {
+ *outSocket = theSocket;
+ break;
+ }
+ }
+ }
+ papiClose( theSocket );
+ if ( inRetryCount > 0 )
+ {
+ papiSleep( 1 );
+ }
+ } while ( --inRetryCount > 0 );
+ return theResult;
+}
+
+int mapToName(const char *inName)
+{
+ if (strcmp(inName, "DaemonPort") == 0)
+ { return PAPIDaemonPort ; }
+ else if (strcmp(inName, "DataDir") == 0)
+ { return PAPIDaemonDataDir ; }
+ else if (strcmp(inName, "DaemonInstallDir") == 0)
+ { return PAPIDaemonInstallDir ; }
+ else if (strcmp(inName, "TransactionTimeout") == 0)
+ { return PAPITransactionTimeout ; }
+ else return PAPIUnknown ;
+}
+
+void loadConfig( void )
+{
+ static const char * sPropertiesFile = "/apocd.properties";
+ static const char * sOsPropertiesFile = "/os.properties" ;
+ PAPIConfigList * theConfigList = 0 ;
+ PAPIConfigList * theTmpList = 0 ;
+ char * thePropertiesFileName = 0;
+ int theSize;
+ int prefixLength;
+
+ if ( sDaemonPropertiesDir == 0 )
+ {
+ sDaemonPropertiesDir = getPropertiesDir();
+ }
+ prefixLength = strlen( sDaemonPropertiesDir );
+ theSize = prefixLength + strlen( sPropertiesFile ) + 1;
+ thePropertiesFileName = ( char * )malloc( theSize );
+ snprintf( thePropertiesFileName,
+ theSize,
+ "%s%s",
+ sDaemonPropertiesDir,
+ sPropertiesFile );
+ loadConfigFile( thePropertiesFileName, &theConfigList );
+ free( ( void * )thePropertiesFileName );
+
+ theSize = prefixLength + strlen( sOsPropertiesFile ) + 1;
+ thePropertiesFileName = ( char * )malloc( theSize );
+ snprintf( thePropertiesFileName,
+ theSize,
+ "%s%s",
+ sDaemonPropertiesDir,
+ sOsPropertiesFile );
+ loadConfigFile( thePropertiesFileName, &theConfigList );
+ free( ( void *)thePropertiesFileName );
+
+ theTmpList = theConfigList;
+ while ( theTmpList != 0 )
+ {
+ switch( theTmpList->mName )
+ {
+ case PAPIDaemonPort:
+ sDaemonPort = atoi( theTmpList->mValue );
+ break;
+
+ case PAPIDaemonDataDir:
+#ifndef WNT
+ sDataDir = strdup( theTmpList->mValue );
+#else
+ sDataDir = convertDataDir( theTmpList->mValue );
+#endif
+ break;
+
+ case PAPITransactionTimeout:
+ sTransactionTimeout = 1000 * atoi( theTmpList->mValue );
+ break;
+
+ default:
+ break;
+ }
+ theTmpList = theTmpList->mNext;
+ }
+ deleteConfigList( theConfigList );
+}
+
+void loadConfigFile(const char *inFileName, PAPIConfigList **inoutConfigList)
+{
+ FILE *theFile = 0 ;
+ int theName = 0 ;
+ char *theValue = 0 ;
+
+ if (inoutConfigList == 0 || inFileName == 0) { return ; }
+ theFile = fopen(inFileName, "r") ;
+ if (theFile == 0) { return ; }
+ while (findNextPair(theFile, &theName, &theValue))
+ {
+ if (theName != PAPIUnknown)
+ {
+ addConfigList(inoutConfigList, theName, theValue) ;
+ }
+ }
+ fclose(theFile) ;
+}
+
+int configLock( void )
+{
+ int theRC = -1;
+ if ( sConfigMutex == 0 )
+ {
+ sConfigMutex = newMutex();
+ }
+ if ( sConfigMutex != 0 )
+ {
+ theRC = lockMutex( sConfigMutex );
+ }
+ return theRC;
+}
+
+PAPIConfigList * newConfigList( void )
+{
+ PAPIConfigList * theConfigList =
+ ( PAPIConfigList * )malloc( sizeof( PAPIConfigList ) );
+ if ( theConfigList != 0 )
+ {
+ theConfigList->mName = PAPIUnknown;
+ theConfigList->mValue = 0;
+ theConfigList->mNext = 0;
+ }
+ return theConfigList;
+}
+
+int skipComments(FILE *inFile)
+{
+ int theChar = -1 ;
+
+ do
+ {
+ theChar = fgetc(inFile) ;
+ if (ISRETURN(theChar) || ISWHITESPACE(theChar)) { continue ; }
+ if (theChar == '/')
+ {
+ theChar = fgetc(inFile) ;
+ if (theChar != '*') { ungetc(theChar, inFile) ; }
+ else
+ {
+ do
+ {
+ theChar = fgetc(inFile) ;
+ if (theChar == '*')
+ {
+ theChar = fgetc(inFile) ;
+ if (theChar == '/') { break ; }
+ }
+ } while (theChar != EOF) ;
+ }
+ }
+ else
+ {
+ ungetc(theChar, inFile) ;
+ break ;
+ }
+ } while (theChar != EOF) ;
+ return fgetc(inFile) ;
+}
+
+int configUnlock( void )
+{
+ int theRC = -1;
+ if ( sConfigMutex != 0 )
+ {
+ theRC = unlockMutex( sConfigMutex );
+ }
+ return theRC;
+}
+
+static int papiConnect( PAPISocket inSocket, struct sockaddr * inRemote )
+{
+ int theRC = -1;
+ int bReuse = 1;
+ int theSocketFlags;
+ if ( setsockopt( inSocket,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ &bReuse,
+ sizeof( bReuse ) ) == -1 )
+ {
+ return theRC;
+ }
+#ifdef SOLARIS
+ theSocketFlags = fcntl( inSocket, F_GETFL, 0);
+ if ( theSocketFlags >= 0 &&
+ fcntl( inSocket, F_SETFL, theSocketFlags | O_NONBLOCK ) != -1 )
+ {
+ theRC = connect( inSocket, inRemote, sizeof( struct sockaddr ) );
+ fcntl( inSocket, F_SETFL, theSocketFlags );
+ }
+#else
+ theRC = connect( inSocket, inRemote, sizeof( struct sockaddr ) );
+#endif
+ if ( theRC == 0 )
+ {
+ /*
+ * Nasty problem on Linux where connecting to daemon port sometimes
+ * works even when daemon is not listening. The following is an
+ * attempt to detect this
+ */
+ struct sockaddr_in theLocal;
+ socklen_t theSize = sizeof( theLocal );
+ if ( getsockname( inSocket,
+ ( struct sockaddr * )&theLocal,
+ &theSize ) == 0 )
+ {
+ if ( ntohs( theLocal.sin_port ) ==
+ ntohs( ( ( struct sockaddr_in * )&inRemote )->sin_port ) )
+ {
+ theRC = -1;
+ }
+ }
+ else
+ {
+ theRC = -1;
+ }
+ }
+ return theRC;
+}
diff --git a/libapoc/papiUtils.h b/libapoc/papiUtils.h
new file mode 100644
index 0000000..118e48d
--- /dev/null
+++ b/libapoc/papiUtils.h
@@ -0,0 +1,167 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#ifndef PAPIUTILS_H_
+#define PAPIUTILS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "papiTypes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+typedef enum
+{
+ PAPIConnectSuccess,
+ PAPIConnectRejected,
+ PAPIConnectFailed,
+ PAPIConnectWrongService
+} PAPIConnectResult;
+
+#ifndef WNT
+#include <pthread.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+typedef pthread_mutex_t PAPIMutex;
+typedef int PAPISocket;
+typedef pthread_t * PAPIThread;
+
+#define FILESEP "/"
+#define PATHSEP ":"
+#define papiClose close
+#define papiSleep sleep
+#define papiPclose pclose
+#define papiPopen popen
+#define papiUmask umask
+#define INVALID_SOCKET -1
+#define SOCKET_ERROR -1
+
+#ifdef SOLARIS
+int isServiceEnabled( void );
+#endif
+
+#else
+#include <windows.h>
+#include <io.h>
+#include <stdio.h>
+
+typedef CRITICAL_SECTION PAPIMutex;
+typedef SOCKET PAPISocket;
+typedef HANDLE PAPIThread;
+typedef int socklen_t;
+
+#define FILESEP "\\\\"
+#define PATHSEP ";"
+#define snprintf _snprintf
+#define papiClose closesocket
+#define papiSleep( inSeconds ) Sleep( inSeconds * 1000 )
+#define papiPclose _pclose
+#define papiPopen _popen
+#define papiUmask _umask
+
+#define APOCENABLEDKEY "Software\\Sun Microsystems\\apoc\\1.0\\Enabled"
+
+#define APOCSERVICENAME "apocd"
+
+const char * convertDataDir( const char * inDir );
+
+int isNewerThanWindows98( void );
+
+#endif
+
+
+typedef void * ( *PAPIThreadFunc )( void * inArg );
+
+int base64_encode( const void * inBuffer,
+ int inBufferSize,
+ char ** outB64Buffer );
+
+PAPIThread createThread( PAPIThreadFunc inThreadFunc,
+ void * inArg );
+
+void destroyThread( PAPIThread inThread );
+
+void deleteMutex( PAPIMutex * inMutex );
+
+PAPIConnectResult getConnectedSocket( int inPort,
+ int inType,
+ int inRetryCount,
+ PAPISocket * outSocket );
+
+const char * getDaemonDataDir( void );
+
+const char * getDaemonInstallDir(void );
+
+const char * getDaemonLibraryDir(void );
+
+const char * getDaemonPropertiesDir(void );
+
+int getDaemonPort( void );
+
+const char * getInstallDir( void );
+
+const char * getLibraryDir( void );
+
+const char * getPropertiesDir( void );
+
+const char * getSASLCreds( const char * inServiceName,
+ PAPIStatus * outStatus );
+
+const char * getTimestamp( void );
+
+int getTransactionTimeout( void );
+
+const char * getUserName( void );
+
+int isDaemonEnabled( void );
+
+int lockMutex( PAPIMutex * inMutex );
+
+int socketPoll( PAPISocket inSocket,
+ int inMillis );
+
+int startDaemon( void );
+
+PAPIMutex * newMutex( void );
+
+int unlockMutex( PAPIMutex * inMutex );
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPIUTILS_H_ */
diff --git a/libapoc/papitool.c b/libapoc/papitool.c
new file mode 100644
index 0000000..cfaec0e
--- /dev/null
+++ b/libapoc/papitool.c
@@ -0,0 +1,521 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+#include <papi/papi.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+char const * g_appname;
+const char * g_entity = NULL;
+
+void show_version(FILE * target);
+
+void show_error(char const * fmt, char const * param);
+void usage(char const * fmt, char const * param);
+void list_usage();
+void show_usage();
+void offline_usage();
+
+void test_connect_avail(int argc, char * const argv[]);
+void list_components(int argc, char * const argv[]);
+void show_components(int argc, char * const argv[]);
+void do_offline(int argc, char * const argv[]);
+
+int match(const char * input, const char * command)
+{
+ if (!input || !*input) return 0;
+
+ return !strncmp(input,command,strlen(input));
+}
+
+int main(int argc, char * argv[])
+{
+ int argindex = 1;
+ int subargc;
+ char * const * subargv;
+
+ if (argv[0] == NULL)
+ g_appname = "[papitool]";
+ else if ( (g_appname = strrchr(argv[0],'/')) != NULL )
+ ++g_appname;
+ else
+ g_appname = argv[0];
+
+ if (argc <= argindex) usage("Too few arguments: %s", "Missing Command");
+
+ /* parse options */
+ if (!strcmp(argv[argindex], "--version") ||
+ !strcmp(argv[argindex], "-V") )
+ {
+ show_version(stdout);
+ if (argc == ++argindex) exit(0);
+ }
+
+ if ( !strcmp(argv[argindex], "-e") ||
+ (!strcmp(argv[argindex], "-Ve") && (show_version(stdout),1)) )
+ {
+ ++argindex;
+ if (argc <= argindex) usage("Too few arguments: %s", "Missing Entity and Command");
+
+ g_entity = argv[argindex++];
+
+ if (argc <= argindex) usage("Too few arguments: %s", "Missing Command");
+ }
+
+ /* do help command/options */
+ if (!strcmp(argv[argindex], "help") ||
+ !strcmp(argv[argindex], "--help") ||
+ !strcmp(argv[argindex], "-h") ||
+ !strcmp(argv[argindex], "-?") )
+ {
+ usage(NULL,NULL);
+ }
+
+ /* end of options */
+ subargc = argc - argindex;
+ subargv = argv + argindex;
+
+ if (match(subargv[0],"test"))
+ test_connect_avail(subargc,subargv);
+
+ else if (match(subargv[0],"list"))
+ list_components(subargc,subargv);
+
+ else if (match(subargv[0],"show"))
+ show_components(subargc,subargv);
+
+ else if (match(subargv[0],"offline"))
+ do_offline(subargc,subargv);
+
+ else
+ usage("Unknown command: '%s'",subargv[0]);
+
+ return 0;
+}
+
+/* PAPI helper functions */
+
+void checkPapiError(PAPIStatus error)
+{
+ const char * errmsg;
+ switch (error)
+ {
+ case PAPISuccess:
+ return;
+
+ case PAPIConnectionFailure:
+ errmsg = "PAPI: Connection Failure for entity %s";
+ break;
+
+ case PAPIAuthenticationFailure:
+ errmsg = "PAPI: Authentication Failure for entity %s";
+ break;
+
+
+ case PAPINoSuchComponentFailure:
+ errmsg = "PAPI: No such component";
+ break;
+
+ case PAPILDBFailure:
+ errmsg = "PAPI: Database (LDB) Failure";
+ break;
+
+ case PAPIInvalidArg:
+ errmsg = "PAPI: Invalid Argument";
+ break;
+
+ case PAPIOutOfMemoryFailure:
+ errmsg = "PAPI: Out of Memory";
+ break;
+
+ case PAPIUnknownFailure:
+ errmsg = "PAPI: Unspecified Failure";
+ break;
+
+ default:
+ errmsg = "PAPI: Unknown PAPI error code";
+ break;
+ }
+ const char * entity = g_entity ? g_entity : "<default entity>";
+
+ show_error(errmsg,entity);
+ fprintf(stderr,"\nTerminating\n");
+
+ exit(-error);
+}
+
+PAPI * initPapi()
+{
+ PAPIStatus error = PAPISuccess;
+ PAPI * result = papiInitialise(g_entity,&error);
+
+ checkPapiError(error);
+ return result;
+}
+
+void exitPapi(PAPI * papi)
+{
+ PAPIStatus error = PAPISuccess;
+
+ papiDeinitialise(papi,&error);
+
+ checkPapiError(error);
+}
+
+/* connection test function */
+
+void describe_test_usage()
+{
+ fprintf(stderr,"\n\n\t%s [options] t[est]", g_appname);
+ fputs( "\n\t\t- Test if a PAPI connection can be established"
+ , stderr);
+}
+
+void test_connect_avail(int argc, char * const argv[])
+{
+ PAPI * papi;
+
+ papi = initPapi();
+
+ fprintf(stderr,"\nOK. PAPI connection was established successfully");
+ if (g_entity)
+ fprintf(stderr," for entity '%s'", g_entity);
+ else
+ fprintf(stderr," for the current user");
+ fputs("\n",stderr);
+
+ exitPapi(papi);
+}
+
+/* list components function */
+
+void describe_list_usage()
+{
+ fprintf(stderr,"\n\n\t%s [options] l[ist] [filter]", g_appname);
+ fputs( "\n\t\t- List components that match a filter"
+ , stderr);
+}
+
+void list_components(int argc, char * const argv[])
+{
+ PAPI * papi;
+ PAPIStatus error = PAPISuccess;
+ PAPIStringList * components;
+ PAPIStringList * component;
+ const char * filter;
+ int count = 0;
+
+ if (argc > 2)
+ {
+ show_error("Too many arguments for 'list' command",NULL);
+ list_usage();
+ }
+
+ if (argc < 2)
+ filter = NULL;
+ else
+ filter = argv[1];
+
+ papi = initPapi();
+
+ components = papiListComponentNames(papi,filter,&error);
+
+ if (error == PAPINoSuchComponentFailure)
+ {
+ fprintf(stderr,"\nNo Component for filter '%s'\n",filter ? filter : "<null>");
+ goto done;
+ }
+
+ checkPapiError(error);
+
+ for (component = components; component; component=component->next)
+ {
+ ++count;
+ if (component->data)
+ printf("%s\n",component->data);
+ else
+ fprintf(stderr, "### Data for component #%d is NULL ###\n",count);
+ }
+ fprintf(stderr,"\n\n%d component(s) found.\n",count );
+
+ papiFreeStringList(components);
+
+done:
+ exitPapi(papi);
+}
+
+/* show component data function */
+
+void describe_show_usage()
+{
+ fprintf(stderr,"\n\n\t%s [options] s[how] (all|time|count|<N>) <component> ...", g_appname);
+
+ fputs( "\n\t\t- Show data for component(s)."
+ "\n\t\t Supported operations:"
+ "\n\t\t all - show entire contents for all layers of each component"
+ "\n\t\t time - show layer count and timestamp for each component"
+ "\n\t\t count - show layer count for each component"
+ "\n\t\t <N> - show Nth layer of component (works best with a single component)"
+ , stderr);
+}
+
+enum {
+ SHOW_FULL = -1,
+ SHOW_TIME = -2,
+ SHOW_COUNT = -3
+};
+
+void dump_layer(PAPILayerList * layer, FILE * tofile)
+{
+ fputs("\n",tofile);
+ if (layer && layer->data && layer->size>0)
+ {
+ size_t size = layer->size, read;
+ const unsigned char * data = layer->data;
+
+ while (size > 0)
+ {
+ read = fwrite(data,1,size,tofile);
+
+ if (read == 0)
+ {
+ fputs("\n### ERROR ###",tofile);
+ show_error("Error writing output: %s", strerror(errno));
+ break;
+ }
+
+ size -= read;
+ data += read;
+ }
+ }
+ else
+ fputs("### No data for this layer ###",tofile);
+
+ fputs("\n",tofile);
+}
+
+void dump_component(const char * component, PAPILayerList * layers, int op)
+{
+ PAPILayerList * layer;
+ int count = 0;
+
+ if (op >= SHOW_FULL)
+ printf("\n========== Start of data for component '%s' ==================", component);
+ else
+ printf("\nComponent '%s':", component);
+
+ for (layer = layers; layer; layer=layer->next)
+ {
+ ++count;
+
+ if (op == SHOW_FULL || op == SHOW_TIME)
+ printf("\n- Layer #%d: Timestamp = %s\t***",
+ count, layer->timestamp ? layer->timestamp : "<null>");
+
+ if (op == SHOW_FULL || op == count)
+ dump_layer(layer,stdout);
+ }
+
+ if (op >= SHOW_FULL)
+ printf("========== End of data for component '%s' ====================", component);
+
+ printf("\n\t%d layer(s)\n",count);
+}
+
+void show_components(int argc, char * const argv[])
+{
+ PAPI * papi;
+ PAPIStatus error = PAPISuccess;
+ const char * component;
+ int argindex = 1;
+ int op;
+
+ if (argc < 3)
+ {
+ show_error("Not enough arguments for 'show' command",NULL);
+ show_usage();
+ }
+
+ if (match(argv[argindex],"all"))
+ op = SHOW_FULL;
+
+ else if (match(argv[argindex],"time"))
+ op = SHOW_TIME;
+
+ else if (match(argv[argindex],"count"))
+ op = SHOW_COUNT;
+
+ else
+ op = atoi(argv[argindex]);
+
+ if (op == 0)
+ {
+ show_error("Invalid operation '%s' for 'show' command",argv[argindex]);
+ show_usage();
+ }
+
+ papi = initPapi();
+
+ while ( (component = argv[++argindex]) != NULL )
+ {
+ PAPILayerList * layers = papiReadComponentLayers(papi,component,&error);
+
+ if (error == PAPINoSuchComponentFailure)
+ {
+ printf("\nNo Such Component '%s'\n",component);
+ continue;
+ }
+
+ checkPapiError(error);
+
+ dump_component(component,layers,op);
+
+ papiFreeLayerList(layers);
+ }
+
+ exitPapi(papi);
+}
+
+/* offline status function */
+
+void describe_offline_usage()
+{
+ fprintf(stderr,"\n\n\t%s [options] o[ffline] (show|add|drop|+|-) <component> ...", g_appname);
+
+ fputs( "\n\t\t- Show or change offline status for component(s)."
+ "\n\t\t Supported operations:"
+ "\n\t\t show - show current offline status for each component"
+ "\n\t\t add - mark each component for offline availability (alias '+')"
+ "\n\t\t drop - mark each component as not availabile offline (alias '-')"
+ , stderr);
+ fputs("\n\t*** NOT YET IMPLEMENTED ***",stderr);
+}
+
+void do_offline(int argc, char * const argv[])
+{
+ PAPI * papi;
+ PAPIStatus error = PAPISuccess;
+
+ offline_usage();
+
+ papi = initPapi();
+ exitPapi(papi);
+}
+
+/* usage reporting */
+
+void show_version(FILE * file)
+{
+ const char * version = "0.1";
+ const char * author = "Joerg Barfurth";
+ fprintf(file,"\n%s - PAPI dumper tool for APOC",g_appname);
+ fprintf(file,"\nVersion: %s\tBuild time: %s",version,__TIME__);
+ fprintf(file,"\nAuthor: %s",author);
+ fprintf(file,"\nCopyright (C) 2003 Sun Microsystems,Inc.\n");
+}
+
+void pre_usage()
+{
+ show_version(stderr);
+ fprintf(stderr,"\nUsage: ");
+}
+
+void post_usage(int exitcode)
+{
+ fprintf(stderr,"\n\nOptions:");
+ fprintf(stderr,"\n\t-V / --version\t- display information about this tool");
+ fprintf(stderr,"\n\t-e <entity>\t- use entity id <entity>");
+ fprintf(stderr,"\n");
+
+ exit(exitcode);
+}
+
+void describe_help_usage()
+{
+ fprintf(stderr,"\n\n\t%s [options] help\n\t\t- show this help screen", g_appname);
+}
+
+void show_error(char const * fmt, char const * param)
+{
+ fprintf(stderr,"### %s Error: ", g_appname);
+ fprintf(stderr,fmt,param);
+}
+
+void usage(char const * fmt, char const * param)
+{
+ if (fmt)
+ show_error(fmt,param);
+
+ pre_usage();
+
+ describe_test_usage();
+ describe_list_usage();
+ describe_show_usage();
+ describe_offline_usage();
+ describe_help_usage();
+
+ post_usage(fmt?1:0);
+}
+
+void list_usage()
+{
+ pre_usage();
+
+ describe_list_usage();
+
+ post_usage(2);
+}
+
+void show_usage()
+{
+ pre_usage();
+
+ describe_show_usage();
+
+ post_usage(3);
+}
+
+void offline_usage()
+{
+ pre_usage();
+
+ describe_offline_usage();
+
+ post_usage(4);
+}
+
+
diff --git a/libapoc/w32/Makefile b/libapoc/w32/Makefile
new file mode 100644
index 0000000..1d4d88a
--- /dev/null
+++ b/libapoc/w32/Makefile
@@ -0,0 +1,55 @@
+#
+#*******************************************************************************
+#* $RCSfile: Makefile,v $
+#*
+#* Description:
+#*
+#* Last change: $Date: 2007/04/20 15:01:50 $ $Revision: 1.3 $
+#*
+#* Copyright 2003 Sun Microsystems, Inc. All rights reserved. Use of this
+#* product is subject to license terms.
+#*
+#*******************************************************************************
+#
+
+
+PRJ=../../..
+
+include $(PRJ)/Makefile.common
+
+ifdef WNT
+
+APOCSOURCES = papiPort.c
+APOCOBJS = $(APOCSOURCES:%.c=$(OBJDIR)/%.o)
+APOCINCLUDES = -I../.. $(GSSINCLUDES) $(INCLUDES)
+
+all: apoc
+
+clean: apocclean
+
+apoc: mkdirs $(APOCOBJS)
+
+apocclean:
+ rm -f $(APOCOBJS)
+
+mkdirs:
+ $(mkoutdirs)
+
+$(OBJDIR)/%.o: %.c
+ $(CC) $(CFLAGSSO) $(APOCINCLUDES) -c $*.c -Fo$(OBJDIR)/$*.o -Fd$(OBJDIR)/$*.pdb
+
+else
+
+apoc:
+
+all:
+
+clean:
+
+apoc:
+
+apocclean:
+
+mkdirs:
+
+endif
diff --git a/libapoc/w32/Makefile.old b/libapoc/w32/Makefile.old
new file mode 100644
index 0000000..c75f42e
--- /dev/null
+++ b/libapoc/w32/Makefile.old
@@ -0,0 +1,110 @@
+#
+#*******************************************************************************
+#* $RCSfile: Makefile,v $
+#*
+#* Description:
+#*
+#* Last change: $Date: 2006/06/27 09:08:56 $ $Revision: 1.9 $
+#*
+#* Copyright 2003 Sun Microsystems, Inc. All rights reserved. Use of this
+#* product is subject to license terms.
+#*
+#*******************************************************************************
+#
+
+
+PRJ=../..
+
+include $(PRJ)/Makefile.common
+
+APOCSOURCES = \
+ papi.c \
+ papiConnection.c \
+ papiDaemon.c \
+ papiDatabase.c \
+ papiInternal.c \
+ papiLayerList.c \
+ papiListenerList.c \
+ papiMessage.c \
+ papiSAXParserContext.c \
+ papiStringList.c \
+ papiEntityList.c \
+ papiUtils.c
+APOCOBJS = $(APOCSOURCES:%.c=$(OBJDIR)/%.o) $(OBJDIR)/papiPort.o
+LIBAPOC = $(LIBDIR)/$(SOPREFIX)apoc$(SOSUFFIX)
+APOCINCLUDES = $(LIBXML2INCLUDES) $(INCLUDES)
+APOCLIBS = $(LIBXML2LIBS) $(GSSLIBS) $(LIBS)
+ifdef SOLARIS
+APOCLIBS += -lscf
+endif
+
+
+APOCJAVASOURCE = papiJava.c
+APOCJAVAOBJS = $(APOCJAVASOURCE:%.c=$(OBJDIR)/%.o)
+LIBAPOCJAVA = $(LIBDIR)/$(SOPREFIX)apoc_java$(SOSUFFIX)
+ifdef UNX
+APOCJAVALIBS = -L$(LIBDIR) -lapoc $(LIBS)
+else
+APOCJAVALIBS = apoc.lib $(LIBS)
+endif
+
+
+APOCWRAPSOURCE = papiWrap.c
+APOCWRAPOBJS = $(APOCWRAPSOURCE:%.c=$(OBJDIR)/%.o)
+LIBAPOCWRAP = $(LIBDIR)/$(SOPREFIX)apocwrap$(SOSUFFIX)
+ifdef UNX
+APOCWRAPLIBS = -L$(LIBDIR) -lapoc $(LIBS) -lrt
+else
+APOCWRAPLIBS = apoc.lib $(LIBS)
+endif
+
+all: apoc apoc-adapter-java
+
+clean: apocclean apoc-adapter-javaclean
+
+apoc: mkdirs $(LIBAPOC)
+
+$(LIBAPOC): $(APOCOBJS)
+ifdef UNX
+ $(CC) $(LDFLAGSSO) -o $(LIBAPOC) $(APOCOBJS) $(APOCLIBS) -ldl
+else
+ $(LINK) $(LDFLAGSSO) $(APOCOBJS) /OUT:$(LIBAPOC) $(APOCLIBS)
+endif
+
+apocclean:
+ rm -f $(APOCOBJS) $(LIBAPOC)
+
+apoc-adapter-java: $(LIBAPOCJAVA)
+
+$(LIBAPOCJAVA): $(APOCJAVAOBJS)
+ifdef UNX
+ $(CC) $(LDFLAGSSO) -o$(LIBAPOCJAVA) $(APOCJAVAOBJS) $(APOCJAVALIBS)
+else
+ $(LINK) $(LDFLAGSSO) $(APOCJAVAOBJS) /OUT:$(LIBAPOCJAVA) $(APOCJAVALIBS)
+endif
+
+apoc-adapter-javaclean:
+ rm -f $(APOCJAVAOBJS) $(LIBAPOCJAVA)
+
+
+apocwrap: $(LIBAPOCWRAP)
+
+$(LIBAPOCWRAP): $(APOCWRAPOBJS)
+ifdef UNX
+ $(CC) $(LDFLAGSSO) -o$(LIBAPOCWRAP) $(APOCWRAPOBJS) $(APOCWRAPLIBS)
+else
+ $(LINK) $(LDFLAGSSO) $(APOCWRAPOBJS) /OUT:$(LIBAPOCWRAP) $(APOCWRAPLIBS)
+endif
+
+apocwrapclean:
+ rm -f $(APOCWRAPOBJS) $(LIBAPOCWRAP)
+
+mkdirs:
+ $(mkoutdirs)
+
+$(OBJDIR)/%.o: %.c
+ifdef UNX
+ $(CC) $(CFLAGSSO) $(APOCINCLUDES) -c $*.c -o $(OBJDIR)/$*.o
+else
+ $(CC) $(CFLAGSSO) -DPAPI_EXPORTS $(APOCINCLUDES) -c $*.c -Fo$(OBJDIR)/$*.o -Fd$(OBJDIR)/$*.pdb
+endif
diff --git a/libapoc/w32/papiPort.c b/libapoc/w32/papiPort.c
new file mode 100755
index 0000000..6383f02
--- /dev/null
+++ b/libapoc/w32/papiPort.c
@@ -0,0 +1,624 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papiUtils.h"
+
+#include <lmcons.h>
+#define SECURITY_WIN32
+#include <security.h>
+#include <sspi.h>
+#include <ntsecapi.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <shlobj.h>
+
+typedef WINADVAPI SC_HANDLE ( WINAPI *OpenSCManagerFunc )
+ ( LPCTSTR, LPCTSTR, DWORD );
+
+typedef WINADVAPI BOOL ( WINAPI * EnumServicesStatusFunc )
+ ( SC_HANDLE, DWORD, DWORD, LPENUM_SERVICE_STATUS, DWORD, LPDWORD, LPDWORD,
+ LPDWORD );
+
+static PSecurityFunctionTable getSecurityInterface( int * outMaxTokenSize );
+
+static int isRegistryEnabled( void );
+
+static int isServiceEnabled( void );
+
+static int loadServiceFuncs( void );
+
+static void writeGSSAPIAuthId(
+ PSecurityFunctionTable inSecurityInterface,
+ CredHandle * inCredentials,
+ CtxtHandle * inContext,
+ SecBuffer * outBuffer,
+ PAPIStatus * outStatus );
+
+static void encodeGSSAPITokens( SecBuffer * inBuffers,
+ int inBufferCount,
+ char ** outB64Buffer );
+
+#define INSTALLDIR "\\Sun\\apoc\\lib"
+
+const char * convertDataDir( const char * inDataDir )
+{
+ char * theDataDir = 0;
+ if ( inDataDir != 0 )
+ {
+ theDataDir = ( char * )malloc( strlen( inDataDir ) + 1 );
+ if ( theDataDir != 0 )
+ {
+ char * theToken = strtok( inDataDir, "\\" );
+ theDataDir[ 0 ] = 0;
+ while ( theToken != 0 )
+ {
+ strcat( theDataDir, theToken );
+ theToken = strtok( 0, "\\" );
+ if ( theToken != 0 )
+ {
+ strcat( theDataDir, "\\" );
+ }
+ }
+ }
+ }
+ return theDataDir;
+}
+
+int createThread( PAPIThreadFunc inThreadFunc,
+ void * inArg )
+{
+ int theThreadId;
+ HANDLE theThread =
+ CreateThread( NULL,
+ 0,
+ ( LPTHREAD_START_ROUTINE )inThreadFunc,
+ inArg,
+ 0,
+ ( LPDWORD )&theThreadId );
+ return theThread != 0 ? 0 : -1;
+}
+
+const char * getInstallDir( void )
+{
+ static char * sInstallDir = 0;
+ if ( sInstallDir == 0 )
+ {
+ char theProgramFiles[ MAX_PATH ];
+ if ( SHGetFolderPath( NULL,
+ CSIDL_PROGRAM_FILES,
+ NULL,
+ SHGFP_TYPE_CURRENT,
+ ( LPTSTR )&theProgramFiles ) == S_OK )
+ {
+ char theShortPath[ MAX_PATH ];
+ DWORD theSize = MAX_PATH;
+ theSize =GetShortPathName( theProgramFiles, &theShortPath, theSize);
+ sInstallDir = malloc( theSize +
+ strlen( INSTALLDIR ) +
+ 1 );
+ if ( sInstallDir != 0 )
+ {
+ sprintf( sInstallDir, "%s%s", theShortPath, INSTALLDIR );
+ }
+ }
+ }
+ return sInstallDir;
+}
+
+const char * getLibraryDir( void )
+{
+ return getInstallDir();
+}
+
+const char * getPropertiesDir( void )
+{
+ return getInstallDir();
+}
+
+int isNewerThanWindows98( void )
+{
+ if ( GetVersion() < 0x80000000 )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+PAPIMutex * newMutex( void )
+{
+ PAPIMutex * theMutex =
+ ( PAPIMutex * )malloc( sizeof( PAPIMutex ) );
+ if ( theMutex != 0 )
+ {
+ InitializeCriticalSection( theMutex );
+ }
+ return theMutex;
+}
+
+void deleteMutex( PAPIMutex * inMutex )
+{
+ if ( inMutex != 0 )
+ {
+ DeleteCriticalSection( inMutex );
+ free( ( void *)inMutex );
+ }
+}
+
+const char * getSASLCreds( const char * inServiceName, PAPIStatus * outStatus )
+{
+ char * theCredentials;
+ static int sMaxTokenSize;
+ PSecurityFunctionTable theSecurityInterface =
+ getSecurityInterface( &sMaxTokenSize );
+
+ *outStatus = PAPIAuthenticationFailure;
+ if ( theSecurityInterface != 0 )
+ {
+ if ( inServiceName != 0 )
+ {
+ CredHandle theCredHandle;
+ TimeStamp theCredLifetime;
+ SECURITY_STATUS theStatus =
+ ( theSecurityInterface->AcquireCredentialsHandle )
+ (
+ 0,
+ "Kerberos",
+ SECPKG_CRED_OUTBOUND,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &theCredHandle,
+ &theCredLifetime
+ );
+ if ( theStatus == SEC_E_OK )
+ {
+ CtxtHandle theContextHandle;
+ SecBufferDesc theOutBufferDesc;
+ SecBuffer theOutBuffer[ 3 ];
+ ULONG theAttrs;
+
+ theOutBuffer[ 1 ].cbBuffer =
+ theOutBuffer[ 2 ].cbBuffer = 0;
+ theOutBufferDesc.ulVersion = SECBUFFER_VERSION;
+ theOutBufferDesc.cBuffers = 1;
+ theOutBufferDesc.pBuffers = &theOutBuffer[ 0 ];
+ theOutBuffer[ 0 ].BufferType = SECBUFFER_TOKEN;
+ theOutBuffer[ 0 ].cbBuffer = sMaxTokenSize;
+ theOutBuffer[ 0 ].pvBuffer =
+ ( PBYTE )malloc( sMaxTokenSize );
+
+ theStatus =
+ ( theSecurityInterface->InitializeSecurityContext )
+ (
+ &theCredHandle,
+ NULL,
+ ( SEC_CHAR * )inServiceName,
+ ISC_REQ_DELEGATE,
+ 0,
+ SECURITY_NATIVE_DREP,
+ NULL,
+ 0,
+ &theContextHandle,
+ &theOutBufferDesc,
+ &theAttrs,
+ &theCredLifetime
+ );
+ if ( theStatus == SEC_E_OK ||
+ theStatus == SEC_I_CONTINUE_NEEDED ||
+ theStatus == SEC_I_COMPLETE_NEEDED ||
+ theStatus == SEC_I_COMPLETE_AND_CONTINUE )
+ {
+ writeGSSAPIAuthId( theSecurityInterface,
+ &theCredHandle,
+ &theContextHandle,
+ &theOutBuffer[ 2 ],
+ outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ encodeGSSAPITokens( theOutBuffer,
+ 3,
+ &theCredentials );
+ }
+ FreeContextBuffer( &theContextHandle );
+ }
+ FreeCredentialsHandle( &theCredHandle );
+ }
+ }
+ }
+ return theCredentials;
+}
+
+const char * getUserName( void )
+{
+ DWORD theBufferSize = UNLEN + 1;
+ LPTSTR theBuffer = ( LPTSTR )malloc( ( size_t )theBufferSize );
+
+ GetUserName( theBuffer, &theBufferSize );
+ return theBuffer;
+}
+
+int isDaemonEnabled( void )
+{
+ return isNewerThanWindows98() == 1 ?
+ isServiceEnabled() : isRegistryEnabled();
+}
+
+int lockMutex( PAPIMutex * inMutex )
+{
+ int theRC = -1;
+ if ( inMutex != 0 )
+ {
+ EnterCriticalSection( inMutex );
+ theRC = 0;
+ }
+ return theRC;
+}
+
+int socketPoll( PAPISocket inSocket, int inMillis )
+{
+ fd_set theReadSet;
+
+ FD_ZERO( &theReadSet );
+ FD_SET( inSocket, &theReadSet );
+ if ( inMillis != -1 )
+ {
+ struct timeval theTimeout;
+ theTimeout.tv_sec = 0;
+ theTimeout.tv_usec = inMillis * 1000;
+ return select( 1, &theReadSet, 0, 0, &theTimeout );
+ }
+ else
+ {
+ return select( 1, &theReadSet, 0, 0, 0 );
+ }
+}
+
+int startDaemon( void )
+{
+ int theRC = 1;
+ static const char * theFormat = "%s%sbin%sapocd start";
+ static char * theCommand = 0;
+
+ if ( isNewerThanWindows98() == 0 && isDaemonEnabled() == 1 )
+ {
+ if ( theCommand == 0 )
+ {
+ const char * theDaemonInstallDir = getDaemonInstallDir();
+ char * theCP = ( char * )theDaemonInstallDir +
+ strlen( theDaemonInstallDir ) - 1;
+ while ( theCP-- != theDaemonInstallDir )
+ {
+ if ( *theCP == '\\' )
+ {
+ *theCP = 0;
+ break;
+ }
+ }
+ theCommand =
+ ( char * )malloc( strlen( theDaemonInstallDir ) +
+ ( strlen( FILESEP ) * 2 ) +
+ strlen( theFormat ) + 1 );
+ if ( theCommand != 0 )
+ {
+ sprintf( theCommand,
+ theFormat,
+ theDaemonInstallDir,
+ FILESEP,
+ FILESEP );
+ }
+ }
+ if ( theCommand != 0 )
+ {
+ STARTUPINFO theStartupInfo;
+ PROCESS_INFORMATION theProcessInfo;
+
+ ZeroMemory( &theStartupInfo, sizeof( theStartupInfo ) );
+ theStartupInfo.dwFlags = STARTF_USESHOWWINDOW;
+ theStartupInfo.wShowWindow = SW_HIDE;
+ theStartupInfo.cb = sizeof( theStartupInfo );
+ ZeroMemory( &theProcessInfo, sizeof( theProcessInfo ) );
+ if ( CreateProcess( 0,
+ theCommand,
+ 0,
+ 0,
+ FALSE,
+ DETACHED_PROCESS,
+ 0,
+ 0,
+ &theStartupInfo,
+ &theProcessInfo ) != 0 )
+ {
+ theRC = 0;
+ CloseHandle( theProcessInfo.hProcess );
+ CloseHandle( theProcessInfo.hThread );
+ }
+ }
+ }
+ return theRC;
+}
+
+int unlockMutex( PAPIMutex * inMutex )
+{
+ int theRC = -1;
+ if ( inMutex != 0 )
+ {
+ LeaveCriticalSection( inMutex );
+ theRC = 0;
+ }
+ return theRC;
+}
+
+void encodeGSSAPITokens( SecBuffer * inBuffers,
+ int inBufferCount,
+ char ** outB64Buffer )
+{
+ void * theBuffer;
+ char * theTmpPtr;
+ int theBufferSize = 0;
+ int theIndex;
+
+ for ( theIndex = 0; theIndex < inBufferCount; ++ theIndex )
+ {
+ theBufferSize += inBuffers[ theIndex ].cbBuffer + 5;
+ }
+
+ theBuffer = malloc( theBufferSize );
+ theTmpPtr = ( char *)theBuffer;
+ for ( theIndex = 0; theIndex < inBufferCount; ++ theIndex )
+ {
+ /* Write the token size */
+ snprintf( theTmpPtr, 6, "%05d", inBuffers[ theIndex ].cbBuffer );
+ theTmpPtr[ 5 ] = 0;
+ theTmpPtr += 5;
+
+ /* Write the token */
+ memcpy( ( void *)theTmpPtr,
+ inBuffers[ theIndex ].pvBuffer,
+ inBuffers[ theIndex ].cbBuffer );
+ theTmpPtr += inBuffers[ theIndex ].cbBuffer;
+ }
+ base64_encode( theBuffer, theBufferSize, outB64Buffer );
+ free( ( void * )theBuffer );
+}
+
+PSecurityFunctionTable getSecurityInterface( int * outMaxTokenSize )
+{
+ static PSecurityFunctionTable theSecurityInterface = 0;
+ static int isInitialised = 0;
+
+ if ( isInitialised == 0 )
+ {
+ isInitialised = 1;
+ theSecurityInterface = InitSecurityInterface();
+ if ( theSecurityInterface != 0 )
+ {
+ PSecPkgInfo thePkgInfo;
+ if ( ( theSecurityInterface->QuerySecurityPackageInfo )
+ (
+ "Kerberos",
+ &thePkgInfo
+ ) != SEC_E_OK )
+ {
+ theSecurityInterface = 0;
+ }
+ *outMaxTokenSize = thePkgInfo->cbMaxToken;
+ }
+ }
+ return theSecurityInterface;
+}
+
+int isRegistryEnabled( void )
+{
+ int theRC = 0;
+ HKEY theKey;
+ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ APOCENABLEDKEY,
+ 0,
+ KEY_QUERY_VALUE,
+ &theKey ) == ERROR_SUCCESS )
+ {
+ RegCloseKey( theKey );
+ theRC = 1;
+ }
+ return theRC;
+}
+
+int isServiceEnabled( void )
+{
+ int theRC = 0;
+ HMODULE theModule = GetModuleHandle( "advapi32" );
+
+ if ( theModule != 0 )
+ {
+ OpenSCManagerFunc fOpenSCManager =
+ ( OpenSCManagerFunc )GetProcAddress( theModule, "OpenSCManagerA" );
+ EnumServicesStatusFunc fEnumServicesStatus =
+ ( EnumServicesStatusFunc )GetProcAddress( theModule,
+ "EnumServicesStatusA" );
+ if ( fOpenSCManager != 0 && fEnumServicesStatus != 0 )
+ {
+ SC_HANDLE theSCManager =
+ fOpenSCManager( 0, 0, SC_MANAGER_ENUMERATE_SERVICE );
+ if ( theSCManager != 0 )
+ {
+ DWORD theBytes;
+ DWORD theCount;
+ DWORD theHandle = 0;
+
+ if ( fEnumServicesStatus(
+ theSCManager,
+ SERVICE_WIN32,
+ SERVICE_STATE_ALL,
+ 0,
+ 0,
+ &theBytes,
+ &theCount,
+ &theHandle ) == 0 &&
+ GetLastError() == ERROR_MORE_DATA &&
+ theBytes > 0 )
+ {
+ ENUM_SERVICE_STATUS * theServices =
+ ( ENUM_SERVICE_STATUS * )malloc( theBytes );
+ if ( theServices != 0 )
+ {
+ DWORD theIndex;
+
+ fEnumServicesStatus(
+ theSCManager,
+ SERVICE_WIN32,
+ SERVICE_STATE_ALL,
+ theServices,
+ theBytes,
+ &theBytes,
+ &theCount,
+ &theHandle );
+ for ( theIndex = 0; theIndex < theCount; ++ theIndex )
+ {
+ if ( strcmp( theServices[ theIndex ].lpServiceName,
+ APOCSERVICENAME ) == 0 )
+ {
+ theRC = 1;
+ break;
+ }
+ }
+ }
+ }
+ CloseServiceHandle( theSCManager );
+ }
+ }
+ }
+ return theRC;
+}
+
+void writeGSSAPIAuthId( PSecurityFunctionTable inSecurityInterface,
+ CredHandle * inCredentials,
+ CtxtHandle * inContext,
+ SecBuffer * outBuffer,
+ PAPIStatus * outStatus )
+{
+ SecPkgContext_Sizes theContextSizes;
+ SecPkgContext_Names theSourceName;
+ SECURITY_STATUS theStatus =
+ ( inSecurityInterface->QueryCredentialsAttributes )
+ (
+ inCredentials,
+ SECPKG_CRED_ATTR_NAMES,
+ ( PVOID )&theSourceName
+ );
+ *outStatus = PAPIAuthenticationFailure;
+ if ( theStatus == SEC_E_OK )
+ {
+ theStatus = ( inSecurityInterface->QueryContextAttributes )
+ (
+ inContext,
+ SECPKG_ATTR_SIZES,
+ ( PVOID )&theContextSizes
+ );
+ if ( theStatus == SEC_E_OK )
+ {
+ SecBufferDesc theBufferDesc;
+ SecBuffer theBuffers[ 3 ];
+ int theSourceNameSize = strlen(theSourceName.sUserName);
+ char * theCP;
+ BYTE * theOutput =
+ ( PBYTE )malloc( theContextSizes.cbSecurityTrailer +
+ theSourceNameSize +
+ 4 +
+ sizeof( DWORD ) );
+
+ theBufferDesc.ulVersion = SECBUFFER_VERSION;
+ theBufferDesc.cBuffers = 3;
+ theBufferDesc.pBuffers = theBuffers;
+
+ theBuffers[ 0 ].cbBuffer = theContextSizes.cbSecurityTrailer;
+ theBuffers[ 0 ].BufferType = SECBUFFER_TOKEN;
+ theBuffers[ 0 ].pvBuffer = theOutput + sizeof( DWORD );
+
+
+ theBuffers[ 1 ].cbBuffer = theSourceNameSize + 4;
+ theBuffers[ 1 ].BufferType = SECBUFFER_DATA;
+ theBuffers[ 1 ].pvBuffer = malloc( theBuffers[ 1 ].cbBuffer );
+ theCP = ( char * )theBuffers[ 1 ].pvBuffer;
+ theCP[ 0 ] = 1;
+ theCP[ 1 ] = theCP[ 2 ] = theCP[ 3 ] = ( char )0;
+ memcpy( theCP + 4,
+ theSourceName.sUserName,
+ theSourceNameSize );
+
+ theBuffers[ 2 ].cbBuffer = theContextSizes.cbBlockSize;
+ theBuffers[ 2 ].BufferType = SECBUFFER_PADDING;
+ theBuffers[ 2 ].pvBuffer = malloc( theBuffers[ 2 ].cbBuffer );
+
+ theStatus = inSecurityInterface->EncryptMessage( inContext,
+ KERB_WRAP_NO_ENCRYPT,
+ &theBufferDesc,
+ 0 );
+ if ( theStatus == SEC_E_OK )
+ {
+ outBuffer->cbBuffer = theBuffers[ 0 ].cbBuffer +
+ theBuffers[ 1 ].cbBuffer +
+ theBuffers[ 2 ].cbBuffer;
+ outBuffer->pvBuffer = malloc( outBuffer->cbBuffer );
+ if ( outBuffer->pvBuffer != 0 )
+ {
+ theCP = ( char * )outBuffer->pvBuffer;
+ memcpy( theCP,
+ theBuffers[ 0 ].pvBuffer,
+ theBuffers[ 0 ].cbBuffer );
+ memcpy( theCP + theBuffers[ 0 ].cbBuffer,
+ theBuffers[ 1 ].pvBuffer,
+ theBuffers[ 1 ].cbBuffer );
+ memcpy( theCP +
+ theBuffers[ 0 ].cbBuffer +
+ theBuffers[ 1 ].cbBuffer,
+ theBuffers[ 2 ].pvBuffer,
+ theBuffers[ 2 ].cbBuffer );
+ *outStatus = PAPISuccess;
+ }
+ else
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ }
+ }
+ }
+ }
+ else
+ {
+ *outStatus = PAPIAuthenticationFailure;
+ }
+}
diff --git a/libfileaccess/FileAccess.c b/libfileaccess/FileAccess.c
new file mode 100644
index 0000000..35dfca7
--- /dev/null
+++ b/libfileaccess/FileAccess.c
@@ -0,0 +1,493 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "FileAccess.h"
+
+#ifndef WNT
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#else
+
+#include <windows.h>
+#include <aclapi.h>
+
+static BOOL addACE( PACL inACL,
+ DWORD inMask,
+ PSID inSid );
+
+static int chmod( const char * inFile,
+ int inMode );
+
+static int chown( const char * inFile,
+ const char * inUser );
+
+static BOOL initSid( PSID_IDENTIFIER_AUTHORITY inAuthority,
+ DWORD inSubAuthority,
+ PSID * outSid );
+
+static BOOL getSID( const char * inOwner,
+ PSID * outSID );
+
+static void modeToAccessMask( int inMode,
+ DWORD * outOwnerMask,
+ DWORD * outGroupMask,
+ DWORD * outOthersMask );
+
+
+static BOOL setOwner( PSID inSID,
+ const char * inFile );
+
+static BOOL setPrivelege( LPCTSTR inPrivelege );
+
+static BOOL setPriveleges( LPCTSTR * inPriveleges,
+ int inCount );
+
+static BOOL setSecurity( const char * inFileName,
+ PACL inDACL );
+
+int S_IRWXU=0700;
+int S_IRUSR=0400;
+int S_IWUSR=0200;
+int S_IXUSR=0100;
+int S_IRWXG=0070;
+int S_IRGRP=0040;
+int S_IWGRP=0020;
+int S_IXGRP=0010;
+int S_IRWXO=0007;
+int S_IROTH=0004;
+int S_IWOTH=0002;
+int S_IXOTH=0001;
+
+#endif
+
+JNIEXPORT int JNICALL
+Java_com_sun_apoc_daemon_misc_FileAccess_chmod
+ ( JNIEnv * inEnv,
+ jclass inClass,
+ jstring inFileName,
+ jint inMode )
+{
+ int theResult;
+ const char * theFileName =
+ ( *inEnv )->GetStringUTFChars( inEnv, inFileName, 0);
+
+#ifndef WNT
+
+ theResult = chmod( theFileName, ( mode_t )inMode );
+
+#else
+
+ theResult = chmod( theFileName, inMode );
+
+#endif
+
+ ( *inEnv )->ReleaseStringUTFChars( inEnv, inFileName, theFileName );
+ return theResult;
+}
+
+JNIEXPORT int JNICALL
+Java_com_sun_apoc_daemon_misc_FileAccess_chown
+ ( JNIEnv * inEnv,
+ jclass inClass,
+ jstring inFileName,
+ jstring inUserName )
+{
+ int theResult;
+ const char * theFileName =
+ ( *inEnv )->GetStringUTFChars( inEnv, inFileName, 0 );
+ const char * theUserName =
+ ( *inEnv )->GetStringUTFChars( inEnv, inUserName, 0 );
+#ifndef WNT
+
+ struct passwd * thePasswd = getpwnam( theUserName );
+ if ( thePasswd != 0 )
+ {
+ theResult = chown( theFileName,
+ thePasswd->pw_uid,
+ thePasswd->pw_gid );
+ }
+ else
+ {
+ theResult = 1;
+ }
+
+#else
+ theResult = chown( theFileName, theUserName );
+
+#endif
+ ( *inEnv )->ReleaseStringUTFChars( inEnv, inFileName, theFileName );
+ ( *inEnv )->ReleaseStringUTFChars( inEnv, inUserName, theUserName );
+ return theResult;
+}
+
+#ifdef WNT
+
+BOOL addACE( PACL inACL, DWORD inMask, PSID inSid )
+{
+ return inMask != 0 ?
+ AddAccessAllowedAce( inACL, ACL_REVISION, inMask, inSid ) :
+ AddAccessDeniedAce( inACL, ACL_REVISION, GENERIC_ALL, inSid );
+}
+
+int chmod( const char * inFileName, int inMode )
+{
+ #define sizeofACE( inACE ) \
+ sizeof( ACCESS_ALLOWED_ACE ) - sizeof( DWORD ) + GetLengthSid( inACE )
+ SID_IDENTIFIER_AUTHORITY theCreator = SECURITY_CREATOR_SID_AUTHORITY;
+ PSID theOwner = 0;
+ PSID theGroup = 0;
+ PSID theOthers = 0;
+ PSID theAdmin = 0;
+ DWORD theOwnerMask;
+ DWORD theGroupMask;
+ DWORD theOthersMask;
+ DWORD theDACLSize;
+ PACL theDACL = 0;
+ int theResult = 1;
+
+ if ( GetVersion() < 0x80000000 )
+ {
+ getSID( "Administrators", &theAdmin );
+ modeToAccessMask( inMode, &theOwnerMask, &theGroupMask, &theOthersMask);
+ if ( initSid( &theCreator, SECURITY_CREATOR_OWNER_RID, &theOwner )!=0 &&
+ initSid( &theCreator, SECURITY_CREATOR_GROUP_RID, &theGroup )!=0 )
+ {
+ getSID( "Users", &theOthers );
+ theDACLSize = sizeof( ACL ) +
+ sizeofACE( theOwner ) +
+ sizeofACE( theGroup ) +
+ sizeofACE( theOthers ) +
+ sizeofACE( theAdmin );
+ theDACL = ( PACL ) malloc( theDACLSize );
+ if ( theDACL != 0 )
+ {
+ InitializeAcl( theDACL, theDACLSize, ACL_REVISION );
+ if ( addACE( theDACL, GENERIC_ALL, theAdmin ) != 0 &&
+ addACE( theDACL, GENERIC_ALL, theOwner ) != 0 &&
+ addACE( theDACL, theGroupMask, theGroup ) != 0 &&
+ addACE( theDACL, theOthersMask, theOthers ) != 0 )
+ {
+ theResult = setSecurity( inFileName, theDACL ) != 0 ? 0 : 1;
+ }
+ free( ( void *)theDACL );
+ }
+ }
+ if ( theOwner != 0 ) { FreeSid( theOwner ); }
+ if ( theGroup != 0 ) { FreeSid( theGroup ); }
+ }
+ else
+ {
+ theResult = _chmod( inFileName, inMode );
+ }
+ return theResult;
+}
+
+int chown( const char * inFileName, const char * inUserName )
+{
+ int theResult = 1;
+ PSID theSID;
+ LPCTSTR thePriveleges[ 4 ] =
+ {
+ SE_TAKE_OWNERSHIP_NAME,
+ SE_RESTORE_NAME,
+ SE_BACKUP_NAME,
+ SE_CHANGE_NOTIFY_NAME
+ };
+
+ if ( GetVersion() < 0x80000000 )
+ {
+ if ( setPriveleges( thePriveleges, 4 ) )
+ {
+ if ( getSID( inUserName, &theSID ) )
+ {
+ theResult = setOwner( theSID, inFileName ) ? 0 : 1;
+ }
+ }
+ }
+ else
+ {
+ theResult = 0;
+ }
+ return theResult;
+}
+
+BOOL initSid( PSID_IDENTIFIER_AUTHORITY inAuthority,
+ DWORD inSubAuthority,
+ PSID * outSid )
+{
+ return AllocateAndInitializeSid(
+ inAuthority,
+ 1,
+ inSubAuthority,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ outSid );
+}
+
+BOOL getSID( const char * inOwner, PSID * outSID )
+{
+ BOOL theRC = FALSE;
+ DWORD theSIDSize = 128;
+ LPTSTR theDomain = NULL;
+ DWORD theDomainSize = 16;
+ SID_NAME_USE theUse;
+
+ *outSID = ( PSID )HeapAlloc( GetProcessHeap(), 0, theSIDSize );
+ theDomain =
+ ( LPTSTR )HeapAlloc(GetProcessHeap(), 0, theDomainSize *sizeof( TCHAR));
+ if ( *outSID != 0 )
+ {
+ while ( TRUE )
+ {
+ if ( ! LookupAccountName( NULL,
+ inOwner,
+ *outSID,
+ &theSIDSize,
+ theDomain,
+ &theDomainSize,
+ &theUse ) )
+ {
+ DWORD theError = GetLastError();
+ if ( theError == ERROR_INSUFFICIENT_BUFFER )
+ {
+ *outSID = ( PSID )HeapReAlloc(
+ GetProcessHeap(),
+ 0,
+ *outSID,
+ theSIDSize );
+
+ if ( *outSID == 0 )
+ {
+ break;
+ }
+
+ theDomain = ( LPTSTR )HeapReAlloc(
+ GetProcessHeap(),
+ 0,
+ theDomain,
+ theDomainSize *sizeof( TCHAR) );
+ if ( theDomain == 0 )
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ theRC = TRUE;
+ break;
+ }
+ }
+ if ( theDomain != 0 )
+ {
+ HeapFree( GetProcessHeap(), 0, theDomain );
+ }
+ if ( theRC == FALSE && *outSID != 0 )
+ {
+ HeapFree( GetProcessHeap(), 0, *outSID );
+ }
+ }
+ return theRC;
+}
+
+void modeToAccessMask( int inMode,
+ DWORD * outOwnerMask,
+ DWORD * outGroupMask,
+ DWORD * outOthersMask )
+{
+ *outOwnerMask = *outGroupMask = *outOthersMask = 0;
+
+ if ( ( inMode & S_IRUSR ) == S_IRUSR )
+ {
+ *outOwnerMask |= GENERIC_READ;
+ }
+ if ( ( inMode & S_IWUSR ) == S_IWUSR )
+ {
+ *outOwnerMask |= GENERIC_WRITE;
+ }
+ if ( ( inMode & S_IXUSR ) == S_IXUSR )
+ {
+ *outOwnerMask |= GENERIC_EXECUTE;
+ }
+
+ if ( ( inMode & S_IRGRP ) == S_IRGRP )
+ {
+ *outGroupMask |= GENERIC_READ;
+ }
+ if ( ( inMode & S_IWGRP ) == S_IWGRP )
+ {
+ *outGroupMask |= GENERIC_WRITE;
+ }
+ if ( ( inMode & S_IXGRP ) == S_IXGRP )
+ {
+ *outGroupMask |= GENERIC_EXECUTE;
+ }
+
+ if ( ( inMode & S_IROTH ) == S_IROTH )
+ {
+ *outOthersMask |= GENERIC_READ;
+ }
+ if ( ( inMode & S_IWOTH ) == S_IWOTH )
+ {
+ *outOthersMask |= GENERIC_WRITE;
+ }
+ if ( ( inMode & S_IXOTH ) == S_IXOTH )
+ {
+ *outOthersMask |= GENERIC_EXECUTE;
+ }
+}
+
+BOOL setOwner( PSID * inSID, const char * inFileName )
+{
+ BOOL theRC = FALSE;
+ SECURITY_DESCRIPTOR theDescriptor;
+
+ if ( InitializeSecurityDescriptor( &theDescriptor,
+ SECURITY_DESCRIPTOR_REVISION ) )
+ {
+ if ( SetSecurityDescriptorOwner( &theDescriptor,
+ inSID,
+ FALSE ) )
+ {
+ if ( SetFileSecurity(
+ inFileName,
+ ( SECURITY_INFORMATION )( OWNER_SECURITY_INFORMATION ),
+ &theDescriptor ) )
+ {
+ theRC = TRUE;
+ }
+ }
+ }
+ return theRC;
+}
+
+BOOL setPrivelege( LPCTSTR inPrivelege )
+{
+ BOOL theRC = FALSE;
+ HANDLE theToken;
+ LUID theLUID;
+ TOKEN_PRIVILEGES theTP;
+ TOKEN_PRIVILEGES thePreviousTP;
+ DWORD thePreviousTPSize = sizeof( TOKEN_PRIVILEGES );
+
+ if ( OpenProcessToken(
+ GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
+ &theToken ) )
+ {
+ if ( LookupPrivilegeValue( NULL, inPrivelege, &theLUID ) )
+ {
+ theTP.PrivilegeCount = 1;
+ theTP.Privileges[0].Luid = theLUID;
+ theTP.Privileges[0].Attributes = 0;
+
+ AdjustTokenPrivileges( theToken,
+ FALSE,
+ &theTP,
+ sizeof( TOKEN_PRIVILEGES ),
+ &thePreviousTP,
+ &thePreviousTPSize );
+
+ thePreviousTP.PrivilegeCount = 1;
+ thePreviousTP.Privileges[0].Luid = theLUID;
+ thePreviousTP.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED;
+
+ AdjustTokenPrivileges( theToken,
+ FALSE,
+ &thePreviousTP,
+ thePreviousTPSize,
+ NULL,
+ NULL );
+ CloseHandle( theToken );
+ theRC = TRUE;
+ }
+ }
+ return theRC;
+}
+
+BOOL setPriveleges( LPCTSTR * inPriveleges, int inCount )
+{
+ BOOL theRC;
+ int theIndex;
+ for ( theIndex = 0 ; theIndex < inCount; theIndex ++ )
+ {
+ if ( ( theRC = setPrivelege( inPriveleges[ theIndex ] ) ) == FALSE )
+ {
+ break;
+ }
+ }
+ return theRC;
+}
+
+BOOL setSecurity( const char * inFileName, PACL inDACL )
+{
+ BOOL theRC = 0;
+ SECURITY_DESCRIPTOR theDescriptor;
+
+ if ( InitializeSecurityDescriptor( &theDescriptor,
+ SECURITY_DESCRIPTOR_REVISION ) != 0 )
+ {
+ if ( SetSecurityDescriptorDacl( &theDescriptor,
+ TRUE,
+ inDACL,
+ FALSE ) != 0 )
+ {
+
+ theRC = SetNamedSecurityInfo( ( char *)inFileName,
+ SE_FILE_OBJECT,
+ ( SECURITY_INFORMATION )( DACL_SECURITY_INFORMATION ),
+ NULL,
+ NULL,
+ inDACL,
+ NULL ) == ERROR_SUCCESS ? 1 : 0;
+ }
+ }
+ return theRC;
+}
+#endif
diff --git a/libfileaccess/FileAccess.h b/libfileaccess/FileAccess.h
new file mode 100644
index 0000000..148cc00
--- /dev/null
+++ b/libfileaccess/FileAccess.h
@@ -0,0 +1,63 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_sun_apoc_daemon_misc_FileAccess */
+
+#ifndef _Included_com_sun_apoc_daemon_misc_FileAccess
+#define _Included_com_sun_apoc_daemon_misc_FileAccess
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_sun_apoc_daemon_misc_FileAccess
+ * Method: chmod
+ * Signature: (Ljava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_apoc_daemon_misc_FileAccess_chmod
+ (JNIEnv *, jclass, jstring, jint);
+
+/*
+ * Class: com_sun_apoc_daemon_misc_FileAccess
+ * Method: chown
+ * Signature: (Ljava/lang/String;Ljava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_apoc_daemon_misc_FileAccess_chown
+ (JNIEnv *, jclass, jstring, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libfileaccess/Makefile.am b/libfileaccess/Makefile.am
new file mode 100644
index 0000000..a3a01be
--- /dev/null
+++ b/libfileaccess/Makefile.am
@@ -0,0 +1,7 @@
+lib_LTLIBRARIES = libFileAccess.la
+
+libFileAccessdir = $(includedir)/apoc/papi
+
+libFileAccess_la_SOURCES = \
+ FileAccess.c \
+ FileAccess.h
diff --git a/m4/ac_check_class.m4 b/m4/ac_check_class.m4
new file mode 100644
index 0000000..b12e7f0
--- /dev/null
+++ b/m4/ac_check_class.m4
@@ -0,0 +1,107 @@
+dnl @synopsis AC_CHECK_CLASS
+dnl
+dnl AC_CHECK_CLASS tests the existence of a given Java class, either in
+dnl a jar or in a '.class' file.
+dnl
+dnl *Warning*: its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_check_class.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_CHECK_CLASS],[
+AC_REQUIRE([AC_PROG_JAVA])
+ac_var_name=`echo $1 | sed 's/\./_/g'`
+dnl Normaly I'd use a AC_CACHE_CHECK here but since the variable name is
+dnl dynamic I need an extra level of extraction
+AC_MSG_CHECKING([for $1 class])
+AC_CACHE_VAL(ac_cv_class_$ac_var_name, [
+if test x$ac_cv_prog_uudecode_base64 = xyes; then
+dnl /**
+dnl * Test.java: used to test dynamicaly if a class exists.
+dnl */
+dnl public class Test
+dnl {
+dnl
+dnl public static void
+dnl main( String[] argv )
+dnl {
+dnl Class lib;
+dnl if (argv.length < 1)
+dnl {
+dnl System.err.println ("Missing argument");
+dnl System.exit (77);
+dnl }
+dnl try
+dnl {
+dnl lib = Class.forName (argv[0]);
+dnl }
+dnl catch (ClassNotFoundException e)
+dnl {
+dnl System.exit (1);
+dnl }
+dnl lib = null;
+dnl System.exit (0);
+dnl }
+dnl
+dnl }
+cat << \EOF > Test.uue
+begin-base64 644 Test.class
+yv66vgADAC0AKQcAAgEABFRlc3QHAAQBABBqYXZhL2xhbmcvT2JqZWN0AQAE
+bWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51
+bWJlclRhYmxlDAAKAAsBAANlcnIBABVMamF2YS9pby9QcmludFN0cmVhbTsJ
+AA0ACQcADgEAEGphdmEvbGFuZy9TeXN0ZW0IABABABBNaXNzaW5nIGFyZ3Vt
+ZW50DAASABMBAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWCgAV
+ABEHABYBABNqYXZhL2lvL1ByaW50U3RyZWFtDAAYABkBAARleGl0AQAEKEkp
+VgoADQAXDAAcAB0BAAdmb3JOYW1lAQAlKExqYXZhL2xhbmcvU3RyaW5nOylM
+amF2YS9sYW5nL0NsYXNzOwoAHwAbBwAgAQAPamF2YS9sYW5nL0NsYXNzBwAi
+AQAgamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb24BAAY8aW5pdD4B
+AAMoKVYMACMAJAoAAwAlAQAKU291cmNlRmlsZQEACVRlc3QuamF2YQAhAAEA
+AwAAAAAAAgAJAAUABgABAAcAAABtAAMAAwAAACkqvgSiABCyAAwSD7YAFBBN
+uAAaKgMyuAAeTKcACE0EuAAaAUwDuAAasQABABMAGgAdACEAAQAIAAAAKgAK
+AAAACgAAAAsABgANAA4ADgATABAAEwASAB4AFgAiABgAJAAZACgAGgABACMA
+JAABAAcAAAAhAAEAAQAAAAUqtwAmsQAAAAEACAAAAAoAAgAAAAQABAAEAAEA
+JwAAAAIAKA==
+====
+EOF
+ if uudecode$EXEEXT Test.uue; then
+ :
+ else
+ echo "configure: __oline__: uudecode had trouble decoding base 64 file 'Test.uue'" >&AC_FD_CC
+ echo "configure: failed file was:" >&AC_FD_CC
+ cat Test.uue >&AC_FD_CC
+ ac_cv_prog_uudecode_base64=no
+ fi
+ rm -f Test.uue
+ if AC_TRY_COMMAND($JAVA $JAVAFLAGS Test $1) >/dev/null 2>&1; then
+ eval "ac_cv_class_$ac_var_name=yes"
+ else
+ eval "ac_cv_class_$ac_var_name=no"
+ fi
+ rm -f Test.class
+else
+ AC_TRY_COMPILE_JAVA([$1], , [eval "ac_cv_class_$ac_var_name=yes"],
+ [eval "ac_cv_class_$ac_var_name=no"])
+fi
+eval "ac_var_val=$`eval echo ac_cv_class_$ac_var_name`"
+eval "HAVE_$ac_var_name=$`echo ac_cv_class_$ac_var_val`"
+HAVE_LAST_CLASS=$ac_var_val
+if test x$ac_var_val = xyes; then
+ ifelse([$2], , :, [$2])
+else
+ ifelse([$3], , :, [$3])
+fi
+])
+dnl for some reason the above statment didn't fall though here?
+dnl do scripts have variable scoping?
+eval "ac_var_val=$`eval echo ac_cv_class_$ac_var_name`"
+AC_MSG_RESULT($ac_var_val)
+])
diff --git a/m4/ac_check_classpath.m4 b/m4/ac_check_classpath.m4
new file mode 100644
index 0000000..b18d479
--- /dev/null
+++ b/m4/ac_check_classpath.m4
@@ -0,0 +1,23 @@
+dnl @synopsis AC_CHECK_CLASSPATH
+dnl
+dnl AC_CHECK_CLASSPATH just displays the CLASSPATH, for the edification
+dnl of the user.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_check_classpath.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_CHECK_CLASSPATH],[
+if test "x$CLASSPATH" = x; then
+ echo "You have no CLASSPATH, I hope it is good"
+else
+ echo "You have CLASSPATH $CLASSPATH, hope it is correct"
+fi
+])
diff --git a/m4/ac_check_junit.m4 b/m4/ac_check_junit.m4
new file mode 100644
index 0000000..cc02e32
--- /dev/null
+++ b/m4/ac_check_junit.m4
@@ -0,0 +1,54 @@
+dnl @synopsis AC_CHECK_JUNIT
+dnl
+dnl AC_CHECK_JUNIT tests the availability of the Junit testing
+dnl framework, and set some variables for conditional compilation
+dnl of the test suite by automake.
+dnl
+dnl If available, JUNIT is set to a command launching the text
+dnl based user interface of Junit, @JAVA_JUNIT@ is set to $JAVA_JUNIT
+dnl and @TESTS_JUNIT@ is set to $TESTS_JUNIT, otherwise they are set
+dnl to empty values.
+dnl
+dnl You can use these variables in your Makefile.am file like this :
+dnl
+dnl # Some of the following classes are built only if junit is available
+dnl JAVA_JUNIT = Class1Test.java Class2Test.java AllJunitTests.java
+dnl
+dnl noinst_JAVA = Example1.java Example2.java @JAVA_JUNIT@
+dnl
+dnl EXTRA_JAVA = $(JAVA_JUNIT)
+dnl
+dnl TESTS_JUNIT = AllJunitTests
+dnl
+dnl TESTS = StandaloneTest1 StandaloneTest2 @TESTS_JUNIT@
+dnl
+dnl EXTRA_TESTS = $(TESTS_JUNIT)
+dnl
+dnl AllJunitTests :
+dnl echo "#! /bin/sh" > $@
+dnl echo "exec @JUNIT@ my.package.name.AllJunitTests" >> $@
+dnl chmod +x $@
+dnl
+dnl @author Luc Maisonobe
+dnl @version $Id: ac_check_junit.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_CHECK_JUNIT],[
+AC_CACHE_VAL(ac_cv_prog_JUNIT,[
+AC_CHECK_CLASS(junit.textui.TestRunner)
+if test x"`eval 'echo $ac_cv_class_junit_textui_TestRunner'`" != xno ; then
+ ac_cv_prog_JUNIT='$(CLASSPATH_ENV) $(JAVA) $(JAVAFLAGS) junit.textui.TestRunner'
+fi])
+AC_MSG_CHECKING([for junit])
+if test x"`eval 'echo $ac_cv_prog_JUNIT'`" != x ; then
+ JUNIT="$ac_cv_prog_JUNIT"
+ JAVA_JUNIT='$(JAVA_JUNIT)'
+ TESTS_JUNIT='$(TESTS_JUNIT)'
+else
+ JUNIT=
+ JAVA_JUNIT=
+ TESTS_JUNIT=
+fi
+AC_MSG_RESULT($JAVA_JUNIT)
+AC_SUBST(JUNIT)
+AC_SUBST(JAVA_JUNIT)
+AC_SUBST(TESTS_JUNIT)])
diff --git a/m4/ac_check_rqrd_class.m4 b/m4/ac_check_rqrd_class.m4
new file mode 100644
index 0000000..c7c26b8
--- /dev/null
+++ b/m4/ac_check_rqrd_class.m4
@@ -0,0 +1,26 @@
+dnl @synopsis AC_CHECK_RQRD_CLASS
+dnl
+dnl AC_CHECK_RQRD_CLASS tests the existence of a given Java class, either in
+dnl a jar or in a '.class' file and fails if it doesn't exist.
+dnl Its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_check_rqrd_class.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+
+AC_DEFUN([AC_CHECK_RQRD_CLASS],[
+CLASS=`echo $1|sed 's/\./_/g'`
+AC_CHECK_CLASS($1)
+if test "$HAVE_LAST_CLASS" = "no"; then
+ AC_MSG_ERROR([Required class $1 missing, exiting.])
+fi
+])
diff --git a/m4/ac_expand.m4 b/m4/ac_expand.m4
new file mode 100644
index 0000000..ae8188a
--- /dev/null
+++ b/m4/ac_expand.m4
@@ -0,0 +1,8 @@
+AC_DEFUN([AC_EXPAND], [
+ test "x$prefix" = xNONE && prefix="$ac_default_prefix"
+ test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+ ac_expand=[$]$1
+ test "x$ac_expand" = xNONE && ac_expand="[$]$2"
+ ac_expand=`eval echo [$]ac_expand`
+ $3=`eval echo [$]ac_expand`
+])
diff --git a/m4/ac_java_options.m4 b/m4/ac_java_options.m4
new file mode 100644
index 0000000..e71adfe
--- /dev/null
+++ b/m4/ac_java_options.m4
@@ -0,0 +1,32 @@
+dnl @synopsis AC_JAVA_OPTIONS
+dnl
+dnl AC_JAVA_OPTIONS adds configure command line options used for Java m4
+dnl macros. This Macro is optional.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Devin Weaver <ktohg@tritarget.com>
+dnl @version $Id: ac_java_options.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_JAVA_OPTIONS],[
+AC_ARG_WITH(java-prefix,
+ [ --with-java-prefix=PFX prefix where Java runtime is installed (optional)])
+AC_ARG_WITH(javac-flags,
+ [ --with-javac-flags=FLAGS flags to pass to the Java compiler (optional)])
+AC_ARG_WITH(java-flags,
+ [ --with-java-flags=FLAGS flags to pass to the Java VM (optional)])
+JAVAPREFIX=$with_java_prefix
+JAVACFLAGS=$with_javac_flags
+JAVAFLAGS=$with_java_flags
+AC_SUBST(JAVAPREFIX)dnl
+AC_SUBST(JAVACFLAGS)dnl
+AC_SUBST(JAVAFLAGS)dnl
+AC_SUBST(JAVA)dnl
+AC_SUBST(JAVAC)dnl
+])
diff --git a/m4/ac_jni_include_dirs.m4 b/m4/ac_jni_include_dirs.m4
new file mode 100644
index 0000000..35cdda3
--- /dev/null
+++ b/m4/ac_jni_include_dirs.m4
@@ -0,0 +1,114 @@
+dnl @synopsis AC_JNI_INCLUDE_DIR
+dnl
+dnl AC_JNI_INCLUDE_DIR finds include directories needed
+dnl for compiling programs using the JNI interface.
+dnl
+dnl JNI include directories are usually in the java distribution
+dnl This is deduced from the value of JAVAC. When this macro
+dnl completes, a list of directories is left in the variable
+dnl JNI_INCLUDE_DIRS.
+dnl
+dnl Example usage follows:
+dnl
+dnl AC_JNI_INCLUDE_DIR
+dnl
+dnl for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS
+dnl do
+dnl CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR"
+dnl done
+dnl
+dnl If you want to force a specific compiler:
+dnl
+dnl - at the configure.in level, set JAVAC=yourcompiler before calling
+dnl AC_JNI_INCLUDE_DIR
+dnl
+dnl - at the configure level, setenv JAVAC
+dnl
+dnl Note: This macro can work with the autoconf M4 macros for Java programs.
+dnl This particular macro is not part of the original set of macros.
+dnl
+dnl @author Don Anderson <dda@sleepycat.com>
+dnl @version $Id: ac_jni_include_dirs.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN(AC_JNI_INCLUDE_DIR,[
+
+JNI_INCLUDE_DIRS=""
+
+test "x$JAVAC" = x && AC_MSG_ERROR(['$JAVAC' undefined])
+AC_PATH_PROG(_ACJNI_JAVAC, $JAVAC, $JAVAC)
+test ! -x "$_ACJNI_JAVAC" && AC_MSG_ERROR([$JAVAC could not be found in path])
+AC_MSG_CHECKING(absolute path of $JAVAC)
+case "$_ACJNI_JAVAC" in
+/*) AC_MSG_RESULT($_ACJNI_JAVAC);;
+*) AC_MSG_ERROR([$_ACJNI_JAVAC is not an absolute path name]);;
+esac
+
+_ACJNI_FOLLOW_SYMLINKS("$_ACJNI_JAVAC")
+_JTOPDIR=`echo "$_ACJNI_FOLLOWED" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'`
+case "$host_os" in
+ darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'`
+ _JINC="$_JTOPDIR/Headers";;
+ *) _JINC="$_JTOPDIR/include";;
+esac
+
+# If we find jni.h in /usr/include, then it's not a java-only tree, so
+# don't add /usr/include or subdirectories to the list of includes.
+# An extra -I/usr/include can foul things up with newer gcc's.
+#
+# If we don't find jni.h, just keep going. Hopefully javac knows where
+# to find its include files, even if we can't.
+if test -r "$_JINC/jni.h"; then
+ if test "$_JINC" != "/usr/include"; then
+ JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JINC"
+ fi
+else
+ _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'`
+ if test -r "$_JTOPDIR/include/jni.h"; then
+ if test "$_JTOPDIR" != "/usr"; then
+ JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include"
+ fi
+ fi
+fi
+
+# get the likely subdirectories for system specific java includes
+if test "$_JTOPDIR" != "/usr"; then
+ case "$host_os" in
+ aix*) _JNI_INC_SUBDIRS="aix";;
+ bsdi*) _JNI_INC_SUBDIRS="bsdos";;
+ freebsd*) _JNI_INC_SUBDIRS="freebsd";;
+ hp*) _JNI_INC_SUBDIRS="hp-ux";;
+ linux*) _JNI_INC_SUBDIRS="linux genunix";;
+ osf*) _JNI_INC_SUBDIRS="alpha";;
+ solaris*) _JNI_INC_SUBDIRS="solaris";;
+ *) _JNI_INC_SUBDIRS="genunix";;
+ esac
+fi
+
+# add any subdirectories that are present
+for _JINCSUBDIR in $_JNI_INC_SUBDIRS
+do
+ if test -d "$_JTOPDIR/include/$_JINCSUBDIR"; then
+ JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$_JINCSUBDIR"
+ fi
+done
+])
+
+# _ACJNI_FOLLOW_SYMLINKS <path>
+# Follows symbolic links on <path>,
+# finally setting variable _ACJNI_FOLLOWED
+# --------------------
+AC_DEFUN(_ACJNI_FOLLOW_SYMLINKS,[
+# find the include directory relative to the javac executable
+_cur="$1"
+while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do
+ AC_MSG_CHECKING(symlink for $_cur)
+ _slink=`ls -ld "$_cur" | sed 's/.* -> //'`
+ case "$_slink" in
+ /*) _cur="$_slink";;
+ # 'X' avoids triggering unwanted echo options.
+ *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$_slink";;
+ esac
+ AC_MSG_RESULT($_cur)
+done
+_ACJNI_FOLLOWED="$_cur"
+])# _ACJNI
diff --git a/m4/ac_prog_jar.m4 b/m4/ac_prog_jar.m4
new file mode 100644
index 0000000..c60a79a
--- /dev/null
+++ b/m4/ac_prog_jar.m4
@@ -0,0 +1,36 @@
+dnl @synopsis AC_PROG_JAR
+dnl
+dnl AC_PROG_JAR tests for an existing jar program. It uses the environment
+dnl variable JAR then tests in sequence various common jar programs.
+dnl
+dnl If you want to force a specific compiler:
+dnl
+dnl - at the configure.in level, set JAR=yourcompiler before calling
+dnl AC_PROG_JAR
+dnl
+dnl - at the configure level, setenv JAR
+dnl
+dnl You can use the JAR variable in your Makefile.in, with @JAR@.
+dnl
+dnl Note: This macro depends on the autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download that whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl
+dnl The general documentation of those macros, as well as the sample
+dnl configure.in, is included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Egon Willighagen <egonw@sci.kun.nl>
+dnl @version $Id: ac_prog_jar.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_PROG_JAR],[
+AC_REQUIRE([AC_EXEEXT])dnl
+if test "x$JAVAPREFIX" = x; then
+ test "x$JAR" = x && AC_CHECK_PROGS(JAR, jar$EXEEXT)
+else
+ test "x$JAR" = x && AC_CHECK_PROGS(JAR, jar, $JAVAPREFIX)
+fi
+test "x$JAR" = x && AC_MSG_ERROR([no acceptable jar program found in \$PATH])
+AC_PROVIDE([$0])dnl
+])
diff --git a/m4/ac_prog_java.m4 b/m4/ac_prog_java.m4
new file mode 100644
index 0000000..05c65e7
--- /dev/null
+++ b/m4/ac_prog_java.m4
@@ -0,0 +1,79 @@
+dnl @synopsis AC_PROG_JAVA
+dnl
+dnl Here is a summary of the main macros:
+dnl
+dnl AC_PROG_JAVAC: finds a Java compiler.
+dnl
+dnl AC_PROG_JAVA: finds a Java virtual machine.
+dnl
+dnl AC_CHECK_CLASS: finds if we have the given class (beware of CLASSPATH!).
+dnl
+dnl AC_CHECK_RQRD_CLASS: finds if we have the given class and stops otherwise.
+dnl
+dnl AC_TRY_COMPILE_JAVA: attempt to compile user given source.
+dnl
+dnl AC_TRY_RUN_JAVA: attempt to compile and run user given source.
+dnl
+dnl AC_JAVA_OPTIONS: adds Java configure options.
+dnl
+dnl AC_PROG_JAVA tests an existing Java virtual machine. It uses the
+dnl environment variable JAVA then tests in sequence various common Java
+dnl virtual machines. For political reasons, it starts with the free ones.
+dnl You *must* call [AC_PROG_JAVAC] before.
+dnl
+dnl If you want to force a specific VM:
+dnl
+dnl - at the configure.in level, set JAVA=yourvm before calling AC_PROG_JAVA
+dnl (but after AC_INIT)
+dnl
+dnl - at the configure level, setenv JAVA
+dnl
+dnl You can use the JAVA variable in your Makefile.in, with @JAVA@.
+dnl
+dnl *Warning*: its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl TODO: allow to exclude virtual machines (rationale: most Java programs
+dnl cannot run with some VM like kaffe).
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl
+dnl A Web page, with a link to the latest CVS snapshot is at
+dnl <http://www.internatif.org/bortzmeyer/autoconf-Java/>.
+dnl
+dnl This is a sample configure.in
+dnl Process this file with autoconf to produce a configure script.
+dnl
+dnl AC_INIT(UnTag.java)
+dnl
+dnl dnl Checks for programs.
+dnl AC_CHECK_CLASSPATH
+dnl AC_PROG_JAVAC
+dnl AC_PROG_JAVA
+dnl
+dnl dnl Checks for classes
+dnl AC_CHECK_RQRD_CLASS(org.xml.sax.Parser)
+dnl AC_CHECK_RQRD_CLASS(com.jclark.xml.sax.Driver)
+dnl
+dnl AC_OUTPUT(Makefile)
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_prog_java.ac,v 12.1 2006/08/24 14:45:36 bostic Exp $
+dnl
+dnl Note: Modified to prefer java over kaffe. [#8059]
+dnl
+AC_DEFUN([AC_PROG_JAVA],[
+AC_REQUIRE([AC_EXEEXT])dnl
+if test x$JAVAPREFIX = x; then
+ test x$JAVA = x && AC_CHECK_PROGS(JAVA, java$EXEEXT kaffe$EXEEXT)
+else
+ test x$JAVA = x && AC_CHECK_PROGS(JAVA, java$EXEEXT kaffe$EXEEXT, $JAVAPREFIX)
+fi
+test x$JAVA = x && AC_MSG_ERROR([no acceptable Java virtual machine found in \$PATH])
+AC_PROG_JAVA_WORKS
+AC_PROVIDE([$0])dnl
+])
diff --git a/m4/ac_prog_java_works.m4 b/m4/ac_prog_java_works.m4
new file mode 100644
index 0000000..f0ff8c5
--- /dev/null
+++ b/m4/ac_prog_java_works.m4
@@ -0,0 +1,97 @@
+dnl @synopsis AC_PROG_JAVA_WORKS
+dnl
+dnl Internal use ONLY.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_prog_java_works.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_PROG_JAVA_WORKS], [
+AC_CHECK_PROG(uudecode, uudecode$EXEEXT, yes)
+if test x$uudecode = xyes; then
+AC_CACHE_CHECK([if uudecode can decode base 64 file], ac_cv_prog_uudecode_base64, [
+dnl /**
+dnl * Test.java: used to test if java compiler works.
+dnl */
+dnl public class Test
+dnl {
+dnl
+dnl public static void
+dnl main( String[] argv )
+dnl {
+dnl System.exit (0);
+dnl }
+dnl
+dnl }
+cat << \EOF > Test.uue
+begin-base64 644 Test.class
+yv66vgADAC0AFQcAAgEABFRlc3QHAAQBABBqYXZhL2xhbmcvT2JqZWN0AQAE
+bWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51
+bWJlclRhYmxlDAAKAAsBAARleGl0AQAEKEkpVgoADQAJBwAOAQAQamF2YS9s
+YW5nL1N5c3RlbQEABjxpbml0PgEAAygpVgwADwAQCgADABEBAApTb3VyY2VG
+aWxlAQAJVGVzdC5qYXZhACEAAQADAAAAAAACAAkABQAGAAEABwAAACEAAQAB
+AAAABQO4AAyxAAAAAQAIAAAACgACAAAACgAEAAsAAQAPABAAAQAHAAAAIQAB
+AAEAAAAFKrcAErEAAAABAAgAAAAKAAIAAAAEAAQABAABABMAAAACABQ=
+====
+EOF
+if uudecode$EXEEXT Test.uue; then
+ ac_cv_prog_uudecode_base64=yes
+else
+ echo "configure: __oline__: uudecode had trouble decoding base 64 file 'Test.uue'" >&AC_FD_CC
+ echo "configure: failed file was:" >&AC_FD_CC
+ cat Test.uue >&AC_FD_CC
+ ac_cv_prog_uudecode_base64=no
+fi
+rm -f Test.uue])
+fi
+if test x$ac_cv_prog_uudecode_base64 != xyes; then
+ rm -f Test.class
+ AC_MSG_WARN([I have to compile Test.class from scratch])
+ if test x$ac_cv_prog_javac_works = xno; then
+ AC_MSG_ERROR([Cannot compile java source. $JAVAC does not work properly])
+ fi
+ if test x$ac_cv_prog_javac_works = x; then
+ AC_PROG_JAVAC
+ fi
+fi
+AC_CACHE_CHECK(if $JAVA works, ac_cv_prog_java_works, [
+JAVA_TEST=Test.java
+CLASS_TEST=Test.class
+TEST=Test
+changequote(, )dnl
+cat << \EOF > $JAVA_TEST
+/* [#]line __oline__ "configure" */
+public class Test {
+public static void main (String args[]) {
+ System.exit (0);
+} }
+EOF
+changequote([, ])dnl
+if test x$ac_cv_prog_uudecode_base64 != xyes; then
+ if AC_TRY_COMMAND($JAVAC $JAVACFLAGS $JAVA_TEST) && test -s $CLASS_TEST; then
+ :
+ else
+ echo "configure: failed program was:" >&AC_FD_CC
+ cat $JAVA_TEST >&AC_FD_CC
+ AC_MSG_ERROR(The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?))
+ fi
+fi
+if AC_TRY_COMMAND($JAVA $JAVAFLAGS $TEST) >/dev/null 2>&1; then
+ ac_cv_prog_java_works=yes
+else
+ echo "configure: failed program was:" >&AC_FD_CC
+ cat $JAVA_TEST >&AC_FD_CC
+ AC_MSG_ERROR(The Java VM $JAVA failed (see config.log, check the CLASSPATH?))
+fi
+rm -fr $JAVA_TEST $CLASS_TEST Test.uue
+])
+AC_PROVIDE([$0])dnl
+]
+)
diff --git a/m4/ac_prog_javac.m4 b/m4/ac_prog_javac.m4
new file mode 100644
index 0000000..b3607dc
--- /dev/null
+++ b/m4/ac_prog_javac.m4
@@ -0,0 +1,43 @@
+dnl @synopsis AC_PROG_JAVAC
+dnl
+dnl AC_PROG_JAVAC tests an existing Java compiler. It uses the environment
+dnl variable JAVAC then tests in sequence various common Java compilers. For
+dnl political reasons, it starts with the free ones.
+dnl
+dnl If you want to force a specific compiler:
+dnl
+dnl - at the configure.in level, set JAVAC=yourcompiler before calling
+dnl AC_PROG_JAVAC
+dnl
+dnl - at the configure level, setenv JAVAC
+dnl
+dnl You can use the JAVAC variable in your Makefile.in, with @JAVAC@.
+dnl
+dnl *Warning*: its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl TODO: allow to exclude compilers (rationale: most Java programs cannot compile
+dnl with some compilers like guavac).
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_prog_javac.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_PROG_JAVAC],[
+AC_REQUIRE([AC_EXEEXT])dnl
+if test "x$JAVAPREFIX" = x; then
+ test "x$JAVAC" = x && AC_CHECK_PROGS(JAVAC, javac$EXEEXT "gcj$EXEEXT -C" guavac$EXEEXT jikes$EXEEXT)
+else
+ test "x$JAVAC" = x && AC_CHECK_PROGS(JAVAC, javac$EXEEXT "gcj$EXEEXT -C" guavac$EXEEXT jikes$EXEEXT, $JAVAPREFIX)
+fi
+test "x$JAVAC" = x && AC_MSG_ERROR([no acceptable Java compiler found in \$PATH])
+AC_PROG_JAVAC_WORKS
+AC_PROVIDE([$0])dnl
+])
diff --git a/m4/ac_prog_javac_works.m4 b/m4/ac_prog_javac_works.m4
new file mode 100644
index 0000000..0cfd1f2
--- /dev/null
+++ b/m4/ac_prog_javac_works.m4
@@ -0,0 +1,35 @@
+dnl @synopsis AC_PROG_JAVAC_WORKS
+dnl
+dnl Internal use ONLY.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+dnl @version $Id: ac_prog_javac_works.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_PROG_JAVAC_WORKS],[
+AC_CACHE_CHECK([if $JAVAC works], ac_cv_prog_javac_works, [
+JAVA_TEST=Test.java
+CLASS_TEST=Test.class
+cat << \EOF > $JAVA_TEST
+/* [#]line __oline__ "configure" */
+public class Test {
+}
+EOF
+if AC_TRY_COMMAND($JAVAC $JAVACFLAGS $JAVA_TEST) >/dev/null 2>&1; then
+ ac_cv_prog_javac_works=yes
+else
+ AC_MSG_ERROR([The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)])
+ echo "configure: failed program was:" >&AC_FD_CC
+ cat $JAVA_TEST >&AC_FD_CC
+fi
+rm -f $JAVA_TEST $CLASS_TEST
+])
+AC_PROVIDE([$0])dnl
+])
diff --git a/m4/ac_prog_javadoc.m4 b/m4/ac_prog_javadoc.m4
new file mode 100644
index 0000000..36b95bd
--- /dev/null
+++ b/m4/ac_prog_javadoc.m4
@@ -0,0 +1,37 @@
+dnl @synopsis AC_PROG_JAVADOC
+dnl
+dnl AC_PROG_JAVADOC tests for an existing javadoc generator. It uses the environment
+dnl variable JAVADOC then tests in sequence various common javadoc generator.
+dnl
+dnl If you want to force a specific compiler:
+dnl
+dnl - at the configure.in level, set JAVADOC=yourgenerator before calling
+dnl AC_PROG_JAVADOC
+dnl
+dnl - at the configure level, setenv JAVADOC
+dnl
+dnl You can use the JAVADOC variable in your Makefile.in, with @JAVADOC@.
+dnl
+dnl Note: This macro depends on the autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download that whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl
+dnl The general documentation of those macros, as well as the sample
+dnl configure.in, is included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Egon Willighagen <egonw@sci.kun.nl>
+dnl @version $Id: ac_prog_javadoc.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_PROG_JAVADOC],[
+AC_REQUIRE([AC_EXEEXT])dnl
+if test "x$JAVAPREFIX" = x; then
+ test "x$JAVADOC" = x && AC_CHECK_PROGS(JAVADOC, javadoc$EXEEXT)
+else
+ test "x$JAVADOC" = x && AC_CHECK_PROGS(JAVADOC, javadoc, $JAVAPREFIX)
+fi
+test "x$JAVADOC" = x && AC_MSG_ERROR([no acceptable javadoc generator found in \$PATH])
+AC_PROVIDE([$0])dnl
+])
+
diff --git a/m4/ac_prog_javah.m4 b/m4/ac_prog_javah.m4
new file mode 100644
index 0000000..7563036
--- /dev/null
+++ b/m4/ac_prog_javah.m4
@@ -0,0 +1,26 @@
+dnl @synopsis AC_PROG_JAVAH
+dnl
+dnl AC_PROG_JAVAH tests the availability of the javah header generator
+dnl and looks for the jni.h header file. If available, JAVAH is set to
+dnl the full path of javah and CPPFLAGS is updated accordingly.
+dnl
+dnl @author Luc Maisonobe
+dnl @version $Id: ac_prog_javah.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_PROG_JAVAH],[
+AC_REQUIRE([AC_CANONICAL_SYSTEM])dnl
+AC_REQUIRE([AC_PROG_CPP])dnl
+AC_PATH_PROG(JAVAH,javah)
+if test x"`eval 'echo $ac_cv_path_JAVAH'`" != x ; then
+ AC_TRY_CPP([#include <jni.h>],,[
+ ac_save_CPPFLAGS="$CPPFLAGS"
+changequote(, )dnl
+ ac_dir=`echo $ac_cv_path_JAVAH | sed 's,\(.*\)/[^/]*/[^/]*$,\1/include,'`
+ ac_machdep=`echo $build_os | sed 's,[-0-9].*,,'`
+changequote([, ])dnl
+ CPPFLAGS="$ac_save_CPPFLAGS -I$ac_dir -I$ac_dir/$ac_machdep"
+ AC_TRY_CPP([#include <jni.h>],
+ ac_save_CPPFLAGS="$CPPFLAGS",
+ AC_MSG_WARN([unable to include <jni.h>]))
+ CPPFLAGS="$ac_save_CPPFLAGS"])
+fi])
diff --git a/m4/ac_try_compile_java.m4 b/m4/ac_try_compile_java.m4
new file mode 100644
index 0000000..d22aeab
--- /dev/null
+++ b/m4/ac_try_compile_java.m4
@@ -0,0 +1,39 @@
+dnl @synopsis AC_TRY_COMPILE_JAVA
+dnl
+dnl AC_TRY_COMPILE_JAVA attempt to compile user given source.
+dnl
+dnl *Warning*: its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Devin Weaver <ktohg@tritarget.com>
+dnl @version $Id: ac_try_compile_java.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_TRY_COMPILE_JAVA],[
+AC_REQUIRE([AC_PROG_JAVAC])dnl
+cat << \EOF > Test.java
+/* [#]line __oline__ "configure" */
+ifelse([$1], , , [import $1;])
+public class Test {
+[$2]
+}
+EOF
+if AC_TRY_COMMAND($JAVAC $JAVACFLAGS Test.java) && test -s Test.class
+then
+dnl Don't remove the temporary files here, so they can be examined.
+ ifelse([$3], , :, [$3])
+else
+ echo "configure: failed program was:" >&AC_FD_CC
+ cat Test.java >&AC_FD_CC
+ifelse([$4], , , [ rm -fr Test*
+ $4
+])dnl
+fi
+rm -fr Test*])
diff --git a/m4/ac_try_run_javac.m4 b/m4/ac_try_run_javac.m4
new file mode 100644
index 0000000..0124935
--- /dev/null
+++ b/m4/ac_try_run_javac.m4
@@ -0,0 +1,40 @@
+dnl @synopsis AC_TRY_RUN_JAVA
+dnl
+dnl AC_TRY_RUN_JAVA attempt to compile and run user given source.
+dnl
+dnl *Warning*: its success or failure can depend on a proper setting of the
+dnl CLASSPATH env. variable.
+dnl
+dnl Note: This is part of the set of autoconf M4 macros for Java programs.
+dnl It is VERY IMPORTANT that you download the whole set, some
+dnl macros depend on other. Unfortunately, the autoconf archive does not
+dnl support the concept of set of macros, so I had to break it for
+dnl submission.
+dnl The general documentation, as well as the sample configure.in, is
+dnl included in the AC_PROG_JAVA macro.
+dnl
+dnl @author Devin Weaver <ktohg@tritarget.com>
+dnl @version $Id: ac_try_run_javac.ac,v 12.0 2004/11/17 03:43:38 bostic Exp $
+dnl
+AC_DEFUN([AC_TRY_RUN_JAVA],[
+AC_REQUIRE([AC_PROG_JAVAC])dnl
+AC_REQUIRE([AC_PROG_JAVA])dnl
+cat << \EOF > Test.java
+/* [#]line __oline__ "configure" */
+ifelse([$1], , , [include $1;])
+public class Test {
+[$2]
+}
+EOF
+if AC_TRY_COMMAND($JAVAC $JAVACFLAGS Test.java) && test -s Test.class && ($JAVA $JAVAFLAGS Test; exit) 2>/dev/null
+then
+dnl Don't remove the temporary files here, so they can be examined.
+ ifelse([$3], , :, [$3])
+else
+ echo "configure: failed program was:" >&AC_FD_CC
+ cat Test.java >&AC_FD_CC
+ifelse([$4], , , [ rm -fr Test*
+ $4
+])dnl
+fi
+rm -fr Test*])
diff --git a/smf/apocd.xml.in b/smf/apocd.xml.in
new file mode 100755
index 0000000..452634e
--- /dev/null
+++ b/smf/apocd.xml.in
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+ Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ ident "@(#)x11-server.xml.cpp 1.2 04/11/17 SMI"
+-->
+
+<service_bundle type='manifest' name='SUNWapoc:apocd'>
+
+<service
+ name='network/apocd/udp'
+ type='service'
+ version='1'>
+
+ <dependency
+ type='service'
+ name='fs-local'
+ grouping='require_all'
+ restart_on='none'>
+ <service_fmri value='svc:/system/filesystem/local'/>
+ </dependency>
+
+ <dependency
+ type='service'
+ name='name-services'
+ grouping='require_all'
+ restart_on='refresh'>
+ <service_fmri value='svc:/milestone/name-services'/>
+ </dependency>
+
+ <exec_method
+ type='method'
+ name='start'
+ exec='@APOCD_DIR@/apocd svcStart'
+ timeout_seconds='30'>
+ <method_context>
+ <method_credential user='root' group='root'/>
+ </method_context>
+ </exec_method>
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec='@APOCD_DIR@/apocd svcStop'
+ timeout_seconds='20'>
+ <method_context>
+ <method_credential user='root' group='root'/>
+ </method_context>
+ </exec_method>
+
+ <exec_method
+ type='method'
+ name='refresh'
+ exec='@APOCD_DIR@/apocd reload'
+ timeout_seconds='5'>
+ <method_context>
+ <method_credential user='root' group='root'/>
+ </method_context>
+ </exec_method>
+
+ <instance name='default' enabled='false'/>
+
+ <stability value='External'/>
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>Configuration Agent</loctext>
+ </common_name>
+ </template>
+
+</service>
+
+</service_bundle>
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..05023f1
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = com/
diff --git a/src/com/Makefile.am b/src/com/Makefile.am
new file mode 100644
index 0000000..1d06788
--- /dev/null
+++ b/src/com/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = sun
diff --git a/src/com/sun/Makefile.am b/src/com/sun/Makefile.am
new file mode 100644
index 0000000..b5d5f2c
--- /dev/null
+++ b/src/com/sun/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = apoc
diff --git a/src/com/sun/apoc/Makefile.am b/src/com/sun/apoc/Makefile.am
new file mode 100644
index 0000000..75ad827
--- /dev/null
+++ b/src/com/sun/apoc/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = daemon
diff --git a/src/com/sun/apoc/daemon/Makefile.am b/src/com/sun/apoc/daemon/Makefile.am
new file mode 100644
index 0000000..f76f046
--- /dev/null
+++ b/src/com/sun/apoc/daemon/Makefile.am
@@ -0,0 +1,5 @@
+all:
+ $(ANT)
+
+clean-local:
+ $(ANT) -q clean
diff --git a/src/com/sun/apoc/daemon/admin/AdminManager.java b/src/com/sun/apoc/daemon/admin/AdminManager.java
new file mode 100644
index 0000000..3dfcf68
--- /dev/null
+++ b/src/com/sun/apoc/daemon/admin/AdminManager.java
@@ -0,0 +1,286 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.admin;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.io.*;
+import java.net.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.util.*;
+
+public class AdminManager extends Thread
+{
+ private static final byte[] sSuccess = { 0 };
+ private static final byte[] sFailure = { 1 };
+ private static final byte sOpChangeDetect = ( byte )1;
+ private static final byte sOpReload = ( byte )6;
+ private static final byte sOpStatus = ( byte )9;
+ private static final byte sOpStop = ( byte )10;
+
+ private static final byte[] sAcceptByte = { 1 };
+ private static final ByteBuffer sAccept =
+ ( ByteBuffer )ByteBuffer.wrap( sAcceptByte );
+
+ private Selector mSelector;
+ private ServerSocketChannel mChannel;
+ private AdminOpHandler mAdminOpHandler;
+ private final Object mTerminateLock = new Object();
+ private boolean mTerminate = false;
+
+ public AdminManager( final AdminOpHandler inAdminOpHandler )
+ throws APOCException
+ {
+ setName( "AdminManager" );
+ mAdminOpHandler = inAdminOpHandler;
+ initChannel();
+ }
+
+ public void run()
+ {
+ APOCLogger.fine( "Admr001" );
+ while ( ! shouldTerminate() )
+ {
+ try
+ {
+ final ClientChannel theChannel = acceptClientChannel();
+ if ( theChannel != null )
+ {
+ if ( authenticate( theChannel ) )
+ {
+ try
+ {
+ handleRequest( theChannel );
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "AdminManager",
+ "run",
+ theException );
+ }
+ }
+ theChannel.close();
+ }
+ }
+ catch ( IOException theException )
+ {
+ APOCLogger.throwing( "AdminManager", "run", theException );
+ break;
+ }
+ }
+ closeServerChannel();
+ APOCLogger.fine( "Admr002" );
+ }
+
+ public void terminate()
+ {
+ synchronized( mTerminateLock )
+ {
+ mTerminate = true;
+ }
+ }
+
+ private ClientChannel acceptClientChannel()
+ throws IOException
+ {
+ ClientChannel theChannel = null;
+ if ( mSelector.select() > 0 )
+ {
+ final Iterator theIterator = mSelector.selectedKeys().iterator();
+ while ( theIterator.hasNext() )
+ {
+ final SelectionKey theKey = ( SelectionKey )theIterator.next();
+ theIterator.remove();
+ if ( theKey.isAcceptable() )
+ {
+ SocketChannel theSocketChannel = null;
+ try
+ {
+ theSocketChannel =
+ (( ServerSocketChannel )theKey.channel() ).accept();
+ if ( theSocketChannel.
+ socket().
+ getInetAddress().
+ isLoopbackAddress() )
+ {
+ theChannel =
+ new ClientChannel( theSocketChannel, null);
+ theChannel.write( sAccept );
+ sAccept.flip();
+ break;
+ }
+ }
+ catch( IOException theException )
+ {
+ if ( theSocketChannel != null )
+ {
+ try
+ {
+ theSocketChannel.close();
+ }
+ catch( IOException ignore ){}
+ }
+ APOCLogger.throwing( "AdminManager",
+ "acceptClientChannel",
+ theException );
+ }
+ }
+ }
+ }
+ return theChannel;
+ }
+
+ private boolean authenticate( final ClientChannel inChannel )
+ {
+ boolean isAuthenticated;
+ APOCAuthenticator theAuthenticator = null;
+ try
+ {
+ theAuthenticator = new APOCAuthenticator( null );
+ byte[] theChallenge = theAuthenticator.getChallenge();
+ inChannel.write(
+ ( ByteBuffer )ByteBuffer.allocate( theChallenge.length + 1 )
+ .put( theChallenge )
+ .put( ( byte )0 )
+ .flip() );
+ ByteBuffer theAuthBuffer =
+ ByteBuffer.wrap(
+ new byte[ APOCAuthenticator.getAuthBufferSize() ] );
+ while ( inChannel.read( theAuthBuffer ) == 0 ){}
+ theAuthenticator.processResponse( theAuthBuffer.array() );
+ inChannel.write(
+ ( ByteBuffer )ByteBuffer.allocate( 1 ).put( sSuccess ).flip() );
+ isAuthenticated = true;
+ }
+ catch( Exception theException )
+ {
+ inChannel.write(
+ ( ByteBuffer )ByteBuffer.allocate( 1 ).put( sFailure ).flip() );
+ isAuthenticated = false;
+ }
+ finally
+ {
+ if ( theAuthenticator != null )
+ {
+ theAuthenticator.cleanup();
+ }
+ }
+ return isAuthenticated;
+ }
+
+ private void closeServerChannel()
+ {
+ try
+ {
+ mSelector.close();
+ mChannel.close();
+ }
+ catch( IOException theException )
+ {
+ APOCLogger.throwing( "AdminManager",
+ "closeServerChannel",
+ theException );
+ }
+ }
+
+ private void handleRequest( final ClientChannel inChannel )
+ throws Exception
+ {
+ int theRC;
+ ByteBuffer theBuffer = ByteBuffer.wrap( new byte[ 1 ] );
+ while ( inChannel.read( theBuffer ) != 1 ){}
+ switch( theBuffer.array()[ 0 ] )
+ {
+ case sOpStop:
+ theRC = mAdminOpHandler.onStop();
+ terminate();
+ break;
+
+ case sOpStatus:
+ theRC = mAdminOpHandler.onStatus();
+ break;
+
+ case sOpReload:
+ theRC = mAdminOpHandler.onReload();
+ break;
+
+ case sOpChangeDetect:
+ theRC = mAdminOpHandler.onChangeDetect();
+ break;
+
+ default:
+ theRC = -1;
+ break;
+ }
+ theBuffer = ByteBuffer.wrap( theRC == 0 ? sSuccess : sFailure );
+ inChannel.write( theBuffer );
+ }
+
+ private void initChannel()
+ throws APOCException
+ {
+ try
+ {
+ mSelector = Selector.open();
+ mChannel = ServerSocketChannel.open();
+ mChannel.configureBlocking( false );
+ mChannel.socket().bind( null );
+ mChannel.register( mSelector, SelectionKey.OP_ACCEPT );
+ /*
+ * 6417539 - Need to use IANA registered port
+ * Use a PortMapper instance to let admin. clients
+ * know which port the agent is using.
+ */
+ new PortMapper(
+ ( ( InetSocketAddress )mChannel.socket().getLocalSocketAddress() )
+ .getPort() ).start();
+ }
+ catch( IOException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ private boolean shouldTerminate()
+ {
+ synchronized( mTerminateLock )
+ {
+ return mTerminate;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/admin/AdminOpHandler.java b/src/com/sun/apoc/daemon/admin/AdminOpHandler.java
new file mode 100644
index 0000000..edc357c
--- /dev/null
+++ b/src/com/sun/apoc/daemon/admin/AdminOpHandler.java
@@ -0,0 +1,43 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.admin;
+
+public interface AdminOpHandler
+{
+ int onStop();
+ int onStatus();
+ int onReload();
+ int onChangeDetect();
+}
diff --git a/src/com/sun/apoc/daemon/admin/PortMapper.java b/src/com/sun/apoc/daemon/admin/PortMapper.java
new file mode 100644
index 0000000..04c3b5f
--- /dev/null
+++ b/src/com/sun/apoc/daemon/admin/PortMapper.java
@@ -0,0 +1,100 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.admin;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.net.*;
+
+/*
+ * Not really a port mapper but ....
+ *
+ * This class is used to inform admin. clients which port is currently being
+ * used for admin. access. It simply accepts a udp connection and reponds
+ * with the relevant port number. This is repeated indefinitely.
+ */
+public class PortMapper extends Thread
+{
+ private static int sPort =
+ DaemonConfig.getIntProperty( DaemonConfig.sDaemonPort );
+ private ByteBuffer mAdminPort;
+ private DatagramChannel mChannel;
+
+ public PortMapper( int inAdminPort )
+ throws APOCException
+ {
+ try
+ {
+ setName( "PortMapper" );
+ setDaemon( true );
+ mAdminPort =
+ ( ByteBuffer )ByteBuffer.allocate( 6 )
+ .put( String.valueOf( inAdminPort ).getBytes() )
+ .put( ( byte )0 );
+ mChannel = DatagramChannel.open();
+ mChannel.socket().bind( new InetSocketAddress( sPort ) );
+ }
+ catch( Exception theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public void run()
+ {
+ ByteBuffer theBuffer = ByteBuffer.allocate( 1 );
+ while ( true )
+ {
+ try
+ {
+ InetSocketAddress theClient =
+ ( InetSocketAddress )mChannel.receive(
+ ( ByteBuffer )theBuffer.position( 0 ) );
+ if ( theClient != null &&
+ theClient.getAddress().isLoopbackAddress() )
+ {
+ mChannel.send( ( ByteBuffer )mAdminPort.position( 0 ),
+ theClient );
+ }
+ }
+ catch( Exception theIgnore )
+ {}
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/Cache.java b/src/com/sun/apoc/daemon/apocd/Cache.java
new file mode 100755
index 0000000..515ce09
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/Cache.java
@@ -0,0 +1,927 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.misc.*;
+
+import com.sun.apoc.spi.*;
+import com.sun.apoc.spi.policies.*;
+
+import java.util.*;
+import javax.security.auth.callback.*;
+
+
+public class Cache implements ConfigEventListener
+{
+ private String mUserName;
+ private String mEntityType;
+ private String mEntityId;
+ private CallbackHandler mHandler;
+ private DataSource mDataSources[] = null;
+ private final HashSet mSessions = new HashSet();
+ private int mRefCount = 0;
+ private boolean mIsLocalPolicyEnabled =
+ DaemonConfig.getBooleanProperty( DaemonConfig.sApplyLocalPolicy );
+ private static final String[] sStringModel = new String[ 0 ];
+
+ public Cache( final String inUserName,
+ final String inEntityType,
+ final String inEntityId,
+ final SaslAuthCallbackHandler inHandler )
+ {
+ mUserName = inUserName;
+ mEntityType = inEntityType;
+ mEntityId = inEntityId;
+ mHandler = inHandler;
+ createDataSources();
+ inHandler.setReconnectMode();
+ DaemonConfig.addConfigEventListener( this );
+ }
+
+ public synchronized int acquire( final Session inSession )
+ {
+ mSessions.add( inSession );
+ return ++ mRefCount;
+ }
+ public synchronized int release( final Session inSession )
+ {
+ mSessions.remove( inSession );
+ return -- mRefCount;
+ }
+ public synchronized Session [] getSessions()
+ {
+ return (Session []) mSessions.toArray(new Session [0]);
+ }
+ public synchronized ArrayList changeDetect()
+ {
+ for ( int theIndex = 0 ; theIndex < mDataSources.length ; ++ theIndex )
+ {
+ mDataSources[ theIndex ].open(mHandler);
+ }
+ ArrayList theResults = new ArrayList();
+ HashSet theOriginalList = null;
+ int theOnlineDataSourceCount = 0;
+
+ for ( int theIndex = 0 ; theIndex < mDataSources.length ; ++ theIndex )
+ {
+ if ( mDataSources[ theIndex ].isOnline())
+ {
+ ++ theOnlineDataSourceCount;
+ }
+ }
+ if ( theOnlineDataSourceCount > 1 )
+ {
+ theOriginalList = list();
+ }
+ for ( int theIndex = 0 ; theIndex < mDataSources.length ; theIndex ++ )
+ {
+ final ArrayList theResult =
+ changeDetect( mDataSources[ theIndex ] );
+ if ( theResult != null )
+ {
+ theResults.addAll( theResult );
+ }
+ }
+ if ( theOnlineDataSourceCount > 1 )
+ {
+ theResults = mergeUpdateResults( theResults, theOriginalList );
+ }
+ return theResults;
+ }
+
+ public synchronized void close()
+ {
+ for ( int theIndex = 0; theIndex < mDataSources.length ; theIndex ++ )
+ {
+ mDataSources[ theIndex ].close();
+ }
+ }
+
+ public String getEntityType() { return mEntityType; }
+
+ public String getEntityId() { return mEntityId; }
+
+ public boolean isOutOfDate()
+ {
+ long lastChangeDetect = Timestamp.getMillis(getLastChangeDetect()) ;
+
+ if (lastChangeDetect == 0) { return true ; }
+ return lastChangeDetect +
+ (long) (DaemonConfig.getFloatProperty(
+ DaemonConfig.sChangeDetectionInterval) * 60000) <
+ Timestamp.getMillis(Timestamp.getTimestamp()) ;
+ }
+
+ public synchronized String getLastChangeDetect()
+ {
+ String theResult = null;
+ for ( int theIndex = 0; theIndex < mDataSources.length; theIndex ++ )
+ {
+ final LocalDatabase theDatabase =
+ mDataSources[ theIndex ].getLocalDatabase();
+ if ( theDatabase != null )
+ {
+ try
+ {
+ theDatabase.beginTransaction();
+ final String theTimestamp=theDatabase.getLastChangeDetect();
+ if ( theTimestamp.compareTo( Timestamp.sEpoch ) == 0 )
+ {
+ break;
+ }
+ else if ( theResult == null )
+ {
+ theResult = theTimestamp;
+ }
+ else if ( Timestamp.isNewer( theResult, theTimestamp ) )
+ {
+ theResult = theTimestamp;
+ }
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache",
+ "getLastChangeDetect",
+ theException );
+ }
+ finally
+ {
+ try
+ {
+ theDatabase.endTransaction();
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache",
+ "getLastChangeDetect",
+ theException );
+ }
+ }
+ }
+ }
+ return theResult != null ? theResult : Timestamp.sEpoch;
+ }
+
+ public String getUserId() { return mUserName; }
+
+ public synchronized boolean hasDatabase( final Database inDatabase )
+ {
+ boolean haveLocalDatabase = false;
+ for ( int theIndex = 0; theIndex < mDataSources.length; theIndex ++ )
+ {
+ if ( mDataSources[ theIndex ].getLocalDatabase() == inDatabase )
+ {
+ haveLocalDatabase = true;
+ break;
+ }
+ }
+ return haveLocalDatabase;
+ }
+
+ public synchronized HashSet list()
+ {
+ HashSet theComponents = new HashSet();
+ for ( int theIndex = 0; theIndex < mDataSources.length; theIndex ++ )
+ {
+ final HashSet theSet = list ( mDataSources[ theIndex ] );
+ if ( theSet != null )
+ {
+ theComponents.addAll( theSet );
+ }
+ }
+ return theComponents;
+ }
+
+ public synchronized void onConfigEvent()
+ {
+ boolean isLocalPolicyEnabled =
+ DaemonConfig.getBooleanProperty( DaemonConfig.sApplyLocalPolicy );
+ if ( isLocalPolicyEnabled != mIsLocalPolicyEnabled )
+ {
+ mIsLocalPolicyEnabled = isLocalPolicyEnabled;
+ if ( mIsLocalPolicyEnabled )
+ {
+ enableLocalPolicy();
+ }
+ else
+ {
+ disableLocalPolicy();
+ }
+ }
+ }
+
+ public synchronized ArrayList read( final String inComponentName )
+ {
+ final ArrayList theResults = new ArrayList();
+ for ( int theIndex = 0; theIndex < mDataSources.length; theIndex ++ )
+ {
+ final ArrayList theResult =
+ read( mDataSources[ theIndex ], inComponentName );
+ if ( theResult != null )
+ {
+ theResults.addAll( theResult );
+ }
+ }
+ return theResults;
+ }
+
+ public synchronized String toString()
+ {
+ final StringBuffer theBuffer = new StringBuffer();
+ for ( int theIndex = 0; theIndex < mDataSources.length; theIndex ++ )
+ {
+ theBuffer.append( " dataSource" + ( theIndex + 1 ) )
+ .append( "\n " )
+ .append( mDataSources[ theIndex ].toString() )
+ .append( "\n" );
+ }
+ return theBuffer.toString();
+ }
+
+ private ArrayList changeDetect( final DataSource inDataSource )
+ {
+ ArrayList theResult = null;
+ if ( inDataSource.isOnline() )
+ {
+ final LocalDatabase theDatabase = inDataSource.getLocalDatabase();
+ try
+ {
+ theDatabase.beginTransaction();
+ switch( inDataSource.getState() )
+ {
+ case DataSource.sStateEnabled:
+ theResult = updateLocalDatabase( inDataSource );
+ break;
+
+ case DataSource.sStateDisabling:
+ theResult = new ArrayList();
+ addRemovalItems( theResult,
+ theDatabase.getLocalComponentList() );
+ break;
+ case DataSource.sStateEnabling:
+ theResult = new ArrayList();
+ addAdditionItems( theResult,
+ inDataSource,
+ theDatabase.getLocalComponentList() );
+ inDataSource.setState( DataSource.sStateEnabled );
+ break;
+
+ default:
+ break;
+ }
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "Cache", "changeDetect", theException );
+ }
+ finally
+ {
+ try
+ {
+ theDatabase.endTransaction();
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache",
+ "changeDetect",
+ theException );
+ }
+ }
+ if ( inDataSource.mState == DataSource.sStateDisabling )
+ {
+ inDataSource.close();
+ }
+ }
+ return theResult;
+ }
+
+ private void createDataSources()
+ {
+ mDataSources = new DataSource [2];
+ mDataSources[ 0 ] = new DataSource( mUserName,
+ mEntityType,
+ mEntityId,
+ true );
+ mDataSources[ 1 ] = new DataSource( mUserName,
+ mEntityType,
+ mEntityId,
+ false );
+ if ( mIsLocalPolicyEnabled )
+ {
+ mDataSources[ 0 ].open( mHandler );
+ }
+ mDataSources[ 1 ].open( mHandler );
+ }
+
+ private void disableLocalPolicy()
+ {
+ mDataSources[ 0 ].setState( DataSource.sStateDisabling );
+ }
+
+ private void enableLocalPolicy()
+ {
+ mDataSources[ 0 ].setState( DataSource.sStateEnabling );
+ }
+
+ private HashSet list( final DataSource inDataSource )
+ {
+ HashSet theSet = null;
+ if ( inDataSource.getState() == DataSource.sStateEnabled )
+ {
+ final LocalDatabase theDatabase = inDataSource.getLocalDatabase();
+ if ( theDatabase != null )
+ {
+ try
+ {
+ theDatabase.beginTransaction();
+ theSet = theDatabase.getRemoteComponentList();
+ }
+ catch ( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache", "list", theException );
+ }
+ finally
+ {
+ try
+ {
+ theDatabase.endTransaction();
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache", "list", theException );
+ }
+ }
+ }
+ }
+ return theSet;
+ }
+
+ private ArrayList mergeUpdateResults( final ArrayList inResults,
+ final HashSet inOriginalList )
+ {
+ ArrayList theResult = inResults;
+ if ( inResults.size() > 0 &&
+ inOriginalList != null &&
+ inOriginalList.size() > 0 )
+ {
+ final HashSet theNewList = list();
+ final HashSet theUpdatedComponents = new HashSet();
+ final Iterator theIterator = inResults.iterator();
+ theResult = new ArrayList();
+ while ( theIterator.hasNext() )
+ {
+ final UpdateItem theItem = ( UpdateItem )theIterator.next();
+ final String theName = theItem.getComponentName();
+ if ( theUpdatedComponents.add( theName ) )
+ {
+ if ( ( theItem.getUpdateType() == UpdateItem.ADD &&
+ inOriginalList.contains( theName ) ) ||
+ ( theItem.getUpdateType() == UpdateItem.REMOVE ) &&
+ theNewList.contains( theName ) )
+ {
+ theItem.setUpdateType( UpdateItem.MODIFY );
+ }
+ theResult.add( theItem );
+ }
+ }
+ }
+ return theResult;
+ }
+
+ private ArrayList read( final DataSource inDataSource,
+ final String inComponentName )
+ {
+ final ArrayList theResult = new ArrayList();
+ final LocalDatabase theDatabase = inDataSource.getLocalDatabase();
+ if ( theDatabase != null )
+ {
+ try
+ {
+ theDatabase.beginTransaction();
+ boolean haveComponent =
+ theDatabase.hasComponent( inComponentName );
+ if ( ! haveComponent && inDataSource.isOnline() )
+ {
+ final HashSet theSet = theDatabase.getRemoteComponentList();
+ if ( theSet != null && theSet.contains( inComponentName ) )
+ {
+ final Policy[] thePolicies =
+ inDataSource.
+ getPolicyBackend().
+ getLayeredPolicies(
+ inComponentName,
+ false );
+ if ( thePolicies != null )
+ {
+ theDatabase.
+ update(
+ new UpdateItem(
+ UpdateItem.ADD,
+ inComponentName,
+ thePolicies ),
+ Timestamp.getTimestamp() );
+ haveComponent = true;
+ }
+ }
+ }
+ if ( haveComponent )
+ {
+ final Vector theLayerIds =
+ theDatabase.getLayerIds( inComponentName );
+ for ( int theIndex = 0;
+ theIndex < theLayerIds.size();
+ ++ theIndex )
+ {
+ final String theLayerId =
+ ( String )theLayerIds.elementAt( theIndex );
+ theResult.add(
+ new CacheReadResult(
+ theDatabase.
+ getLastModified( theLayerId,
+ inComponentName ),
+ theDatabase.
+ getLayer( inComponentName, theLayerId ) ) );
+ }
+ }
+ }
+ catch ( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache", "read", theException );
+ }
+ finally
+ {
+ try
+ {
+ theDatabase.endTransaction();
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "Cache", "read", theException );
+ }
+ }
+ }
+ return theResult;
+ }
+
+ private void addDownloadItems( final ArrayList outResult,
+ final DataSource inDataSource,
+ final HashSet inAddComponents,
+ final HashSet inModifyComponents )
+ throws APOCException
+ {
+ if ( inAddComponents != null && inModifyComponents != null )
+ {
+ final HashSet theSet = ( HashSet)inAddComponents.clone();
+ int theAddCount = theSet.size();
+ theSet.addAll( inModifyComponents );
+ final Policy[][] thePolicies =
+ ( Policy[][] )inDataSource.getPolicyBackend().
+ getLayeredPolicies( theSet, false );
+ final Iterator theIterator = theSet.iterator();
+ int theIndex = 0;
+ while ( theIterator.hasNext() )
+ {
+ final String theComponent = ( String )theIterator.next();
+ outResult.add(
+ new UpdateItem( inAddComponents.contains( theComponent ) ?
+ UpdateItem.ADD : UpdateItem.MODIFY,
+ theComponent,
+ thePolicies[ theIndex ++ ] ) );
+ }
+
+ }
+ else
+ if ( inAddComponents != null )
+ {
+ addAdditionItems( outResult, inDataSource, inAddComponents );
+ }
+ else if ( inModifyComponents != null )
+ {
+ addModificationItems( outResult, inDataSource, inModifyComponents );
+ }
+
+ }
+
+ private void addAdditionItems( final ArrayList outResult,
+ final DataSource inDataSource,
+ final HashSet inComponents )
+ throws APOCException
+ {
+ if ( inComponents != null )
+ {
+ final Policy[][] thePolicies =
+ ( Policy[][] )inDataSource.
+ getPolicyBackend().
+ getLayeredPolicies( inComponents, false );
+ final Iterator theIterator = inComponents.iterator();
+ int theIndex = 0;
+ while ( theIterator.hasNext() )
+ {
+ outResult.add(
+ new UpdateItem( UpdateItem.ADD,
+ ( String )theIterator.next(),
+ thePolicies[ theIndex ++ ] ) );
+ }
+ }
+ }
+
+ private void addModificationItems( final ArrayList outResult,
+ final DataSource inDataSource,
+ final HashSet inComponents )
+ throws APOCException
+ {
+ if ( inComponents != null )
+ {
+ final Policy[][] thePolicies =
+ ( Policy[][] )inDataSource.
+ getPolicyBackend().
+ getLayeredPolicies( inComponents, false );
+ final Iterator theIterator = inComponents.iterator();
+ int theIndex = 0;
+ while ( theIterator.hasNext() )
+ {
+ outResult.add(
+ new UpdateItem( UpdateItem.MODIFY,
+ ( String )theIterator.next(),
+ thePolicies[ theIndex ++ ] ) );
+ }
+ }
+ }
+
+ private void addRemovalItems( final ArrayList outResult,
+ final HashSet inComponents )
+ throws APOCException
+ {
+ if ( inComponents != null )
+ {
+ final Iterator theIterator = inComponents.iterator();
+ while ( theIterator.hasNext() )
+ {
+ outResult.add(
+ new UpdateItem( UpdateItem.REMOVE,
+ ( String )theIterator.next(),
+ null ) );
+ }
+ }
+ }
+
+ private int compareLayers( final DataSource inDataSource,
+ final String inComponentName,
+ final PolicyInfo[] inPolicies )
+ throws APOCException
+ {
+ int theRC = 0;
+ final LocalDatabase theDatabase = inDataSource.getLocalDatabase();
+ final Vector theLayerIds =
+ theDatabase.getLayerIds( inComponentName );
+ if ( theLayerIds.size() != inPolicies.length )
+ {
+ theRC = 1;
+ }
+ else
+ {
+ final String theComponentName = inPolicies[ 0 ].getId();
+ for ( int theIndex = 0 ; theIndex < inPolicies.length; ++ theIndex)
+ {
+ final String theLayerId =
+ ( String )theLayerIds.elementAt( theIndex );
+
+
+ if ( theLayerId.compareTo(
+ String.valueOf(
+ inPolicies[ theIndex ].getProfileId().hashCode() ) )
+ != 0
+ ||
+ Timestamp.getTimestamp(
+ inPolicies[ theIndex ].getLastModified() ).compareTo(
+ theDatabase.
+ getLastModified( theLayerId, theComponentName ))
+ != 0 )
+ {
+ theRC = 1;
+ break;
+ }
+ }
+ }
+ return theRC;
+ }
+
+ private void createUpdateItems( final ArrayList outResult,
+ final DataSource inDataSource,
+ final HashSet inRemoteComponents )
+ throws APOCException
+ {
+ final HashSet theLocalComponents =
+ inDataSource.getLocalDatabase().getLocalComponentList();
+ final HashSet theAdditions =
+ diff( inRemoteComponents, theLocalComponents );
+ final HashSet theRemovals =
+ diff( theLocalComponents, inRemoteComponents );
+ final HashSet theModifications =
+ getModifications( inDataSource,
+ diff( theLocalComponents, theRemovals ) );
+ addDownloadItems( outResult,
+ inDataSource,
+ theAdditions,
+ theModifications );
+ addRemovalItems( outResult, theRemovals );
+ }
+
+ private HashSet diff( final HashSet inSet1, final HashSet inSet2 )
+ {
+ HashSet theResult = null;
+ if ( inSet2 == null )
+ {
+ theResult = inSet1;
+ }
+ else
+ if ( inSet1 != null )
+ {
+ theResult = ( HashSet )inSet1.clone();
+ theResult.removeAll( inSet2 );
+ if ( theResult.size() == 0 )
+ {
+ theResult = null;
+ }
+ }
+ return theResult;
+ }
+
+ private HashSet getModifications( final DataSource inDataSource,
+ final HashSet inSet )
+ throws APOCException
+ {
+ HashSet theModifications = null;
+ if ( inSet != null )
+ {
+ final PolicyInfo[][] thePolicies =
+ inDataSource.
+ getPolicyBackend().
+ getLayeredPolicies( inSet, true );
+ final String[] theComponents =
+ ( String[] )inSet.toArray( sStringModel );
+ theModifications = new HashSet();
+ for ( int theIndex = 0 ; theIndex < thePolicies.length; ++ theIndex)
+ {
+ if ( isUpdated( inDataSource,
+ theComponents[ theIndex ],
+ thePolicies[ theIndex ] ) )
+ {
+ theModifications.add( theComponents[ theIndex ] );
+ }
+ }
+ if ( theModifications.size() == 0 )
+ {
+ theModifications = null;
+ }
+ }
+ return theModifications;
+ }
+
+ private boolean isUpdated( final DataSource inDataSource,
+ final String inComponent,
+ final PolicyInfo[] inPolicies )
+ throws APOCException
+ {
+ boolean isUpdated = false;
+ if ( inPolicies == null )
+ {
+ isUpdated = true;
+ }
+ else
+ {
+ isUpdated = compareLayers( inDataSource, inComponent, inPolicies )
+ == 0 ? false : true;
+ }
+ return isUpdated;
+ }
+
+ private ArrayList updateLocalDatabase( final DataSource inDataSource )
+ throws APOCException
+ {
+ final ArrayList theResult = new ArrayList();
+ try
+ {
+ final PolicyBackend theBackend = inDataSource.getPolicyBackend();
+ theBackend.refreshProfiles();
+ final HashSet theRemoteComponents = theBackend.getComponentList();
+ createUpdateItems( theResult, inDataSource, theRemoteComponents );
+ theResult.trimToSize();
+ final String theTimestamp= Timestamp.getTimestamp();
+ final LocalDatabase theDatabase = inDataSource.getLocalDatabase();
+ theDatabase.update( theResult, theTimestamp );
+ theDatabase.putLastChangeDetect( theTimestamp );
+ theDatabase.putRemoteComponentList(
+ theRemoteComponents != null ?
+ theRemoteComponents : new HashSet() );
+ }
+ catch( SPIException theException )
+ {
+ throw new APOCException( theException );
+ }
+ return theResult;
+ }
+
+ private static class DataSource
+ {
+ protected LocalDatabase mLocalDatabase;
+ protected PolicyBackend mPolicyBackend;
+ protected Name mName;
+ protected int mState = sStateDisabled;
+ protected boolean mInitialised = false;
+
+ static final int sStateEnabled = 0;
+ static final int sStateDisabled = 1;
+ static final int sStateEnabling = 2;
+ static final int sStateDisabling = 3;
+
+ DataSource( final String inUserName,
+ final String inEntityType,
+ final String inEntityId,
+ final boolean inIsLocal )
+ {
+ mName = new Name( inUserName, inEntityType, inEntityId, inIsLocal );
+ }
+
+ void close()
+ {
+ closePolicyBackend();
+ closeLocalDatabase();
+ }
+
+ synchronized LocalDatabase getLocalDatabase() { return mLocalDatabase; }
+
+ synchronized PolicyBackend getPolicyBackend() { return mPolicyBackend; }
+
+ synchronized int getState() { return mState; }
+
+ synchronized boolean isOnline() {
+ return mPolicyBackend != null && mLocalDatabase != null; }
+
+ synchronized void open( final CallbackHandler inHandler )
+ {
+ boolean isLocal = mName.isLocal();
+ if ( ! isLocal ||
+ DaemonConfig.getBooleanProperty(
+ DaemonConfig.sApplyLocalPolicy ) )
+ {
+ if ( mLocalDatabase == null )
+ {
+ mLocalDatabase = openLocalDatabase();
+ }
+ try
+ {
+ if ( mLocalDatabase != null && mPolicyBackend == null &&
+ ( mInitialised ||
+ mLocalDatabase.getLastChangeDetect().compareTo(
+ Timestamp.sEpoch ) == 0 ) )
+ {
+ mPolicyBackend = openPolicyBackend( inHandler );
+ if ( ! mInitialised && mPolicyBackend != null )
+ {
+ initialiseDatabase();
+ }
+ }
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "DataSource", "open", theException );
+ }
+ mInitialised = true;
+ if ( ! isLocal || mState != sStateEnabling )
+ {
+ mState = sStateEnabled;
+ }
+ }
+ }
+
+ synchronized void setState( int inState ) { mState = inState; }
+
+ public String toString()
+ {
+ return new StringBuffer( " Name: " )
+ .append( mName.toString() )
+ .append( "\n Cache: " )
+ .append( mLocalDatabase )
+ .append( "\n Backend: " )
+ .append( mPolicyBackend )
+ .toString();
+ }
+
+ protected void initialiseDatabase()
+ {
+ try
+ {
+ final HashSet theSet = mPolicyBackend.getComponentList();
+ if ( theSet != null )
+ {
+ mLocalDatabase.beginTransaction();
+ mLocalDatabase.putRemoteComponentList( theSet );
+ mLocalDatabase.endTransaction();
+ }
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "DataSource",
+ "initialiseDatabase",
+ theException);
+ }
+ }
+
+ protected void closeLocalDatabase()
+ {
+ if ( mLocalDatabase != null )
+ {
+ try
+ {
+ LocalDatabaseFactory.getInstance().closeLocalDatabase(
+ mLocalDatabase );
+ }
+ catch( Exception theException ){}
+ finally { mLocalDatabase = null; }
+ }
+ }
+
+ protected void closePolicyBackend()
+ {
+ if ( mPolicyBackend != null )
+ {
+ PolicyBackendFactory.getInstance().closePolicyBackend(
+ mPolicyBackend );
+ mPolicyBackend = null;
+ }
+ }
+
+ protected LocalDatabase openLocalDatabase()
+ {
+ LocalDatabase theLocalDatabase = null;
+ try
+ {
+ theLocalDatabase =
+ LocalDatabaseFactory.getInstance().
+ openLocalDatabase( mName );
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "DataSource",
+ "openLocalDatabase",
+ theException );
+ }
+ return theLocalDatabase;
+ }
+
+ protected PolicyBackend openPolicyBackend(
+ final CallbackHandler inHandler )
+ {
+ PolicyBackend theBackend = null;
+ try
+ {
+ theBackend =
+ PolicyBackendFactory
+ .getInstance()
+ .openPolicyBackend( mName, inHandler );
+ }
+ catch( APOCException theException )
+ {
+ APOCLogger.throwing( "PolicyBackend",
+ "openPolicyBackend",
+ theException );
+ }
+ return theBackend;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/CacheFactory.java b/src/com/sun/apoc/daemon/apocd/CacheFactory.java
new file mode 100755
index 0000000..65d5f39
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/CacheFactory.java
@@ -0,0 +1,151 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+import javax.security.auth.callback.*;
+
+public class CacheFactory
+{
+ private final HashMap mCaches = new HashMap();
+ private static final CacheFactory sInstance = new CacheFactory();
+ private static final Cache[] sCacheModel = new Cache[ 0 ];
+
+ private synchronized void closeCache( final Cache inCache,
+ final Session inSession )
+ {
+ if ( inCache.release( inSession ) == 0 )
+ {
+ final Cache theCache =
+ ( Cache )mCaches.remove(
+ makeKey( inCache.getUserId(),
+ inCache.getEntityType(),
+ inCache.getEntityId() ) );
+ if ( theCache != null )
+ {
+ theCache.close();
+ }
+ }
+ }
+
+ public void closeCaches( final Cache[] inCaches, final Session inSession )
+ {
+ for ( int theIndex = 0 ; theIndex < inCaches.length ; ++ theIndex )
+ {
+ closeCache( inCaches[ theIndex ], inSession );
+ }
+ }
+
+ public synchronized Cache[] getCaches()
+ {
+ Cache[] theCaches = null;
+ if ( mCaches.size() > 0 )
+ {
+ theCaches = ( Cache[] )mCaches.values().toArray( sCacheModel );
+ }
+ return theCaches;
+ }
+
+ public static CacheFactory getInstance() { return sInstance; }
+
+ public synchronized Cache [] openCaches(
+ final String inUserId,
+ final Hashtable inEntities,
+ final Session inSession,
+ final SaslAuthCallbackHandler inHandler )
+ throws APOCException
+ {
+ String [] theSources = PolicyBackendFactory.getInstance().getSources();
+ ArrayList theCaches = new ArrayList();
+
+ for ( int theIndex = 0 ; theIndex < theSources.length ; ++ theIndex )
+ {
+ String theEntity =
+ (String) inEntities.get( theSources[ theIndex ] );
+ Cache theCache = getCache( inUserId, theSources[ theIndex ],
+ theEntity, inHandler );
+
+ theCache.acquire( inSession );
+ theCaches.add( theCache );
+ }
+ return (Cache []) theCaches.toArray( sCacheModel );
+ }
+
+ private CacheFactory(){}
+
+ private Cache getCache(final String inUserId,
+ final String inEntityType,
+ final String inEntityId,
+ final SaslAuthCallbackHandler inHandler)
+ throws APOCException
+ {
+ Cache retCode = getExistingCache(inUserId, inEntityType, inEntityId) ;
+
+ if (retCode == null)
+ {
+ retCode = createNewCache(inUserId, inEntityType,
+ inEntityId, inHandler) ;
+ }
+ return retCode ;
+ }
+ private Cache createNewCache( final String inUserId,
+ final String inEntityType,
+ final String inEntityId,
+ final SaslAuthCallbackHandler inHandler )
+ throws APOCException
+ {
+ Cache theCache = new Cache( inUserId, inEntityType,
+ inEntityId, inHandler );
+ mCaches.put( makeKey( inUserId, inEntityType, inEntityId ), theCache );
+ return theCache;
+ }
+
+ private Cache getExistingCache( final String inUserId,
+ final String inEntityType,
+ final String inEntityId )
+ {
+ return ( Cache )mCaches.get( makeKey( inUserId, inEntityType,
+ inEntityId ) );
+ }
+
+ private String makeKey( final String inUserId, final String inEntityType,
+ final String inEntityId )
+ {
+ return inUserId + "/" + inEntityType + "/" +
+ ( inEntityId != null ? inEntityId : "" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/CacheReadResult.java b/src/com/sun/apoc/daemon/apocd/CacheReadResult.java
new file mode 100755
index 0000000..e7e9a75
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/CacheReadResult.java
@@ -0,0 +1,47 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+public class CacheReadResult
+{
+ public String mTimestamp;
+ public String mData;
+
+ public CacheReadResult( final String inTimestamp, final String inData )
+ {
+ mTimestamp = inTimestamp;
+ mData = inData;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/ChangeDetectEventHandler.java b/src/com/sun/apoc/daemon/apocd/ChangeDetectEventHandler.java
new file mode 100644
index 0000000..0ee5bb6
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/ChangeDetectEventHandler.java
@@ -0,0 +1,93 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.transaction.*;
+
+class ChangeDetectEventHandler implements EventHandler
+{
+ private final ChangeDetectTransaction mTransaction;
+ private long sTimeout = 100;
+ private final Object mCompleteLock = new Object();
+ private boolean mComplete = false;
+
+ ChangeDetectEventHandler( final ClientManager inManager,
+ final Cache inCache,
+ final UpdateAggregator inAggregator )
+ {
+ mTransaction = TransactionFactory
+ .getInstance()
+ .createChangeDetectTransaction( inManager,
+ inCache,
+ inAggregator );
+ }
+
+ public void handleEvent( final Messenger inMessenger )
+ {
+ mTransaction.execute();
+ setComplete();
+ }
+
+ public synchronized void waitForCompletion()
+ {
+ while ( ! isComplete() )
+ {
+ try
+ {
+ wait( sTimeout );
+ }
+ catch( InterruptedException theException )
+ {}
+ }
+ }
+
+ private boolean isComplete()
+ {
+ synchronized( mCompleteLock )
+ {
+ return mComplete;
+ }
+ }
+
+ private void setComplete()
+ {
+ synchronized( mCompleteLock )
+ {
+ mComplete = true;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/Client.java b/src/com/sun/apoc/daemon/apocd/Client.java
new file mode 100644
index 0000000..ff67959
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/Client.java
@@ -0,0 +1,148 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+import java.util.*;
+
+public class Client
+{
+ private final ClientChannel mChannel;
+ private final HashMap mSessions = new HashMap( 1 ); // norm is 1 session
+ private final HashSet mSessionListeners = new HashSet( 1 );
+
+ public Client( final ClientChannel inChannel )
+ {
+ mChannel = inChannel;
+ }
+
+ public ClientChannel getClientChannel() { return mChannel; }
+
+ // Changing this from a simple accessor because when change detection
+ // and session closure occur around the same time, the toArray() call
+ // below ( originally located in ClientManager ) can get confused.
+ public Object[] getSessions()
+ {
+ synchronized( mSessions )
+ {
+ return mSessions.values().toArray();
+ }
+ }
+
+ public Session getSession( final String inSessionId )
+ {
+ synchronized( mSessions )
+ {
+ return inSessionId != null ?
+ ( Session )mSessions.get( inSessionId ):
+ null;
+ }
+ }
+
+ public void addSession( final Session inSession )
+ {
+ synchronized( mSessions )
+ {
+ mSessions.put( inSession.getSessionId(), inSession );
+ }
+ notifySessionCreated( inSession );
+ }
+
+ public void addSessionListener( final SessionListener inSessionListener )
+ {
+ synchronized( mSessionListeners )
+ {
+ mSessionListeners.add( inSessionListener );
+ }
+ }
+
+ public void closeSession( final Session inSession )
+ {
+ synchronized( mSessions )
+ {
+ mSessions.remove( inSession.getSessionId() );
+ }
+ inSession.close();
+ notifySessionDestroyed( inSession );
+ }
+
+ synchronized public void close()
+ {
+ final Iterator theIterator = mSessions.keySet().iterator();
+ while ( theIterator.hasNext() )
+ {
+ final Session theSession =
+ ( Session )mSessions.get( theIterator.next() );
+ theSession.close();
+ notifySessionDestroyed( theSession );
+ }
+ mSessions.clear();
+ }
+
+ public void removeSessionListener( final SessionListener inSessionListener )
+ {
+ synchronized( mSessionListeners )
+ {
+ mSessionListeners.remove( inSessionListener );
+ }
+ }
+
+ private void notifySessionCreated( final Session inSession )
+ {
+ synchronized( mSessionListeners )
+ {
+ final Iterator theIterator = mSessionListeners.iterator();
+ while ( theIterator.hasNext() )
+ {
+ ( ( SessionListener )theIterator.next() )
+ .onSessionCreate( inSession );
+ }
+ }
+ }
+
+ private void notifySessionDestroyed( final Session inSession )
+ {
+ synchronized( mSessionListeners )
+ {
+ final Iterator theIterator = mSessionListeners.iterator();
+ while ( theIterator.hasNext() )
+ {
+ ( ( SessionListener )theIterator.next() )
+ .onSessionDestroy( inSession );
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/ClientEventHandler.java b/src/com/sun/apoc/daemon/apocd/ClientEventHandler.java
new file mode 100644
index 0000000..9df1cba
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/ClientEventHandler.java
@@ -0,0 +1,79 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transaction.*;
+
+import java.io.*;
+
+class ClientEventHandler implements EventHandler
+{
+ private final Client mClient;
+
+ ClientEventHandler( final Client inClient)
+ {
+ mClient = inClient;
+ }
+
+ public void handleEvent( final Messenger inMessenger )
+ {
+ try
+ {
+ inMessenger.setClientChannel( mClient.getClientChannel() );
+ final Transaction theTransaction =
+ TransactionFactory
+ .getInstance()
+ .createTransaction(
+ mClient,
+ inMessenger.receiveRequest() );
+ inMessenger.sendResponse( theTransaction.execute() );
+ }
+ catch( APOCException theException )
+ {
+ final Throwable theThrowable = theException.getCause();
+ if ( theThrowable == null || !(theThrowable instanceof IOException))
+ {
+ APOCLogger.throwing( "ClientEventHandler",
+ "handleEvent",
+ theException );
+ inMessenger.sendResponse(
+ MessageFactory.createResponse(
+ APOCSymbols.sSymRespInvalidRequest, null, null ) );
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/ClientManager.java b/src/com/sun/apoc/daemon/apocd/ClientManager.java
new file mode 100644
index 0000000..061e184
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/ClientManager.java
@@ -0,0 +1,311 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transaction.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.util.*;
+
+public class ClientManager implements ClientChannelEventListener,
+ ConfigEventListener,
+ SessionListener
+{
+ private final HashMap mClients =
+ new HashMap( DaemonConfig.getIntProperty(
+ DaemonConfig.sMaxClientConnections ) );
+ private final EventQueue mPendingEvents =
+ new EventQueue();
+ private final EventWorkerThreadPool mThreadPool =
+ new EventWorkerThreadPool(
+ mPendingEvents,
+ DaemonConfig.getIntProperty( DaemonConfig.sMaxClientThreads ) );
+ private final DaemonTimerTask mChangeDetector =
+ new DaemonTimerTask( new ChangeDetector( this ) );
+ private int mSessionCount = 0;
+
+ public ClientManager( final ChannelManager inChannelManager )
+ throws APOCException
+ {
+ inChannelManager.addClientChannelEventListener( this );
+ DaemonConfig.addConfigEventListener( this );
+ APOCLogger.fine( "Clmr001" );
+ }
+
+ public void changeDetect()
+ {
+ new ChangeDetector( this ).run();
+ }
+
+ public void onPending( final ClientChannel inClientChannel )
+ {
+ putEventHandler(
+ new ClientEventHandler( getClient( inClientChannel)) );
+ }
+
+ public void onClosed( final ClientChannel inClientChannel )
+ {
+ synchronized( mClients )
+ {
+ final Client theClient =
+ ( Client )mClients.remove( inClientChannel );
+ if ( theClient != null )
+ {
+ theClient.close();
+ APOCLogger.finer( "Clmr002" );
+ }
+ }
+ }
+
+ public void onConfigEvent()
+ {
+ startChangeDetectionTimer();
+
+ mThreadPool.resizePool(
+ DaemonConfig.getIntProperty(
+ DaemonConfig.sMaxClientThreads ) );
+ }
+
+ /* Warning: putting this here because we need access to the EventQueue.
+ * This Queue should be separated from this class in future.
+ */
+ public void onGarbageCollect()
+ {
+ try
+ {
+ Object[] theDatabases =
+ LocalDatabaseFactory.getInstance().getDatabases();
+ if ( theDatabases != null )
+ {
+ for ( int theIndex = 0;
+ theIndex < theDatabases.length;
+ ++ theIndex )
+ {
+ putEventHandler(
+ new GarbageCollectEventHandler(
+ ( Database )theDatabases[ theIndex ] ) );
+ }
+ }
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "ClientManager",
+ "onGarbageCollect",
+ theException );
+ }
+ }
+
+ synchronized public void onSessionCreate( final Session inSession )
+ {
+ mSessionCount ++;
+ doInitialChangeDetect( inSession );
+ }
+
+ synchronized public void onSessionDestroy( final Session inSession )
+ {
+ mSessionCount --;
+ stopChangeDetectionTimer();
+ }
+
+ public void terminate()
+ {
+ mThreadPool.terminate();
+ APOCLogger.fine( "Clmr007" );
+ }
+
+ private void doInitialChangeDetect( final Session inSession )
+ {
+ try
+ {
+ Cache [] theCaches = inSession.getCaches() ;
+ ArrayList theOutOfDateCaches = new ArrayList() ;
+
+ for (int i = 0 ; i < theCaches.length ; ++ i)
+ {
+ if (theCaches [i].isOutOfDate())
+ {
+ theOutOfDateCaches.add(theCaches [i]) ;
+ }
+ }
+ final DaemonTimerTask theTask =
+ new DaemonTimerTask(
+ new ChangeDetector(
+ this,
+ (Cache []) theOutOfDateCaches.toArray(
+ new Cache [0])),
+ true) ;
+
+ theTask.setPeriod(
+ DaemonConfig.getIntProperty(
+ DaemonConfig.sInitialChangeDetectionDelay) *
+ 1000) ;
+ startChangeDetectionTimer() ;
+ }
+ catch( Exception theException )
+ {}
+ }
+
+ private Client getClient( final ClientChannel inClientChannel )
+ {
+ synchronized( mClients )
+ {
+ Client theClient = ( Client )mClients.get( inClientChannel );
+ if ( theClient == null )
+ {
+ theClient = new Client( inClientChannel );
+ theClient.addSessionListener( this );
+ mClients.put( inClientChannel, theClient );
+ APOCLogger.finer( "Clmr005" );
+ }
+ return theClient;
+ }
+ }
+
+ private boolean putEventHandler( final EventHandler inEventHandler )
+ {
+ boolean theRC = true;
+ mPendingEvents.put( inEventHandler );
+ try
+ {
+ mThreadPool.ensureThread();
+ }
+ catch( APOCException theException )
+ {
+ theRC = false;
+ APOCLogger.throwing( "ChangeDetector", "run", theException );
+ }
+ return theRC;
+ }
+
+ private void startChangeDetectionTimer()
+ {
+ if ( mSessionCount > 0 )
+ {
+ final float theMinuteDelay =
+ DaemonConfig.getFloatProperty(
+ DaemonConfig.sChangeDetectionInterval );
+ if ( mChangeDetector.setPeriod( ( long )(60000 * theMinuteDelay) ) )
+ {
+ if ( mChangeDetector.getPeriod() > 0 )
+ {
+ APOCLogger.fine( "Clmr004",
+ String.valueOf( theMinuteDelay ) );
+ }
+ else
+ {
+ APOCLogger.fine( "Clmr006" );
+ }
+ }
+ }
+ }
+
+ private void stopChangeDetectionTimer()
+ {
+ if ( mSessionCount < 1 )
+ {
+ mChangeDetector.cancel();
+ }
+ }
+
+ static class ChangeDetector implements Runnable
+ {
+ private ClientManager mManager;
+ private Cache [] mCaches = null;
+ boolean mCheckCaches = false ;
+
+ public ChangeDetector( final ClientManager inManager,
+ final Cache [] inCaches )
+ {
+ mManager = inManager;
+ mCaches = inCaches ;
+ mCheckCaches = true ;
+ }
+
+ public ChangeDetector( final ClientManager inManager )
+ {
+ mManager = inManager;
+ }
+
+ public void run()
+ {
+ Cache [] theCaches = mCaches ;
+
+ if ( theCaches == null )
+ {
+ synchronized( mManager.mClients )
+ {
+ if ( ! mManager.mClients.isEmpty() )
+ {
+ theCaches = CacheFactory.getInstance().getCaches();
+ }
+ }
+ }
+ if ( theCaches != null )
+ {
+ final ArrayList theHandlers = new ArrayList();
+ final UpdateAggregator theAggregator = new UpdateAggregator() ;
+
+ for ( int theIndex = 0;
+ theIndex < theCaches.length;
+ ++ theIndex )
+ {
+ if (!mCheckCaches || theCaches [theIndex].isOutOfDate()) {
+ final ChangeDetectEventHandler theHandler =
+ new ChangeDetectEventHandler(
+ mManager, theCaches[ theIndex ],
+ theAggregator );
+ if ( mManager.putEventHandler( theHandler ) )
+ {
+ theHandlers.add( theHandler );
+ }
+ }
+ }
+ int theHandlerCount = theHandlers.size();
+ for ( int theIndex = 0;
+ theIndex < theHandlerCount;
+ ++ theIndex )
+ {
+ ( ( ChangeDetectEventHandler )theHandlers
+ .get( theIndex ) ).waitForCompletion();
+ }
+ theAggregator.sendNotifications() ;
+ mManager.startChangeDetectionTimer();
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/Daemon.java b/src/com/sun/apoc/daemon/apocd/Daemon.java
new file mode 100644
index 0000000..8eddcaa
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/Daemon.java
@@ -0,0 +1,209 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.admin.*;
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.io.*;
+import java.util.*;
+
+public class Daemon implements ConfigEventListener, AdminOpHandler
+{
+ private ChannelManager mChannelManager;
+ private ClientManager mClientManager;
+ private AdminManager mAdminManager;
+ private final DaemonTimerTask mGarbageCollector =
+ new DaemonTimerTask( new GarbageCollector() );
+
+ public static void main( final String[] inArgs )
+ {
+ try
+ {
+ new Daemon( inArgs ).run();
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "Daemon", "main", theException );
+ }
+ }
+
+ public Daemon( final String[] inArgs )
+ throws APOCException, IOException, InterruptedException
+ {
+ if ( inArgs.length != 2 )
+ {
+ usage();
+ System.exit( 1 );
+ }
+ init( inArgs );
+ }
+
+ public void onConfigEvent()
+ {
+ startGarbageCollectionTimer();
+ DaemonConfig.log();
+ }
+
+ public int onStop()
+ {
+ mChannelManager.terminate();
+ return 0;
+ }
+
+ public int onStatus()
+ {
+ return 0;
+ }
+
+ public int onReload()
+ {
+ int theRC;
+ try
+ {
+ DaemonConfig.reload();
+ DaemonConfig.log();
+ theRC = 0;
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "Daemon", "onReload", theException );
+ theRC = 1;
+ }
+ return theRC;
+ }
+
+ public int onChangeDetect()
+ {
+ mClientManager.changeDetect();
+ return 0;
+ }
+
+ public void run()
+ throws APOCException, InterruptedException
+ {
+ APOCLogger.info( "Dmon001" );
+
+ startGarbageCollectionTimer();
+ mChannelManager = new ChannelManager();
+ mClientManager = new ClientManager( mChannelManager );
+ verifyConfig();
+ mChannelManager.start();
+ DaemonConfig.addConfigEventListener( this );
+ mAdminManager = new AdminManager( this );
+ mAdminManager.start();
+ mChannelManager.join();
+
+ mClientManager.terminate();
+ mChannelManager.closeChannels();
+ APOCLogger.info( "Dmon002" );
+ }
+
+ private void usage()
+ {
+ System.err.println( "Usage: apocd <daemon installation directory>" );
+ }
+
+ private void init( final String[] inArgs )
+ throws IOException, APOCException
+ {
+ System.loadLibrary( "FileAccess" );
+ initConfig( inArgs );
+ initAuthDir();
+ }
+
+ private void initAuthDir()
+ throws APOCException
+ {
+ if ( ! APOCAuthenticator.sAuthDir.exists() )
+ {
+ if ( ! APOCAuthenticator.sAuthDir.mkdirs() )
+ {
+ throw new APOCException();
+ }
+ }
+ else
+ {
+ if ( ! APOCAuthenticator.sAuthDir.isDirectory() )
+ {
+ throw new APOCException();
+ }
+ }
+ FileAccess.chmod( APOCAuthenticator.sAuthDir.getAbsolutePath(), 0755 );
+ FileAccess.chmod( APOCAuthenticator.sAuthDir.getParent(), 0755 );
+ }
+
+ private void initConfig( final String[] inArgs )
+ throws IOException, APOCException
+ {
+ DaemonConfig.init( inArgs );
+ DaemonConfig.log();
+ }
+
+ private void startGarbageCollectionTimer()
+ {
+ final long theMinuteDelay =
+ DaemonConfig.getIntProperty(
+ DaemonConfig.sGarbageCollectionInterval );
+ if ( mGarbageCollector.setPeriod( 60000 * theMinuteDelay ) )
+ {
+ if ( mGarbageCollector.getPeriod() > 0 )
+ {
+ APOCLogger.fine( "Dmon003", String.valueOf( theMinuteDelay ) );
+ }
+ else
+ {
+ APOCLogger.fine( "Dmon004" );
+ }
+ }
+ }
+
+ private void verifyConfig()
+ throws APOCException
+ {
+ LocalDatabaseFactory.getInstance();
+ }
+
+ class GarbageCollector implements Runnable
+ {
+ public void run()
+ {
+ mClientManager.onGarbageCollect();
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/EventHandler.java b/src/com/sun/apoc/daemon/apocd/EventHandler.java
new file mode 100644
index 0000000..a1550a4
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/EventHandler.java
@@ -0,0 +1,42 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.messaging.*;
+
+interface EventHandler
+{
+ public void handleEvent( final Messenger inMessenger );
+}
diff --git a/src/com/sun/apoc/daemon/apocd/EventQueue.java b/src/com/sun/apoc/daemon/apocd/EventQueue.java
new file mode 100644
index 0000000..b913754
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/EventQueue.java
@@ -0,0 +1,100 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import java.util.*;
+
+class EventQueue
+{
+ private final List mList = new ArrayList();
+ static private final long sTimeout = 100;
+
+ public void put( final EventHandler inEventHandler )
+ {
+ add( inEventHandler );
+ synchronized( mList )
+ {
+ mList.notify();
+ }
+ }
+
+ public EventHandler get()
+ {
+ EventHandler theEventHandler = remove();
+ if ( theEventHandler == null )
+ {
+ try
+ {
+ synchronized( mList )
+ {
+ mList.wait( sTimeout );
+ }
+ }
+ catch ( InterruptedException theException )
+ {}
+ theEventHandler = remove();
+ }
+ return theEventHandler;
+ }
+
+ public void releaseWaitingThreads()
+ {
+ synchronized( mList )
+ {
+ mList.notifyAll();
+ }
+ }
+
+ private void add( final EventHandler inEventHandler )
+ {
+ synchronized( mList )
+ {
+ mList.add( inEventHandler );
+ }
+ }
+
+ private EventHandler remove()
+ {
+ EventHandler theEventHandler = null;
+ synchronized( mList )
+ {
+ if ( ! mList.isEmpty() )
+ {
+ theEventHandler = ( EventHandler )mList.remove( 0 );
+ }
+ }
+ return theEventHandler;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/EventWorkerThread.java b/src/com/sun/apoc/daemon/apocd/EventWorkerThread.java
new file mode 100644
index 0000000..bfef9f7
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/EventWorkerThread.java
@@ -0,0 +1,122 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transaction.*;
+
+import java.io.*;
+import java.util.*;
+
+class EventWorkerThread extends Thread
+{
+ private final EventQueue mQueue;
+ private final Messenger mMessenger = new Messenger();
+ private final Object mStateLock = new Object();
+ private long mTimestamp = System.currentTimeMillis();
+ private int mState = sStateIdle;
+
+ private static int sStateIdle = 0;
+ private static int sStateBusy = 1;
+ private static int sStateTerminating = 2;
+ private static long sIdleTimeout =
+ ( long )DaemonConfig.
+ getIntProperty( DaemonConfig.sThreadTimeToLive ) * 60000;
+
+ public EventWorkerThread( final EventQueue inQueue )
+ throws APOCException
+ {
+ setName( "EventWorker" );
+ setDaemon( true );
+ mQueue = inQueue;
+ }
+
+ public boolean isAvailable()
+ {
+ return privgetState() == sStateIdle;
+ }
+
+ public void run()
+ {
+ while ( ! ( privgetState() == sStateTerminating ) )
+ {
+ final EventHandler theEventHandler = mQueue.get();
+ if ( theEventHandler != null )
+ {
+ setState( sStateBusy );
+ theEventHandler.handleEvent( mMessenger );
+ setState( sStateIdle );
+ }
+ }
+ }
+
+ public boolean terminate( boolean inIfIdle )
+ {
+ boolean isTerminated = true;
+ if ( ! inIfIdle )
+ {
+ setState( sStateTerminating );
+ }
+ else
+ {
+ long theIdleTime =
+ privgetState() == sStateIdle ?
+ System.currentTimeMillis() - mTimestamp : 0;
+ if ( theIdleTime > sIdleTimeout )
+ {
+ setState( sStateTerminating );
+ }
+ else
+ {
+ isTerminated = false;
+ }
+ }
+ return isTerminated;
+ }
+
+ private synchronized int privgetState() { return mState; }
+
+ private synchronized void setState( int inState )
+ {
+ if ( mState != sStateTerminating )
+ {
+ mTimestamp = inState == sStateTerminating ?
+ 0 : System.currentTimeMillis();
+ mState = inState;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/EventWorkerThreadPool.java b/src/com/sun/apoc/daemon/apocd/EventWorkerThreadPool.java
new file mode 100644
index 0000000..191015b
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/EventWorkerThreadPool.java
@@ -0,0 +1,191 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transaction.*;
+
+import java.io.*;
+import java.util.*;
+
+class EventWorkerThreadPool
+{
+ private final EventQueue mQueue;
+ private final ArrayList mPool = new ArrayList();
+ private int mMaxPoolSize;
+ private int mPoolSize = 0;
+ private final DaemonTimerTask mIdleDetector =
+ new DaemonTimerTask( new IdleDetector() );
+
+ private static long sIdleDetectorPeriod =
+ ( long )DaemonConfig.
+ getIntProperty( DaemonConfig.sIdleThreadDetectionInterval ) * 60000;
+
+ public EventWorkerThreadPool( final EventQueue inQueue,
+ final int inPoolSize )
+ throws APOCException
+ {
+ mQueue = inQueue;
+ mMaxPoolSize = inPoolSize;
+ mIdleDetector.setPeriod( sIdleDetectorPeriod );
+ }
+
+ synchronized public void ensureThread()
+ throws APOCException
+ {
+ if ( mPoolSize < mMaxPoolSize && ! haveIdleThread() )
+ {
+ final EventWorkerThread theThread = new EventWorkerThread( mQueue );
+ mPool.add( theThread );
+ mPoolSize ++;
+ theThread.start();
+ }
+ }
+
+ synchronized public void resizePool( int inPoolSize )
+ {
+ inPoolSize = inPoolSize > 0 ? inPoolSize : 1;
+ if ( inPoolSize != mMaxPoolSize )
+ {
+ if ( inPoolSize > mMaxPoolSize )
+ {
+ mMaxPoolSize = inPoolSize;
+ }
+ else if ( inPoolSize < mMaxPoolSize )
+ {
+ shrinkPool( inPoolSize );
+ }
+ }
+ }
+
+ public synchronized void terminate()
+ {
+ terminateThreads();
+ waitForLiveThreads();
+ }
+
+ private boolean haveIdleThread()
+ {
+ boolean haveIdleThread = false;
+ for ( int theIndex = 0; theIndex < mPoolSize; theIndex ++ )
+ {
+ if ( ( ( EventWorkerThread )mPool.get( theIndex ) ).isAvailable() )
+ {
+ haveIdleThread = true;
+ break;
+ }
+ }
+ return haveIdleThread;
+ }
+
+ private boolean haveLiveThread()
+ {
+ boolean haveLiveThread = false;
+ for ( int theIndex = 0; theIndex < mPoolSize; theIndex ++ )
+ {
+ if ( ( ( EventWorkerThread )mPool.get( theIndex ) ).isAlive() )
+ {
+ haveLiveThread = true;
+ break;
+ }
+ }
+ return haveLiveThread;
+ }
+
+ private void shrinkPool( int inPoolSize )
+ {
+ for ( int theIndex = mPoolSize; theIndex > inPoolSize; theIndex -- )
+ {
+ ( ( EventWorkerThread )( mPool.remove( 0 ) ) ).terminate( false );
+ }
+ mPool.trimToSize();
+ mMaxPoolSize = inPoolSize;
+ }
+
+ private void terminateThreads()
+ {
+ terminateThreads( false );
+ }
+
+ private synchronized void terminateThreads( boolean inIdleOnly )
+ {
+ int theTerminatedCount = 0;
+ for ( int theIndex = mPoolSize - 1; theIndex >= 0; theIndex -- )
+ {
+ EventWorkerThread theThread =
+ ( EventWorkerThread )mPool.get( theIndex );
+ if ( theThread.terminate( inIdleOnly ) )
+ {
+ mPool.remove( theIndex );
+ theTerminatedCount ++;
+ }
+ }
+ if ( theTerminatedCount > 0 )
+ {
+ mQueue.releaseWaitingThreads();
+ mPoolSize -= theTerminatedCount;
+ }
+ }
+
+ private void waitForLiveThreads()
+ {
+ for ( int theIndex = 0; theIndex < 5; theIndex ++ )
+ {
+ if ( haveLiveThread() )
+ {
+ try
+ {
+ wait( 1000 );
+ }
+ catch( Exception theException ){}
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ class IdleDetector implements Runnable
+ {
+ public void run()
+ {
+ terminateThreads( true );
+ }
+ }
+}
+
diff --git a/src/com/sun/apoc/daemon/apocd/GarbageCollectEventHandler.java b/src/com/sun/apoc/daemon/apocd/GarbageCollectEventHandler.java
new file mode 100644
index 0000000..8c09ba5
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/GarbageCollectEventHandler.java
@@ -0,0 +1,56 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.transaction.*;
+
+class GarbageCollectEventHandler implements EventHandler
+{
+ private final GarbageCollectTransaction mTransaction;
+
+ GarbageCollectEventHandler( final Database inDatabase )
+ {
+ mTransaction = TransactionFactory
+ .getInstance()
+ .createGarbageCollectTransaction( inDatabase );
+ }
+
+ public void handleEvent( final Messenger inMessenger )
+ {
+ mTransaction.execute();
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/PolicyBackend.java b/src/com/sun/apoc/daemon/apocd/PolicyBackend.java
new file mode 100644
index 0000000..66e8401
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/PolicyBackend.java
@@ -0,0 +1,366 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.spi.*;
+import com.sun.apoc.spi.entities.*;
+import com.sun.apoc.spi.environment.*;
+import com.sun.apoc.spi.policies.*;
+import com.sun.apoc.spi.profiles.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.security.auth.callback.*;
+
+public class PolicyBackend
+{
+ protected static final PolicyInfo[] sPolicyInfoModel= new PolicyInfo[ 0 ];
+ protected static final Policy[] sPolicyModel = new Policy[ 0 ];
+ protected static final Profile[] sProfileModel = new Profile[ 0 ];
+
+ protected Name mName;
+ protected PolicyManager mPolicyMgr;
+ protected Entity mEntity;
+ protected Profile[] mProfiles;
+ private int mRefCount = 0;
+ private Object mLock = new Object();
+ private boolean mProfilesInitialised = false;
+
+ public synchronized int acquire() { return ++ mRefCount; }
+ public synchronized int release() { return -- mRefCount; }
+
+ public PolicyBackend( final Name inName,
+ final Properties inProperties )
+ throws APOCException
+ {
+ mName = inName;
+ try
+ {
+ mPolicyMgr =
+ PolicyBackendFactory
+ .getInstance()
+ .openPolicyMgr( inProperties, mName );
+ }
+ catch( Exception theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public void close()
+ {
+ PolicyBackendFactory.getInstance().closePolicyMgr( mPolicyMgr );
+ }
+
+ public String toString() { return mName.toString() ; }
+
+ public synchronized HashSet getComponentList()
+ throws APOCException
+ {
+ try
+ {
+ initProfiles();
+ HashSet theComponentList = null;
+ if ( mProfiles != null && mProfiles.length > 0 )
+ {
+ theComponentList = new HashSet();
+ for ( int theIndex = 0;
+ theIndex < mProfiles.length;
+ theIndex ++ )
+ {
+ Iterator theIterator = mProfiles[ theIndex ].getPolicies();
+ if ( theIterator != null )
+ {
+ while ( theIterator.hasNext() )
+ {
+ Policy policy = (Policy) theIterator.next() ;
+
+ theComponentList.add(policy.getId()) ;
+ }
+ }
+ }
+ }
+ return theComponentList;
+ }
+ catch( SPIException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public synchronized PolicyInfo[][] getLayeredPolicies(
+ final Set inComponentList,
+ boolean inTimeStampOnly )
+ throws APOCException
+ {
+ try
+ {
+ initProfiles();
+ PolicyInfo[][] thePolicies = null;
+
+ if ( inComponentList != null &&
+ mProfiles != null &&
+ mProfiles.length > 0 )
+ {
+ int theIndex;
+ int theComponentCount = inComponentList.size();
+ if ( theComponentCount > 0 )
+ {
+ final Hashtable theTable =
+ new Hashtable( theComponentCount );
+ final ArrayList theComponentList =
+ new ArrayList( inComponentList );
+ for ( theIndex = 0;
+ theIndex < theComponentCount;
+ ++ theIndex )
+ {
+ theTable.put( theComponentList.get( theIndex ),
+ new ArrayList() );
+ }
+ for ( theIndex = 0;
+ theIndex < mProfiles.length;
+ ++ theIndex )
+ {
+ final Iterator theIterator =
+ inTimeStampOnly ?
+ mProfiles[ theIndex ].getPolicyInfos(
+ inComponentList.iterator() ) :
+ mProfiles[ theIndex ].getPolicies(
+ inComponentList.iterator() );
+ while ( theIterator.hasNext() )
+ {
+ final PolicyInfo thePolicy =
+ ( PolicyInfo )theIterator.next();
+ ( ( ArrayList )theTable.get( thePolicy.getId() ) )
+ .add( thePolicy );
+ }
+ }
+ thePolicies = inTimeStampOnly ?
+ new PolicyInfo[ theComponentCount ][] :
+ new Policy[ theComponentCount ][];
+ for ( theIndex = 0;
+ theIndex < theComponentCount;
+ ++ theIndex )
+ {
+ ArrayList theList =
+ ( ArrayList )theTable.get(
+ theComponentList.get( theIndex ) );
+ theList.trimToSize();
+ if ( theList.size() > 0 )
+ {
+ thePolicies[ theIndex ] =
+ inTimeStampOnly ?
+ ( PolicyInfo[] )theList.
+ toArray( sPolicyInfoModel ) :
+ ( Policy[] )theList.toArray( sPolicyModel );
+ }
+ else
+ {
+ thePolicies[ theIndex ] = null;
+ }
+ }
+ }
+ }
+ return thePolicies;
+ }
+ catch( SPIException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public synchronized Policy[] getLayeredPolicies(
+ final String inComponentName,
+ boolean inTimeStampOnly )
+ throws APOCException
+ {
+ try
+ {
+ Policy[] thePolicies = null;
+
+ if ( inComponentName != null )
+ {
+ if ( mProfiles != null && mProfiles.length > 0 )
+ {
+ ArrayList theList = new ArrayList();
+ for ( int theIndex = 0;
+ theIndex < mProfiles.length;
+ ++ theIndex )
+ {
+ Policy thePolicy = mProfiles[ theIndex ].
+ getPolicy( inComponentName );
+ if ( thePolicy != null )
+ {
+ theList.add( thePolicy );
+ }
+ }
+ theList.trimToSize();
+ if ( theList.size() > 0 )
+ {
+ thePolicies =
+ ( Policy[] )theList.toArray( sPolicyModel );
+ }
+ }
+ }
+ return thePolicies;
+ }
+ catch( SPIException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public Name getName() { return mName; }
+
+ public synchronized void refreshProfiles()
+ throws SPIException
+ {
+ if ( mName.isLocal() )
+ {
+ refreshLocalProfiles();
+ }
+ else
+ {
+ refreshGlobalProfiles();
+ }
+ }
+
+ private Entity findEntity()
+ {
+ Entity theEntity = null;
+
+ try
+ {
+ final Node theRoot =
+ ( Node ) mPolicyMgr.getRootEntity( mName.getEntityType() );
+ final Iterator theIterator =
+ theRoot.findEntities( mName.getEntityName(), true );
+ if ( theIterator != null && theIterator.hasNext() )
+ {
+ theEntity = ( Entity ) theIterator.next();
+ }
+ }
+ catch ( Exception theException ){}
+ return theEntity;
+ }
+
+ private void initProfiles()
+ throws SPIException
+ {
+ // There are two special cases to handle here
+ // 1. Creation of a first ever session for a user.
+ // In this case, we need to write the remote component list to bdb
+ // and we need profiles to figure out the list
+ // 2. Reading a component for the first time
+ // If a component isn't yet in bdb, we'll need the profiles to
+ // get the appropriate layers
+ synchronized( mLock )
+ {
+ if ( ! mProfilesInitialised )
+ {
+ refreshProfiles();
+ mProfilesInitialised = true;
+ }
+ }
+ }
+
+ private void refreshGlobalProfiles()
+ throws SPIException
+ {
+ mProfiles = null;
+ if ( mEntity == null )
+ {
+ mEntity = findEntity();
+ }
+ if ( mEntity != null )
+ {
+ final Iterator theIterator = mEntity.getLayeredProfiles();
+ if ( theIterator != null )
+ {
+ final ArrayList theProfiles = new ArrayList();
+ while ( theIterator.hasNext() )
+ {
+ theProfiles.add( theIterator.next() );
+ }
+ if ( mEntity instanceof User )
+ {
+ final Profile theProfile =
+ ( ( User ) mEntity ).getUserProfile();
+ if ( theProfile != null )
+ {
+ theProfiles.add( theProfile );
+ }
+ }
+ if ( theProfiles.size() > 0 )
+ {
+ mProfiles =
+ ( Profile[] )theProfiles.toArray( sProfileModel );
+ }
+ }
+ }
+ }
+
+ private void refreshLocalProfiles()
+ throws SPIException
+ {
+ mProfiles = null;
+ final ProfileProvider theProvider =
+ mPolicyMgr.getProfileProvider( mName.getEntityType() );
+ final Iterator theIterator = theProvider.getAllProfiles();
+
+ if ( theIterator != null )
+ {
+ final ArrayList theProfiles = new ArrayList();
+ while ( theIterator.hasNext() )
+ {
+ final Profile theProfile = ( Profile )theIterator.next();
+ final Applicability theApp = theProfile.getApplicability();
+ if ( theApp.equals( Applicability.ALL ) ||
+ theApp.equals( mName.getEntityType() ) )
+ {
+ theProfiles.add( theProfile );
+ }
+ }
+ if ( theProfiles.size() > 0 )
+ {
+ mProfiles =
+ ( Profile[] )theProfiles.toArray( sProfileModel );
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/PolicyBackendFactory.java b/src/com/sun/apoc/daemon/apocd/PolicyBackendFactory.java
new file mode 100644
index 0000000..35dddf9
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/PolicyBackendFactory.java
@@ -0,0 +1,235 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+
+import com.sun.apoc.spi.*;
+import com.sun.apoc.spi.entities.*;
+import com.sun.apoc.spi.environment.*;
+import com.sun.apoc.spi.profiles.*;
+
+import java.io.*;
+import java.util.*;
+import javax.security.auth.callback.*;
+
+public class PolicyBackendFactory
+{
+ public static int sTypeHost = 0;
+ public static int sTypeUser = 1;
+ public static final String sLocalHostName = "localHost";
+ public static final String sLocalUserName = "localUsers";
+ public static final Properties sLocalProperties= new Properties();
+
+ private HashMap mPolicyBackends = new HashMap();
+ private HashMap mPolicyMgrs = new HashMap();
+ private static PolicyBackendFactory sInstance;
+ private static final String sLocalPolicyDir =
+ new StringBuffer( "file://" )
+ .append( DaemonConfig.getStringProperty( DaemonConfig.sDataDir ) )
+ .append( "/" )
+ .append( "Policies/" )
+ .toString();
+
+ static
+ {
+ sLocalProperties.setProperty(
+ EnvironmentConstants.URL_KEY, sLocalPolicyDir );
+ String sourcesList =
+ (String) ((Properties) DaemonConfig.getLocalConfig()).get(
+ EnvironmentConstants.SOURCES_KEY) ;
+
+ if (sourcesList != null) {
+ sLocalProperties.setProperty(EnvironmentConstants.SOURCES_KEY,
+ sourcesList);
+ }
+ try
+ {
+ new File (
+ new java.net.URI( sLocalPolicyDir + "/assignments" ) ).mkdirs();
+ new File (
+ new java.net.URI( sLocalPolicyDir + "/profiles" ) ).mkdirs();
+ new File (
+ new java.net.URI(
+ sLocalPolicyDir + "/entities.txt" ) ).createNewFile();
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "PolicyBackendFactory", "init", theException );
+ }
+ }
+
+ public void closePolicyBackend( final PolicyBackend inPolicyBackend )
+ {
+ synchronized( mPolicyBackends )
+ {
+ if ( inPolicyBackend.release() == 0 )
+ {
+ inPolicyBackend.close();
+ mPolicyBackends.remove(
+ createPolicyBackendKey( inPolicyBackend.getName() ) );
+ }
+ }
+ }
+
+ public void closePolicyMgr( final PolicyManager inPolicyMgr )
+ {
+ synchronized( mPolicyMgrs )
+ {
+ final RefCountedPolicyMgr thePolicyMgr =
+ ( RefCountedPolicyMgr )inPolicyMgr;
+ if ( thePolicyMgr.release() == 0 )
+ {
+ try
+ {
+ thePolicyMgr.close();
+ }
+ catch( SPIException theException ){}
+ mPolicyMgrs.remove(
+ createPolicyMgrKey( thePolicyMgr.mName ) );
+ }
+ }
+ }
+
+ public static PolicyBackendFactory getInstance()
+ {
+ if ( sInstance == null )
+ {
+ sInstance = new PolicyBackendFactory();
+ }
+ return sInstance;
+ }
+
+ public PolicyBackend openPolicyBackend(
+ final Name inName,
+ final CallbackHandler inHandler )
+ throws APOCException
+ {
+ final String theKey = createPolicyBackendKey( inName );
+ PolicyBackend theBackend = null;
+ synchronized( mPolicyBackends )
+ {
+ theBackend = ( PolicyBackend )mPolicyBackends.get( theKey );
+ if ( theBackend == null )
+ {
+ final Properties theProperties = inName.isLocal() ?
+ sLocalProperties :
+ ( Properties )(
+ ( Properties )DaemonConfig.getLocalConfig() ).clone();
+ if ( inHandler != null )
+ {
+ theProperties.put( EnvironmentConstants.LDAP_AUTH_CBH,
+ inHandler );
+ }
+ theBackend = new PolicyBackend( inName, theProperties );
+ mPolicyBackends.put( theKey, theBackend );
+ }
+ if ( theBackend != null )
+ {
+ theBackend.acquire();
+ }
+ }
+ return theBackend;
+ }
+
+ public static String [] getSources()
+ {
+ return EnvironmentMgr.getSources( DaemonConfig.getLocalConfig() );
+ }
+
+ public PolicyManager openPolicyMgr( final Properties inProperties,
+ final Name inName )
+ throws APOCException
+ {
+ final String theKey = createPolicyMgrKey( inName );
+ RefCountedPolicyMgr thePolicyMgr = null;
+ synchronized( mPolicyMgrs )
+ {
+ try
+ {
+ thePolicyMgr =
+ ( RefCountedPolicyMgr )mPolicyMgrs.get( theKey );
+ if ( thePolicyMgr == null )
+ {
+ thePolicyMgr =
+ new RefCountedPolicyMgr(
+ inName,
+ inProperties );
+ mPolicyMgrs.put( theKey, thePolicyMgr );
+ }
+ if ( thePolicyMgr != null )
+ {
+ thePolicyMgr.acquire();
+ }
+ }
+ catch( Exception theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+ return thePolicyMgr;
+ }
+
+ private PolicyBackendFactory()
+ {
+ }
+
+ private String createPolicyBackendKey( final Name inName )
+ {
+ return inName.toString();
+ }
+
+ private String createPolicyMgrKey( final Name inName )
+ {
+ return inName.getUserName() + Name.sSep + inName.getLocation();
+ }
+
+ class RefCountedPolicyMgr extends PolicyManager
+ {
+ private int mRefCount = 0;
+ private Name mName;
+
+ RefCountedPolicyMgr( final Name inName,
+ final Hashtable inProperties ) throws SPIException
+ {
+ super( inProperties );
+ mName = inName;
+ }
+
+ int acquire() { return ++ mRefCount; }
+ int release() { return -- mRefCount; }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/SaslAuthCallbackHandler.java b/src/com/sun/apoc/daemon/apocd/SaslAuthCallbackHandler.java
new file mode 100644
index 0000000..f594b25
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/SaslAuthCallbackHandler.java
@@ -0,0 +1,221 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import com.sun.apoc.spi.ldap.authentication.*;
+
+import java.io.IOException;
+import java.nio.*;
+import javax.security.auth.callback.*;
+
+class SaslAuthCallbackHandler implements CallbackHandler
+{
+ private Messenger mMessenger = new Messenger();
+ private ClientChannel mChannel;
+ private ByteBuffer mBuffer;
+ private boolean mReconnectMode = false;
+
+ SaslAuthCallbackHandler( final Client inClient )
+ throws APOCException
+ {
+ mChannel = inClient.getClientChannel();
+ mMessenger.setClientChannel( mChannel );
+ }
+
+ public void handle( Callback[] inCallbacks )
+ throws IOException, UnsupportedCallbackException
+ {
+ final LdapSaslGSSAPICallback theCallback =
+ ( LdapSaslGSSAPICallback )inCallbacks[ 0 ];
+ if ( mBuffer == null )
+ {
+ createTokens( theCallback );
+ }
+ theCallback.setResponse( getToken() );
+ }
+
+ public void setReconnectMode() { mReconnectMode = true; }
+
+ private void createTokens( final LdapSaslGSSAPICallback inCallback )
+ {
+ try
+ {
+ if ( mReconnectMode )
+ {
+ mChannel.registerForSelection( false );
+ }
+ mMessenger.sendResponse(
+ MessageFactory.createResponse(
+ APOCSymbols.sSymRespSuccessContinueSASLAuth,
+ null,
+ new StringBuffer( inCallback.getServiceName() )
+ .append( "/" )
+ .append( inCallback.getHostname() )
+ .toString() ),
+ false );
+ final CredentialsProviderMessage theMessage =
+ ( CredentialsProviderMessage )mMessenger.receiveRequest(
+ ! mReconnectMode );
+
+ if ( theMessage != null )
+ {
+ final String theCreds = theMessage.getCredentials();
+ if ( theCreds != null )
+ {
+ mBuffer =
+ ByteBuffer.wrap(
+ base64ToByteArray( theCreds.toCharArray() ) );
+ }
+ }
+ if ( mReconnectMode )
+ {
+ mMessenger.sendResponse(
+ MessageFactory.createResponse(
+ APOCSymbols.sSymRespSuccess, null, null ),
+ true );
+ }
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "SaslAuthCallbackHandler",
+ "createTokens",
+ theException );
+ }
+ }
+
+ private byte[] getToken()
+ {
+ byte[] theToken = null;
+ if ( mBuffer != null && mBuffer.hasRemaining() )
+ {
+ int theTokenSize = nextTokenSize();
+ if ( theTokenSize > 0 )
+ {
+ theToken = new byte[ theTokenSize ];
+ mBuffer = mBuffer.get( theToken );
+ }
+ if ( ! mBuffer.hasRemaining() )
+ {
+ mBuffer = null;
+ }
+ }
+ return theToken;
+ }
+
+ private int nextTokenSize()
+ {
+ int theTokenSize = 0;
+ try
+ {
+ if ( mBuffer.hasRemaining() )
+ {
+ final byte[] theTokenSizeBytes = new byte[ 5 ];
+ mBuffer = mBuffer.get( theTokenSizeBytes );
+ theTokenSize =
+ Integer.parseInt( new String( theTokenSizeBytes ) );
+ }
+ }
+ catch( Exception theException )
+ {}
+ return theTokenSize;
+ }
+
+ // Code borrowed from java.util.prefs.Base64
+ private static final byte base64ToInt[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+ };
+
+ private byte[] base64ToByteArray(char[] encoded) {
+ byte[] alphaToInt = base64ToInt;
+ int encodedLen = encoded.length;
+ int numGroups = encodedLen/4;
+ if (4*numGroups != encodedLen)
+ throw new IllegalArgumentException(
+ "String length must be a multiple of four.");
+ int missingBytesInLastGroup = 0;
+ int numFullGroups = numGroups;
+ if (encodedLen != 0) {
+ if (encoded[encodedLen-1] == '=') {
+ missingBytesInLastGroup++;
+ numFullGroups--;
+ }
+ if (encoded[encodedLen-2] == '=')
+ missingBytesInLastGroup++;
+ }
+ byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
+
+ // Translate all full groups from base64 to byte array elements
+ int inCursor = 0, outCursor = 0;
+ for (int i=0; i<numFullGroups; i++) {
+ int ch0 = base64toInt(encoded[inCursor++], alphaToInt);
+ int ch1 = base64toInt(encoded[inCursor++], alphaToInt);
+ int ch2 = base64toInt(encoded[inCursor++], alphaToInt);
+ int ch3 = base64toInt(encoded[inCursor++], alphaToInt);
+ result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
+ result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
+ result[outCursor++] = (byte) ((ch2 << 6) | ch3);
+ }
+
+ // Translate partial group, if present
+ if (missingBytesInLastGroup != 0) {
+ int ch0 = base64toInt(encoded[inCursor++], alphaToInt);
+ int ch1 = base64toInt(encoded[inCursor++], alphaToInt);
+ result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
+
+ if (missingBytesInLastGroup == 1) {
+ int ch2 = base64toInt(encoded[inCursor++], alphaToInt);
+ result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
+ }
+ }
+ return result;
+ }
+
+ private int base64toInt(char c, byte[] alphaToInt) {
+ int result = alphaToInt[c];
+ if (result < 0)
+ throw new IllegalArgumentException("Illegal character " + c);
+ return result;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/Session.java b/src/com/sun/apoc/daemon/apocd/Session.java
new file mode 100644
index 0000000..44d2416
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/Session.java
@@ -0,0 +1,335 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+import com.sun.apoc.daemon.config.DaemonConfig;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import com.sun.apoc.spi.entities.*;
+import com.sun.apoc.spi.environment.*;
+
+import java.io.*;
+import java.nio.*;
+import java.net.*;
+import java.util.*;
+import java.util.logging.*;
+
+
+public class Session
+{
+ private Client mClient;
+ private String mSessionId;
+ private HashMap mListeners = new HashMap();
+ private Cache[] mCaches;
+ private Object mLock = new Object();
+ private Hashtable mEntities = null ;
+
+ private static final String sSep = ".";
+ private static final Random sRandom = new Random();
+ private static int sAuthBufferSize = 20;
+ private static int sCantLock = 0;
+ private static int sUnlocked = 1;
+ private static int sLocked = 2;
+ private int mState = sUnlocked;
+
+ Session() {}
+
+ public Session( final Client inClient,
+ final String inUserId,
+ String inEntityName )
+ throws APOCException
+ {
+ Hashtable theEntities = new Hashtable();
+
+ if (inEntityName == null) { inEntityName = inUserId ; }
+ theEntities.put( EnvironmentConstants.USER_SOURCE, inEntityName );
+ initialise( inClient, inUserId, theEntities );
+ }
+ public Session( final Client inClient,
+ final String inUserId,
+ final Hashtable inEntities)
+ throws APOCException
+ {
+ initialise( inClient, inUserId, inEntities );
+ }
+ private void initialise( final Client inClient,
+ final String inUserId,
+ Hashtable inoutEntities) throws APOCException {
+ APOCLogger.finer( "Sess001" );
+ try
+ {
+ authenticate( inClient, inUserId );
+ mClient = inClient;
+ mSessionId = String.valueOf ( sRandom.nextLong() );
+ if (!inoutEntities.containsKey(EnvironmentConstants.HOST_SOURCE)) {
+ String hostName = DaemonConfig.getHostIdentifier() ;
+
+ if (hostName != null) {
+ inoutEntities.put(EnvironmentConstants.HOST_SOURCE,
+ hostName) ;
+ }
+ }
+ mEntities = inoutEntities ;
+ mCaches = CacheFactory
+ .getInstance()
+ .openCaches(
+ inUserId,
+ mEntities,
+ this,
+ new SaslAuthCallbackHandler( mClient ) );
+ }
+ catch( APOCException theException )
+ {
+ close();
+ throw theException;
+ }
+ APOCLogger.finer( "Sess002", toString( inUserId ) );
+ }
+
+ public Cache[] getCaches() { return mCaches; }
+ public Client getClient() { return mClient; }
+ public String getSessionId() { return mSessionId; }
+
+ public void addListeners( final Vector inComponentNames,
+ final String inClientData )
+ {
+ synchronized( mListeners )
+ {
+ for ( int theIndex = 0;
+ theIndex < inComponentNames.size();
+ ++theIndex )
+ {
+ mListeners.put( inComponentNames.elementAt( theIndex ),
+ inClientData );
+ }
+ }
+ }
+
+ public void removeListeners( final Vector inComponentNames )
+ {
+ synchronized( mListeners )
+ {
+ for ( int theIndex = 0;
+ theIndex < inComponentNames.size();
+ ++ theIndex )
+ {
+ mListeners.remove( inComponentNames.elementAt( theIndex ) );
+ }
+ }
+ }
+
+ public void close()
+ {
+ synchronized( mLock )
+ {
+ if ( mState == sLocked )
+ {
+ try
+ {
+ mLock.wait();
+ }
+ catch( Exception e )
+ {}
+ }
+ mState = sCantLock;
+ mLock.notify();
+ }
+ if ( mCaches != null )
+ {
+ CacheFactory.getInstance().closeCaches( mCaches, this );
+ mCaches = null;
+ }
+ if ( mSessionId != null )
+ {
+ APOCLogger.finer( "Sess003", mSessionId );
+ }
+ }
+
+ public String getListenerClientData( final String inComponentName )
+ {
+ return ( String )mListeners.get( inComponentName );
+ }
+
+ public String getListenerComponentName( final String inComponentName )
+ {
+ synchronized( mListeners )
+ {
+ String theComponentName =
+ mListeners.containsKey( inComponentName ) ? inComponentName :
+ null;
+ if ( theComponentName == null )
+ {
+ final StringTokenizer theTokenizer =
+ new StringTokenizer( inComponentName, sSep );
+ final StringBuffer theBuffer = new StringBuffer();
+ int theCount = theTokenizer.countTokens();
+ for ( int theIndex = 0; theIndex < theCount - 1 ; theIndex ++ )
+ {
+ final String theContainerName =
+ theBuffer.append( theTokenizer.nextToken() )
+ .append( sSep )
+ .toString();
+ if ( mListeners.containsKey( theContainerName ) )
+ {
+ theComponentName = theContainerName;
+ break;
+ }
+ }
+ }
+ return theComponentName;
+ }
+ }
+
+ //
+ // lock() & unlock() are provided to support the case where a
+ // change detection transaction and a destroy session transaction are
+ // happening at the same time. lock() will allow a change detection to
+ // continue using the session until it's complete without fear of the
+ // session being closed. Once complete, the change detection transaction
+ // will unlock the session, allowing it to be destroyed.
+ //
+ public boolean lock()
+ {
+ boolean isLocked = false;
+ synchronized( mLock )
+ {
+ if ( mState == sUnlocked )
+ {
+ mState = sLocked;
+ isLocked = true;
+ }
+ }
+ return isLocked;
+ }
+
+ public void unlock()
+ {
+ synchronized( mLock )
+ {
+ mState = sUnlocked;
+ mLock.notify();
+ }
+ }
+
+ public void sendNotification(UpdateItem aUpdate) {
+ String component = aUpdate.getComponentName() ;
+ String listenerComponent = getListenerComponentName(component) ;
+
+ if (listenerComponent == null) { return ; }
+ int notificationType = -1 ;
+ StringBuffer logMessage = new StringBuffer(" sessionId = ")
+ .append(mSessionId).append("\n")
+ .append(" component name = ")
+ .append(component).append("\n")
+ .append(" type = ") ;
+
+ switch (aUpdate.getUpdateType()) {
+ case UpdateItem.ADD:
+ notificationType = APOCSymbols.sSymAddNotification ;
+ logMessage.append("Add") ;
+ break ;
+ case UpdateItem.REMOVE:
+ notificationType = APOCSymbols.sSymRemoveNotification ;
+ logMessage.append("Remove") ;
+ break ;
+ case UpdateItem.MODIFY:
+ notificationType = APOCSymbols.sSymModifyNotification ;
+ logMessage.append("Modify") ;
+ break ;
+ default:
+ notificationType = -1 ;
+ logMessage.append("Unknown") ;
+ break ;
+ }
+ APOCLogger.finer("Cdtn003", logMessage.toString()) ;
+ final Notification notification =
+ (Notification) MessageFactory.createNotification(mSessionId,
+ notificationType) ;
+
+ notification.setComponentName(component) ;
+ notification.setClientData(getListenerClientData(listenerComponent)) ;
+ mClient.getClientChannel().write(notification.serialise()) ;
+ }
+
+ private void authenticate( final Client inClient,
+ final String inUserId )
+ throws APOCException
+ {
+ APOCAuthenticator theAuthenticator = null;
+ try
+ {
+ theAuthenticator = new APOCAuthenticator( inUserId );
+ final Messenger theMessenger = new Messenger();
+ theMessenger.setClientChannel( inClient.getClientChannel() );
+ theMessenger.sendResponse(
+ MessageFactory.createResponse(
+ APOCSymbols.sSymRespSuccessContinueLocalAuth,
+ null,
+ new String( theAuthenticator.getChallenge() ) ),
+ false );
+ final CredentialsProviderMessage theMessage =
+ ( CredentialsProviderMessage )theMessenger.receiveRequest();
+ theAuthenticator.processResponse(
+ theMessage.getCredentials().getBytes() );
+ }
+ finally
+ {
+ if ( theAuthenticator != null )
+ {
+ theAuthenticator.cleanup();
+ }
+ }
+ }
+
+ private String toString( final String inUserId )
+ {
+ StringBuffer theMessage = new StringBuffer()
+ .append( " userId = " )
+ .append( inUserId )
+ .append( "\n" )
+
+ .append( " sessionId = ")
+ .append( mSessionId )
+ .append( "\n" );
+ for ( int theIndex = 0 ; theIndex < mCaches.length ; ++ theIndex )
+ {
+ theMessage.append( mCaches[ theIndex ].toString() ).append( "\n ");
+ }
+ return theMessage.toString();
+ }
+}
diff --git a/src/com/sun/apoc/daemon/apocd/SessionListener.java b/src/com/sun/apoc/daemon/apocd/SessionListener.java
new file mode 100644
index 0000000..3648b92
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/SessionListener.java
@@ -0,0 +1,42 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd;
+
+public interface SessionListener
+{
+ void onSessionCreate( final Session inSession );
+
+ void onSessionDestroy( final Session inSession );
+}
diff --git a/src/com/sun/apoc/daemon/apocd/UpdateAggregator.java b/src/com/sun/apoc/daemon/apocd/UpdateAggregator.java
new file mode 100644
index 0000000..a51b058
--- /dev/null
+++ b/src/com/sun/apoc/daemon/apocd/UpdateAggregator.java
@@ -0,0 +1,92 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.apocd ;
+
+import com.sun.apoc.daemon.localdatabase.UpdateItem ;
+
+import java.util.ArrayList ;
+import java.util.HashMap ;
+import java.util.Iterator ;
+import java.util.Map ;
+
+public class UpdateAggregator {
+ // Key = session, value = updates
+ private Map mUpdates = new HashMap() ;
+
+ public synchronized void addUpdate(Session [] aSessions,
+ UpdateItem aUpdate) {
+ for (int i = 0 ; i < aSessions.length ; ++ i) {
+ Session session = aSessions [i] ;
+
+ if (!mUpdates.containsKey(session)) {
+ ArrayList updateList = new ArrayList() ;
+
+ updateList.add(aUpdate) ;
+ mUpdates.put(session, updateList) ;
+ }
+ else {
+ ArrayList updateList = (ArrayList) mUpdates.get(session) ;
+
+ for (int j = 0 ; j < updateList.size() ; ++ j) {
+ UpdateItem update = (UpdateItem) updateList.get(j) ;
+
+ if (update.getComponentName().equals(
+ aUpdate.getComponentName())) {
+ if (update.getUpdateType() != aUpdate.getUpdateType()) {
+ update.setUpdateType(UpdateItem.MODIFY) ;
+ }
+ return ;
+ }
+ }
+ updateList.add(aUpdate) ;
+ }
+ }
+ }
+ public void sendNotifications() {
+ Iterator updates = mUpdates.entrySet().iterator() ;
+
+ while (updates.hasNext()) {
+ Map.Entry update = (Map.Entry) updates.next();
+ Session session = (Session) update.getKey() ;
+ ArrayList updateList = (ArrayList) update.getValue() ;
+ int nbUpdates = updateList.size() ;
+
+ for (int i = 0 ; i < nbUpdates ; ++ i) {
+ session.sendNotification((UpdateItem) updateList.get(i)) ;
+ }
+ }
+ }
+}
+
diff --git a/src/com/sun/apoc/daemon/build.xml.in b/src/com/sun/apoc/daemon/build.xml.in
new file mode 100644
index 0000000..0ddc898
--- /dev/null
+++ b/src/com/sun/apoc/daemon/build.xml.in
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+#*************************************************************************
+#*
+#* $RCSfile: build.xml,v $
+#*
+#* Creation date cas 12 February, 2002
+#* last change $Author: cm122549 $ $Date: 2006/11/27 15:42:26 $
+#* $Revision: 1.4 $
+#*
+#* Copyright 2003, Sun Microsystems, Inc. All Rights Reserved.
+#*
+#*************************************************************************
+-->
+<project name="ap_policy" default="main" basedir="../../../../../">
+
+ <property name="jarname" value="apocd.jar"/>
+ <property name="package" value="com/sun/apoc/daemon"/>
+ <property name="build.dir" value="build"/>
+ <property name="build.class" value="build/class"/>
+ <property name="build.inc" value="build/inc"/>
+
+ <target name="info">
+ <echo message="-------------------------------"/>
+ <echo message="| APOC Daemon |"/>
+ <echo message="-------------------------------"/>
+ </target>
+
+ <path id="classpath">
+ <pathelement location="@SPIJDK@"/>
+ <pathelement location="@BDBJDK@"/>
+ </path>
+
+ <target name="prepare">
+ <mkdir dir="${build.dir}"/>
+ <mkdir dir="${build.class}"/>
+ </target>
+
+ <target name="compile" depends="prepare">
+ <javac srcdir="src"
+ destdir="${build.class}"
+ optimize="${optimize}"
+ debug="${debug}"
+ classpathref="classpath">
+ <include name="${package}/**/*.java"/>
+ </javac>
+ </target>
+
+ <target name="jar" depends="compile">
+ <condition property="dataDir" value="@APOC_DATADIR@">
+ <os name="SunOS"/>
+ </condition>
+ <condition property="dataDir" value="@APOC_DATADIR@">
+ <os name="Linux"/>
+ </condition>
+ <condition property="dataDir" value="\\Documents and Settings\\All Users\\Application Data\\apoc">
+ <os family="Windows"/>
+ </condition>
+
+ <copy file="src/${package}/properties/defaults.properties"
+ tofile="${build.class}/${package}/defaults.properties"/>
+ <copy file="src/${package}/properties/os.properties" filtering="true"
+ tofile="${build.class}/${package}/os.properties">
+ <filterset>
+ <filter token="DataDir" value="${dataDir}"/>
+ </filterset>
+ </copy>
+ <copy file="src/${package}/properties/daemon.properties"
+ tofile="${build.class}/com/sun/apoc/daemon.properties"/>
+
+ <jar jarfile="${build.class}/${jarname}"
+ basedir="${build.class}"
+ includes="${package}/** ${package}/defaults.properties ${package}/os.properties com/sun/apoc/daemon.properties">
+ <manifest>
+ <attribute name="Class-Path" value="@SPIJDK@ @BDBJDK@"/>
+ </manifest>
+ </jar>
+ </target>
+
+ <target name="main" depends="info, jar"/>
+
+ <target name="clean" depends="info">
+ <delete file="${build.class}/${jarname}"/>
+ <delete dir="${build.class}/${package}"/>
+ </target>
+
+</project>
diff --git a/src/com/sun/apoc/daemon/config/ConfigEventListener.java b/src/com/sun/apoc/daemon/config/ConfigEventListener.java
new file mode 100644
index 0000000..52e31fb
--- /dev/null
+++ b/src/com/sun/apoc/daemon/config/ConfigEventListener.java
@@ -0,0 +1,40 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.config;
+
+public interface ConfigEventListener
+{
+ public void onConfigEvent();
+}
diff --git a/src/com/sun/apoc/daemon/config/DaemonConfig.java b/src/com/sun/apoc/daemon/config/DaemonConfig.java
new file mode 100644
index 0000000..639d712
--- /dev/null
+++ b/src/com/sun/apoc/daemon/config/DaemonConfig.java
@@ -0,0 +1,418 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.config;
+
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.spi.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.logging.*;
+import java.util.zip.*;
+
+public class DaemonConfig implements ConfigEventListener
+{
+ // Public bootstrap properties
+ public static final String sDaemonPort = "DaemonPort";
+ public static final String sDataDir = "DataDir";
+
+ // Non bootstrap
+ public static final String sMaxClientThreads =
+ "MaxClientThreads";
+ public static final String sMaxClientConnections =
+ "MaxClientConnections";
+ public static final String sMaxRequestSize =
+ "MaxRequestSize";
+ public static final String sConfigCDInterval =
+ "DaemonChangeDetectionInterval";
+ public static final String sChangeDetectionInterval =
+ "ChangeDetectionInterval";
+ public static final String sGarbageCollectionInterval =
+ "GarbageCollectionInterval";
+ public static final String sTimeToLive =
+ "TimeToLive";
+ public static final String sLogLevel =
+ "LogLevel";
+ public static final String sIdleThreadDetectionInterval =
+ "IdleThreadDetectionInterval";
+ public static final String sThreadTimeToLive =
+ "ThreadTimeToLive";
+ public static final String sConnectionReadTimeout =
+ "ConnectionReadTimeout";
+ public static final String sInitialChangeDetectionDelay =
+ "InitialChangeDetectionDelay";
+ public static final String sApplyLocalPolicy =
+ "ApplyLocalPolicy";
+ public static final String sMaxDbLocks =
+ "MaxDatabaseLocks";
+ private static DaemonConfig sInstance;
+
+ private static final String sAPOCJarFile = "apocd.jar";
+ private static final String sDefaultsPropertiesFile = "defaults.properties";
+ public static final String sOSPropertiesFile = "os.properties";
+ public static final String sApocPropertiesFile = "apocd.properties";
+ public static final String sJProxyPropertiesFile = "policymgr.properties";
+ private static final String[] sLocalPropertiesFiles =
+ { sOSPropertiesFile, sApocPropertiesFile, sJProxyPropertiesFile };
+ private static String sDaemonInstallDir;
+ private static String sDaemonPropertiesDir;
+
+ private Properties mDefaultProperties;
+ private RemoteConfig mRemoteConfig;
+ private LocalConfig mLocalConfig;
+ private final HashSet mConfigEventListeners = new HashSet();
+ private String mHostIdentifier;
+ private final DaemonTimerTask mConfigLoader =
+ new DaemonTimerTask( new ConfigLoader() );
+
+ public static void addConfigEventListener(
+ final ConfigEventListener inConfigListener )
+ {
+ synchronized( sInstance.mConfigEventListeners )
+ {
+ sInstance.mConfigEventListeners.add( inConfigListener );
+ }
+ }
+
+ static public String getHostIdentifier()
+ {
+ return sInstance.mHostIdentifier;
+ }
+
+ public static DaemonConfig getInstance()
+ {
+ return sInstance;
+ }
+
+ public static boolean getBooleanProperty( final String inPropertyName )
+ {
+ return getBooleanProperty( inPropertyName, null );
+ }
+
+ public static boolean getBooleanProperty( final String inPropertyName,
+ final String inDefaultValue )
+ {
+ return Boolean.valueOf(
+ getStringProperty( inPropertyName, inDefaultValue ).trim() ).
+ booleanValue();
+ }
+
+ public static float getFloatProperty( final String inPropertyName )
+ {
+ return getFloatProperty( inPropertyName, null );
+ }
+
+ public static float getFloatProperty( final String inPropertyName,
+ final String inDefaultValue )
+ {
+ return Float.parseFloat(
+ getStringProperty( inPropertyName, inDefaultValue ).trim() );
+ }
+
+ public static int getIntProperty( final String inPropertyName )
+ {
+ return getIntProperty( inPropertyName, null );
+ }
+
+ public static int getIntProperty( final String inPropertyName,
+ final String inDefaultValue )
+ {
+ return Integer.parseInt(
+ getStringProperty( inPropertyName, inDefaultValue ).trim() );
+ }
+
+ public static LocalConfig getLocalConfig()
+ {
+ return sInstance.mLocalConfig;
+ }
+
+ public static String getStringProperty( final String inPropertyName )
+ {
+ return getStringProperty( inPropertyName, null );
+ }
+
+ public static String getStringProperty( final String inPropertyName,
+ final String inDefaultValue )
+ {
+ return sInstance.mLocalConfig.getProperty( inPropertyName,
+ inDefaultValue );
+ }
+
+ public static void init( final String[] inArgs )
+ throws IOException, APOCException
+ {
+ sInstance = new DaemonConfig( inArgs );
+ reload();
+ addConfigEventListener( sInstance );
+ sInstance.pollForChanges();
+ }
+
+ public static void log()
+ {
+ if ( APOCLogger.isLoggable( Level.CONFIG ) &&
+ sInstance != null &&
+ sInstance.mLocalConfig != null )
+ {
+ final StringBuffer theBuffer = new StringBuffer( "" );
+ final Enumeration theEnumeration =
+ sInstance.mLocalConfig.propertyNames();
+ while ( theEnumeration.hasMoreElements() )
+ {
+ final String theName = ( String )theEnumeration.nextElement();
+ theBuffer.append( " " )
+ .append( theName )
+ .append( " = " )
+ .append(
+ theName.compareTo( "Password" ) == 0 ?
+ obscure(
+ DaemonConfig.getStringProperty( theName ) ):
+ DaemonConfig.getStringProperty( theName ) )
+ .append( "\n" );
+ }
+ APOCLogger.config( "Dcfg001", theBuffer.toString() );
+ }
+ }
+
+ public void onConfigEvent()
+ {
+ pollForChanges();
+ }
+
+ public static void reload()
+ throws IOException
+ {
+ reload( false );
+ }
+
+ public static void reload( boolean inRemoteOnly )
+ throws IOException
+ {
+ final Set theOriginalValues = sInstance.getAllValues();
+ if ( ! inRemoteOnly )
+ {
+ sInstance.mLocalConfig.load( sLocalPropertiesFiles );
+ sInstance.setHostIdentifier();
+ }
+ sInstance.mRemoteConfig.load();
+ if ( ! sInstance.getAllValues().equals( theOriginalValues ) )
+ {
+ sInstance.configLoaded();
+ }
+ }
+
+ public static void removeConfigEventListener(
+ final ConfigEventListener inConfigListener)
+ {
+ synchronized( sInstance.mConfigEventListeners )
+ {
+ sInstance.mConfigEventListeners.remove( inConfigListener );
+ }
+ }
+
+ private DaemonConfig( final String[] inArgs )
+ throws IOException
+ {
+ sDaemonInstallDir = inArgs[ 0 ];
+ sDaemonPropertiesDir = inArgs[ 1 ];
+ createDefaults();
+ mLocalConfig = new LocalConfig( sDaemonPropertiesDir );
+ mRemoteConfig = new RemoteConfig();
+ mLocalConfig.setDefaults( mRemoteConfig );
+ mRemoteConfig.setDefaults( mDefaultProperties );
+ }
+
+ private void configLoaded()
+ {
+ Object[] theConfigEventListeners;
+ synchronized( mConfigEventListeners )
+ {
+ theConfigEventListeners = mConfigEventListeners.toArray();
+ }
+ if ( theConfigEventListeners != null )
+ {
+ for ( int theIndex = 0;
+ theIndex < theConfigEventListeners.length;
+ ++ theIndex )
+ {
+ ( ( ConfigEventListener )theConfigEventListeners[ theIndex ] )
+ .onConfigEvent();
+ }
+ }
+ }
+
+ private void createDefaults()
+ throws IOException
+ {
+ ZipFile theZipFile =
+ new ZipFile(
+ new StringBuffer( sDaemonInstallDir )
+ .append( File.separatorChar )
+ .append( sAPOCJarFile )
+ .toString() );
+
+ String thePath = new String( "com/sun/apoc/daemon/" );
+
+ mDefaultProperties = new Properties();
+ mDefaultProperties.load(
+ theZipFile.getInputStream(
+ theZipFile.getEntry(
+ new StringBuffer( thePath )
+ .append( sDefaultsPropertiesFile )
+ .toString() ) ) );
+
+ mDefaultProperties.load(
+ theZipFile.getInputStream(
+ theZipFile.getEntry(
+ new StringBuffer( thePath )
+ .append( sOSPropertiesFile )
+ .toString() ) ) );
+ }
+
+ private Set getAllValues()
+ {
+ final HashSet theSet = new HashSet();
+ if ( mLocalConfig != null )
+ {
+ final Enumeration theEnumeration = mLocalConfig.propertyNames();
+ while ( theEnumeration.hasMoreElements() )
+ {
+ theSet.add(
+ mLocalConfig.getProperty(
+ ( String )theEnumeration.nextElement() ) );
+ }
+ }
+ return theSet;
+ }
+
+ /**
+ * Check if the address can be used to identify the machine from
+ * an external point of view. For the moment limited to checking
+ * that it's not the loopback address.
+ */
+ private static boolean isAcceptableAddress(InetAddress inAddress) {
+ return !inAddress.isLoopbackAddress() ;
+ }
+
+ private String guessHostIdentifer()
+ {
+ String theHostIdentifier = null;
+ try
+ {
+ Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
+ if ( theInterfaces != null )
+ {
+ while ( theInterfaces.hasMoreElements() )
+ {
+ NetworkInterface theInterface =
+ ( NetworkInterface )theInterfaces.nextElement();
+ Enumeration theInetAddresses=
+ theInterface.getInetAddresses();
+ if ( theInetAddresses != null )
+ {
+ while ( theInetAddresses.hasMoreElements() )
+ {
+ InetAddress theAddress =
+ ( InetAddress )theInetAddresses.nextElement();
+ if (isAcceptableAddress(theAddress))
+ {
+ theHostIdentifier = theAddress.getHostAddress();
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( Exception theException ){}
+ return theHostIdentifier;
+ }
+
+ private static String obscure( final String inString )
+ {
+ String theString = null;
+ if ( inString != null )
+ {
+ theString = inString.replaceAll( "\\p{Alnum}", "*" );
+ }
+ return theString;
+ }
+
+ private void pollForChanges()
+ {
+ mConfigLoader.setPeriod( 60000 * getIntProperty( sConfigCDInterval ) );
+ }
+
+ private void setHostIdentifier()
+ {
+ try
+ {
+ if ( mLocalConfig.getProperty( "HostIdentifierType", "Hostname" )
+ .compareTo( "IPAddress" ) == 0 )
+ {
+ InetAddress theLocalHost = InetAddress.getLocalHost() ;
+ if (isAcceptableAddress(theLocalHost))
+ {
+ mHostIdentifier = theLocalHost.getHostAddress() ;
+ }
+ else
+ {
+ mHostIdentifier = guessHostIdentifer();
+ }
+ }
+ else
+ {
+ mHostIdentifier = InetAddress.getLocalHost().getHostName();
+ }
+ }
+ catch( UnknownHostException theException )
+ {
+ mHostIdentifier = null;
+ }
+ }
+
+ class ConfigLoader implements Runnable
+ {
+ public void run()
+ {
+ try
+ {
+ sInstance.reload( true );
+ }
+ catch( IOException theException )
+ {}
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/config/LocalConfig.java b/src/com/sun/apoc/daemon/config/LocalConfig.java
new file mode 100644
index 0000000..26c8e65
--- /dev/null
+++ b/src/com/sun/apoc/daemon/config/LocalConfig.java
@@ -0,0 +1,79 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.config;
+
+import java.io.*;
+import java.util.*;
+
+class LocalConfig extends Properties
+{
+ private String mPropertiesDir;
+
+ public LocalConfig( final String inPropertiesDir )
+ {
+ super();
+ mPropertiesDir =
+ new StringBuffer( inPropertiesDir )
+ .append( File.separatorChar )
+ .toString();
+ }
+
+ public void load ( final String[] inFileNames )
+ {
+ clear();
+ for ( int theIndex = 0; theIndex < inFileNames.length; theIndex ++ )
+ {
+ load( inFileNames[ theIndex ] );
+ }
+ }
+
+ public void setDefaults( final Properties inDefaults )
+ {
+ defaults = inDefaults;
+ }
+
+ private void load( final String inFileName )
+ {
+ try
+ {
+ load(
+ new FileInputStream(
+ new StringBuffer( mPropertiesDir )
+ .append( inFileName )
+ .toString() ) );
+ }
+ catch( IOException theException ) {}
+ }
+}
diff --git a/src/com/sun/apoc/daemon/config/RemoteConfig.java b/src/com/sun/apoc/daemon/config/RemoteConfig.java
new file mode 100644
index 0000000..b3935f9
--- /dev/null
+++ b/src/com/sun/apoc/daemon/config/RemoteConfig.java
@@ -0,0 +1,198 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.config;
+
+import com.sun.apoc.daemon.misc.*;
+
+import com.sun.apoc.spi.*;
+import com.sun.apoc.spi.cfgtree.*;
+import com.sun.apoc.spi.cfgtree.property.*;
+import com.sun.apoc.spi.cfgtree.policynode.*;
+import com.sun.apoc.spi.cfgtree.readwrite.*;
+import com.sun.apoc.spi.entities.*;
+import com.sun.apoc.spi.environment.*;
+import com.sun.apoc.spi.policies.*;
+import com.sun.apoc.spi.profiles.*;
+
+import java.util.*;
+
+class RemoteConfig extends Properties
+{
+ private static final String sParentNodeName = "com.sun.apoc.apocd";
+
+ public void load()
+ {
+ clear();
+ PolicyManager thePolicyMgr = null;
+ try
+ {
+ final Properties theProperties =
+ ( Properties )DaemonConfig.getLocalConfig().clone();
+ theProperties.put( EnvironmentConstants.LDAP_AUTH_TYPE_KEY,
+ EnvironmentConstants.LDAP_AUTH_TYPE_ANONYMOUS );
+ thePolicyMgr = new PolicyManager( theProperties );
+ load( thePolicyMgr );
+ }
+ catch ( Exception theException )
+ {}
+ finally
+ {
+ if ( thePolicyMgr != null )
+ {
+ try
+ {
+ thePolicyMgr.close();
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "RemoteConfig", "load", theException );
+ }
+ }
+ }
+ }
+
+ public void setDefaults( final Properties inProperties )
+ {
+ defaults = inProperties;
+ }
+
+ private String getPropertyValue( final PolicyNode inParentNode,
+ final String inPropertyName )
+ {
+ String theValue = null;
+ if ( inParentNode != null )
+ {
+ final Property theProperty =
+ inParentNode.getProperty( inPropertyName );
+ if ( theProperty != null )
+ {
+ try
+ {
+ theValue = theProperty.getValue();
+ }
+ catch( SPIException theException ){}
+ }
+ }
+ return theValue;
+ }
+
+ private void load( final PolicyManager inPolicyMgr )
+ throws SPIException
+ {
+ final Entity theDomain =
+ inPolicyMgr.getRootEntity( EnvironmentConstants.HOST_SOURCE );
+ final Iterator theIterator = ((Domain) theDomain).findEntities(
+ DaemonConfig.getHostIdentifier(),
+ true );
+ if ( theIterator != null && theIterator.hasNext() )
+ {
+ final Entity theEntity = ( Entity )theIterator.next();
+ final Iterator theProfiles = theEntity.getLayeredProfiles();
+ if ( theProfiles != null )
+ {
+ final ArrayList thePolicies = new ArrayList();
+ while ( theProfiles.hasNext() )
+ {
+ final Profile theProfile = ( Profile )theProfiles.next();
+ final Policy thePolicy =
+ theProfile.getPolicy( sParentNodeName);
+ if ( thePolicy != null )
+ {
+ thePolicies.add( thePolicy );
+ }
+ }
+ if ( thePolicies.size() > 0 )
+ {
+ final PolicyTree theTree =
+ new ReadWritePolicyTreeFactoryImpl()
+ .getPolicyTree( thePolicies.iterator() );
+ if ( theTree != null )
+ {
+ final PolicyNode theParentNode =
+ theTree.getNode( sParentNodeName );
+ if ( theParentNode != null )
+ {
+ setProp( DaemonConfig.sMaxClientThreads,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sMaxClientThreads ) );
+ setProp( DaemonConfig.sMaxClientConnections,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sMaxClientConnections ) );
+ setProp( DaemonConfig.sMaxRequestSize,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sMaxRequestSize ) );
+ setProp( DaemonConfig.sConfigCDInterval,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sConfigCDInterval ) );
+ setProp( DaemonConfig.sChangeDetectionInterval,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sChangeDetectionInterval ) );
+ setProp( DaemonConfig.sGarbageCollectionInterval,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sGarbageCollectionInterval ) );
+ setProp( DaemonConfig.sTimeToLive,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sTimeToLive ) );
+ setProp( DaemonConfig.sLogLevel,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sLogLevel ) );
+ setProp( DaemonConfig.sApplyLocalPolicy,
+ getPropertyValue(
+ theParentNode,
+ DaemonConfig.sApplyLocalPolicy ) );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void setProp( final String inPropertyName,
+ final String inPropertyValue )
+ {
+ if ( inPropertyValue != null )
+ {
+ setProperty( inPropertyName, inPropertyValue );
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/Database.java b/src/com/sun/apoc/daemon/localdatabase/Database.java
new file mode 100644
index 0000000..6470c6c
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/Database.java
@@ -0,0 +1,365 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.util.*;
+
+public class Database extends Db
+{
+ protected final Name mName;
+ private Dbc mDbc;
+
+ private static final int sDbType = Db.DB_BTREE;
+ private static final int sDbFlags = Db.DB_CREATE;
+ private static final int sDbMode = 0600;
+ private static final String sValueEpoch = "19700101000000Z";
+
+ public static final String sKeyLastChangeDetect = "lastChangeDetect";
+ public static final String sKeyLastModified = "lastModified/";
+ public static final String sKeyLastRead = "lastRead";
+ public static final String sKeyLayerIds = "layerIds/";
+ public static final String sKeyDBs = "dbs";
+ public static final String sKeyRemoteComponentList =
+ "remoteComponentList";
+ public static final String sKeyLocalComponentList =
+ "localComponentList";
+
+ public Database( final Name inName )
+ throws APOCException, DbException, FileNotFoundException
+ {
+ super( LocalDatabaseFactory.getInstance(), 0 );
+ mName = inName;
+ openDatabase( LocalDatabaseFactory.getLocalDatabaseFileName(mName),
+ getDatabaseName(mName));
+ }
+
+ public Database(final Name inName, final String inFileName)
+ throws APOCException, DbException, FileNotFoundException
+ {
+ super(LocalDatabaseFactory.getInstance(), 0) ;
+ mName = inName ;
+ openDatabase(inFileName, getDatabaseName(mName)) ;
+ }
+ private void openDatabase(final String inFileName,
+ final String inDatabaseName)
+ throws APOCException, DbException, FileNotFoundException
+ {
+ open(null, inFileName, inDatabaseName, sDbType, sDbFlags, sDbMode) ;
+ }
+
+ public Name getName() { return mName; }
+
+ public static String getDatabaseName(Name aName)
+ {
+ return new StringBuffer(aName.getEntityType()).append(Name.sSep)
+ .append(aName.getEntityName()).append(Name.sSep)
+ .append(aName.getLocation()).toString() ;
+ }
+
+ public static Database createDatabase(String aName)
+ throws APOCException, DbException, FileNotFoundException
+ {
+ String [] components = aName.split(Name.sSep) ;
+
+ if (components != null && components.length > 2)
+ {
+ return new Database(new Name(null,
+ components [0],
+ components [1],
+ components [2])) ;
+ }
+ throw new APOCException() ;
+ }
+
+ public String toString() { return getDatabaseName(mName) ; }
+
+ public void beginTransaction()
+ throws APOCException
+ {
+ try
+ {
+ final Dbc theCursor = cursor( null, Db.DB_WRITECURSOR );
+ mDbc = theCursor;
+ }
+ catch( DbException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public void endTransaction()
+ throws APOCException
+ {
+ if ( mDbc != null )
+ {
+ try
+ {
+ final Dbc theCursor = mDbc;
+ mDbc = null;
+ theCursor.close();
+ }
+ catch( DbException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+ }
+
+ public int get( String inKey, final Dbt outValue )
+ throws APOCException
+ {
+ return get( new StringDbt( inKey ), outValue );
+ }
+
+ public int get( final Dbt inKey, final Dbt outValue )
+ throws APOCException
+ {
+ try
+ {
+ return get( null, inKey, outValue, 0 );
+ }
+ catch( DbException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public HashSet getDBList()
+ throws APOCException
+ {
+ final SetDbt theSetDbt = new SetDbt();
+ get( sKeyDBs, theSetDbt );
+ return theSetDbt.getApocData();
+ }
+
+ public String getLastChangeDetect()
+ throws APOCException
+ {
+ final StringDbt theValue = new StringDbt();
+ get( sKeyLastChangeDetect, theValue );
+ if ( theValue.get_size() > 0 )
+ {
+ return theValue.getApocData();
+ }
+ else
+ {
+ return sValueEpoch;
+ }
+ }
+
+ public String getLastModified( final String inLayerId,
+ final String inComponentName )
+ throws APOCException
+ {
+ final StringDbt theValue = new StringDbt();
+ get( new StringBuffer( sKeyLastModified )
+ .append( inLayerId )
+ .append( "/" )
+ .append( inComponentName )
+ .toString(),
+ theValue );
+ if ( theValue.get_size() > 0 )
+ {
+ return theValue.getApocData();
+ }
+ else
+ {
+ return sValueEpoch;
+ }
+ }
+
+ public String getLastRead()
+ throws APOCException
+ {
+ final StringDbt theValue = new StringDbt();
+ get( sKeyLastRead, theValue );
+ if ( theValue.get_size() > 0 )
+ {
+ return theValue.getApocData();
+ }
+ else
+ {
+ return sValueEpoch;
+ }
+ }
+
+ public String getLayer( final String inComponentName,
+ final String inLayerId )
+ throws APOCException
+ {
+ final String theKey = new StringBuffer( inLayerId )
+ .append( "/" )
+ .append( inComponentName )
+ .toString();
+ StringDbt theValue = new StringDbt();
+ get( theKey, theValue );
+ return theValue.getApocData();
+ }
+
+ public Vector getLayerIds( final String inComponentName )
+ throws APOCException
+ {
+ final VectorStringDbt theVectorDbt = new VectorStringDbt();
+ get( new StringBuffer( sKeyLayerIds )
+ .append( inComponentName )
+ .toString(),
+ theVectorDbt );
+ return theVectorDbt.retrieveData();
+ }
+
+ public HashSet getLocalComponentList()
+ throws APOCException
+ {
+ final SetDbt theSetDbt = new SetDbt();
+ get( sKeyLocalComponentList, theSetDbt );
+ return theSetDbt.getApocData();
+ }
+
+ public HashSet getRemoteComponentList()
+ throws APOCException
+ {
+ final SetDbt theSetDbt = new SetDbt();
+ get( sKeyRemoteComponentList, theSetDbt );
+ return theSetDbt.getApocData();
+ }
+
+ public int put( final Dbt inKey, final String inData )
+ throws APOCException
+ {
+ return put( inKey, new StringDbt( inData ) );
+ }
+
+ public int put( final String inKey, final HashSet inData )
+ throws APOCException
+ {
+ return put( new StringDbt( inKey ), new SetDbt( inData ) );
+ }
+
+ public int put( final Dbt inKey, final HashSet inData )
+ throws APOCException
+ {
+ return put( inKey, new SetDbt( inData ) );
+ }
+
+ public int put(final String inKey, final Vector inData)
+ throws APOCException
+ {
+ return put(new StringDbt(inKey), new VectorStringDbt(inData)) ;
+ }
+
+ public int put( final String inKey, final String inData )
+ throws APOCException
+ {
+ return put( new StringDbt( inKey ), new StringDbt( inData ) );
+ }
+
+ public int put( final String inKey, final Dbt inData )
+ throws APOCException
+ {
+ return put( new StringDbt( inKey ), inData );
+ }
+
+ public int put( final Dbt inKey, final Dbt inData )
+ throws APOCException
+ {
+ try
+ {
+ return mDbc.put( inKey, inData, Db.DB_KEYFIRST );
+ }
+ catch( DbException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public void putDBList( final HashSet inDBList )
+ throws APOCException
+ {
+ put( sKeyDBs, inDBList );
+ }
+
+ public void putLastChangeDetect( final String inTimestamp )
+ throws APOCException
+ {
+ put( sKeyLastChangeDetect, inTimestamp );
+ }
+
+ public void putLastModified( final String inLayerId,
+ final String inComponentName,
+ final String inTimestamp )
+ throws APOCException
+ {
+ put( new StringBuffer( sKeyLastModified )
+ .append( inLayerId )
+ .append( "/" )
+ .append( inComponentName )
+ .toString(),
+ inTimestamp );
+ }
+
+ public void putLayerIds( final String inComponentName,
+ final Vector inLayerIds )
+ throws APOCException
+ {
+ put ( new StringBuffer( sKeyLayerIds )
+ .append( inComponentName )
+ .toString(),
+ inLayerIds );
+ }
+
+ public void putRemoteComponentList( final HashSet inRemoteComponentList )
+ throws APOCException
+ {
+ put( sKeyRemoteComponentList, inRemoteComponentList );
+ }
+
+ public void putLocalComponentList( final HashSet inComponentNames )
+ throws APOCException
+ {
+ put( sKeyLocalComponentList, inComponentNames );
+ }
+
+ protected void putLastRead()
+ throws APOCException
+ {
+ put( sKeyLastRead, Timestamp.getTimestamp() );
+ }
+
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/LocalDatabase.java b/src/com/sun/apoc/daemon/localdatabase/LocalDatabase.java
new file mode 100644
index 0000000..6154dff
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/LocalDatabase.java
@@ -0,0 +1,200 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.misc.*;
+
+import com.sun.apoc.spi.policies.*;
+
+import java.io.*;
+import java.nio.*;
+import java.util.*;
+
+public class LocalDatabase extends Database
+{
+ private HashSet mLocalComponentList;
+ private int mRefCount = 0;
+
+ public LocalDatabase( final Name inName )
+ throws APOCException, DbException, FileNotFoundException
+ {
+ super( inName );
+ initLocalComponentList();
+ }
+
+ synchronized public int acquire() { return ++mRefCount; }
+ synchronized public int release()
+ {
+ if ( --mRefCount == 0 )
+ {
+ try
+ {
+ beginTransaction();
+ putLastRead();
+ endTransaction();
+ close( 0 );
+ }
+ catch( DbException theException )
+ {}
+ catch( APOCException theException )
+ {}
+ }
+ return mRefCount;
+ }
+
+ public boolean hasComponent( final String inComponentName )
+ {
+ return mLocalComponentList.contains( inComponentName );
+ }
+
+ public void putLocalComponentList( final HashSet inLocalComponentList )
+ throws APOCException
+ {
+ mLocalComponentList = inLocalComponentList;
+ super.putLocalComponentList( mLocalComponentList );
+ }
+
+ public void update( final UpdateItem inUpdateItem, final String inTimestamp)
+ throws APOCException
+ {
+ if ( inUpdateItem != null )
+ {
+ updateItem( inUpdateItem, new StringDbt( inTimestamp ) );
+ }
+ }
+
+ public void update( final ArrayList inUpdateItems, final String inTimestamp)
+ throws APOCException
+ {
+ int theSize;
+ if ( inUpdateItems != null && ( theSize = inUpdateItems.size() ) > 0 )
+ {
+ StringDbt theTimestamp = new StringDbt( inTimestamp );
+ for ( int theIndex = 0; theIndex < theSize; ++ theIndex )
+ {
+ updateItem( ( UpdateItem )inUpdateItems.get( theIndex ),
+ theTimestamp );
+ }
+ }
+ }
+
+ private void addLocalComponent( final String inComponentName )
+ throws APOCException
+ {
+ mLocalComponentList.add( inComponentName );
+ super.putLocalComponentList( mLocalComponentList );
+ }
+
+ private void initLocalComponentList()
+ throws APOCException
+ {
+ if ( ( mLocalComponentList = super.getLocalComponentList() ) == null )
+ {
+ mLocalComponentList = new HashSet();
+ }
+ }
+
+ private void putComponent( final String inComponentName,
+ final Policy[] inPolicies )
+ throws APOCException
+ {
+ if ( inPolicies != null && inPolicies.length > 0 )
+ {
+ final Vector theLayerIds = new Vector( inPolicies.length );
+ for ( int theIndex = 0; theIndex < inPolicies.length; theIndex ++ )
+ {
+ final String theLayerId =
+ String.valueOf(
+ inPolicies[ theIndex].getProfileId().hashCode() );
+
+ String theKey = new StringBuffer( theLayerId )
+ .append( "/" )
+ .append( inComponentName )
+ .toString();
+ put( theKey, inPolicies[ theIndex ].getData() );
+
+ theLayerIds.add( theLayerId );
+
+ putLastModified( theLayerId,
+ inComponentName,
+ Timestamp.getTimestamp(
+ inPolicies[ theIndex ].getLastModified() ));
+ }
+ putLayerIds( inComponentName, theLayerIds );
+ }
+ }
+
+ private void removeLocalComponent( final String inComponentName )
+ throws APOCException
+ {
+ mLocalComponentList.remove( inComponentName );
+ super.putLocalComponentList( mLocalComponentList );
+ }
+
+ private void updateItem( final UpdateItem inUpdateItem )
+ throws APOCException
+ {
+ updateItem( inUpdateItem, new StringDbt( Timestamp.getTimestamp() ) );
+ }
+
+ private void updateItem( final UpdateItem inUpdateItem,
+ final Dbt inTimestamp )
+ throws APOCException
+ {
+ String theComponentName = inUpdateItem.getComponentName();
+ Policy[] thePolicies = inUpdateItem.getPolicies();
+ switch ( inUpdateItem.getUpdateType() )
+ {
+ case UpdateItem.ADD:
+ putComponent( theComponentName, thePolicies );
+ addLocalComponent( theComponentName );
+ break;
+
+ case UpdateItem.MODIFY:
+ putComponent( theComponentName, thePolicies );
+ break;
+
+ case UpdateItem.REMOVE:
+ removeLocalComponent( theComponentName );
+ break;
+
+ default:
+ break;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/LocalDatabaseFactory.java b/src/com/sun/apoc/daemon/localdatabase/LocalDatabaseFactory.java
new file mode 100644
index 0000000..13ae22b
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/LocalDatabaseFactory.java
@@ -0,0 +1,460 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.util.*;
+
+public class LocalDatabaseFactory extends DbEnv
+{
+ private static LocalDatabaseFactory sInstance;
+ private static final HashMap sDatabases =
+ new HashMap( DaemonConfig.getIntProperty(
+ DaemonConfig.sMaxClientConnections ) );
+ private static final String sLDBHome =
+ new StringBuffer(
+ DaemonConfig.getStringProperty( DaemonConfig.sDataDir ) )
+ .append( File.separatorChar )
+ .append( "LocalDB" )
+ .toString();
+ private static final Name sDbListDbName =
+ new Name(null, "DbListType", "DbList", true) ;
+
+
+ private static final int sDbEnvFlags = Db.DB_CREATE |
+ Db.DB_INIT_CDB |
+ Db.DB_INIT_MPOOL |
+ Db.DB_PRIVATE;
+
+ private static final int sDbEnvMode = 0600;
+ private static final String s__dbPrefix = "__db.";
+
+ private LocalDatabaseFactory()
+ throws APOCException, DbException
+ {
+ super( 0 );
+ createDBHome();
+ initLocks();
+ openEnv();
+ }
+
+ public void deleteDatabase( final Database inDatabase )
+ {
+ final Name theName = inDatabase.getName();
+ synchronized ( sDatabases )
+ {
+ if ( ! sDatabases.containsKey( createDatabaseKey( theName ) ) )
+ {
+ try
+ {
+ final HashSet theDBs = removeDbFromDbList( theName );
+ if ( theDBs == null || theDBs.size() == 0 )
+ {
+ new File(getLocalDatabaseFilePath(theName)).delete() ;
+ }
+ }
+ catch( Exception theException )
+ {}
+ }
+ }
+ }
+ public static LocalDatabaseFactory getInstance()
+ throws APOCException
+ {
+ if ( sInstance == null )
+ {
+ try
+ {
+ sInstance = new LocalDatabaseFactory();
+ Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+ public void run() {
+ try {
+ Iterator databases =
+ sDatabases.values().iterator() ;
+
+ while (databases.hasNext()) {
+ ((Database) databases.next()).close(0) ;
+ }
+ sInstance.close(0) ;
+ }
+ catch (DbException ignored) {}
+ }
+ })) ;
+
+ }
+ catch ( DbException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+ return sInstance;
+ }
+
+ public Object[] getDatabases()
+ {
+ Object[] theDatabases = null;
+ final String[] theDBFileNames = new File( sLDBHome ).list();
+ if ( theDBFileNames != null )
+ {
+ final ArrayList theDBList = new ArrayList( theDBFileNames.length );
+ for ( int theIndex = 0;
+ theIndex < theDBFileNames.length;
+ ++ theIndex )
+ {
+ if ( theDBFileNames[ theIndex ].startsWith( s__dbPrefix ) )
+ {
+ continue;
+ }
+ String[] theNames =
+ getDatabaseNames( theDBFileNames[ theIndex ] );
+ if ( theNames != null )
+ {
+ for ( int theNamesIndex = 0;
+ theNamesIndex < theNames.length;
+ ++ theNamesIndex )
+ {
+ synchronized( sDatabases )
+ {
+ // No need to include LocalDatabase instances
+ // ( i.e. databases with client connections )
+ // in return array
+ Database theDatabase =
+ ( Database )sDatabases.
+ get( theNames[ theNamesIndex ] );
+ if ( theDatabase == null )
+ {
+ try
+ {
+ theDatabase =
+ Database.createDatabase(
+ theNames [ theNamesIndex ] ) ;
+ theDBList.add( theDatabase );
+ }
+ catch( Exception theException)
+ {}
+ }
+ }
+ }
+ }
+ }
+ theDatabases = theDBList.toArray();
+ }
+ return theDatabases;
+ }
+
+ public String[] getDatabaseNames( final String inDBFileName )
+ {
+ String[] theDatabaseNames = null;
+ try
+ {
+ final HashSet theDBNames = getDBList( inDBFileName );
+ if ( theDBNames != null && theDBNames.size() > 0 )
+ {
+ theDatabaseNames =
+ ( String[] )theDBNames.toArray( new String[ 0 ] );
+ }
+ }
+ catch( Exception theException )
+ {}
+ return theDatabaseNames;
+ }
+
+ public Object[] openLocalDatabases()
+ {
+ Object[] theLocalDatabases = null;
+ if ( ! sDatabases.isEmpty() )
+ {
+ theLocalDatabases = sDatabases.values().toArray();
+ }
+ return theLocalDatabases;
+ }
+
+ public LocalDatabase openLocalDatabase( final Name inName )
+ throws APOCException
+ {
+ final String theKey = createDatabaseKey( inName );
+ LocalDatabase theLocalDatabase = null;
+ synchronized( sDatabases )
+ {
+ theLocalDatabase = ( LocalDatabase )sDatabases.get( theKey );
+ if ( theLocalDatabase == null )
+ {
+ theLocalDatabase = createNewLocalDatabase( inName );
+ }
+ if ( theLocalDatabase != null )
+ {
+ theLocalDatabase.acquire();
+ }
+ }
+ return theLocalDatabase;
+ }
+
+ public void closeLocalDatabase( final LocalDatabase inLocalDatabase )
+ {
+ synchronized( sDatabases )
+ {
+ if ( inLocalDatabase.release() == 0 )
+ {
+ sDatabases.remove(
+ createDatabaseKey(
+ inLocalDatabase.getName() ) );
+ }
+ }
+ }
+
+ private void addDbToDbList( final Name inName )
+ throws APOCException, DbException, FileNotFoundException
+ {
+ final Database theDatabase =
+ new Database(sDbListDbName, getLocalDatabaseFileName(inName)) ;
+ HashSet theDBList = theDatabase.getDBList();
+ if ( theDBList == null )
+ {
+ theDBList = new HashSet( 1 );
+ }
+ theDBList.add( createDatabaseKey(inName) );
+ theDatabase.beginTransaction();
+ theDatabase.putDBList( theDBList );
+ theDatabase.endTransaction();
+ theDatabase.close( 0 );
+ }
+
+ private static String createDatabaseKey( final Name inName )
+ {
+ return Database.getDatabaseName(inName);
+ }
+
+ private void createDBHome()
+ throws APOCException
+ {
+ final File theFile = new File( sLDBHome );
+ if ( ! theFile.exists() )
+ {
+ if ( ! theFile.mkdirs() )
+ {
+ throw new APOCException( APOCSymbols.sSymDBEnvCreateFailed );
+ }
+ }
+ else
+ {
+ if ( ! theFile.isDirectory() )
+ {
+ throw new APOCException( APOCSymbols.sSymDBEnvCreateFailed );
+ }
+ }
+ FileAccess.chmod( sLDBHome, 0700 );
+ FileAccess.chmod( theFile.getParent(), 0755 );
+ }
+
+ private LocalDatabase createNewLocalDatabase( final Name inName )
+ throws APOCException
+ {
+ return createNewLocalDatabase( inName, true );
+ }
+
+ private LocalDatabase createNewLocalDatabase( final Name inName,
+ boolean inDeleteRetry )
+ throws APOCException
+ {
+ ensureNonZeroLengthDBFile( inName );
+ try
+ {
+ final LocalDatabase theLocalDatabase = new LocalDatabase( inName );
+ addDbToDbList( inName );
+ sDatabases.put( createDatabaseKey( inName ), theLocalDatabase );
+ return theLocalDatabase;
+ }
+ catch ( Exception theException )
+ {
+ if ( inDeleteRetry )
+ {
+ new File( getLocalDatabaseFilePath(inName)).delete();
+ return createNewLocalDatabase( inName, false );
+ }
+ else
+ {
+ throw new APOCException( theException );
+ }
+ }
+ }
+
+ private void ensureNonZeroLengthDBFile( final Name inName )
+ throws APOCException
+ {
+ File theFile = new File( getLocalDatabaseTmpFilePath( inName ) );
+ try
+ {
+ if ( theFile.exists() )
+ {
+ theFile.delete();
+ }
+ }
+ catch( Exception theException )
+ {
+ throw new APOCException( theException );
+ }
+
+ theFile = new File ( getLocalDatabaseFilePath( inName ) );
+ try
+ {
+ if ( theFile.exists() && theFile.length() == 0 )
+ {
+ theFile.delete();
+ }
+ }
+ catch( Exception theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ /*
+ * 6417522 - default bdb values ( 1000 )for max lockers etc. too small
+ * Adjusting the max. number of lockers dynamically ( based
+ * roughly on MaxClientConnections ) would require the ability
+ * to close & reopen the db environment and all database
+ * dynamically. That's not terribly easy ... at least for our
+ * current implementation.
+ *
+ * As an alternative and considering that additional locks etc.
+ * are really quite cheap ( in terms of memory usge ), have
+ * decided that a practical solution to running out of locks etc.
+ * is to set the max at a ( most likely ) unreachable value.
+ * The number of locks required per user connection seems to
+ * vary dependent on the platform but 12 is a reasonable
+ * generalisation.
+ * For the moment, I'm using a default value of 12000 for max.
+ * locks. This would allow approx. 1000 users to connect. It
+ * also has no significant impact on memory use.
+ */
+ private void initLocks()
+ throws DbException
+ {
+ int theCount = DaemonConfig.getIntProperty( DaemonConfig.sMaxDbLocks );
+ setLockMaxLockers( theCount );
+ setLockMaxLocks( theCount );
+ setLockMaxObjects( theCount );
+ }
+
+ private void openEnv()
+ throws APOCException
+ {
+ try
+ {
+ new DbEnv( 0 ).remove( sLDBHome, Db.DB_FORCE );
+ open( sLDBHome, sDbEnvFlags, sDbEnvMode );
+ }
+ catch( DbException theException )
+ {
+ APOCLogger.throwing( "LocalDatabaseFactory",
+ "openEnv",
+ theException );
+ throw new APOCException( theException );
+ }
+ catch( FileNotFoundException theException )
+ {
+ APOCLogger.throwing( "LocalDatabaseFactory",
+ "openEnv",
+ theException );
+ throw new APOCException( theException );
+ }
+ }
+
+ private HashSet getDBList( final String inDBFileName )
+ throws APOCException, DbException, FileNotFoundException
+ {
+ final Database theDatabase = new Database(sDbListDbName,
+ inDBFileName) ;
+ final HashSet theList = theDatabase.getDBList();
+ theDatabase.close( 0 );
+ return theList;
+ }
+
+ public static String getLocalDatabaseFileName( final Name inName )
+ {
+ return new StringBuffer(inName.getEntityType())
+ .append(".")
+ .append(inName.getEntityName()).toString();
+ }
+
+ private static String getLocalDatabaseFilePath( final Name inName )
+ {
+ return new StringBuffer( sLDBHome )
+ .append( File.separatorChar )
+ .append(getLocalDatabaseFileName(inName) )
+ .toString();
+ }
+
+ private static String getLocalDatabaseTmpFilePath( final Name inName )
+ {
+ return new StringBuffer( sLDBHome )
+ .append( File.separatorChar )
+ .append( s__dbPrefix )
+ .append( getLocalDatabaseFileName( inName ) )
+ .toString();
+ }
+
+ private HashSet removeDbFromDbList( final Name inName )
+ throws APOCException, DbException, FileNotFoundException
+ {
+ final Database theDatabase =
+ new Database( sDbListDbName, getLocalDatabaseFileName( inName ) );
+ /*
+ * 6417504 - ensure Db handle is closed to avoid leak
+ */
+ HashSet theDBList = null;
+ try
+ {
+ theDBList = theDatabase.getDBList();
+ if ( theDBList != null )
+ {
+ theDBList.remove( inName.toString() );
+ theDatabase.beginTransaction();
+ theDatabase.putDBList( theDBList );
+ theDatabase.endTransaction();
+ }
+ }
+ finally
+ {
+ theDatabase.close( 0 );
+ }
+ return theDBList;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/SetDbt.java b/src/com/sun/apoc/daemon/localdatabase/SetDbt.java
new file mode 100644
index 0000000..e06fe6c
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/SetDbt.java
@@ -0,0 +1,96 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+import java.nio.*;
+import java.util.*;
+
+class SetDbt extends Dbt
+{
+ SetDbt()
+ {
+ set_flags( Db.DB_DBT_MALLOC );
+ }
+
+ SetDbt( final HashSet inValue )
+ {
+ setApocData( inValue );
+ set_flags( Db.DB_DBT_MALLOC );
+ }
+
+ void setApocData( final HashSet inValue )
+ {
+ int theSize = 0;
+ Iterator theIterator = inValue.iterator();
+ while ( theIterator.hasNext() )
+ {
+ theSize += ( ( String )theIterator.next() ).length() + 1;
+ }
+ ByteBuffer theBuffer = ByteBuffer.allocate( theSize );
+ theIterator = inValue.iterator();
+ while ( theIterator.hasNext() )
+ {
+ theBuffer
+ .put( ( ( String )theIterator.next() ).getBytes() )
+ .put( ( byte )0 );
+ }
+ theBuffer.flip();
+ set_data( theBuffer.array() );
+ set_size( theSize );
+ }
+
+ HashSet getApocData()
+ {
+ byte[] theByte = { 0 };
+ String theString = new String( theByte );
+ HashSet theData = null;
+ int theSize = get_size();
+ if ( theSize > 0 )
+ {
+ final StringTokenizer theTokenizer =
+ new StringTokenizer(
+ new String( get_data(), get_offset(), theSize ),
+ theString );
+ theData = new HashSet();
+ while ( theTokenizer.hasMoreTokens() )
+ {
+ theData.add( theTokenizer.nextToken() );
+ }
+ }
+ return theData;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/StringDbt.java b/src/com/sun/apoc/daemon/localdatabase/StringDbt.java
new file mode 100644
index 0000000..afd46da
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/StringDbt.java
@@ -0,0 +1,70 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+class StringDbt extends Dbt
+{
+ StringDbt()
+ {
+ set_flags( Db.DB_DBT_MALLOC );
+ }
+
+ StringDbt( final String inValue )
+ {
+ setApocData( inValue );
+ set_flags( Db.DB_DBT_MALLOC );
+ }
+
+ void setApocData( final String inValue )
+ {
+ final byte[] theData = inValue.getBytes();
+ set_data( theData );
+ set_size( theData.length );
+ }
+
+ String getApocData()
+ {
+ String theData = null;
+ int theSize = get_size();
+
+ if ( theSize > 0 )
+ {
+ theData = new String( get_data(), get_offset(), theSize );
+ }
+ return theData;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/Timestamp.java b/src/com/sun/apoc/daemon/localdatabase/Timestamp.java
new file mode 100644
index 0000000..7faff34
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/Timestamp.java
@@ -0,0 +1,108 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import java.util.*;
+
+public class Timestamp
+{
+ private static final TimeZone sUTC = TimeZone.getTimeZone( "UTC" );
+
+ public static final String sEpoch = "19700101000000Z";
+ public static final long sEpochMillis = 0;
+
+ public static String getTimestamp()
+ {
+ StringBuffer theBuffer = new StringBuffer( 15 );
+ Calendar theCalendar = Calendar.getInstance( sUTC );
+ theBuffer.append( theCalendar.get( Calendar.YEAR ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.MONTH ) + 1 );
+ padAppend( theBuffer, theCalendar.get( Calendar.DAY_OF_MONTH ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.HOUR_OF_DAY ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.MINUTE ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.SECOND ) );
+ theBuffer.append( "Z" );
+ return theBuffer.toString();
+ }
+
+ public static String getTimestamp( long inMillis )
+ {
+ StringBuffer theBuffer = new StringBuffer( 15 );
+ Calendar theCalendar = Calendar.getInstance( sUTC );
+ theCalendar.setTimeInMillis( inMillis );
+ theBuffer.append( theCalendar.get( Calendar.YEAR ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.MONTH ) + 1 );
+ padAppend( theBuffer, theCalendar.get( Calendar.DAY_OF_MONTH ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.HOUR_OF_DAY ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.MINUTE ) );
+ padAppend( theBuffer, theCalendar.get( Calendar.SECOND ) );
+ theBuffer.append( "Z" );
+ return theBuffer.toString();
+ }
+
+ public static long getMillis( String inTimestamp )
+ {
+ if ( inTimestamp == null || inTimestamp.compareTo( sEpoch ) == 0 )
+ {
+ return sEpochMillis;
+ }
+ Calendar theCalendar = Calendar.getInstance( sUTC );
+ theCalendar.set(
+ Integer.parseInt( inTimestamp.substring( 0, 4 ) ),
+ Integer.parseInt( inTimestamp.substring( 4, 6 ) ) - 1,
+ Integer.parseInt( inTimestamp.substring( 6, 8 ) ),
+ Integer.parseInt( inTimestamp.substring( 8, 10 ) ),
+ Integer.parseInt( inTimestamp.substring( 10, 12 ) ),
+ Integer.parseInt( inTimestamp.substring( 12, 14 ) ) );
+ return theCalendar.getTimeInMillis();
+ }
+
+ public static boolean isNewer( String inTimestamp1, String inTimestamp2 )
+ {
+ String theTimestamp1 = inTimestamp1.substring( 0, 14 );
+ String theTimestamp2 = inTimestamp2.substring( 0, 14 );
+ return Long.parseLong( theTimestamp1 ) >
+ Long.parseLong( theTimestamp2 );
+ }
+
+ private static void padAppend( StringBuffer inBuffer, int inValue )
+ {
+ if ( inValue < 10 )
+ {
+ inBuffer.append( 0 );
+ }
+ inBuffer.append( inValue );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/UpdateItem.java b/src/com/sun/apoc/daemon/localdatabase/UpdateItem.java
new file mode 100755
index 0000000..f3045fd
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/UpdateItem.java
@@ -0,0 +1,75 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sun.apoc.spi.policies.*;
+
+import java.util.*;
+
+public class UpdateItem
+{
+ public static final int NOCHANGE = 0;
+ public static final int ADD = 1;
+ public static final int REMOVE = 2;
+ public static final int MODIFY = 3;
+
+ private int mUpdateType;
+ private final String mComponentName;
+ private final Policy[] mPolicies;
+
+ public UpdateItem()
+ {
+ mComponentName = null;
+ mPolicies = null;
+ }
+
+ public UpdateItem( int inUpdateType,
+ final String inComponentName,
+ final Policy[] inPolicies )
+ {
+ mUpdateType = inUpdateType;
+ mComponentName = inComponentName;
+ mPolicies = inPolicies;
+ }
+
+ public int getUpdateType() { return mUpdateType; }
+ public final String getComponentName() { return mComponentName; }
+ public final Policy[] getPolicies() { return mPolicies; }
+
+ public void setUpdateType( int inUpdateType )
+ {
+ mUpdateType = inUpdateType;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/localdatabase/VectorStringDbt.java b/src/com/sun/apoc/daemon/localdatabase/VectorStringDbt.java
new file mode 100644
index 0000000..5ea9394
--- /dev/null
+++ b/src/com/sun/apoc/daemon/localdatabase/VectorStringDbt.java
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.localdatabase;
+
+import com.sleepycat.db.*;
+
+import java.util.*;
+
+class VectorStringDbt extends Dbt
+{
+ VectorStringDbt()
+ {
+ super() ;
+ set_flags(Db.DB_DBT_MALLOC) ;
+ }
+
+ VectorStringDbt(final Vector inValue)
+ {
+ super() ;
+ fillData(inValue) ;
+ set_flags(Db.DB_DBT_MALLOC) ;
+ }
+
+ private void fillData(final Vector inValue)
+ {
+ Iterator theIterator = inValue.iterator() ;
+ int theTotalLength = 0 ;
+
+ while (theIterator.hasNext())
+ {
+ theTotalLength += ((String) theIterator.next()).length() ;
+ ++ theTotalLength ; // The intermediate 0
+ }
+ byte [] theData = new byte [theTotalLength] ;
+ int theCurrentIndex = 0 ;
+
+ theIterator = inValue.iterator() ;
+ while (theIterator.hasNext())
+ {
+ byte [] theSource = ((String) theIterator.next()).getBytes() ;
+
+ for (int i = 0 ; i < theSource.length ; ++ i)
+ {
+ theData [theCurrentIndex ++] = theSource [i] ;
+ }
+ theData [theCurrentIndex ++] = 0 ;
+ }
+ set_data(theData) ;
+ set_size(theTotalLength) ;
+ }
+
+ Vector retrieveData()
+ {
+ Vector theData = null ;
+ int theSize = get_size() ;
+
+ if (theSize > 0)
+ {
+ int theStart = 0 ;
+ int theEnd = 0 ;
+ byte [] theArray = get_data() ;
+
+ theData = new Vector() ;
+ do
+ {
+ while (theEnd < theSize && theArray [theEnd] != 0)
+ {
+ ++ theEnd ;
+ }
+ theData.add(new String(theArray, theStart, theEnd - theStart)) ;
+ ++ theEnd ;
+ theStart = theEnd ;
+ } while (theEnd < theSize) ;
+ }
+ return theData ;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/AddListenerMessage.java b/src/com/sun/apoc/daemon/messaging/AddListenerMessage.java
new file mode 100644
index 0000000..bfc203e
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/AddListenerMessage.java
@@ -0,0 +1,133 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import java.util.*;
+
+public class AddListenerMessage extends Message
+{
+ private Vector mComponentNames;
+ private String mClientData;
+ private int[] mExpectedSymbols = { APOCSymbols.sSymParamSessionId,
+ APOCSymbols.sSymUnknown };
+ private boolean mIsValid = false;
+
+ public AddListenerMessage()
+ {
+ super( APOCSymbols.sSymReqAddListener );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ public String getClientData() { return mClientData; }
+ public Vector getComponentNames() { return mComponentNames; }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ switch ( APOCSymbols.getProtocolSymbol( inName ) )
+ {
+ case APOCSymbols.sSymParamSessionId:
+ addSessionId( inValue );
+ break;
+
+ case APOCSymbols.sSymParamClientData:
+ addClientData( inValue );
+ break;
+
+ case APOCSymbols.sSymParamComponentName:
+ addComponentName( inValue );
+ break;
+
+ default:
+ throw new APOCException();
+ }
+ }
+
+ private void addSessionId( final String inSessionId )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamSessionId );
+ mSessionId = inSessionId;
+ setCheckSymbols( APOCSymbols.sSymParamClientData,
+ APOCSymbols.sSymParamComponentName );
+ }
+
+ private void addClientData( final String inClientData )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamClientData );
+ mClientData = inClientData;
+ setCheckSymbols( APOCSymbols.sSymParamComponentName );
+ }
+
+ private void addComponentName( final String inComponentName )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamComponentName );
+ if ( mComponentNames == null )
+ {
+ mComponentNames = new Vector();
+ mIsValid = true;
+ }
+ mComponentNames.add( inComponentName );
+ }
+
+ private void checkSymbol( final int inSymbol )
+ throws APOCException
+ {
+ if ( mExpectedSymbols[ 0 ] == APOCSymbols.sSymUnknown ||
+ ( mExpectedSymbols[ 0 ] != inSymbol &&
+ mExpectedSymbols[ 1 ] != inSymbol ) )
+ {
+ throw new APOCException();
+ }
+ }
+
+ private void setCheckSymbols( final int inSymbol )
+ {
+ setCheckSymbols( inSymbol, APOCSymbols.sSymUnknown );
+ }
+
+ private void setCheckSymbols( final int inSymbol1, final int inSymbol2 )
+ {
+ mExpectedSymbols[ 0 ] = inSymbol1;
+ mExpectedSymbols[ 1 ] = inSymbol2;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/CreateSessionExtMessage.java b/src/com/sun/apoc/daemon/messaging/CreateSessionExtMessage.java
new file mode 100644
index 0000000..571c337
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/CreateSessionExtMessage.java
@@ -0,0 +1,111 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+package com.sun.apoc.daemon.messaging ;
+
+import java.util.Hashtable ;
+
+import com.sun.apoc.daemon.apocd.Client ;
+
+import com.sun.apoc.daemon.misc.APOCException ;
+import com.sun.apoc.daemon.misc.APOCSymbols ;
+
+public class CreateSessionExtMessage extends Message
+ implements CredentialsProviderMessage {
+ private String mUserId = null ;
+ private String mCredentials = null ;
+ private Hashtable mEntities = new Hashtable() ;
+ private int mExpectedSymbol = APOCSymbols.sSymParamUserId ;
+ private String mLastEntityType = null ;
+ private boolean mIsValid = false ;
+
+ public CreateSessionExtMessage() {
+ super(APOCSymbols.sSymReqCreateSessionExt) ;
+ }
+ public boolean isValid() { return mIsValid ; }
+ public String getUserId() { return mUserId ; }
+ public String getCredentials() { return mCredentials ; }
+ public Hashtable getEntities() { return mEntities ; }
+
+ protected void addParameter(final String aName,
+ final String aValue) throws APOCException {
+ switch (APOCSymbols.getProtocolSymbol(aName)) {
+ case APOCSymbols.sSymParamUserId:
+ setUserId(aValue) ;
+ break ;
+ case APOCSymbols.sSymParamCredentials:
+ setCredentials(aValue) ;
+ break ;
+ case APOCSymbols.sSymParamEntityType:
+ setEntityType(aValue) ;
+ break ;
+ case APOCSymbols.sSymParamEntityId:
+ setEntityId(aValue) ;
+ }
+ }
+ private void setUserId(final String aUserId) throws APOCException {
+ checkState(APOCSymbols.sSymParamUserId) ;
+ mUserId = aUserId ;
+ mExpectedSymbol = APOCSymbols.sSymParamCredentials ;
+ }
+ private void setCredentials(
+ final String aCredentials) throws APOCException {
+ checkState(APOCSymbols.sSymParamCredentials) ;
+ mCredentials = aCredentials ;
+ mExpectedSymbol = APOCSymbols.sSymParamEntityType ;
+ }
+ private void setEntityType(final String aEntityType) throws APOCException {
+ try { checkState(APOCSymbols.sSymParamEntityType) ; }
+ catch (APOCException exception) {
+ // Allow for skipping credentials
+ if (mExpectedSymbol != APOCSymbols.sSymParamCredentials) {
+ throw exception ;
+ }
+ }
+ if (mEntities.contains(aEntityType)) { throw new APOCException() ; }
+ mLastEntityType = aEntityType ;
+ mExpectedSymbol = APOCSymbols.sSymParamEntityId ;
+ }
+ private void setEntityId(final String aEntityId) throws APOCException {
+ checkState(APOCSymbols.sSymParamEntityId) ;
+ mEntities.put(mLastEntityType, aEntityId) ;
+ mIsValid = true ;
+ mExpectedSymbol = APOCSymbols.sSymParamEntityType ;
+ }
+ private void checkState(final int aSymbol) throws APOCException {
+ if (aSymbol != mExpectedSymbol) { throw new APOCException() ; }
+ }
+}
+
diff --git a/src/com/sun/apoc/daemon/messaging/CreateSessionMessage.java b/src/com/sun/apoc/daemon/messaging/CreateSessionMessage.java
new file mode 100644
index 0000000..3b85514
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/CreateSessionMessage.java
@@ -0,0 +1,134 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+public class CreateSessionMessage extends Message
+ implements CredentialsProviderMessage
+{
+ private String mUserId;
+ private String mEntityId;
+ private String mCredentials;
+ private int[] mExpectedSymbols= { APOCSymbols.sSymParamUserId,
+ APOCSymbols.sSymUnknown };
+ private boolean mIsValid = false;
+
+ public CreateSessionMessage()
+ {
+ super( APOCSymbols.sSymReqCreateSession );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ public String getUserId() { return mUserId; }
+ public String getEntityId() { return mEntityId; }
+ public String getCredentials() { return mCredentials; }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ switch ( APOCSymbols.getProtocolSymbol( inName ) )
+ {
+ case APOCSymbols.sSymParamUserId:
+ addUserId( inValue );
+ break;
+
+ case APOCSymbols.sSymParamEntityId:
+ addEntityId( inValue );
+ break;
+
+ case APOCSymbols.sSymParamCredentials:
+ addCredentials( inValue );
+ break;
+
+ default:
+ throw new APOCException();
+ }
+ }
+
+ private void addUserId( final String inUserId )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamUserId );
+ mUserId = inUserId;
+ setCheckSymbols( APOCSymbols.sSymParamEntityId,
+ APOCSymbols.sSymParamCredentials );
+ mIsValid = true;
+ }
+
+ private void addEntityId( final String inEntityId )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamEntityId );
+ mEntityId = inEntityId;
+ setCheckSymbols( APOCSymbols.sSymParamCredentials );
+ }
+
+ private void addCredentials( final String inCredentials )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamCredentials );
+ mCredentials = inCredentials;
+ setCheckSymbols( APOCSymbols.sSymUnknown );
+ }
+
+ private void checkSymbol( final int inSymbol )
+ throws APOCException
+ {
+ if ( mExpectedSymbols[ 0 ] == APOCSymbols.sSymUnknown ||
+ ( mExpectedSymbols[ 0 ] != inSymbol &&
+ mExpectedSymbols[ 1 ] != inSymbol ) )
+ {
+ throw new APOCException();
+ }
+ }
+
+ private void setCheckSymbols( final int inSymbol )
+ {
+ setCheckSymbols( inSymbol,
+ APOCSymbols.sSymUnknown );
+ }
+
+ private void setCheckSymbols( final int inSymbol1,
+ final int inSymbol2 )
+ {
+ mExpectedSymbols[ 0 ] = inSymbol1;
+ mExpectedSymbols[ 1 ] = inSymbol2;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/CredentialsProviderMessage.java b/src/com/sun/apoc/daemon/messaging/CredentialsProviderMessage.java
new file mode 100644
index 0000000..1815090
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/CredentialsProviderMessage.java
@@ -0,0 +1,41 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+package com.sun.apoc.daemon.messaging ;
+
+public interface CredentialsProviderMessage {
+ public String getCredentials() ;
+}
+
diff --git a/src/com/sun/apoc/daemon/messaging/DestroySessionMessage.java b/src/com/sun/apoc/daemon/messaging/DestroySessionMessage.java
new file mode 100644
index 0000000..f136497
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/DestroySessionMessage.java
@@ -0,0 +1,65 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+public class DestroySessionMessage extends Message
+{
+ private boolean mIsValid = false;
+
+ public DestroySessionMessage()
+ {
+ super( APOCSymbols.sSymReqDestroySession );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ if ( APOCSymbols.getProtocolSymbol( inName ) !=
+ APOCSymbols.sSymParamSessionId ||
+ mSessionId != null )
+ {
+ throw new APOCException();
+ }
+ mSessionId = inValue;
+ mIsValid = true;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/ListMessage.java b/src/com/sun/apoc/daemon/messaging/ListMessage.java
new file mode 100644
index 0000000..78e65c8
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/ListMessage.java
@@ -0,0 +1,65 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+public class ListMessage extends Message
+{
+ private boolean mIsValid = false;
+
+ public ListMessage()
+ {
+ super( APOCSymbols.sSymReqList );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ if ( APOCSymbols.getProtocolSymbol( inName ) !=
+ APOCSymbols.sSymParamSessionId ||
+ mSessionId != null )
+ {
+ throw new APOCException();
+ }
+ mSessionId = inValue;
+ mIsValid = true;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/Message.java b/src/com/sun/apoc/daemon/messaging/Message.java
new file mode 100644
index 0000000..90f1a9e
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/Message.java
@@ -0,0 +1,80 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+import java.nio.ByteBuffer;
+
+public abstract class Message
+{
+ protected int mName;
+ protected String mSessionId;
+
+ public int getName() { return mName; }
+ public String getSessionId() { return mSessionId; }
+
+ protected Message( final int inName )
+ {
+ mName = inName;
+ }
+
+ protected abstract void addParameter( String inName, String inValue )
+ throws APOCException;
+
+ public abstract boolean isValid();
+
+ private static final byte [] sBindingHeader =
+ APOCSymbols.sContentLength.getBytes() ;
+ private static final int sBindingHeaderLen = sBindingHeader.length ;
+
+ public ByteBuffer serialise()
+ {
+ final byte [] theContent = toString().getBytes() ;
+ final byte [] theContentLength =
+ String.valueOf(theContent.length).getBytes() ;
+
+ return (ByteBuffer) ByteBuffer.allocate(sBindingHeaderLen +
+ theContentLength.length +
+ 2 + // "\r\n"
+ theContent.length)
+ .put(sBindingHeader)
+ .put(theContentLength)
+ .put((byte) '\r')
+ .put((byte) '\n')
+ .put(theContent)
+ .flip() ;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/MessageFactory.java b/src/com/sun/apoc/daemon/messaging/MessageFactory.java
new file mode 100644
index 0000000..1f99e91
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/MessageFactory.java
@@ -0,0 +1,113 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+public class MessageFactory
+{
+ public static Message createRequest( final String inMessageName )
+ throws APOCException
+ {
+ Message theMessage;
+ switch ( APOCSymbols.getProtocolSymbol( inMessageName ) )
+ {
+ case APOCSymbols.sSymReqRead:
+ theMessage = new ReadMessage();
+ break;
+
+ case APOCSymbols.sSymReqList:
+ theMessage = new ListMessage();
+ break;
+
+ case APOCSymbols.sSymReqAddListener:
+ theMessage = new AddListenerMessage();
+ break;
+
+ case APOCSymbols.sSymReqCreateSession:
+ theMessage = new CreateSessionMessage();
+ break;
+
+ case APOCSymbols.sSymReqCreateSessionExt:
+ theMessage = new CreateSessionExtMessage();
+ break;
+
+ case APOCSymbols.sSymReqDestroySession:
+ theMessage = new DestroySessionMessage();
+ break;
+
+ case APOCSymbols.sSymReqRemoveListener:
+ theMessage = new RemoveListenerMessage();
+ break;
+
+ default:
+ throw new APOCException();
+ }
+ return theMessage;
+ }
+
+ public static Message createResponse( final int inResponseType,
+ final String inSessionId,
+ final String inResponseMessage )
+ {
+ Message theMessage = null;
+ switch ( inResponseType )
+ {
+ case APOCSymbols.sSymRespSuccess:
+ case APOCSymbols.sSymRespInvalidRequest:
+ case APOCSymbols.sSymRespConnectionFailure:
+ case APOCSymbols.sSymRespAuthenticationFailure:
+ case APOCSymbols.sSymRespInvalidSessionId:
+ case APOCSymbols.sSymRespNoSuchComponent:
+ case APOCSymbols.sSymRespUnknownFailure:
+ case APOCSymbols.sSymRespSuccessContinueLocalAuth:
+ case APOCSymbols.sSymRespSuccessContinueSASLAuth:
+ theMessage = new Response( inResponseType,
+ inSessionId,
+ inResponseMessage );
+ break;
+
+ default:
+ break;
+ }
+ return theMessage;
+ }
+
+ public static Message createNotification( final String inSessionId,
+ int inType )
+ {
+ return new Notification( inSessionId, inType );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/Messenger.java b/src/com/sun/apoc/daemon/messaging/Messenger.java
new file mode 100644
index 0000000..874f0bf
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/Messenger.java
@@ -0,0 +1,91 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.io.*;
+
+public class Messenger
+{
+ private ClientChannel mClientChannel;
+ private RequestReceiver mRequestReceiver = new RequestReceiver();
+
+ public Messenger()
+ throws APOCException
+ {
+ }
+
+ public void setClientChannel( final ClientChannel inClientChannel )
+ {
+ mClientChannel = inClientChannel;
+ }
+
+ public Message receiveRequest()
+ throws APOCException
+ {
+ return receiveRequest( true );
+ }
+
+ public Message receiveRequest( boolean inSetBusy )
+ throws APOCException
+ {
+ return mRequestReceiver.receiveRequest( mClientChannel );
+ }
+
+ public void sendResponse( final Message inResponse )
+ {
+ sendResponse( inResponse, true );
+ }
+
+ public void sendResponse( final Message inResponse, boolean inSetIdle )
+ {
+ try
+ {
+ if ( inSetIdle )
+ {
+ mClientChannel.registerForSelection( true );
+ }
+ mClientChannel.write( inResponse.serialise() );
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.finest( "Msgr001" );
+ APOCLogger.throwing( "Messenger", "sendResponse", theException );
+ }
+ }
+
+}
diff --git a/src/com/sun/apoc/daemon/messaging/Notification.java b/src/com/sun/apoc/daemon/messaging/Notification.java
new file mode 100644
index 0000000..3518041
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/Notification.java
@@ -0,0 +1,119 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import java.util.*;
+
+public class Notification extends Message
+{
+ private String mComponentName;
+ private String mClientData;
+
+ public Notification( final String inSessionId,
+ int inType )
+ {
+ super( inType );
+ mSessionId = inSessionId;
+ }
+
+ public boolean isValid()
+ {
+ return true;
+ }
+
+ public void setComponentName( final String inComponentName )
+ {
+ mComponentName = inComponentName;
+ }
+
+ public void setClientData( final String inClientData )
+ {
+ mClientData = inClientData;
+ }
+
+ public String toString()
+ {
+ StringBuffer theBuffer =
+ new StringBuffer()
+ .append( "<" )
+ .append( APOCSymbols.getProtocolString( mName ) )
+ .append( ">" )
+
+ .append( "<" )
+ .append( APOCSymbols.sParamSessionId )
+ .append( ">" )
+
+ .append( mSessionId )
+
+ .append( "</" )
+ .append( APOCSymbols.sParamSessionId )
+ .append( ">");
+
+ if ( mClientData != null )
+ {
+ theBuffer.append( "<" )
+ .append( APOCSymbols.sParamClientData )
+ .append( ">" )
+
+ .append( mClientData )
+
+ .append( "</" )
+ .append( APOCSymbols.sParamClientData )
+ .append( ">" );
+ }
+
+ theBuffer.append( "<" )
+ .append( APOCSymbols.sParamComponentName )
+ .append( ">" )
+
+ .append( mComponentName )
+
+ .append( "</" )
+ .append( APOCSymbols.sParamComponentName )
+ .append( ">" )
+
+ .append( "</" )
+ .append( APOCSymbols.getProtocolString( mName ) )
+ .append( ">" );
+ return theBuffer.toString();
+ }
+
+ protected void addParameter( String inName, String inValue )
+ throws APOCException
+ {
+ throw new APOCException();
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/ProtocolDeserialiser.java b/src/com/sun/apoc/daemon/messaging/ProtocolDeserialiser.java
new file mode 100644
index 0000000..607e1ef
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/ProtocolDeserialiser.java
@@ -0,0 +1,72 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.nio.charset.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+import javax.xml.parsers.*;
+
+class ProtocolDeserialiser
+{
+ private InputStream mInputStream;
+ private final XMLReader mXMLReader;
+ private final ProtocolHandler mHandler =
+ new ProtocolHandler();
+ private static final SAXParserFactory sSAXParserFactory =
+ SAXParserFactory.newInstance();
+
+ public ProtocolDeserialiser()
+ throws SAXException, ParserConfigurationException
+ {
+ mXMLReader = sSAXParserFactory.newSAXParser().getXMLReader();
+ mXMLReader.setContentHandler( mHandler );
+ }
+
+ public void setInputStream( final InputStream inInputStream )
+ {
+ mInputStream = inInputStream;
+ }
+
+ public Message deserialise()
+ throws IOException, SAXException
+ {
+ mXMLReader.parse( new InputSource( mInputStream ) );
+ return mHandler.getMessage();
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/ProtocolHandler.java b/src/com/sun/apoc/daemon/messaging/ProtocolHandler.java
new file mode 100644
index 0000000..20d77e2
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/ProtocolHandler.java
@@ -0,0 +1,103 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+
+class ProtocolHandler extends DefaultHandler
+{
+ private Message mMessage;
+ private String mCurrentParamName;
+
+ public Message getMessage()
+ {
+ return mMessage;
+ }
+
+ public void characters( final char[] inCharArray, final int inStart, final int inLength )
+ throws SAXException
+ {
+ if ( mMessage == null )
+ {
+ throw new SAXException( new APOCException() );
+ }
+
+ try
+ {
+ mMessage.addParameter( mCurrentParamName,
+ new String( inCharArray, inStart, inLength ) );
+ }
+ catch ( APOCException theException )
+ {
+ throw new SAXException( theException );
+ }
+ }
+
+ public void startDocument()
+ {
+ init();
+ }
+
+ public void startElement( final String inURI,
+ final String inName,
+ final String inQName,
+ final Attributes inAttributes )
+ throws SAXException
+ {
+ if ( mMessage == null )
+ {
+ try
+ {
+ mMessage = MessageFactory.createRequest( inQName );
+ }
+ catch( APOCException theException )
+ {
+ throw new SAXException( theException );
+ }
+ }
+ else
+ {
+ mCurrentParamName = inQName;
+ }
+ }
+
+ private void init()
+ {
+ mMessage = null;
+ mCurrentParamName = null;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/ProtocolUnbinder.java b/src/com/sun/apoc/daemon/messaging/ProtocolUnbinder.java
new file mode 100644
index 0000000..36eb9f6
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/ProtocolUnbinder.java
@@ -0,0 +1,206 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.io.*;
+import java.nio.*;
+
+class ProtocolUnbinder extends InputStream implements ConfigEventListener
+{
+ private ClientChannel mClientChannel;
+ private final ByteBuffer mInputBuffer = ByteBuffer.allocate( 1024 );
+ private int mContentLength;
+ private final StringBuffer mContentLengthBuffer =
+ new StringBuffer( sContentLengthValueSize );
+ private long mAvailableByteCount;
+
+ private static int sMaxRequestLengthMinimum= 4096;
+ private static Integer sMaxRequestLength =
+ new Integer( sMaxRequestLengthMinimum );
+ private static final byte[] sContentLengthHeader =
+ APOCSymbols.sContentLength.getBytes();
+ private static final int sContentLengthValueSize = 5;
+
+ static
+ {
+ setMaxRequestLength();
+ }
+
+ public ProtocolUnbinder()
+ {
+ DaemonConfig.addConfigEventListener( this );
+ }
+
+ public void setClientChannel( final ClientChannel inClientChannel )
+ {
+ mClientChannel = inClientChannel;
+ mAvailableByteCount = 0;
+ }
+
+ public void onConfigEvent()
+ {
+ setMaxRequestLength();
+ }
+
+ public int read()
+ throws IOException
+ {
+ int theByte = -1;
+ if ( mContentLength-- > 0 )
+ {
+ theByte = ( int )getByte();
+ }
+ return theByte;
+ }
+
+ public int read( final byte[] outBytes, final int inOffset, final int inByteCount )
+ throws IOException
+ {
+ int theByteCount = 0;
+ while ( mContentLength > 0 && theByteCount < inByteCount )
+ {
+ outBytes[ inOffset + theByteCount++ ] = getByte();
+ mContentLength--;
+ }
+ return theByteCount > 0 ? theByteCount : -1;
+ }
+
+ public InputStream unbind()
+ throws APOCException, IOException
+ {
+ mContentLength = getContentLength();
+ if ( mContentLength == 0 || mContentLength > getMaxRequestLength() )
+ {
+ throw new APOCException( APOCSymbols.sSymRespInvalidRequest );
+ }
+ return this;
+ }
+
+ private byte getByte()
+ throws IOException
+ {
+ if ( mAvailableByteCount == 0 )
+ {
+ mInputBuffer.clear();
+ mAvailableByteCount = mClientChannel.read( mInputBuffer );
+ mInputBuffer.flip();
+ }
+ mAvailableByteCount--;
+ return mInputBuffer.get();
+ }
+
+ private int getContentLength()
+ throws IOException
+ {
+ return hasContentHeader() ? readContentLength() : 0;
+ }
+
+ private int getMaxRequestLength()
+ {
+ synchronized( sMaxRequestLength )
+ {
+ return sMaxRequestLength.intValue();
+ }
+ }
+
+ private boolean hasContentHeader()
+ throws IOException
+ {
+ boolean hasContentHeader = true;
+ for ( int theIndex = 0;
+ theIndex < sContentLengthHeader.length;
+ theIndex ++ )
+ {
+ if ( getByte() != sContentLengthHeader[ theIndex ] )
+ {
+ hasContentHeader = false;
+ break;
+ }
+ }
+ return hasContentHeader;
+ }
+
+ private int readContentLength()
+ throws IOException
+ {
+
+ mContentLengthBuffer.delete( 0, sContentLengthValueSize );
+ byte theByte = 0;
+ for ( int theIndex = 0 ;
+ theIndex < sContentLengthValueSize ;
+ theIndex ++ )
+ {
+ if ( ( theByte = getByte() ) == '\r' )
+ {
+ break;
+ }
+ else
+ {
+ mContentLengthBuffer.append( ( char )theByte );
+ }
+ }
+ if ( theByte != '\r' )
+ {
+ getByte(); // skip '\r'
+ }
+ getByte(); // skip '\n'
+ return Integer.parseInt( mContentLengthBuffer.toString() );
+ }
+
+ private static void setMaxRequestLength()
+ {
+ synchronized( sMaxRequestLength )
+ {
+ int theMaxRequestLength =
+ DaemonConfig.getIntProperty( DaemonConfig.sMaxRequestSize );
+ if ( theMaxRequestLength < sMaxRequestLengthMinimum )
+ {
+ String theRequestSizes[] =
+ {
+ String.valueOf( theMaxRequestLength ),
+ String.valueOf( sMaxRequestLengthMinimum ),
+ String.valueOf( sMaxRequestLengthMinimum )
+ };
+ APOCLogger.warning( "Punb001", theRequestSizes );
+ theMaxRequestLength = sMaxRequestLengthMinimum;
+ }
+ sMaxRequestLength = new Integer( theMaxRequestLength );
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/ReadMessage.java b/src/com/sun/apoc/daemon/messaging/ReadMessage.java
new file mode 100644
index 0000000..e7399f2
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/ReadMessage.java
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import java.util.*;
+
+public class ReadMessage extends Message
+{
+ private Vector mComponentNames;
+ private int mExpectedSymbol = APOCSymbols.sSymParamSessionId;
+ private boolean mIsValid = false;
+
+ public ReadMessage()
+ {
+ super( APOCSymbols.sSymReqRead );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ public Vector getComponentNames() { return mComponentNames; }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ switch ( APOCSymbols.getProtocolSymbol( inName ) )
+ {
+ case APOCSymbols.sSymParamSessionId:
+ addSessionId( inValue );
+ break;
+
+ case APOCSymbols.sSymParamComponentName:
+ addComponentName( inValue );
+ break;
+
+ default:
+ throw new APOCException();
+ }
+ }
+
+ private void addSessionId( final String inSessionId )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamSessionId );
+ mSessionId = inSessionId;
+ setCheckSymbol( APOCSymbols.sSymParamComponentName );
+ }
+
+ private void addComponentName( final String inComponentName )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamComponentName );
+ if ( mComponentNames == null )
+ {
+ mComponentNames = new Vector();
+ mIsValid = true;
+ }
+ mComponentNames.add( inComponentName );
+ }
+
+ private void checkSymbol( final int inSymbol )
+ throws APOCException
+ {
+ if ( mExpectedSymbol != inSymbol )
+ {
+ throw new APOCException();
+ }
+ }
+
+ private void setCheckSymbol( final int inSymbol )
+ {
+ mExpectedSymbol = inSymbol;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/RemoveListenerMessage.java b/src/com/sun/apoc/daemon/messaging/RemoveListenerMessage.java
new file mode 100644
index 0000000..d50fd0c
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/RemoveListenerMessage.java
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import java.util.*;
+
+public class RemoveListenerMessage extends Message
+{
+ private Vector mComponentNames;
+ private int mExpectedSymbol = APOCSymbols.sSymParamSessionId;
+ private boolean mIsValid = false;
+
+ public RemoveListenerMessage()
+ {
+ super( APOCSymbols.sSymReqRemoveListener );
+ }
+
+ public boolean isValid()
+ {
+ return mIsValid;
+ }
+
+ public Vector getComponentNames() { return mComponentNames; }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ switch ( APOCSymbols.getProtocolSymbol( inName ) )
+ {
+ case APOCSymbols.sSymParamSessionId:
+ addSessionId( inValue );
+ break;
+
+ case APOCSymbols.sSymParamComponentName:
+ addComponentName( inValue );
+ break;
+
+ default:
+ throw new APOCException();
+ }
+ }
+
+ private void addSessionId( final String inSessionId )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamSessionId );
+ mSessionId = inSessionId;
+ setCheckSymbol( APOCSymbols.sSymParamComponentName );
+ }
+
+ private void addComponentName( final String inComponentName )
+ throws APOCException
+ {
+ checkSymbol( APOCSymbols.sSymParamComponentName );
+ if ( mComponentNames == null )
+ {
+ mComponentNames = new Vector();
+ mIsValid = true;
+ }
+ mComponentNames.add( inComponentName );
+ }
+
+ private void checkSymbol( final int inSymbol )
+ throws APOCException
+ {
+ if ( mExpectedSymbol != inSymbol )
+ {
+ throw new APOCException();
+ }
+ }
+
+ private void setCheckSymbol( final int inSymbol )
+ {
+ mExpectedSymbol = inSymbol;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/RequestReceiver.java b/src/com/sun/apoc/daemon/messaging/RequestReceiver.java
new file mode 100644
index 0000000..0781793
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/RequestReceiver.java
@@ -0,0 +1,92 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import com.sun.apoc.daemon.transport.*;
+
+import java.io.*;
+
+class RequestReceiver
+{
+ private ProtocolUnbinder mUnbinder;
+ private ProtocolDeserialiser mDeserialiser;
+
+ public RequestReceiver()
+ throws APOCException
+ {
+ try
+ {
+ mUnbinder = new ProtocolUnbinder();
+ mDeserialiser = new ProtocolDeserialiser();
+ }
+ catch ( org.xml.sax.SAXException theException )
+ {
+ throw new APOCException( theException );
+ }
+ catch ( javax.xml.parsers.ParserConfigurationException theException )
+ {
+ throw new APOCException( theException );
+ }
+ }
+
+ public Message receiveRequest( final ClientChannel inClientChannel )
+ throws APOCException
+ {
+ Message theMessage;
+ try
+ {
+ mUnbinder.setClientChannel( inClientChannel );
+ mDeserialiser.setInputStream( mUnbinder.unbind() );
+ theMessage = mDeserialiser.deserialise();
+ if ( ! theMessage.isValid() )
+ {
+ throw new APOCException( APOCSymbols.sSymRespInvalidRequest );
+ }
+ }
+ catch ( org.xml.sax.SAXException theException )
+ {
+ APOCLogger.throwing( "RequestReceiver",
+ "receiveRequest",
+ theException );
+ throw new APOCException( theException );
+ }
+ catch ( IOException theException )
+ {
+ throw new APOCException( theException );
+ }
+ return theMessage;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/messaging/Response.java b/src/com/sun/apoc/daemon/messaging/Response.java
new file mode 100644
index 0000000..3c8f2de
--- /dev/null
+++ b/src/com/sun/apoc/daemon/messaging/Response.java
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.messaging;
+
+import com.sun.apoc.daemon.misc.*;
+import java.util.*;
+
+public class Response extends Message
+{
+ private String mBody;
+
+ public Response( final int inResponseType,
+ final String inSessionId,
+ final String inResponseMessage )
+ {
+ super( inResponseType );
+ setBody( inResponseType, inSessionId, inResponseMessage );
+ }
+
+ public boolean isValid()
+ {
+ return true;
+ }
+
+ protected void addParameter( final String inName, final String inValue )
+ throws APOCException
+ {
+ throw new APOCException();
+ }
+
+ public String toString()
+ {
+ return mBody;
+ }
+
+ private void setBody( final int inResponseType,
+ final String inSessionId,
+ final String inResponseMessage )
+ {
+ final String theResponseType =
+ APOCSymbols.getProtocolString( inResponseType );
+
+ final StringBuffer theBuffer = new StringBuffer()
+ .append( "<" )
+ .append( theResponseType )
+ .append( ">" )
+
+ .append( "<" )
+ .append( APOCSymbols.sParamSessionId )
+ .append( ">" )
+
+ .append( inSessionId )
+
+ .append( "</" )
+ .append( APOCSymbols.sParamSessionId )
+ .append( ">");
+
+ if ( inResponseMessage != null )
+ {
+ theBuffer.append( "<" )
+ .append( APOCSymbols.sParamMessage )
+ .append( ">")
+
+ .append( inResponseMessage )
+
+ .append( "</" )
+ .append( APOCSymbols.sParamMessage )
+ .append( ">");
+ }
+
+ theBuffer.append( "</" )
+ .append( theResponseType )
+ .append( ">" );
+
+ mBody = theBuffer.toString();
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/APOCAuthenticator.java b/src/com/sun/apoc/daemon/misc/APOCAuthenticator.java
new file mode 100644
index 0000000..b275830
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/APOCAuthenticator.java
@@ -0,0 +1,169 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import com.sun.apoc.daemon.config.*;
+
+import java.io.*;
+import java.util.*;
+
+public class APOCAuthenticator
+{
+ public static final File sAuthDir =
+ new File(
+ new StringBuffer(
+ DaemonConfig.getStringProperty( DaemonConfig.sDataDir ) )
+ .append( File.separatorChar )
+ .append( ".auth" )
+ .toString() );
+
+ private File mFile;
+ private String mFileName;
+ private byte[] mResponse;
+
+ private static final Random sRandom = new Random();
+ private static int sAuthBufferSize = 20;
+
+ public APOCAuthenticator( final String inUserId )
+ throws APOCException
+ {
+ final String theUserId =
+ inUserId != null ? inUserId : "<Daemon administrator>";
+ APOCLogger.finest( "Auth001", theUserId );
+ try
+ {
+ createAuthFile( inUserId );
+ createAuthToken();
+ }
+ catch( Exception theException )
+ {
+ cleanup();
+ APOCLogger.finest( "Auth003" );
+ throw new APOCException( theException );
+ }
+ }
+
+ public void cleanup()
+ {
+ try
+ {
+ if ( mFile != null )
+ {
+ mFile.delete();
+ mFile = null;
+ }
+ }
+ catch( Exception theException )
+ {}
+ }
+
+ public static int getAuthBufferSize() { return sAuthBufferSize; }
+
+ public byte[] getChallenge()
+ {
+ return mFileName.getBytes();
+ }
+
+ public void processResponse( final byte[] inResponse )
+ throws APOCException
+ {
+ try
+ {
+ if ( inResponse == null || inResponse.length != sAuthBufferSize )
+ {
+ APOCLogger.finest( "Auth003" );
+ throw new APOCException();
+ }
+ for ( int theIndex = 0; theIndex < sAuthBufferSize; theIndex ++ )
+ {
+ if ( mResponse[ theIndex ] != inResponse[ theIndex ] )
+ {
+ APOCLogger.finest( "Auth003" );
+ throw new APOCException();
+ }
+ }
+ APOCLogger.finest( "Auth002" );
+ }
+ finally
+ {
+ cleanup();
+ }
+ }
+
+ private void createAuthFile( final String inUserId )
+ throws Exception
+ {
+ long thePrefix = sRandom.nextLong();
+ thePrefix = thePrefix < 0 ? -thePrefix : thePrefix;
+ mFile =
+ File.createTempFile( String.valueOf( thePrefix ), null, sAuthDir );
+ mFile.deleteOnExit();
+ mFileName = mFile.getAbsolutePath();
+ if ( inUserId != null )
+ {
+ FileAccess.chown( mFileName, inUserId );
+ }
+ FileAccess.chmod( mFileName, 0600 );
+ }
+
+ private void createAuthToken()
+ throws Exception
+ {
+ final FileOutputStream theOutputStream =
+ new FileOutputStream( mFileName );
+ long theValue = sRandom.nextLong();
+ theValue = theValue < 0 ? -theValue : theValue;
+ final StringBuffer theStringBuffer =
+ new StringBuffer().append( theValue );
+ int theLength = theStringBuffer.length();
+ if ( theLength > sAuthBufferSize )
+ {
+ theStringBuffer.delete( sAuthBufferSize + 1, theLength );
+ }
+ else
+ if ( theLength < sAuthBufferSize )
+ {
+ int theExtraCharacters = sAuthBufferSize - theLength;
+ for ( int theIndex = 0; theIndex < theExtraCharacters; theIndex ++ )
+ {
+ theStringBuffer.append( ( int )0 );
+ }
+ }
+ mResponse = theStringBuffer.toString().getBytes();
+ theOutputStream.write( mResponse );
+ theOutputStream.close();
+ }
+
+}
diff --git a/src/com/sun/apoc/daemon/misc/APOCException.java b/src/com/sun/apoc/daemon/misc/APOCException.java
new file mode 100644
index 0000000..b84033a
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/APOCException.java
@@ -0,0 +1,98 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import com.sun.apoc.spi.*;
+
+public class APOCException extends Exception
+{
+ private int mCode = APOCSymbols.sSymRespUnknownFailure;
+
+ public APOCException(){}
+
+ public APOCException( final int inCode )
+ {
+ this( inCode, null );
+ }
+
+ public APOCException( final Throwable inThrowable )
+ {
+ this( APOCSymbols.sSymRespUnknownFailure, inThrowable );
+ mCode = getCode( inThrowable );
+ }
+
+ public APOCException( final int inCode, final Throwable inThrowable )
+ {
+ super( inThrowable );
+ mCode = inCode;
+ }
+
+ public int getCode() { return mCode; }
+
+ private int getCode( final Throwable inThrowable )
+ {
+ int theCode = APOCSymbols.sSymRespUnknownFailure;
+ if ( inThrowable != null )
+ {
+ if ( inThrowable instanceof SPIException )
+ {
+ theCode = getCode( ( SPIException )inThrowable );
+ }
+ }
+ return theCode;
+ }
+
+ private int getCode( final SPIException inException )
+ {
+ int theCode = APOCSymbols.sSymRespUnknownFailure;
+ final String theStringCode =
+ inException.getLocalizedErrorMessageCode();
+ if ( theStringCode != null )
+ {
+ if ( theStringCode.compareTo(
+ SPIException.ERROR_OPEN_CONNECTION ) == 0 )
+ {
+ theCode = APOCSymbols.sSymRespConnectionFailure;
+ }
+ else
+ if ( theStringCode.compareTo(
+ SPIException.ERROR_USER_INVALID ) == 0 )
+ {
+ theCode = APOCSymbols.sSymRespAuthenticationFailure;
+ }
+ }
+ return theCode;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/APOCLogger.java b/src/com/sun/apoc/daemon/misc/APOCLogger.java
new file mode 100644
index 0000000..cab6c00
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/APOCLogger.java
@@ -0,0 +1,227 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import com.sun.apoc.daemon.config.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.logging.*;
+
+public class APOCLogger
+{
+ private static final String sLoggerName = "com.sun.apoc.daemon";
+ private static final String sLogDir = "/Logs";
+ private static final String sLogFile = "/apocd.log";
+ private static final Logger sLogger =
+ ConfigurableLogger.getLogger( sLoggerName, sLoggerName );
+ private static final int sLimit = 1000000;
+ private static final int sCount = 5;
+
+ static
+ {
+ try
+ {
+ final Handler theHandler =
+ createHandler(
+ DaemonConfig.getStringProperty( DaemonConfig.sDataDir ) );
+ final Level theLevel =
+ Level.parse(
+ DaemonConfig.getStringProperty( DaemonConfig.sLogLevel ) );
+ theHandler.setLevel( theLevel );
+ theHandler.setFormatter( new SimpleFormatter() );
+
+ sLogger.addHandler( theHandler );
+ sLogger.setLevel( theLevel );
+ }
+ catch( Exception theException )
+ {
+ theException.printStackTrace();
+ }
+ }
+
+ public static void config( final String inKey )
+ {
+ sLogger.log( Level.CONFIG, inKey );
+ }
+
+ public static void config( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.CONFIG, inKey, inParam );
+ }
+
+ public static void fine( final String inKey )
+ {
+ sLogger.log( Level.FINE, inKey );
+ }
+
+ public static void fine( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.FINE, inKey, inParam );
+ }
+
+ public static void finer( final String inKey )
+ {
+ sLogger.log( Level.FINER, inKey );
+ }
+
+ public static void finer( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.FINER, inKey, inParam );
+ }
+
+ public static void finest( final String inKey )
+ {
+ sLogger.log( Level.FINEST, inKey );
+ }
+
+ public static void finest( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.FINEST, inKey, inParam );
+ }
+
+ public static boolean isLoggable( final Level inLevel )
+ {
+ return sLogger.isLoggable( inLevel );
+ }
+
+ public static void info( final String inKey )
+ {
+ sLogger.log( Level.INFO, inKey );
+ }
+
+ public static void info( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.INFO, inKey, inParam );
+ }
+
+ public static void severe( final String inKey )
+ {
+ sLogger.log( Level.SEVERE, inKey );
+ }
+
+ public static void severe( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.SEVERE, inKey, inParam );
+ }
+
+ public static void throwing( final String inClass,
+ final String inMethod,
+ final Throwable inThrowable )
+ {
+ sLogger.throwing( inClass, inMethod, inThrowable );
+ }
+
+ public static void warning( final String inKey )
+ {
+ sLogger.log( Level.WARNING, inKey );
+ }
+
+ public static void warning( final String inKey, final Object inParam )
+ {
+ sLogger.log( Level.WARNING, inKey, inParam );
+ }
+
+ public static void warning( final String inKey, final Object[] inParams )
+ {
+ sLogger.log( Level.WARNING, inKey, inParams );
+ }
+
+ private static Handler createHandler( final String inDataDir )
+ {
+ Handler theHandler;
+ if ( needFileHandler() && inDataDir != null )
+ {
+ final String theLogDir =
+ new StringBuffer( inDataDir ).append( sLogDir ).toString();
+ createLogDir( theLogDir );
+ try
+ {
+ theHandler =
+ new FileHandler(
+ new StringBuffer( theLogDir )
+ .append( sLogFile )
+ .toString(),
+ sLimit,
+ sCount,
+ true );
+ }
+ catch( Exception theException )
+ {
+ System.err.println("Warning:Failed to create log file handler");
+ theHandler = new ConsoleHandler();
+ }
+ }
+ else
+ {
+ theHandler = new ConsoleHandler();
+ }
+ return theHandler;
+ }
+
+ private static void createLogDir( final String inLogDir )
+ {
+ final File theFile = new File( inLogDir );
+ if ( ! theFile.exists() )
+ {
+ if ( ! theFile.mkdirs() )
+ {
+ System.err.println( "Warning: Cannot create Log directory '" +
+ inLogDir + "'" );
+ }
+ }
+ else
+ {
+ if ( ! theFile.isDirectory() )
+ {
+ System.err.println( "Warning: Log directory '" +
+ inLogDir +
+ "' is actually a file" );
+ }
+ }
+ }
+
+ private static boolean needFileHandler()
+ {
+ boolean needsFileHandler = false;
+ final String theHandler = DaemonConfig.getStringProperty( "handlers" );
+ if ( theHandler == null ||
+ theHandler.compareTo( "java.util.logging.FileHandler" ) == 0 )
+ {
+ needsFileHandler = true;
+ }
+ return needsFileHandler;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/APOCSymbols.java b/src/com/sun/apoc/daemon/misc/APOCSymbols.java
new file mode 100644
index 0000000..8e09528
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/APOCSymbols.java
@@ -0,0 +1,246 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import java.util.*;
+
+public class APOCSymbols
+{
+ public static final int sSymUnknown = 0;
+
+
+ // Protocol Stuff
+ // Binding
+ public static final String sContentLength = "CONTENT-LENGTH:";
+
+ public static final int sSymContentLength = 1;
+
+ // Message Names - Requests
+ public static final String sReqAddListener = "addListener";
+ public static final String sReqCreateSession = "createSession";
+ public static final String sReqDestroySession = "destroySession";
+ public static final String sReqList = "list";
+ public static final String sReqRead = "read";
+ public static final String sReqRemoveListener = "removeListener";
+ public static final String sReqCreateSessionExt = "createSessionExt";
+
+ public static final int sSymReqAddListener = 11;
+ public static final int sSymReqCreateSession = 12;
+ public static final int sSymReqDestroySession = 13;
+ public static final int sSymReqList = 14;
+ public static final int sSymReqRead = 15;
+ public static final int sSymReqRemoveListener = 16;
+ public static final int sSymReqCreateSessionExt = 17;
+
+ // Message Names - Responses
+ public static final String sRespSuccess = "success";
+ public static final String sRespInvalidRequest =
+ "invalidRequest";
+ public static final String sRespConnectionFailure =
+ "connectionFailure";
+ public static final String sRespAuthenticationFailure =
+ "authenticationFailure";
+ public static final String sRespInvalidSessionId =
+ "invalidSessionId";
+ public static final String sRespNoSuchComponent =
+ "noSuchComponent";
+ public static final String sRespUnknownFailure =
+ "unknownFailure";
+ public static final String sRespSuccessContinueLocalAuth =
+ "successContinueLocalAuth";
+ public static final String sRespSuccessContinueSASLAuth =
+ "successContinueSASLAuth";
+
+ public static final int sSymRespSuccess = 20;
+ public static final int sSymRespInvalidRequest = 21;
+ public static final int sSymRespConnectionFailure = 22;
+ public static final int sSymRespAuthenticationFailure = 23;
+ public static final int sSymRespInvalidSessionId = 24;
+ public static final int sSymRespNoSuchComponent = 25;
+ public static final int sSymRespUnknownFailure = 26;
+ public static final int sSymRespSuccessContinueLocalAuth= 27;
+ public static final int sSymRespSuccessContinueSASLAuth = 28;
+
+ // Message Names - Notification
+ public static final String sAddNotification = "addNotification";
+ public static final String sRemoveNotification = "removeNotification";
+ public static final String sModifyNotification = "modifyNotification";
+
+ public static final int sSymAddNotification = 30;
+ public static final int sSymRemoveNotification = 31;
+ public static final int sSymModifyNotification = 32;
+
+ // Message Parameters
+ public static final String sParamUserId = "userId";
+ public static final String sParamEntityId = "entityId";
+ public static final String sParamCredentials = "credentials";
+ public static final String sParamSessionId = "sessionId";
+ public static final String sParamComponentName = "componentName";
+ public static final String sParamClientData = "clientData";
+ public static final String sParamMessage = "message";
+ public static final String sParamVersion = "version";
+ public static final String sParamServer = "server";
+ public static final String sParamAuthType = "authType";
+ public static final String sParamLayer = "layer";
+ public static final String sParamEntityType = "entityType";
+
+ public static final int sSymParamUserId = 40;
+ public static final int sSymParamEntityId = 41;
+ public static final int sSymParamCredentials = 42;
+ public static final int sSymParamSessionId = 43;
+ public static final int sSymParamComponentName = 44;
+ public static final int sSymParamClientData = 45;
+ public static final int sSymParamMessage = 46;
+ public static final int sSymParamVersion = 47;
+ public static final int sSymParamServer = 48;
+ public static final int sSymParamAuthType = 49;
+ public static final int sSymParamLayer = 50;
+ public static final int sSymParamEntityType = 51;
+
+ // Misc
+ public static final String sDBCreateFailed =
+ "Failed to create a db handle";
+ public static final String sDBEnvCreateFailed =
+ "Failed to create a db environment handle";
+ public static final String sCreateServerChannelFailed =
+ "Failed to create a server channel";
+
+ public static final int sSymDBCreateFailed = 60;
+ public static final int sSymDBEnvCreateFailed = 61;
+ public static final int sSymCreateServerChannelFailed = 62;
+
+ private static final Hashtable sProtocolSyms = new Hashtable();
+ private static final Hashtable sProtocolStrs = new Hashtable();
+
+ static
+ {
+ addEntries( sContentLength,
+ new Integer( sSymContentLength ) );
+ addEntries( sReqAddListener,
+ new Integer( sSymReqAddListener ) );
+ addEntries( sReqCreateSession,
+ new Integer( sSymReqCreateSession ) );
+ addEntries( sReqDestroySession,
+ new Integer( sSymReqDestroySession ) );
+ addEntries( sReqList,
+ new Integer( sSymReqList ) );
+ addEntries( sReqRead,
+ new Integer( sSymReqRead ) );
+ addEntries( sReqRemoveListener,
+ new Integer( sSymReqRemoveListener ) );
+ addEntries( sReqCreateSessionExt,
+ new Integer( sSymReqCreateSessionExt ) );
+ addEntries( sRespSuccess,
+ new Integer( sSymRespSuccess ) );
+ addEntries( sRespInvalidRequest,
+ new Integer( sSymRespInvalidRequest ) );
+ addEntries( sRespConnectionFailure,
+ new Integer( sSymRespConnectionFailure ) );
+ addEntries( sRespAuthenticationFailure,
+ new Integer( sSymRespAuthenticationFailure ) );
+ addEntries( sRespInvalidSessionId,
+ new Integer( sSymRespInvalidSessionId ) );
+ addEntries( sRespNoSuchComponent,
+ new Integer( sSymRespNoSuchComponent ) );
+ addEntries( sRespUnknownFailure,
+ new Integer( sSymRespUnknownFailure ) );
+ addEntries( sRespSuccessContinueLocalAuth,
+ new Integer( sSymRespSuccessContinueLocalAuth ) );
+ addEntries( sRespSuccessContinueSASLAuth,
+ new Integer( sSymRespSuccessContinueSASLAuth ) );
+ addEntries( sAddNotification,
+ new Integer( sSymAddNotification ) );
+ addEntries( sRemoveNotification,
+ new Integer( sSymRemoveNotification ) );
+ addEntries( sModifyNotification,
+ new Integer( sSymModifyNotification ) );
+ addEntries( sParamUserId,
+ new Integer( sSymParamUserId ) );
+ addEntries( sParamEntityId,
+ new Integer( sSymParamEntityId ) );
+ addEntries( sParamCredentials,
+ new Integer( sSymParamCredentials ) );
+ addEntries( sParamSessionId,
+ new Integer( sSymParamSessionId ) );
+ addEntries( sParamComponentName,
+ new Integer( sSymParamComponentName ) );
+ addEntries( sParamClientData,
+ new Integer( sSymParamClientData ) );
+ addEntries( sParamMessage,
+ new Integer( sSymParamMessage ) );
+ addEntries( sParamVersion,
+ new Integer( sSymParamVersion ) );
+ addEntries( sParamServer,
+ new Integer( sSymParamServer ) );
+ addEntries( sParamAuthType,
+ new Integer( sSymParamAuthType ) );
+ addEntries( sParamLayer,
+ new Integer( sSymParamLayer ) );
+ addEntries( sParamEntityType,
+ new Integer( sSymParamEntityType ) );
+ addEntries( sDBCreateFailed,
+ new Integer( sSymDBCreateFailed ) );
+ addEntries( sDBEnvCreateFailed,
+ new Integer( sSymDBEnvCreateFailed ) );
+ addEntries( sCreateServerChannelFailed,
+ new Integer( sSymCreateServerChannelFailed ) );
+ }
+
+ private static void addEntries( final String inProtocolString,
+ final Integer inProtocolSymbol )
+ {
+ sProtocolSyms.put( inProtocolString, inProtocolSymbol );
+ sProtocolStrs.put( inProtocolSymbol, inProtocolString );
+ }
+
+ public static int getProtocolSymbol( final String inString )
+ {
+ int theSym = sSymUnknown;
+ if ( inString != null )
+ {
+ final Integer theValue = ( Integer )sProtocolSyms.get( inString );
+ if ( theValue != null )
+ {
+ theSym = theValue.intValue();
+ }
+ }
+ return theSym;
+ }
+
+ public static String getProtocolString( final int inSymbol )
+ {
+ return ( String )sProtocolStrs.get( new Integer( inSymbol ) );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/ConfigurableLogger.java b/src/com/sun/apoc/daemon/misc/ConfigurableLogger.java
new file mode 100644
index 0000000..8753741
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/ConfigurableLogger.java
@@ -0,0 +1,72 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import com.sun.apoc.daemon.config.*;
+
+import java.util.logging.*;
+
+public class ConfigurableLogger extends Logger
+ implements ConfigEventListener
+{
+ protected ConfigurableLogger( String inLoggerName,
+ String inResourceBundleName )
+ {
+ super( inLoggerName, inResourceBundleName );
+ DaemonConfig.addConfigEventListener( this );
+ }
+
+ public static Logger getLogger( String inLoggerName,
+ String inResourceBundleName )
+ {
+ return new ConfigurableLogger( inLoggerName, inResourceBundleName);
+ }
+
+ public void onConfigEvent()
+ {
+ final Level theLevel =
+ Level.parse(
+ DaemonConfig.getStringProperty( DaemonConfig.sLogLevel ) );
+ setLevel( theLevel );
+ final Handler[] theHandlers = getHandlers();
+ if ( theHandlers != null )
+ {
+ for ( int theIndex = 0; theIndex < theHandlers.length; ++ theIndex )
+ {
+ theHandlers[ theIndex ].setLevel( theLevel );
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/DaemonTimerTask.java b/src/com/sun/apoc/daemon/misc/DaemonTimerTask.java
new file mode 100644
index 0000000..312bfa5
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/DaemonTimerTask.java
@@ -0,0 +1,110 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+import java.util.*;
+
+public class DaemonTimerTask
+{
+ private Runnable mRunnable;
+ private long mPeriod = 0;
+ private TimerTask mTimerTask = null;
+ private boolean mIsOneTime = false;
+ private static final Timer sTimer = new Timer( true );
+
+ public DaemonTimerTask( final Runnable inRunnable )
+ {
+ mRunnable = inRunnable;
+ }
+
+ public DaemonTimerTask( final Runnable inRunnable, boolean inIsOneTime )
+ {
+ this( inRunnable );
+ mIsOneTime = inIsOneTime;
+ }
+
+ public void cancel()
+ {
+ setPeriod( -1 );
+ }
+
+ public long getPeriod()
+ {
+ return mPeriod;
+ }
+
+ public boolean setPeriod( long inPeriod )
+ {
+ boolean isChanged = false;
+ if ( inPeriod != mPeriod )
+ {
+ mPeriod = inPeriod;
+ schedule();
+ isChanged = true;
+ }
+ return isChanged;
+ }
+
+ private void schedule()
+ {
+ if ( mPeriod > 0 )
+ {
+ if ( mTimerTask != null )
+ {
+ mTimerTask.cancel();
+ }
+ mTimerTask = new Task();
+ sTimer.schedule( mTimerTask, mPeriod, mPeriod );
+ }
+ else
+ if ( mTimerTask != null )
+ {
+ mTimerTask.cancel();
+ mTimerTask = null;
+ }
+ }
+
+ class Task extends TimerTask
+ {
+ public void run()
+ {
+ mRunnable.run();
+ if ( mIsOneTime )
+ {
+ cancel();
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/misc/FileAccess.java b/src/com/sun/apoc/daemon/misc/FileAccess.java
new file mode 100644
index 0000000..f3b3b02
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/FileAccess.java
@@ -0,0 +1,42 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+public class FileAccess
+{
+ public static native int chmod( final String inFileName, int inMode );
+ public static native int chown( final String inFileName,
+ final String inUserName );
+}
diff --git a/src/com/sun/apoc/daemon/misc/Name.java b/src/com/sun/apoc/daemon/misc/Name.java
new file mode 100644
index 0000000..cc5f9be
--- /dev/null
+++ b/src/com/sun/apoc/daemon/misc/Name.java
@@ -0,0 +1,128 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.misc;
+
+public class Name
+{
+ // Location
+ private static int sLocationLocal = 0;
+ private static int sLocationGlobal = 1;
+
+ // Applicability
+ private static int sApplicabilityHost = 2;
+ private static int sApplicabilityUser = 3;
+
+ // Entities
+ private static int sEntityLocalHost = 4;
+ private static int sEntityLocalUser = 5;
+
+ private static int sUndefined = 6;
+
+ private static final String sLocationLocalStr = "local";
+ private static final String sLocationGlobalStr = "global";
+ private static final String sApplicabilityHostStr = "host";
+ private static final String sApplicabilityUserStr = "user";
+ public static final String sEntityLocalHostStr = "localHost";
+ public static final String sEntityLocalUserStr = "localUser";
+
+ public static final String sSep = "/";
+
+ public static final String sNames[] =
+ {
+ sLocationLocalStr,
+ sLocationGlobalStr,
+ sApplicabilityHostStr,
+ sApplicabilityUserStr,
+ sEntityLocalHostStr,
+ sEntityLocalUserStr
+ };
+
+ private String mUserName;
+ private String mEntityType;
+ private String mEntityName;
+ private boolean mIsLocal;
+
+ public Name( final String inUserName,
+ final String inEntityType,
+ final String inEntityName,
+ boolean inIsLocal )
+ {
+ mUserName = inUserName;
+ mEntityType = inEntityType;
+ mEntityName = inEntityName;
+ mIsLocal = inIsLocal;
+ }
+ public Name( final String inUserName,
+ final String inEntityType,
+ final String inEntityName,
+ final String inIsLocal )
+ {
+ mUserName = inUserName ;
+ mEntityType = inEntityType ;
+ mEntityName = inEntityName ;
+ mIsLocal = inIsLocal.compareTo(sLocationLocalStr) == 0 ;
+ }
+
+ public String getUserName() { return mUserName; }
+
+ public String getEntityType() { return mEntityType; }
+
+ public String getEntityName() { return mEntityName; }
+
+ public String getLocation()
+ {
+ return sNames[ getLocationAsInt() ];
+ }
+
+ public int getLocationAsInt()
+ {
+ return mIsLocal ? sLocationLocal : sLocationGlobal;
+ }
+
+ public boolean isLocal() { return mIsLocal; }
+ public boolean isGlobal() { return ! isLocal(); }
+
+ public String toString()
+ {
+ return new StringBuffer(mUserName)
+ .append(sSep)
+ .append(mEntityType)
+ .append(sSep)
+ .append(mEntityName)
+ .append(sSep)
+ .append(getLocation())
+ .toString() ;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/properties/apocd.properties b/src/com/sun/apoc/daemon/properties/apocd.properties
new file mode 100644
index 0000000..bdb350f
--- /dev/null
+++ b/src/com/sun/apoc/daemon/properties/apocd.properties
@@ -0,0 +1,66 @@
+#
+# The port used by the APOC daemon for client requests
+#
+#DaemonPort=3809
+
+#
+# The maximum number of client threads dictates the number of client requests
+# which may be executed simultaneously.
+#
+#MaxClientThreads=5
+
+#
+# The maximum number of client connections allowed
+#
+#MaxClientConnections=50
+
+#
+# The maximum size of requests issued by clients
+#
+#MaxRequestSize=4096
+
+#
+# The interval ( in minutes ) between change detections for daemon config.
+# data
+#
+#DaemonChangeDetectionInterval=10
+
+#
+# The interval ( in minutes ) between change detection for the local database
+#
+#ChangeDetectionInterval=60
+
+#
+# The delay ( in seconds ) between a user session creation and an initial
+# change detection for that user ( if one is due )
+#
+#InitialChangeDetectionDelay=10
+
+#
+# The local database garbage collection interval ( in minutes )
+#
+#GarbageCollectionInterval=10080
+
+#
+# The length of time ( in minutes ) since last read, which non offline
+# components will remain in the local database
+#
+#TimeToLive=10080
+
+#
+# Daemon Log level
+#
+#LogLevel=INFO
+
+#
+# Whether or not local policy should be applied ( if available )
+#ApplyLocalPolicy=true
+
+#
+# The number of seconds after which an uncompleted transaction will be
+# cancelled. A minimum value of 1 second is imposed.
+#TransactionTimeout=15
+
+#
+# The maximum number of Berkeley DB locks available
+#MaxDatabaseLocks=12000
diff --git a/src/com/sun/apoc/daemon/properties/daemon.properties b/src/com/sun/apoc/daemon/properties/daemon.properties
new file mode 100644
index 0000000..2d54129
--- /dev/null
+++ b/src/com/sun/apoc/daemon/properties/daemon.properties
@@ -0,0 +1,82 @@
+#com.sun.apoc.daemon.admin.AdminManager
+Admr001=Admin manager started
+Admr002=Admin manager stopped
+
+#com.sun.apoc.daemon.apocd.ClientManager
+Clmr001=Client manager started
+Clmr002=Client removed
+Clmr003=Failed to resize thread pool
+Clmr004=Change detection scheduled ( interval = {0} minutes )
+Clmr005=New client added
+Clmr006=Change detection switched off
+Clmr007=Client manager stopped
+
+#com.sun.apoc.daemon.apocd.Daemon
+Dmon001=Daemon starting
+Dmon002=Daemon finishing
+Dmon003=Garbage collection scheduled ( interval = {0} minutes )
+Dmon004=Garbage collection switched off
+
+#com.sun.apoc.daemon.apocd.Session
+Sess001=Creating new client session
+Sess002=New client session created:\n{0}\n
+Sess003=Client session ( sessionId = {0} ) closed
+
+#com.sun.apoc.daemon.config.DaemonConfig
+Dcfg001=Daemon configuration:\n{0}\n
+
+#com.sun.apoc.daemon.messaging.Messenger
+Msgr001=Failed to send response
+
+#com.sun.apoc.daemon.messaging.ProtocolUnbinder
+Punb001=Configured value of MaxRequestSize, {0}, is less than the minimum allowed value ( {1} ). Adjusting MaxRequestsize to {1}.
+
+#com.sun.apoc.daemon.misc.APOCAuthenticator
+Auth001=Authenticating user {0}
+Auth002=Authentication successful
+Auth003=Authentication failed
+
+#com.sun.apoc.daemon.transaction.AddListenerTransaction
+Altn001=AddListener transaction started
+Altn002=AddListener transaction completed
+
+#com.sun.apoc.daemon.transaction.ChangeDetectTransaction
+Cdtn001=ChangeDetect transaction started
+Cdtn002=ChangeDetect transaction completed
+Cdtn003=Notification sent:\n{0}\n
+
+#com.sun.apoc.daemon.transaction.CreateSessionTransaction
+Cstn001=CreateSession transaction started
+Cstn002=CreateSession transaction completed
+
+#com.sun.apoc.daemon.transaction.DestroySessionTransaction
+Dstn001=DestroySession transaction started
+Dstn002=DestroySession transaction completed
+
+#com.sun.apoc.daemon.transaction.GarbageCollectTransaction
+Gctn001=GarbageCollect transaction started
+Gctn002=GarbageCollect transaction completed
+
+#com.sun.apoc.daemon.transaction.ListTransaction
+Lstn001=List transaction started
+Lstn002=List transaction completed
+
+#com.sun.apoc.daemon.transaction.ReadTransaction
+Rdtn001=Read transaction started
+Rdtn002=Read transaction completed
+
+#com.sun.apoc.daemon.transaction.RemoveListenerTransaction
+Rltn001=RemoveListener transaction started
+Rltn002=RemoveListener transaction completed
+
+#com.sun.apoc.daemon.transport.ChannelManager
+Chmr001=Channel manager started
+Chmr002=The maximum number of client connections ( {0} ) has been reached. No new client connections can be established at this time.
+Chmr003=Channel manager stopped
+
+#com.sun.apoc.daemon.transport.ClientChannel
+Clch001=Error while changing channel state ... closing channel
+Clch002=Unexpected EOF while reading client channel
+
+#com.sun.apoc.daemon.transport.ServerChannel
+Svch001=Error while accepting new client channel
diff --git a/src/com/sun/apoc/daemon/properties/defaults.properties b/src/com/sun/apoc/daemon/properties/defaults.properties
new file mode 100644
index 0000000..ae78be6
--- /dev/null
+++ b/src/com/sun/apoc/daemon/properties/defaults.properties
@@ -0,0 +1,83 @@
+#
+# The port used by the APOC daemon for client requests
+#
+DaemonPort=3809
+
+#
+# The maximum number of client threads dictates the number of client requests
+# which may be executed simultaneously.
+#
+MaxClientThreads=5
+
+#
+# The maximum number of client connections allowed
+#
+MaxClientConnections=50
+
+#
+# The maximum size of requests issued by clients
+#
+MaxRequestSize=4096
+
+#
+# The interval ( in minutes ) between change detections for daemon config.
+# data
+#
+DaemonChangeDetectionInterval=10
+
+#
+# The interval ( in minutes ) between change detection for the local database
+#
+ChangeDetectionInterval=60
+
+#
+# The delay ( in seconds ) between a user session creation and an initial
+# change detection for that user ( if one is due )
+#
+InitialChangeDetectionDelay=10
+
+#
+# The local database garbage collection interval ( in minutes )
+#
+GarbageCollectionInterval=10080
+
+#
+# The length of time ( in minutes ) since last read, which non offline
+# components will remain in the local database
+#
+TimeToLive=10080
+
+#
+# The interval ( in minutes ) between detection and removal of idle threads
+#
+IdleThreadDetectionInterval=15
+
+#
+# The length of time ( in minutes ) a thread may remain idle before being
+# removed
+#
+ThreadTimeToLive=5
+
+#
+# The length of time ( in milliseconds ) to wait before timing out a read on
+# client connections
+#
+ConnectionReadTimeout=5000
+
+#
+# Daemon Log level
+#
+LogLevel=INFO
+
+#
+# Whether or not local policy should be applied ( if available )
+ApplyLocalPolicy=true
+
+#
+# The number of seconds after which an uncompleted transaction will be
+# cancelled. A minimum value of 1 second is imposed.
+TransactionTimeout=15
+
+#
+# The maximum number of Berkeley DB locks available
+MaxDatabaseLocks=12000
diff --git a/src/com/sun/apoc/daemon/properties/os.properties.in b/src/com/sun/apoc/daemon/properties/os.properties.in
new file mode 100644
index 0000000..b7e1485
--- /dev/null
+++ b/src/com/sun/apoc/daemon/properties/os.properties.in
@@ -0,0 +1,4 @@
+#
+# The daemon data directory ... where databases, logs etc. are kept
+#
+DataDir=@APOC_DATADIR@
diff --git a/src/com/sun/apoc/daemon/properties/policymgr.properties b/src/com/sun/apoc/daemon/properties/policymgr.properties
new file mode 100644
index 0000000..baeee3b
--- /dev/null
+++ b/src/com/sun/apoc/daemon/properties/policymgr.properties
@@ -0,0 +1,9 @@
+#-----------------------------#
+# Basic Configuration Example #
+#-----------------------------#
+
+#PROVIDER_URL = ldap://server1.freedesktop.org:389/o=mySuffixDn
+#AuthType=Anonymous
+#AuthDn=
+#Password=
+#ConnectTimeout=1
diff --git a/src/com/sun/apoc/daemon/transaction/AddListenerTransaction.java b/src/com/sun/apoc/daemon/transaction/AddListenerTransaction.java
new file mode 100644
index 0000000..e4a2522
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/AddListenerTransaction.java
@@ -0,0 +1,58 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+class AddListenerTransaction extends Transaction
+{
+ public AddListenerTransaction( final Client inClient,
+ final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ public void executeTransaction()
+ {
+ APOCLogger.finer( "Altn001" );
+ mSession.addListeners(
+ ( ( AddListenerMessage )mRequest ).getComponentNames(),
+ ( ( AddListenerMessage )mRequest ).getClientData() );
+ setResponse( APOCSymbols.sSymRespSuccess );
+ APOCLogger.finer( "Altn002" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/ChangeDetectTransaction.java b/src/com/sun/apoc/daemon/transaction/ChangeDetectTransaction.java
new file mode 100644
index 0000000..0c545bf
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/ChangeDetectTransaction.java
@@ -0,0 +1,128 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+import java.nio.*;
+
+public class ChangeDetectTransaction extends Transaction
+{
+ private ClientManager mClientManager;
+ private Cache mCache;
+ private UpdateAggregator mAggregator ;
+ private static final String[] sStringModel = new String[ 0 ];
+
+ public ChangeDetectTransaction( final ClientManager inClientManager,
+ final Cache inCache,
+ final UpdateAggregator inAggregator )
+ {
+ super( null, null);
+ mClientManager = inClientManager;
+ mCache = inCache;
+ mAggregator = inAggregator ;
+ }
+
+ protected void executeTransaction()
+ {
+ Session theSession = null;
+ try
+ {
+ APOCLogger.finer( "Cdtn001" );
+ //
+ // getLockedSession will try to lock 1 of the Session instances
+ // associated with database to be refreshed. If successful,
+ // the returned Session instance should be safe to use ( i.e. it
+ // wont be closed by someone else ) for the duration of the
+ // transaction. If unsuccessful, all relevant Session objects
+ // are already closed or closing so we can skip the change
+ // detection
+ //
+ theSession = getLockedSession();
+ if ( theSession != null )
+ {
+ final ArrayList theResults = mCache.changeDetect();
+ Session [] theSessions = mCache.getSessions();
+ int nbResults = theResults.size() ;
+
+ if ( nbResults > 0 )
+ {
+ for (int theIndex = 0 ; theIndex < nbResults ; ++ theIndex)
+ {
+ mAggregator.addUpdate(
+ theSessions,
+ (UpdateItem) theResults.get(theIndex)) ;
+ }
+ }
+ }
+ APOCLogger.finer( "Cdtn002" );
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "ChangeDetectTransaction",
+ "execute",
+ theException );
+ }
+ if ( theSession != null )
+ {
+ theSession.unlock();
+ }
+ }
+
+ protected boolean needSession() { return false; }
+
+ private Session getLockedSession()
+ {
+ Session theSession = null;
+ Session[] theSessions = mCache.getSessions();
+ if ( theSessions != null )
+ {
+ for ( int theIndex = 0; theIndex < theSessions.length; ++ theIndex )
+ {
+ if ( theSessions[ theIndex ].lock() )
+ {
+ theSession = theSessions[ theIndex ];
+ break;
+ }
+ }
+ }
+ return theSession;
+ }
+
+}
diff --git a/src/com/sun/apoc/daemon/transaction/CreateSessionExtTransaction.java b/src/com/sun/apoc/daemon/transaction/CreateSessionExtTransaction.java
new file mode 100644
index 0000000..312bf52
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/CreateSessionExtTransaction.java
@@ -0,0 +1,76 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+
+package com.sun.apoc.daemon.transaction ;
+
+import com.sun.apoc.daemon.apocd.Client ;
+import com.sun.apoc.daemon.apocd.Session ;
+import com.sun.apoc.daemon.messaging.CreateSessionExtMessage ;
+import com.sun.apoc.daemon.messaging.Message ;
+import com.sun.apoc.daemon.misc.APOCException ;
+import com.sun.apoc.daemon.misc.APOCLogger ;
+import com.sun.apoc.daemon.misc.APOCSymbols ;
+
+class CreateSessionExtTransaction extends Transaction {
+ public CreateSessionExtTransaction(final Client aClient,
+ final Message aMessage) {
+ super(aClient, aMessage) ;
+ }
+ protected boolean needSession() { return false ; }
+ protected void executeTransaction() {
+ try {
+ APOCLogger.finer("Cstn001") ;
+ CreateSessionExtMessage message =
+ (CreateSessionExtMessage) mRequest ;
+
+ mSession = new Session(mClient, message.getUserId(),
+ message.getEntities()) ;
+ mClient.addSession(mSession) ;
+ setResponse(APOCSymbols.sSymRespSuccess, mSession.getSessionId()) ;
+ APOCLogger.finer("Cstn002") ;
+ }
+ catch (APOCException exception) {
+ setResponse(exception.getCode()) ;
+ APOCLogger.throwing("CreateSessionExtTransaction",
+ "executeTransaction", exception) ;
+ }
+ catch (Exception exception) {
+ setResponse(APOCSymbols.sSymRespUnknownFailure) ;
+ APOCLogger.throwing("CreateSessionExtTransaction",
+ "executeTransaction", exception) ;
+ }
+ }
+}
+
diff --git a/src/com/sun/apoc/daemon/transaction/CreateSessionTransaction.java b/src/com/sun/apoc/daemon/transaction/CreateSessionTransaction.java
new file mode 100644
index 0000000..e759397
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/CreateSessionTransaction.java
@@ -0,0 +1,81 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+class CreateSessionTransaction extends Transaction
+{
+ public CreateSessionTransaction( final Client inClient,
+ final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ protected boolean needSession() { return false; }
+
+ protected void executeTransaction()
+ {
+ try
+ {
+ APOCLogger.finer( "Cstn001" );
+ final CreateSessionMessage theMessage =
+ ( CreateSessionMessage )mRequest;
+ mSession = new Session( mClient,
+ theMessage.getUserId(),
+ theMessage.getEntityId() );
+ mClient.addSession( mSession );
+ setResponse( APOCSymbols.sSymRespSuccess,
+ mSession.getSessionId() );
+ APOCLogger.finer( "Cstn002" );
+ }
+ catch ( APOCException theException )
+ {
+ setResponse( theException.getCode() );
+ APOCLogger.throwing( "CreateSessionTransaction",
+ "executeTransaction",
+ theException );
+ }
+ catch ( Exception theException )
+ {
+ setResponse( APOCSymbols.sSymRespUnknownFailure );
+ APOCLogger.throwing( "CreateSessionTransaction",
+ "executeTransaction",
+ theException );
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/DestroySessionTransaction.java b/src/com/sun/apoc/daemon/transaction/DestroySessionTransaction.java
new file mode 100644
index 0000000..4167cea
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/DestroySessionTransaction.java
@@ -0,0 +1,56 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+class DestroySessionTransaction extends Transaction
+{
+ public DestroySessionTransaction( final Client inClient,
+ final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ public void executeTransaction()
+ {
+ APOCLogger.finer( "Dstn001" );
+ mClient.closeSession( mSession );
+ setResponse( APOCSymbols.sSymRespSuccess );
+ APOCLogger.finer( "Dstn002" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/GarbageCollectTransaction.java b/src/com/sun/apoc/daemon/transaction/GarbageCollectTransaction.java
new file mode 100644
index 0000000..4cf92a9
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/GarbageCollectTransaction.java
@@ -0,0 +1,79 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.misc.*;
+
+public class GarbageCollectTransaction extends Transaction
+{
+ private final Database mDatabase;
+
+ public GarbageCollectTransaction( final Database inDatabase )
+ {
+ super( null, null );
+ mDatabase = inDatabase;
+ }
+
+ protected void executeTransaction()
+ {
+ try
+ {
+ APOCLogger.finer( "Gctn001" );
+ mDatabase.beginTransaction();
+ boolean shouldCollect =
+ Timestamp.getMillis( mDatabase.getLastRead() ) <=
+ ( Timestamp.getMillis( Timestamp.getTimestamp() ) -
+ ( DaemonConfig.getIntProperty( DaemonConfig.sTimeToLive ) *
+ 60000 ) );
+ mDatabase.endTransaction();
+ mDatabase.close( 0 );
+ if ( shouldCollect )
+ {
+ LocalDatabaseFactory.getInstance().deleteDatabase( mDatabase );
+ }
+ APOCLogger.finer( "Gctn002" );
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "GarbageCollectTransaction",
+ "execute",
+ theException );
+ }
+ }
+
+ protected boolean needSession() { return false; }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/ListTransaction.java b/src/com/sun/apoc/daemon/transaction/ListTransaction.java
new file mode 100644
index 0000000..404f0ae
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/ListTransaction.java
@@ -0,0 +1,82 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+
+class ListTransaction extends Transaction
+{
+ public ListTransaction( final Client inClient, final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ protected void executeTransaction()
+ {
+ APOCLogger.finer( "Lstn001" );
+ StringBuffer theBuffer = null;
+ final Cache [] theCaches = mSession.getCaches();
+ final HashSet theSet = new HashSet();
+
+ for (int theIndex = 0 ; theIndex < theCaches.length ; ++ theIndex)
+ {
+ theSet.addAll(theCaches [theIndex].list());
+ }
+ if ( theSet != null && theSet.size() > 0 )
+ {
+ final String[] theNames =
+ ( String[] )theSet.toArray( new String[ 0 ] );
+ theBuffer = new StringBuffer();
+ for ( int theIndex = 0; theIndex < theNames.length; theIndex ++)
+ {
+ theBuffer.append( "<" )
+ .append( APOCSymbols.sParamComponentName )
+ .append( ">" )
+ .append( theNames[ theIndex ] )
+ .append( "</" )
+ .append( APOCSymbols.sParamComponentName )
+ .append( ">" );
+ }
+ }
+ APOCLogger.finer( "Lstn002" );
+ setResponse( APOCSymbols.sSymRespSuccess,
+ mRequest.getSessionId(),
+ theBuffer != null ? theBuffer.toString() : "" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/ReadTransaction.java b/src/com/sun/apoc/daemon/transaction/ReadTransaction.java
new file mode 100644
index 0000000..44d0d07
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/ReadTransaction.java
@@ -0,0 +1,86 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+
+class ReadTransaction extends Transaction
+{
+ public ReadTransaction( final Client inClient, final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ protected void executeTransaction()
+ {
+ APOCLogger.finer( "Rdtn001" );
+ StringBuffer theBuffer = null;
+ final String theComponentName =
+ ( String )( ( ReadMessage )mRequest )
+ .getComponentNames().elementAt( 0 );
+ final Cache [] theCaches = mSession.getCaches();
+ final ArrayList theResults = new ArrayList();
+
+ for (int theIndex = 0 ; theIndex < theCaches.length ; ++ theIndex)
+ {
+ theResults.addAll(theCaches [theIndex].read(theComponentName));
+ }
+ if ( theResults.size() > 0 )
+ {
+ theBuffer = new StringBuffer();
+ final Iterator theIterator = theResults.iterator();
+ while ( theIterator.hasNext() )
+ {
+ CacheReadResult theResult = (CacheReadResult)theIterator.next();
+ theBuffer.append( "<" )
+ .append( APOCSymbols.sParamLayer )
+ .append( "><![CDATA[" )
+ .append( theResult.mTimestamp )
+ .append( theResult.mData )
+ .append( "]]></" )
+ .append( APOCSymbols.sParamLayer )
+ .append( ">" );
+ }
+ }
+ APOCLogger.finer( "Rdtn002" );
+ setResponse( APOCSymbols.sSymRespSuccess,
+ mRequest.getSessionId(),
+ theBuffer != null ? theBuffer.toString() : "" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/RemoveListenerTransaction.java b/src/com/sun/apoc/daemon/transaction/RemoveListenerTransaction.java
new file mode 100644
index 0000000..2d346c4
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/RemoveListenerTransaction.java
@@ -0,0 +1,57 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+class RemoveListenerTransaction extends Transaction
+{
+ public RemoveListenerTransaction( final Client inClient,
+ final Message inRequest )
+ {
+ super( inClient, inRequest );
+ }
+
+ public void executeTransaction()
+ {
+ APOCLogger.finer( "Rltn001" );
+ mSession.removeListeners(
+ ( ( RemoveListenerMessage )mRequest ).getComponentNames() );
+ setResponse( APOCSymbols.sSymRespSuccess );
+ APOCLogger.finer( "Rltn002" );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/Transaction.java b/src/com/sun/apoc/daemon/transaction/Transaction.java
new file mode 100644
index 0000000..59fee20
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/Transaction.java
@@ -0,0 +1,148 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+
+public abstract class Transaction
+{
+ protected final Client mClient;
+ protected Session mSession;
+ protected final Message mRequest;
+ protected Message mResponse;
+ private Thread mThread;
+ private Object mThreadLock = new Object();
+ private long mStartTime;
+
+ public Transaction( final Client inClient, final Message inRequest )
+ {
+ mClient = inClient;
+ mRequest = inRequest;
+ if ( inClient != null && inRequest != null )
+ {
+ mSession = inClient.getSession( mRequest.getSessionId() );
+ }
+ }
+
+ public Message execute()
+ {
+ if ( ! needSession() || mSession != null )
+ {
+ try
+ {
+ beginTransaction();
+ executeTransaction();
+ endTransaction();
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "Transaction", "execute", theException );
+ setResponse( APOCSymbols.sSymRespUnknownFailure );
+ }
+ }
+ else
+ {
+ setResponse( APOCSymbols.sSymRespInvalidSessionId );
+ }
+ return mResponse;
+ }
+
+ public long getDuration()
+ {
+ return System.currentTimeMillis() - mStartTime;
+ }
+
+ public void interrupt()
+ {
+ synchronized( mThreadLock )
+ {
+ if ( mThread != null )
+ {
+ mThread.interrupt();
+ mThread = null;
+ }
+ }
+ }
+
+ protected boolean needSession()
+ {
+ return true;
+ }
+
+ protected void beginTransaction()
+ {
+ mStartTime = System.currentTimeMillis();
+ setThread( Thread.currentThread() );
+ TransactionFactory.getInstance().addTransaction( this );
+ }
+ protected abstract void executeTransaction();
+ protected void endTransaction()
+ {
+ setThread( null );
+ TransactionFactory.getInstance().removeTransaction( this );
+ }
+
+ protected void setResponse( final int inResponseType )
+ {
+ setResponse( inResponseType, mRequest.getSessionId(), null );
+ }
+
+ protected void setResponse( final int inResponseType,
+ final String inSessionId )
+ {
+ setResponse( inResponseType, inSessionId, null );
+ }
+
+ protected void setResponse( final int inResponseType,
+ final String inSessionId,
+ final String inResponseMessage )
+ {
+ mResponse = MessageFactory.createResponse( inResponseType,
+ inSessionId,
+ inResponseMessage );
+ }
+
+ private void setThread( final Thread inThread )
+ {
+ synchronized( mThreadLock )
+ {
+ mThread = inThread;
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transaction/TransactionFactory.java b/src/com/sun/apoc/daemon/transaction/TransactionFactory.java
new file mode 100644
index 0000000..3418d7b
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transaction/TransactionFactory.java
@@ -0,0 +1,181 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transaction;
+
+import com.sun.apoc.daemon.apocd.*;
+import com.sun.apoc.daemon.localdatabase.*;
+import com.sun.apoc.daemon.messaging.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.util.*;
+
+public class TransactionFactory
+{
+
+ private static TransactionFactory sInstance;
+ private static final Transaction[] sTransactionModel =
+ new Transaction[ 0 ];
+ //private static long sTransactionTimeout = 30000;
+ private static long sTransactionTimeout = 10000;
+ private final HashSet mTransactions = new HashSet();
+ private final DaemonTimerTask mTransactionInterrupter =
+ new DaemonTimerTask( new TransactionInterrupter() );
+
+ public void addTransaction( final Transaction inTransaction )
+ {
+ synchronized( mTransactions )
+ {
+ if ( mTransactions.size() == 0 )
+ {
+ mTransactionInterrupter.setPeriod( sTransactionTimeout );
+ }
+ mTransactions.add( inTransaction );
+ }
+ }
+
+ public ChangeDetectTransaction createChangeDetectTransaction(
+ final ClientManager inClientManager,
+ final Cache inCache,
+ final UpdateAggregator inAggregator )
+ {
+ return new ChangeDetectTransaction( inClientManager,
+ inCache, inAggregator );
+ }
+
+ public GarbageCollectTransaction createGarbageCollectTransaction(
+ final Database inDatabase )
+ {
+ return new GarbageCollectTransaction( inDatabase );
+ }
+
+ public Transaction createTransaction( final Client inClient,
+ final Message inMessage )
+ {
+ Transaction theTransaction = null;
+ switch ( inMessage.getName() )
+ {
+ case APOCSymbols.sSymReqRead:
+ theTransaction = new ReadTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqAddListener:
+ theTransaction =
+ new AddListenerTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqCreateSession:
+ theTransaction =
+ new CreateSessionTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqCreateSessionExt:
+ theTransaction =
+ new CreateSessionExtTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqDestroySession:
+ theTransaction =
+ new DestroySessionTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqRemoveListener:
+ theTransaction =
+ new RemoveListenerTransaction( inClient, inMessage );
+ break;
+
+ case APOCSymbols.sSymReqList:
+ theTransaction =
+ new ListTransaction( inClient, inMessage );
+ break;
+
+ default:
+ break;
+ }
+ return theTransaction;
+ }
+
+ public static TransactionFactory getInstance()
+ {
+ if ( sInstance == null )
+ {
+ sInstance = new TransactionFactory();
+ }
+ return sInstance;
+ }
+
+ public void removeTransaction( final Transaction inTransaction )
+ {
+ synchronized( mTransactions )
+ {
+ if ( mTransactions.size() == 1 )
+ {
+ mTransactionInterrupter.cancel();
+ }
+ mTransactions.remove( inTransaction );
+ }
+ }
+
+ private TransactionFactory(){}
+
+ class TransactionInterrupter implements Runnable
+ {
+ public void run()
+ {
+ synchronized( mTransactions )
+ {
+ Transaction[] theTransactions = null;
+ if ( mTransactions.size() > 0 )
+ {
+ theTransactions =
+ ( Transaction[] )mTransactions.toArray( sTransactionModel);
+ }
+ if ( theTransactions != null && theTransactions.length > 0 )
+ {
+ for ( int theIndex = 0;
+ theIndex < theTransactions.length;
+ ++ theIndex )
+ {
+ if ( theTransactions[ theIndex ].getDuration() >
+ sTransactionTimeout )
+ {
+ theTransactions[ theIndex ].interrupt();
+ removeTransaction( theTransactions[ theIndex ] );
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transport/ChannelManager.java b/src/com/sun/apoc/daemon/transport/ChannelManager.java
new file mode 100644
index 0000000..f550350
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transport/ChannelManager.java
@@ -0,0 +1,414 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transport;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.net.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.util.*;
+import java.util.logging.*;
+
+public class ChannelManager extends Thread implements ConfigEventListener
+{
+ private Selector mSelector;
+ private ServerSocketChannel mChannel;
+ private final HashSet mRegisteringChannels =
+ new HashSet();
+ private final HashSet mDeRegisteringChannels =
+ new HashSet();
+ private final Object mLock = new Object();
+ private int mMaxClientChannels =
+ DaemonConfig.getIntProperty( DaemonConfig.sMaxClientConnections );
+ private final HashSet mClientChannelEventListeners = new HashSet();
+ private int mChannelCount = 0;
+ private boolean mTerminate = false;
+ private static final byte sReject = 0;
+ private static final byte[] sAcceptByte = { 1 };
+ private static final ByteBuffer sAccept =
+ ( ByteBuffer )ByteBuffer.wrap( sAcceptByte );
+
+ public ChannelManager()
+ throws APOCException
+ {
+ try
+ {
+ initThread();
+ initChannel();
+ DaemonConfig.addConfigEventListener( this );
+ }
+ catch( IOException theException )
+ {
+ throw new APOCException(
+ APOCSymbols.sSymCreateServerChannelFailed,
+ theException );
+ }
+ }
+
+ public void addClientChannelEventListener(
+ final ClientChannelEventListener inListener )
+ {
+ if ( inListener != null )
+ {
+ synchronized( mClientChannelEventListeners )
+ {
+ mClientChannelEventListeners.add( inListener );
+ }
+ }
+ }
+
+ public void closeClientChannels()
+ {
+ final Set theKeys = mSelector.keys();
+ if ( theKeys != null )
+ {
+ final Iterator theIterator = theKeys.iterator();
+ while ( theIterator.hasNext() )
+ {
+ final SelectionKey theKey =
+ ( SelectionKey )theIterator.next();
+ if ( theKey.isValid() )
+ {
+ try
+ {
+ theKey.channel().close();
+ }
+ catch( IOException theException )
+ {}
+ }
+ }
+ }
+ }
+
+ public void closeChannels()
+ {
+ closeClientChannels();
+ closeServerChannel();
+ }
+
+ public void onConfigEvent()
+ {
+ setMaxClientChannels();
+ }
+
+ public void removeClientChannelEventListener(
+ final ClientChannelEventListener inListener )
+ {
+ if ( inListener != null )
+ {
+ synchronized( mClientChannelEventListeners )
+ {
+ mClientChannelEventListeners.remove( inListener );
+ }
+ }
+ }
+
+ public void run()
+ {
+ APOCLogger.fine( "Chmr001" );
+ while ( ! shouldTerminate() )
+ {
+ try
+ {
+ selectChannels();
+ registerChannels();
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "ChannelManager", "run", theException );
+ break;
+ }
+ }
+ APOCLogger.fine( "Chmr003" );
+ }
+
+ public void terminate()
+ {
+ synchronized( mLock )
+ {
+ mTerminate = true;
+ }
+ mSelector.wakeup();
+ }
+
+ void closeClientChannel( final ClientChannel inChannel )
+ {
+ inChannel.close();
+ notifyClosed( inChannel );
+ synchronized( mLock )
+ {
+ -- mChannelCount;
+ }
+ }
+
+ void registerForSelection( final ClientChannel inChannel,boolean inRegister)
+ {
+ final HashSet theSet = inRegister ?
+ mRegisteringChannels : mDeRegisteringChannels;
+ synchronized( theSet )
+ {
+ theSet. add( inChannel.getSocketChannel().keyFor( mSelector ) );
+ mSelector.wakeup();
+ try
+ {
+ theSet.wait();
+ }
+ catch( Exception theException )
+ {}
+ }
+ }
+
+ private void acceptableKey( final SelectionKey inKey )
+ {
+ SocketChannel theSocketChannel = null;
+ try
+ {
+ theSocketChannel =
+ ( ( ServerSocketChannel )inKey.channel() ).accept();
+ if ( ! testMaxChannels() && theSocketChannel != null )
+ {
+ try
+ {
+ theSocketChannel.socket()
+ .getOutputStream().write( sReject );
+ theSocketChannel.close();
+ }
+ catch( Exception theException ){}
+ return;
+ }
+ if ( theSocketChannel.
+ socket().
+ getInetAddress().
+ isLoopbackAddress() )
+ {
+ theSocketChannel.configureBlocking( false );
+ final SelectionKey theClientKey =
+ theSocketChannel.register(
+ mSelector,
+ SelectionKey.OP_READ );
+ ClientChannel theClientChannel =
+ new ClientChannel( theSocketChannel, this );
+ theClientKey.attach( theClientChannel );
+ synchronized( mLock )
+ {
+ ++ mChannelCount;
+ }
+ theClientChannel.write( sAccept );
+ sAccept.flip();
+ }
+ }
+ catch( IOException theException )
+ {
+ if ( theSocketChannel != null )
+ {
+ try
+ {
+ theSocketChannel.close();
+ }
+ catch( Exception ignore )
+ {}
+ }
+ APOCLogger.throwing( "ChannelManager",
+ "acceptableKey",
+ theException );
+ }
+ }
+
+ private void closeServerChannel()
+ {
+ try
+ {
+ mSelector.close();
+ mChannel.close();
+ }
+ catch( IOException theException )
+ {
+ APOCLogger.throwing( "ClientManager", "close", theException );
+ }
+ }
+
+ private int getMaxClientChannels()
+ {
+ synchronized( mLock )
+ {
+ return mMaxClientChannels;
+ }
+ }
+
+ private void initChannel()
+ throws IOException
+ {
+ mSelector = Selector.open();
+ mChannel = ServerSocketChannel.open();
+ mChannel.configureBlocking( false );
+ mChannel.socket().bind(
+ new InetSocketAddress(
+ DaemonConfig.getIntProperty( DaemonConfig.sDaemonPort ) ) );
+ mChannel.register( mSelector, SelectionKey.OP_ACCEPT );
+ }
+
+ private void initThread()
+ {
+ setName( "ChannelManager" );
+ setDaemon( true );
+ }
+
+ private void notifyClosed( final ClientChannel inClientChannel )
+ {
+ final Iterator theIterator = mClientChannelEventListeners.iterator();
+ while ( theIterator.hasNext() )
+ {
+ ( ( ClientChannelEventListener )theIterator.next() ).onClosed(
+ inClientChannel );
+ }
+ }
+
+ private void notifyPending( final ClientChannel inClientChannel )
+ {
+ final Iterator theIterator = mClientChannelEventListeners.iterator();
+ while ( theIterator.hasNext() )
+ {
+ ( ( ClientChannelEventListener )theIterator.next() ).onPending(
+ inClientChannel );
+ }
+ }
+
+ private void readableKey( final SelectionKey inKey )
+ {
+ inKey.interestOps(
+ inKey.interestOps() &
+ ( ~ SelectionKey.OP_READ ) );
+ notifyPending( ( ClientChannel )inKey.attachment() );
+ }
+
+ private void registerChannels()
+ {
+ synchronized( mRegisteringChannels )
+ {
+ if ( mRegisteringChannels.size() > 0 )
+ {
+ final Iterator theIterator = mRegisteringChannels.iterator();
+ while ( theIterator.hasNext() )
+ {
+ final SelectionKey theKey =
+ ( SelectionKey )theIterator.next();
+ theKey.interestOps( theKey.interestOps() |
+ SelectionKey.OP_READ );
+ }
+ mRegisteringChannels.clear();
+ mRegisteringChannels.notifyAll();
+ }
+ }
+ synchronized( mDeRegisteringChannels )
+ {
+ if ( mDeRegisteringChannels.size() > 0 )
+ {
+ final Iterator theIterator = mDeRegisteringChannels.iterator();
+ while ( theIterator.hasNext() )
+ {
+ final SelectionKey theKey =
+ ( SelectionKey )theIterator.next();
+ theKey.interestOps( theKey.interestOps() &
+ ( ~ SelectionKey.OP_READ ) );
+ }
+ }
+ mDeRegisteringChannels.clear();
+ mDeRegisteringChannels.notifyAll();
+ }
+ }
+
+ private void selectChannels()
+ throws IOException
+ {
+ if ( mSelector.select() > 0 )
+ {
+ final Iterator theIterator = mSelector.selectedKeys().iterator();
+ while ( theIterator.hasNext() )
+ {
+ final SelectionKey theKey = ( SelectionKey )theIterator.next();
+ theIterator.remove();
+ if ( theKey.isAcceptable() )
+ {
+ acceptableKey( theKey );
+ }
+ if ( theKey.isReadable() )
+ {
+ readableKey( theKey );
+ }
+ }
+ }
+ }
+
+ private void setMaxClientChannels()
+ {
+ synchronized( mLock )
+ {
+ mMaxClientChannels =
+ DaemonConfig.getIntProperty(
+ DaemonConfig.sMaxClientConnections );
+ }
+ mSelector.wakeup();
+ }
+
+ private boolean shouldTerminate()
+ {
+ synchronized( mLock )
+ {
+ return mTerminate;
+ }
+ }
+
+ private boolean testMaxChannels()
+ {
+ boolean bMoreChannelsAllowed = false;
+ int theMaxClientChannels = getMaxClientChannels();
+ if ( theMaxClientChannels > 0 )
+ {
+ synchronized( mLock )
+ {
+ bMoreChannelsAllowed = theMaxClientChannels > mChannelCount;
+ }
+ }
+ if ( ! bMoreChannelsAllowed )
+ {
+ APOCLogger.warning( "Chmr002",
+ String.valueOf( theMaxClientChannels ) );
+ }
+ return bMoreChannelsAllowed;
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transport/ClientChannel.java b/src/com/sun/apoc/daemon/transport/ClientChannel.java
new file mode 100644
index 0000000..87ae738
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transport/ClientChannel.java
@@ -0,0 +1,150 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transport;
+
+import com.sun.apoc.daemon.config.*;
+import com.sun.apoc.daemon.misc.*;
+
+import java.io.*;
+import java.net.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.util.*;
+
+public class ClientChannel
+{
+ private SocketChannel mChannel;
+ private ChannelManager mManager = null;
+
+ private static int sSoTimeout =
+ DaemonConfig.getIntProperty( DaemonConfig.sConnectionReadTimeout );
+
+ public ClientChannel( final SocketChannel inChannel,
+ final ChannelManager inManager )
+ throws IOException
+ {
+ this( inChannel );
+ mManager = inManager;
+ }
+
+ public ClientChannel( final SocketChannel inChannel )
+ throws IOException
+ {
+ initChannel( inChannel );
+ }
+
+ public SocketChannel getSocketChannel() { return mChannel; }
+
+ public void registerForSelection( boolean inRegister )
+ {
+ mManager.registerForSelection( this, inRegister );
+ }
+
+ public long read( final ByteBuffer outBuffer )
+ throws IOException
+ {
+ long theByteCount = 0;
+ while ( theByteCount == 0 )
+ {
+ try
+ {
+ theByteCount = mChannel.read( outBuffer );
+ if ( theByteCount == 0 )
+ {
+ Thread.currentThread().yield();
+ }
+ }
+ catch( IOException theException )
+ {
+ theByteCount = -1;
+ break;
+ }
+ }
+ if ( theByteCount == -1 )
+ {
+ APOCLogger.finest( "Clch002" );
+ if ( mManager != null )
+ {
+ mManager.closeClientChannel( this );
+ }
+ throw new IOException();
+ }
+ return theByteCount;
+ }
+
+ public void write( final ByteBuffer inBuffer )
+ {
+ try
+ {
+ while ( inBuffer.hasRemaining() )
+ {
+ mChannel.write( inBuffer );
+ }
+ }
+ catch( IOException theException )
+ {
+ APOCLogger.throwing( "ClientChannel", "write", theException );
+ if ( mManager != null )
+ {
+ mManager.closeClientChannel( this );
+ }
+ }
+ }
+
+ public void close()
+ {
+ try
+ {
+ if ( mChannel != null )
+ {
+ mChannel.close();
+ mChannel = null;
+ }
+ }
+ catch( Exception theException )
+ {
+ APOCLogger.throwing( "ClientChannel", "close", theException );
+ }
+ }
+
+ private void initChannel( final SocketChannel inChannel )
+ throws IOException
+ {
+ mChannel = inChannel;
+ final Socket theSocket = mChannel.socket();
+ theSocket.setSoLinger( false, 0 );
+ theSocket.setSoTimeout( sSoTimeout );
+ }
+}
diff --git a/src/com/sun/apoc/daemon/transport/ClientChannelEventListener.java b/src/com/sun/apoc/daemon/transport/ClientChannelEventListener.java
new file mode 100644
index 0000000..dfef31c
--- /dev/null
+++ b/src/com/sun/apoc/daemon/transport/ClientChannelEventListener.java
@@ -0,0 +1,41 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+package com.sun.apoc.daemon.transport;
+
+public interface ClientChannelEventListener
+{
+ public void onPending( ClientChannel inClientChannel );
+ public void onClosed( ClientChannel inClientChannel );
+}