osgi-compendium-4.3.0/0000755000175000017500000000000011656061143014514 5ustar drazzibdrazzibosgi-compendium-4.3.0/LICENSE0000644000175000017500000002613611405717712015533 0ustar drazzibdrazzib Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. osgi-compendium-4.3.0/src/0000755000175000017500000000000011656061143015303 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/META-INF/0000755000175000017500000000000011656061143016443 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/META-INF/MANIFEST.MF0000644000175000017500000001053311632153414020074 0ustar drazzibdrazzibManifest-Version: 1 Bnd-LastModified: 1315493643159 Bundle-Copyright: Copyright (c) OSGi Alliance (2000, 2011). All Rights R eserved. Bundle-Description: OSGi Service Platform Release 4 Version 4.3, Compend ium Interfaces and Classes for use in compiling bundles. Bundle-License: http://opensource.org/licenses/apache2.0.php; link="http ://www.apache.org/licenses/LICENSE-2.0"; description="Apache License, V ersion 2.0" Bundle-ManifestVersion: 2 Bundle-Name: osgi.cmpn Bundle-SymbolicName: osgi.cmpn Bundle-Vendor: OSGi Alliance Bundle-Version: 4.3.0.201109081654 Created-By: 1.6.0_27 (Apple Inc.) DynamicImport-Package: * Export-Package: info.dmtree.registry;uses:="info.dmtree.notification,inf o.dmtree,org.osgi.framework";version="1.0",info.dmtree.spi;uses:="info. dmtree";version="1.0",info.dmtree.notification.spi;uses:="info.dmtree.n otification";version="1.0",info.dmtree.notification;uses:="info.dmtree" ;version="1.0",info.dmtree;version="1.0.2",info.dmtree.security;uses:=" info.dmtree";version="1.0",org.osgi.application;uses:="org.osgi.framewo rk";version="1.0",org.osgi.jmx.framework;uses:="org.osgi.jmx,javax.mana gement.openmbean";version="1.5",org.osgi.jmx.service.permissionadmin;ve rsion="1.2",org.osgi.jmx.service.provisioning;uses:="javax.management.o penmbean";version="1.2",org.osgi.jmx.service.coordinator;uses:="org.osg i.jmx,javax.management.openmbean";version="1.0",org.osgi.jmx.service.cm ;uses:="javax.management.openmbean";version="1.3",org.osgi.jmx.service. useradmin;uses:="org.osgi.jmx,javax.management.openmbean";version="1.1. 1",org.osgi.jmx;uses:="javax.management.openmbean";version="1.0",org.os gi.service.application;uses:="org.osgi.framework";version="1.1",org.osg i.service.blueprint.reflect;version="1.0.1",org.osgi.service.blueprint. container;uses:="org.osgi.service.blueprint.reflect,org.osgi.framework" ;version="1.0.2",org.osgi.service.cm;uses:="org.osgi.framework";version ="1.3",org.osgi.service.component;uses:="org.osgi.framework";version="1 .1",org.osgi.service.component.annotations;version="1.0",org.osgi.servi ce.coordinator;uses:="org.osgi.framework";version="1.0",org.osgi.servic e.deploymentadmin.spi;uses:="org.osgi.framework,org.osgi.service.deploy mentadmin";version="1.0.1",org.osgi.service.deploymentadmin;uses:="org. osgi.framework";version="1.1",org.osgi.service.device;uses:="org.osgi.f ramework";version="1.1",org.osgi.service.event;uses:="org.osgi.framewor k";version="1.3",org.osgi.service.http;uses:="javax.servlet.http,javax. servlet";version="1.2.1",org.osgi.service.io;uses:="javax.microedition. io";version="1.0",org.osgi.service.jdbc;uses:="javax.sql";version="1.0" ,org.osgi.service.jndi;uses:="javax.naming.directory,javax.naming";vers ion="1.0",org.osgi.service.jpa;uses:="javax.persistence";version="1.0", org.osgi.service.log;uses:="org.osgi.framework";version="1.3",org.osgi. service.metatype;uses:="org.osgi.framework";version="1.2",org.osgi.serv ice.monitor;version="1.0",org.osgi.service.prefs;version="1.1.1",org.os gi.service.provisioning;version="1.2",org.osgi.service.remoteserviceadm in;uses:="org.osgi.framework";version="1.0.1",org.osgi.service.upnp;ver sion="1.1",org.osgi.service.useradmin;uses:="org.osgi.framework";versio n="1.1",org.osgi.service.wireadmin;uses:="org.osgi.framework";version=" 1.0.1",org.osgi.util.cdma;uses:="org.osgi.service.condpermadmin,org.osg i.framework";version="1.0",org.osgi.util.gsm;uses:="org.osgi.service.co ndpermadmin,org.osgi.framework";version="1.0.1",org.osgi.util.measureme nt;version="1.0.1",org.osgi.util.mobile;uses:="org.osgi.service.condper madmin,org.osgi.framework";version="1.0",org.osgi.util.position;uses:=" org.osgi.util.measurement";version="1.0.1",org.osgi.util.tracker;uses:= "org.osgi.framework";version="1.5",org.osgi.util.xml;uses:="org.osgi.fr amework,javax.xml.parsers";version="1.0.1" Import-Package: javax.management.openmbean;resolution:=optional,javax.mi croedition.io;resolution:=optional,javax.naming;resolution:=optional,ja vax.naming.directory;resolution:=optional,javax.persistence;resolution: =optional,javax.servlet;resolution:=optional,javax.servlet.http;resolut ion:=optional,javax.sql;resolution:=optional,javax.xml.parsers;resoluti on:=optional,org.osgi.framework;resolution:=optional,org.osgi.service.c ondpermadmin;resolution:=optional Tool: Bnd-1.44.0 osgi-compendium-4.3.0/src/info/0000755000175000017500000000000011632153414016233 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/info/dmtree/0000755000175000017500000000000011632153414017513 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/info/dmtree/MetaNode.java0000644000175000017500000004160111564442770022066 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree; /** * The MetaNode contains meta data as standardized by OMA DM but extends it * (without breaking the compatibility) to provide for better DMT data quality * in an environment where many software components manipulate this data. *

* The interface has several types of functions to describe the nodes in the * DMT. Some methods can be used to retrieve standard OMA DM metadata such as * access type, cardinality, default, etc., others are for data extensions such * as valid names and values. In some cases the standard behaviour has been * extended, for example it is possible to provide several valid MIME types, or * to differentiate between normal and automatic dynamic nodes. *

* Most methods in this interface receive no input, just return information * about some aspect of the node. However, there are two methods that behave * differently, {@link #isValidName} and {@link #isValidValue}. These validation * methods are given a potential node name or value (respectively), and can * decide whether it is valid for the given node. Passing the validation methods * is a necessary condition for a name or value to be used, but it is not * necessarily sufficient: the plugin may carry out more thorough (more * expensive) checks when the node is actually created or set. *

* If a {@code MetaNode} is available for a node, the DmtAdmin must use the * information provided by it to filter out invalid requests on that node. * However, not all methods on this interface are actually used for this * purpose, as many of them (e.g. {@link #getFormat} or {@link #getValidNames}) * can be substituted with the validating methods. For example, * {@link #isValidValue} can be expected to check the format, minimum, maximum, * etc. of a given value, making it unnecessary for the DmtAdmin to call * {@link #getFormat()}, {@link #getMin()}, {@link #getMax()} etc. separately. * It is indicated in the description of each method if the DmtAdmin does not * enforce the constraints defined by it - such methods are only for external * use, for example in user interfaces. *

* Most of the methods of this class return {@code null} if a certain piece * of meta information is not defined for the node or providing this information * is not supported. Methods of this class do not throw exceptions. * * @version $Id: c89bb47db0043e3ae9d2dc45ecb0f1f8e7bf73fa $ */ public interface MetaNode { /** * Constant for the ADD access type. If {@link #can(int)} returns * {@code true} for this operation, this node can potentially be * added to its parent. Nodes with {@link #PERMANENT} or {@link #AUTOMATIC} * scope typically do not have this access type. */ int CMD_ADD = 0; /** * Constant for the DELETE access type. If {@link #can(int)} returns * {@code true} for this operation, the node can potentially be * deleted. */ int CMD_DELETE = 1; /** * Constant for the EXECUTE access type. If {@link #can(int)} returns * {@code true} for this operation, the node can potentially be * executed. */ int CMD_EXECUTE = 2; /** * Constant for the REPLACE access type. If {@link #can(int)} returns * {@code true} for this operation, the value and other properties of * the node can potentially be modified. */ int CMD_REPLACE = 3; /** * Constant for the GET access type. If {@link #can(int)} returns * {@code true} for this operation, the value, the list of child nodes * (in case of interior nodes) and the properties of the node can * potentially be retrieved. */ int CMD_GET = 4; /** * Constant for representing a permanent node in the tree. This must be * returned by {@link #getScope} if the node cannot be added, deleted or * modified in any way through tree operations. Permanent nodes cannot have * non-permanent nodes as parents. */ int PERMANENT = 0; /** * Constant for representing a dynamic node in the tree. This must be * returned by {@link #getScope} for all nodes that are not permanent and * are not created automatically by the management object. */ int DYNAMIC = 1; /** * Constant for representing an automatic node in the tree. This must be * returned by {@link #getScope()} for all nodes that are created * automatically by the management object. Automatic nodes represent a * special case of dynamic nodes, so this scope should be mapped to * {@link #DYNAMIC} when used in an OMA DM context. *

* An automatic node is usually created instantly when its parent is * created, but it is also valid if it only appears later, triggered by some * other condition. The exact behaviour must be defined by the Management * Object. */ int AUTOMATIC = 2; /** * Check whether the given operation is valid for this node. If no meta-data * is provided for a node, all operations are valid. * * @param operation One of the {@code MetaNode.CMD_...} constants. * @return {@code false} if the operation is not valid for this node * or the operation code is not one of the allowed constants */ boolean can(int operation); /** * Check whether the node is a leaf node or an internal one. * * @return {@code true} if the node is a leaf node */ boolean isLeaf(); /** * Return the scope of the node. Valid values are * {@link #PERMANENT MetaNode.PERMANENT}, {@link #DYNAMIC MetaNode.DYNAMIC} * and {@link #AUTOMATIC MetaNode.AUTOMATIC}. Note that a permanent node is * not the same as a node where the DELETE operation is not allowed. * Permanent nodes never can be deleted, whereas a non-deletable node can * disappear in a recursive DELETE operation issued on one of its parents. * If no meta-data is provided for a node, it can be assumed to be a dynamic * node. * * @return {@link #PERMANENT} for permanent nodes, {@link #AUTOMATIC} for * nodes that are automatically created, and {@link #DYNAMIC} * otherwise */ int getScope(); /** * Get the explanation string associated with this node. Can be * {@code null} if no description is provided for this node. * * @return node description string or {@code null} for no description */ String getDescription(); /** * Get the number of maximum occurrences of this type of nodes on the same * level in the DMT. Returns {@code Integer.MAX_VALUE} if there is no * upper limit. Note that if the occurrence is greater than 1 then this node * can not have siblings with different metadata. In other words, if * different types of nodes coexist on the same level, their occurrence can * not be greater than 1. If no meta-data is provided for a node, there is * no upper limit on the number of occurrences. * * @return The maximum allowed occurrence of this node type */ int getMaxOccurrence(); /** * Check whether zero occurrence of this node is valid. If no meta-data is * returned for a node, zero occurrences are allowed. * * @return {@code true} if zero occurrence of this node is valid */ boolean isZeroOccurrenceAllowed(); /** * Get the default value of this node if any. * * @return The default value or {@code null} if not defined */ DmtData getDefault(); /** * Get the list of MIME types this node can hold. The first element of the * returned list must be the default MIME type. *

* All MIME types are considered valid if no meta-data is provided for a * node or if {@code null} is returned by this method. In this case * the default MIME type cannot be retrieved from the meta-data, but the * node may still have a default. This hidden default (if it exists) can be * utilized by passing {@code null} as the type parameter of * {@link DmtSession#setNodeType(String, String)} or * {@link DmtSession#createLeafNode(String, DmtData, String)}. * * @return the list of allowed MIME types for this node, starting with the * default MIME type, or {@code null} if all types are * allowed */ String[] getMimeTypes(); /** * Get the maximum allowed value associated with a node of numeric format. * If no meta-data is provided for a node, there is no upper limit to its * value. This method is only meaningful if the node has integer or float * format. The returned limit has {@code double} type, as this can be * used to denote both integer and float limits with full precision. The * actual maximum should be the largest integer or float number that does * not exceed the returned value. *

* The information returned by this method is not checked by DmtAdmin, it * is only for external use, for example in user interfaces. DmtAdmin only * calls {@link #isValidValue} for checking the value, its behaviour should * be consistent with this method. * * @return the allowed maximum, or {@code Double.MAX_VALUE} if there * is no upper limit defined or the node's format is not integer or * float */ double getMax(); /** * Get the minimum allowed value associated with a node of numeric format. * If no meta-data is provided for a node, there is no lower limit to its * value. This method is only meaningful if the node has integer or float * format. The returned limit has {@code double} type, as this can be * used to denote both integer and float limits with full precision. The * actual minimum should be the smallest integer or float number that is * larger than the returned value. *

* The information returned by this method is not checked by DmtAdmin, it * is only for external use, for example in user interfaces. DmtAdmin only * calls {@link #isValidValue} for checking the value, its behaviour should * be consistent with this method. * * @return the allowed minimum, or {@code Double.MIN_VALUE} if there * is no lower limit defined or the node's format is not integer or * float */ double getMin(); /** * Return an array of DmtData objects if valid values are defined for the * node, or {@code null} otherwise. If no meta-data is provided for a * node, all values are considered valid. *

* The information returned by this method is not checked by DmtAdmin, it * is only for external use, for example in user interfaces. DmtAdmin only * calls {@link #isValidValue} for checking the value, its behaviour should * be consistent with this method. * * @return the valid values for this node, or {@code null} if not * defined */ DmtData[] getValidValues(); /** * Get the node's format, expressed in terms of type constants defined in * {@link DmtData}. If there are multiple formats allowed for the node then * the format constants are OR-ed. Interior nodes must have * {@link DmtData#FORMAT_NODE} format, and this code must not be returned * for leaf nodes. If no meta-data is provided for a node, all applicable * formats are considered valid (with the above constraints regarding * interior and leaf nodes). *

* Note that the 'format' term is a legacy from OMA DM, it is more customary * to think of this as 'type'. *

* The formats returned by this method are not checked by DmtAdmin, they * are only for external use, for example in user interfaces. DmtAdmin only * calls {@link #isValidValue} for checking the value, its behaviour should * be consistent with this method. * * @return the allowed format(s) of the node */ int getFormat(); /** * Get the format names for any raw formats supported by the node. This * method is only meaningful if the list of supported formats returned by * {@link #getFormat()} contains {@link DmtData#FORMAT_RAW_STRING} or * {@link DmtData#FORMAT_RAW_BINARY}: it specifies precisely which raw * format(s) are actually supported. If the node cannot contain data in one * of the raw types, this method must return {@code null}. *

* The format names returned by this method are not checked by DmtAdmin, * they are only for external use, for example in user interfaces. DmtAdmin * only calls {@link #isValidValue} for checking the value, its behaviour * should be consistent with this method. * * @return the allowed format name(s) of raw data stored by the node, or * {@code null} if raw formats are not supported */ String[] getRawFormatNames(); /** * Checks whether the given value is valid for this node. This method can be * used to ensure that the value has the correct format and range, that it * is well formed, etc. This method should be consistent with the * constraints defined by the {@link #getFormat}, {@link #getValidValues}, * {@link #getMin} and {@link #getMax} methods (if applicable), as the Dmt * Admin only calls this method for value validation. *

* This method may return {@code true} even if not all aspects of the * value have been checked, expensive operations (for example those that * require external resources) need not be performed here. The actual value * setting method may still indicate that the value is invalid. * * @param value the value to check for validity * @return {@code false} if the specified value is found to be * invalid for the node described by this meta-node, * {@code true} otherwise */ boolean isValidValue(DmtData value); /** * Return an array of Strings if valid names are defined for the node, or * {@code null} if no valid name list is defined or if this piece of * meta info is not supported. If no meta-data is provided for a node, all * names are considered valid. *

* The information returned by this method is not checked by DmtAdmin, it * is only for external use, for example in user interfaces. DmtAdmin only * calls {@link #isValidName} for checking the name, its behaviour should be * consistent with this method. * * @return the valid values for this node name, or {@code null} if * not defined */ String[] getValidNames(); /** * Checks whether the given name is a valid name for this node. This method * can be used for example to ensure that the node name is always one of a * predefined set of valid names, or that it matches a specific pattern. * This method should be consistent with the values returned by * {@link #getValidNames} (if any), the DmtAdmin only calls this method for * name validation. *

* This method may return {@code true} even if not all aspects of the * name have been checked, expensive operations (for example those that * require external resources) need not be performed here. The actual node * creation may still indicate that the node name is invalid. * * @param name the node name to check for validity * @return {@code false} if the specified name is found to be invalid * for the node described by this meta-node, {@code true} * otherwise */ boolean isValidName(String name); /** * Returns the list of extension property keys, if the provider of this * {@code MetaNode} provides proprietary extensions to node meta * data. The method returns {@code null} if the node doesn't provide * such extensions. * * @return the array of supported extension property keys */ String[] getExtensionPropertyKeys(); /** * Returns the value for the specified extension property key. This method * only works if the provider of this {@code MetaNode} provides * proprietary extensions to node meta data. * * @param key the key for the extension property * @return the value of the requested property, cannot be {@code null} * @throws IllegalArgumentException if the specified key is not supported by * this {@code MetaNode} */ Object getExtensionProperty(String key); } osgi-compendium-4.3.0/src/info/dmtree/registry/0000755000175000017500000000000011632153414021363 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/info/dmtree/registry/package-info.java0000644000175000017500000000323611466514064024565 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Device Management Tree Registry Package Version 1.0. * *

* This package contains the factory class providing access to the different * Device Management services for non-OSGi applications. The * {@code DmtServiceFactory} class contained in this package provides methods * for retrieving {@code NotificationService} and {@code DmtAdmin} * service implementations. * *

* Bundles wishing to use this package must list the package in the * Import-Package header of the bundle's manifest. This package has two types of * users: the consumers that use the API in this package and the providers that * implement the API in this package. * *

* Example import for consumers using the API in this package: *

* {@code Import-Package: info.dmtree.registry; version="[1.0,2.0)"} *

* Example import for providers implementing the API in this package: *

* {@code Import-Package: info.dmtree.registry; version="[1.0,1.1)"} * * @version $Id: 7df579cffa84a035f9198eeda06989cf95f803c9 $ */ package info.dmtree.registry; osgi-compendium-4.3.0/src/info/dmtree/registry/packageinfo0000644000175000017500000000001411405717676023566 0ustar drazzibdrazzibversion 1.0 osgi-compendium-4.3.0/src/info/dmtree/registry/DmtServiceFactory.java0000644000175000017500000000725111466514064025637 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.registry; import info.dmtree.DmtAdmin; import info.dmtree.notification.NotificationService; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; /** * This class is the central access point for Device Management services. * Applications can use the static factory methods provided in this class to * obtain access to the different Device Management related services, such as * the DmtAdmin for manipulating the tree, or the Notification Service for * sending notifications to management servers. *

* These methods are not needed in an OSGi environment, clients should retrieve * the required service objects from the OSGi Service Registry. * * @version $Id: 2e571c170e4e61fef5b829c5aed1983afc394070 $ */ public final class DmtServiceFactory { private static BundleContext context = null; /** * A private constructor to suppress the default public constructor. */ private DmtServiceFactory() {} /** * This method is used to obtain access to {@code DmtAdmin}, which * enables applications to manipulate the Device Management Tree. * * @return a DmtAdmin service object */ public static DmtAdmin getDmtAdmin() { if(context == null) throw new IllegalStateException("Cannot retrieve Dmt Admin " + "service, implementation bundle not started yet."); ServiceReference dmtAdminRef = context.getServiceReference(DmtAdmin.class.getName()); if(dmtAdminRef == null) throw new IllegalStateException("Dmt Admin service not found in " + "service registry."); DmtAdmin dmtAdmin = (DmtAdmin) context.getService(dmtAdminRef); if(dmtAdmin == null) throw new IllegalStateException("Dmt Admin service not found in " + "service registry."); return dmtAdmin; } /** * This method is used to obtain access to {@code NotificationService}, * which enables applications to send asynchronous notifications to * management servers. * * @return a NotificationService service object */ public static NotificationService getNotificationService() { if(context == null) throw new IllegalStateException("Cannot retrieve Notification " + "service, implementation bundle not started yet."); ServiceReference notificationServiceRef = context.getServiceReference(NotificationService.class.getName()); if(notificationServiceRef == null) throw new IllegalStateException("Notification service not found " + "in service registry."); NotificationService notificationService = (NotificationService) context.getService(notificationServiceRef); if(notificationService == null) throw new IllegalStateException("Notification service not found " + "in service registry."); return notificationService; } } osgi-compendium-4.3.0/src/info/dmtree/package-info.java0000644000175000017500000000331511564442770022716 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Device Management Tree Package Version 1.0. * *

This package contains the public API for the Device Management Tree * manipulations. Permission classes are provided by the * {@code info.dmtree.security} package, and DMT plugin interfaces can be found in * the {@code info.dmtree.spi} package. Asynchronous notifications to remote * management servers can be sent using the interfaces in the * {@code info.dmtree.notification} package. * *

* Bundles wishing to use this package must list the package in the * Import-Package header of the bundle's manifest. This package has two types of * users: the consumers that use the API in this package and the providers that * implement the API in this package. * *

* Example import for consumers using the API in this package: *

* {@code Import-Package: info.dmtree; version="[1.0,2.0)"} *

* Example import for providers implementing the API in this package: *

* {@code Import-Package: info.dmtree; version="[1.0,1.1)"} * * @version $Id: 09257aa0c6277a1b2c9731b591d26b5ca0e8a96e $ */ package info.dmtree; osgi-compendium-4.3.0/src/info/dmtree/DmtIllegalStateException.java0000644000175000017500000000514711466514064025272 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2006, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree; /** * Unchecked illegal state exception. This class is used in DMT because * java.lang.IllegalStateException does not exist in CLDC. * * @version $Id: 497b7af9fb2f578792af298367c30e454ac2b104 $ */ public class DmtIllegalStateException extends RuntimeException { private static final long serialVersionUID = 2015244852018469700L; /** * Create an instance of the exception with no message. */ public DmtIllegalStateException() { super(); } /** * Create an instance of the exception with the specified message. * * @param message the reason for the exception */ public DmtIllegalStateException(String message) { super(message); } /** * Create an instance of the exception with the specified cause exception * and no message. * * @param cause the cause of the exception */ public DmtIllegalStateException(Throwable cause) { super(cause); } /** * Create an instance of the exception with the specified message and cause * exception. * * @param message the reason for the exception * @param cause the cause of the exception */ public DmtIllegalStateException(String message, Throwable cause) { super(message, cause); } /** * Returns the cause of this exception or {@code null} if no cause was * set. * * @return The cause of this exception or {@code null} if no cause was * set. */ public Throwable getCause() { return super.getCause(); } /** * Initializes the cause of this exception to the specified value. * * @param cause The cause of this exception. * @return This exception. * @throws IllegalArgumentException If the specified cause is this * exception. * @throws IllegalStateException If the cause of this exception has already * been set. * @since 1.0.1 */ public Throwable initCause(Throwable cause) { return super.initCause(cause); } } osgi-compendium-4.3.0/src/info/dmtree/DmtException.java0000644000175000017500000006333611564442770023006 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree; import java.io.PrintStream; import java.util.Vector; /** * Checked exception received when a DMT operation fails. Beside the exception * message, a {@code DmtException} always contains an error code (one of * the constants specified in this class), and may optionally contain the URI of * the related node, and information about the cause of the exception. *

* Some of the error codes defined in this class have a corresponding error code * defined in OMA DM, in these cases the name and numerical value from OMA DM is * used. Error codes without counterparts in OMA DM were given numbers from a * different range, starting from 1. *

* The cause of the exception (if specified) can either be a single * {@code Throwable} instance, or a list of such instances if several * problems occurred during the execution of a method. An example for the latter * is the {@code close} method of {@code DmtSession} that tries to * close multiple plugins, and has to report the exceptions of all failures. *

* Each constructor has two variants, one accepts a {@code String} node * URI, the other accepts a {@code String[]} node path. The former is used * by the DmtAdmin implementation, the latter by the plugins, who receive the * node URI as an array of segment names. The constructors are otherwise * identical. *

* Getter methods are provided to retrieve the values of the additional * parameters, and the {@code printStackTrace(PrintWriter)} method is * extended to print the stack trace of all causing throwables as well. * * @version $Id: 4c28c365160136f6d2da2229ab0ba127dea78527 $ */ public class DmtException extends Exception { private static final long serialVersionUID = -63006267148118655L; // ----- Public constants -----// /** * The originator's authentication credentials specify a principal with * insufficient rights to complete the command. *

* This status code is used as response to device originated sessions if the * remote management server cannot authorize the device to perform the * requested operation. *

* This error code corresponds to the OMA DM response status code 401 * "Unauthorized". */ public static final int UNAUTHORIZED = 401; /** * The requested target node was not found. No indication is given as to * whether this is a temporary or permanent condition, unless otherwise * noted. *

* This is only used when the requested node name is valid, otherwise the * more specific error codes {@link #URI_TOO_LONG} or {@link #INVALID_URI} * are used. This error code corresponds to the OMA DM response status code * 404 "Not Found". */ public static final int NODE_NOT_FOUND = 404; /** * The requested command is not allowed on the target node. This includes * the following situations: *

*

* This error code corresponds to the OMA DM response status code 405 * "Command not allowed". */ public static final int COMMAND_NOT_ALLOWED = 405; /** * The requested command failed because an optional feature required by the * command is not supported. For example, opening an atomic session might * return this error code if the DmtAdmin implementation does not support * transactions. Similarly, accessing the optional node properties (Title, * Timestamp, Version, Size) might not succeed if either the DmtAdmin * implementation or the underlying plugin does not support the property. *

* When getting or setting values for interior nodes (an optional * optimization feature), a plugin can use this error code to indicate that * the given interior node does not support values. *

* This error code corresponds to the OMA DM response status code 406 * "Optional feature not supported". */ public static final int FEATURE_NOT_SUPPORTED = 406; /** * The requested command failed because the target URI or one of its * segments is too long for what the recipient is able or willing to * process, or the target URI contains too many segments. The length and * segment number limits are implementation dependent, their minimum values * can be found in the Non Functional Requirements section of the OSGi * specification. *

* The {@link Uri#mangle(String)} method provides support for ensuring that * a URI segment conforms to the length limits set by the implementation. *

* This error code corresponds to the OMA DM response status code 414 * "URI too long". * * @see "OSGi Service Platform, Mobile Specification Release 4" */ public static final int URI_TOO_LONG = 414; /** * The requested node creation operation failed because the target already * exists. This can occur if the node is created directly (with one of the * {@code create...} methods), or indirectly (during a * {@code copy} operation). *

* This error code corresponds to the OMA DM response status code 418 * "Already exists". */ public static final int NODE_ALREADY_EXISTS = 418; /** * The requested command failed because the principal associated with the * session does not have adequate access control permissions (ACL) on the * target. This can only appear in case of remote sessions, i.e. if the * session is associated with an authenticated principal. *

* This error code corresponds to the OMA DM response status code 425 * "Permission denied". */ public static final int PERMISSION_DENIED = 425; /** * The recipient encountered an error which prevented it from fulfilling the * request. *

* This error code is only used in situations not covered by any of the * other error codes that a method may use. Some methods specify more * specific error situations for this code, but it can generally be used for * any unexpected condition that causes the command to fail. *

* This error code corresponds to the OMA DM response status code 500 * "Command Failed". */ public static final int COMMAND_FAILED = 500; /** * An error related to the recipient data store occurred while processing * the request. This error code may be thrown by any of the methods * accessing the tree, but whether it is really used depends on the * implementation, and the data store it uses. *

* This error code corresponds to the OMA DM response status code 510 * "Data store failure". */ public static final int DATA_STORE_FAILURE = 510; /** * The rollback command was not completed successfully. The tree might be in * an inconsistent state after this error. *

* This error code corresponds to the OMA DM response status code 516 * "Atomic roll back failed". */ public static final int ROLLBACK_FAILED = 516; /** * A device initiated remote operation failed. This is used when the * protocol adapter fails to send an alert for any reason. *

* Alert routing errors (that occur while looking for the proper protocol * adapter to use) are indicated by {@link #ALERT_NOT_ROUTED}, this code is * only for errors encountered while sending the routed alert. This error * code does not correspond to any OMA DM response status code. It should be * translated to the code 500 "Command Failed" when transferring * over OMA DM. */ public static final int REMOTE_ERROR = 1; /** * Operation failed because of meta data restrictions. This covers any * attempted deviation from the parameters defined by the * {@code MetaNode} objects of the affected nodes, for example in the * following situations: *

*

* This error code can also be used to indicate any other meta data * violation, even if it cannot be described by the {@code MetaNode} * class. For example, detecting a multi-node constraint violation while * committing an atomic session should result in this error. *

* This error code does not correspond to any OMA DM response status code. * It should be translated to the code 405 "Command not allowed" * when transferring over OMA DM. */ public static final int METADATA_MISMATCH = 2; /** * The requested command failed because the target URI or node name is * {@code null} or syntactically invalid. This covers the following * cases: *

*

* See the {@link Uri#mangle(String)} method for support on escaping invalid * characters in a URI. *

* This code is only used if the URI or node name does not match any of the * criteria for {@link #URI_TOO_LONG}. This error code does not correspond * to any OMA DM response status code. It should be translated to the code * 404 "Not Found" when transferring over OMA DM. */ public static final int INVALID_URI = 3; /** * An error occurred related to concurrent access of nodes. This can happen * for example if a configuration node was deleted directly through the * Configuration Admin service, while the node was manipulated via the tree. *

* This error code does not correspond to any OMA DM response status code. * It should be translated to the code 500 "Command Failed" when * transferring over OMA DM. */ public static final int CONCURRENT_ACCESS = 4; /** * An alert can not be sent from the device to the given principal. This can * happen if there is no Remote Alert Sender willing to forward the alert to * the given principal, or if no principal was given and the DmtAdmin did * not find an appropriate default destination. *

* This error code does not correspond to any OMA DM response status code. * It should be translated to the code 500 "Command Failed" when * transferring over OMA DM. */ public static final int ALERT_NOT_ROUTED = 5; /** * A transaction-related error occurred in an atomic session. This error is * caused by one of the following situations: *

* The latter case may leave the tree in an inconsistent state due to the * lack of a two-phase commit system, see {@link DmtSession#commit} for * details. *

* This error code does not correspond to any OMA DM response status code. * It should be translated to the code 500 "Command Failed" when * transferring over OMA DM. */ public static final int TRANSACTION_ERROR = 6; /** * Creation of a session timed out because of another ongoing session. The * length of time while the DmtAdmin waits for the blocking session(s) to * finish is implementation dependant. *

* This error code does not correspond to any OMA DM response status code. * OMA has several status codes related to timeout, but these are meant to * be used when a request times out, not if a session can not be * established. This error code should be translated to the code 500 * "Command Failed" when transferring over OMA DM. */ public static final int SESSION_CREATION_TIMEOUT = 7; // ----- Content fields -----// /** * The URI of the node on which the failed DMT operation was issued, or * {@code null} if the operation was not associated with a node. */ private final String uri; /** * The error code of the failure, one of the constants defined in this * class. */ private final int code; /** * The message associated with the exception, or {@code null} if there * is no error message. */ private final String message; /** * The list of originating exceptions, or empty list or {@code null} if * there are no originating exceptions. */ private final Throwable[] causes; /** * Determines whether the exception is fatal or not. This is basically a * two-state severity indicator, with the 'fatal' severity being the more * serious one. */ private final boolean fatal; // ----- Constructors -----// /** * Create an instance of the exception. The {@code uri} and * {@code message} parameters are optional. No originating exception * is specified. * * @param uri the node on which the failed DMT operation was issued, or * {@code null} if the operation is not associated with a node * @param code the error code of the failure * @param message the message associated with the exception, or * {@code null} if there is no error message */ public DmtException(String uri, int code, String message) { this(uri, code, message, new Throwable[0], false); } /** * Create an instance of the exception, specifying the cause exception. The * {@code uri}, {@code message} and {@code cause} * parameters are optional. * * @param uri the node on which the failed DMT operation was issued, or * {@code null} if the operation is not associated with a node * @param code the error code of the failure * @param message the message associated with the exception, or * {@code null} if there is no error message * @param cause the originating exception, or {@code null} if there * is no originating exception */ public DmtException(String uri, int code, String message, Throwable cause) { this(uri, code, message, (cause == null) ? new Throwable[0] : new Throwable[] { cause }, false); } /** * Create an instance of the exception, specifying the list of cause * exceptions and whether the exception is a fatal one. This constructor is * meant to be used by plugins wishing to indicate that a serious error * occurred which should invalidate the ongoing atomic session. The * {@code uri}, {@code message} and {@code causes} * parameters are optional. *

* If a fatal exception is thrown, no further business methods will be * called on the originator plugin. In case of atomic sessions, all other * open plugins will be rolled back automatically, except if the fatal * exception was thrown during commit. * * @param uri the node on which the failed DMT operation was issued, or * {@code null} if the operation is not associated with a node * @param code the error code of the failure * @param message the message associated with the exception, or * {@code null} if there is no error message * @param causes the list of originating exceptions, or empty list or * {@code null} if there are no originating exceptions * @param fatal whether the exception is fatal */ public DmtException(String uri, int code, String message, Vector causes, boolean fatal) { this(uri, code, message, (causes == null) ? new Throwable[0] : (Throwable[]) causes.toArray(new Throwable[causes.size()]), fatal); } private DmtException(String uri, int code, String message, Throwable[] causes, boolean fatal) { super((Throwable) null); this.uri = uri; this.code = code; this.message = message; this.causes = causes; this.fatal = fatal; } /** * Create an instance of the exception, specifying the target node as an * array of path segments. This method behaves in exactly the same way as if * the path was given as a URI string. * * @param path the path of the node on which the failed DMT operation was * issued, or {@code null} if the operation is not associated * with a node * @param code the error code of the failure * @param message the message associated with the exception, or * {@code null} if there is no error message * @see #DmtException(String, int, String) */ public DmtException(String[] path, int code, String message) { this(pathToUri(path), code, message); } /** * Create an instance of the exception, specifying the target node as an * array of path segments, and specifying the cause exception. This method * behaves in exactly the same way as if the path was given as a URI string. * * @param path the path of the node on which the failed DMT operation was * issued, or {@code null} if the operation is not associated * with a node * @param code the error code of the failure * @param message the message associated with the exception, or * {@code null} if there is no error message * @param cause the originating exception, or {@code null} if there * is no originating exception * @see #DmtException(String, int, String, Throwable) */ public DmtException(String[] path, int code, String message, Throwable cause) { this(pathToUri(path), code, message, cause); } /** * Create an instance of the exception, specifying the target node as an * array of path segments, the list of cause exceptions, and whether the * exception is a fatal one. This method behaves in exactly the same way as * if the path was given as a URI string. * * @param path the path of the node on which the failed DMT operation was * issued, or {@code null} if the operation is not associated * with a node * @param code the error code of the failure * @param message the message associated with the exception, or * {@code null} if there is no error message * @param causes the list of originating exceptions, or empty list or * {@code null} if there are no originating exceptions * @param fatal whether the exception is fatal * @see #DmtException(String, int, String, Vector, boolean) */ public DmtException(String[] path, int code, String message, Vector causes, boolean fatal) { this(pathToUri(path), code, message, causes, fatal); } // ----- Public methods -----// /** * Get the node on which the failed DMT operation was issued. Some * operations like {@code DmtSession.close()} don't require an URI, * in this case this method returns {@code null}. * * @return the URI of the node, or {@code null} */ public String getURI() { return uri; } /** * Get the error code associated with this exception. Most of the error * codes within this exception correspond to OMA DM error codes. * * @return the error code */ public int getCode() { return code; } /** * Get the message associated with this exception. The returned string also * contains the associated URI (if any) and the exception code. The * resulting message has the following format (parts in square brackets are * only included if the field inside them is not {@code null}): * *

     *  <exception_code>[: '<uri>'][: <error_message>]
     * 
* * @return the error message in the format described above */ public String getMessage() { StringBuffer sb = new StringBuffer(getCodeText(code)); if (uri != null) sb.append(": '").append(uri).append('\''); if (message != null) sb.append(": ").append(message); return sb.toString(); } /** * Get the cause of this exception. Returns non-{@code null}, if * this exception is caused by one or more other exceptions (like a * {@code NullPointerException} in a DmtPlugin). If there are more * than one cause exceptions, the first one is returned. * * @return the cause of this exception, or {@code null} if no cause * was given */ public Throwable getCause() { return causes.length == 0 ? null : causes[0]; } /** * Get all causes of this exception. Returns the causing exceptions in an * array. If no cause was specified, an empty array is returned. * * @return the list of causes of this exception */ public Throwable[] getCauses() { return (Throwable[]) causes.clone(); } /** * Check whether this exception is marked as fatal in the session. Fatal * exceptions trigger an automatic rollback of atomic sessions. * * @return whether the exception is marked as fatal */ public boolean isFatal() { return fatal; } /** * Prints the exception and its backtrace to the specified print stream. Any * causes that were specified for this exception are also printed, together * with their backtraces. * * @param s {@code PrintStream} to use for output */ public void printStackTrace(PrintStream s) { super.printStackTrace(s); for (int i = 0; i 0 ? " (" + (i+1) + ")" : "") + ": "); causes[i].printStackTrace(s); } } // ----- Utility methods -----// /** * Converts the given path, given as an array of path segments, to a single * URI string. * * @param path the path to convert * @return the URI string representing the same node as the given path */ static String pathToUri(String[] path) { if (path == null) return null; return Uri.toUri(path); } /** * Returns the name of the given error code. * * @param code the error code * @return a string containing the error code name */ private static String getCodeText(int code) { // todo sync codes switch (code) { case NODE_NOT_FOUND: return "NODE_NOT_FOUND"; case COMMAND_NOT_ALLOWED: return "COMMAND_NOT_ALLOWED"; case FEATURE_NOT_SUPPORTED: return "FEATURE_NOT_SUPPORTED"; case URI_TOO_LONG: return "URI_TOO_LONG"; case NODE_ALREADY_EXISTS: return "NODE_ALREADY_EXISTS"; case PERMISSION_DENIED: return "PERMISSION_DENIED"; case COMMAND_FAILED: return "COMMAND_FAILED"; case DATA_STORE_FAILURE: return "DATA_STORE_FAILURE"; case ROLLBACK_FAILED: return "ROLLBACK_FAILED"; case REMOTE_ERROR: return "REMOTE_ERROR"; case METADATA_MISMATCH: return "METADATA_MISMATCH"; case INVALID_URI: return "INVALID_URI"; case CONCURRENT_ACCESS: return "CONCURRENT_ACCESS"; case ALERT_NOT_ROUTED: return "ALERT_NOT_ROUTED"; case TRANSACTION_ERROR: return "TRANSACTION_ERROR"; case SESSION_CREATION_TIMEOUT: return "SESSION_CREATION_TIMEOUT"; default: return ""; } } } osgi-compendium-4.3.0/src/info/dmtree/security/0000755000175000017500000000000011632153414021362 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/info/dmtree/security/package-info.java0000644000175000017500000000276211466514064024567 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Device Management Tree Security Package Version 1.0. * *

* This package contains the permission classes used by the Device * Management API in environments that support the Java 2 security model. * *

* Bundles wishing to use this package must list the package in the * Import-Package header of the bundle's manifest. This package has two types of * users: the consumers that use the API in this package and the providers that * implement the API in this package. * *

* Example import for consumers using the API in this package: *

* {@code Import-Package: info.dmtree.security; version="[1.0,2.0)"} *

* Example import for providers implementing the API in this package: *

* {@code Import-Package: info.dmtree.security; version="[1.0,1.1)"} * * @version $Id: f113975faaa4bcaaadfbdc8855657559c228897a $ */ package info.dmtree.security; osgi-compendium-4.3.0/src/info/dmtree/security/AlertPermission.java0000644000175000017500000002224711466514064025363 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.security; import java.security.Permission; import java.security.PermissionCollection; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; /** * Indicates the callers authority to send alerts to management servers, * identified by their principal names. *

* {@code AlertPermission} has a target string which controls the principal * names where alerts can be sent. A wildcard is allowed at the end of the * target string, to allow sending alerts to any principal with a name matching * the given prefix. The "*" target means that alerts can be sent to * any destination. * * @version $Id: 2cd204e37cfce557d5466f62fe324e30ac807456 $ */ public class AlertPermission extends Permission { private static final long serialVersionUID = -3206463101788245739L; // specifies whether the target string had a wildcard at the end private final boolean isPrefix; // the target string without the wildcard (if there was one) private final String serverId; /** * Creates a new {@code AlertPermission} object with its name set to * the target string. Name must be non-null and non-empty. * * @param target the name of a principal, can end with {@code *} to * match any principal identifier with the given prefix * @throws NullPointerException if {@code name} is {@code null} * @throws IllegalArgumentException if {@code name} is empty */ public AlertPermission(String target) { super(target); if (target == null) throw new NullPointerException( "'target' parameter must not be null."); if (target.equals("")) throw new IllegalArgumentException( "'target' parameter must not be empty."); isPrefix = target.endsWith("*"); if (isPrefix) serverId = target.substring(0, target.length() - 1); else serverId = target; } /** * Creates a new {@code AlertPermission} object using the 'canonical' * two argument constructor. In this version this class does not define any * actions, the second argument of this constructor must be "*" so that this * class can later be extended in a backward compatible way. * * @param target the name of the server, can end with {@code *} to * match any server identifier with the given prefix * @param actions no actions defined, must be "*" for forward compatibility * @throws NullPointerException if {@code name} or * {@code actions} is {@code null} * @throws IllegalArgumentException if {@code name} is empty or * {@code actions} is not "*" */ public AlertPermission(String target, String actions) { this(target); if (actions == null) throw new NullPointerException( "'actions' parameter must not be null."); if (!actions.equals("*")) throw new IllegalArgumentException( "'actions' parameter must be \"*\"."); } /** * Checks whether the given object is equal to this AlertPermission * instance. Two AlertPermission instances are equal if they have the same * target string. * * @param obj the object to compare to this AlertPermission instance * @return {@code true} if the parameter represents the same * permissions as this instance */ public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof AlertPermission)) return false; AlertPermission other = (AlertPermission) obj; return isPrefix == other.isPrefix && serverId.equals(other.serverId); } /** * Returns the action list (always {@code *} in the current version). * * @return the action string "*" */ public String getActions() { return "*"; } /** * Returns the hash code for this permission object. If two AlertPermission * objects are equal according to the {@link #equals} method, then calling * this method on each of the two AlertPermission objects must produce the * same integer result. * * @return hash code for this permission object */ public int hashCode() { return new Boolean(isPrefix).hashCode() ^ serverId.hashCode(); } /** * Checks if this AlertPermission object implies the specified permission. * Another AlertPermission instance is implied by this permission either if * the target strings are identical, or if this target can be made identical * to the other target by replacing a trailing "*" with any * string. * * @param p the permission to check for implication * @return true if this AlertPermission instance implies the specified * permission */ public boolean implies(Permission p) { if (!(p instanceof AlertPermission)) return false; AlertPermission other = (AlertPermission) p; return impliesServer(other); } /** * Returns a new PermissionCollection object for storing AlertPermission * objects. * * @return the new PermissionCollection */ public PermissionCollection newPermissionCollection() { return new DmtAlertPermissionCollection(); } /* * Returns true if the server name parameter of the given AlertPermission is * implied by the server name of this permission, i.e. this server name is a * prefix of the other one but ends with a *, or the two server names are * equal. */ boolean impliesServer(AlertPermission p) { return isPrefix ? p.serverId.startsWith(serverId) : !p.isPrefix && p.serverId.equals(serverId); } } /** * Represents a homogeneous collection of AlertPermission objects. */ final class DmtAlertPermissionCollection extends PermissionCollection { private static final long serialVersionUID = 2288462124510043429L; private ArrayList perms; /** * Create an empty DmtAlertPermissionCollection object. */ public DmtAlertPermissionCollection() { perms = new ArrayList(); } /** * Adds a permission to the DmtAlertPermissionCollection. * * @param permission the Permission object to add * @exception IllegalArgumentException if the permission is not a * AlertPermission * @exception SecurityException if this DmtAlertPermissionCollection object * has been marked readonly */ public void add(Permission permission) { if (!(permission instanceof AlertPermission)) throw new IllegalArgumentException( "Cannot add permission, invalid permission type: " + permission); if (isReadOnly()) throw new SecurityException( "Cannot add permission, collection is marked read-only."); // only add new permission if it is not already implied by the // permissions in the collection if (!implies(permission)) { // remove all permissions that are implied by the new one Iterator i = perms.iterator(); while (i.hasNext()) if (permission.implies((AlertPermission) i.next())) i.remove(); // no need to synchronize because all adds are done sequentially // before any implies() calls perms.add(permission); } } /** * Check whether this set of permissions implies the permission specified in * the parameter. * * @param permission the Permission object to compare * @return true if the parameter permission is a proper subset of the * permissions in the collection, false otherwise */ public boolean implies(Permission permission) { if (!(permission instanceof AlertPermission)) return false; AlertPermission other = (AlertPermission) permission; Iterator i = perms.iterator(); while (i.hasNext()) if (((AlertPermission) i.next()).impliesServer(other)) return true; return false; } /** * Returns an enumeration of all the AlertPermission objects in the * container. The returned value cannot be {@code null}. * * @return an enumeration of all the AlertPermission objects */ public Enumeration elements() { // Convert Iterator into Enumeration return Collections.enumeration(perms); } } osgi-compendium-4.3.0/src/info/dmtree/security/packageinfo0000644000175000017500000000001411405717676023565 0ustar drazzibdrazzibversion 1.0 osgi-compendium-4.3.0/src/info/dmtree/security/DmtPrincipalPermission.java0000644000175000017500000002303711466514064026700 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.security; import java.security.Permission; import java.security.PermissionCollection; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; /** * Indicates the callers authority to create DMT sessions on behalf of a remote * management server. Only protocol adapters communicating with management * servers should be granted this permission. *

* {@code DmtPrincipalPermission} has a target string which controls the * name of the principal on whose behalf the protocol adapter can act. A * wildcard is allowed at the end of the target string, to allow using any * principal name with the given prefix. The "*" target means the * adapter can create a session in the name of any principal. * * @version $Id: f2894cf7a413e4308702b8f943b70556f6697d77 $ */ public class DmtPrincipalPermission extends Permission { private static final long serialVersionUID = 6388752177325038332L; // specifies whether the target string had a wildcard at the end private final boolean isPrefix; // the target string without the wildcard (if there was one) private final String principal; /** * Creates a new {@code DmtPrincipalPermission} object with its name * set to the target string. Name must be non-null and non-empty. * * @param target the name of the principal, can end with {@code *} to * match any principal with the given prefix * @throws NullPointerException if {@code name} is {@code null} * @throws IllegalArgumentException if {@code name} is empty */ public DmtPrincipalPermission(String target) { super(target); if (target == null) throw new NullPointerException( "'target' parameter must not be null."); if (target.equals("")) throw new IllegalArgumentException( "'target' parameter must not be empty."); isPrefix = target.endsWith("*"); if (isPrefix) principal = target.substring(0, target.length() - 1); else principal = target; } /** * Creates a new {@code DmtPrincipalPermission} object using the * 'canonical' two argument constructor. In this version this class does not * define any actions, the second argument of this constructor must be "*" * so that this class can later be extended in a backward compatible way. * * @param target the name of the principal, can end with {@code *} to * match any principal with the given prefix * @param actions no actions defined, must be "*" for forward compatibility * @throws NullPointerException if {@code name} or * {@code actions} is {@code null} * @throws IllegalArgumentException if {@code name} is empty or * {@code actions} is not "*" */ public DmtPrincipalPermission(String target, String actions) { this(target); if (actions == null) throw new NullPointerException( "'actions' parameter must not be null."); if (!actions.equals("*")) throw new IllegalArgumentException( "'actions' parameter must be \"*\"."); } /** * Checks whether the given object is equal to this DmtPrincipalPermission * instance. Two DmtPrincipalPermission instances are equal if they have the * same target string. * * @param obj the object to compare to this DmtPrincipalPermission instance * @return {@code true} if the parameter represents the same * permissions as this instance */ public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof DmtPrincipalPermission)) return false; DmtPrincipalPermission other = (DmtPrincipalPermission) obj; return isPrefix == other.isPrefix && principal.equals(other.principal); } /** * Returns the action list (always {@code *} in the current version). * * @return the action string "*" */ public String getActions() { return "*"; } /** * Returns the hash code for this permission object. If two * DmtPrincipalPermission objects are equal according to the {@link #equals} * method, then calling this method on each of the two * DmtPrincipalPermission objects must produce the same integer result. * * @return hash code for this permission object */ public int hashCode() { return new Boolean(isPrefix).hashCode() ^ principal.hashCode(); } /** * Checks if this DmtPrincipalPermission object implies the specified * permission. Another DmtPrincipalPermission instance is implied by this * permission either if the target strings are identical, or if this target * can be made identical to the other target by replacing a trailing * "*" with any string. * * @param p the permission to check for implication * @return true if this DmtPrincipalPermission instance implies the * specified permission */ public boolean implies(Permission p) { if (!(p instanceof DmtPrincipalPermission)) return false; DmtPrincipalPermission other = (DmtPrincipalPermission) p; return impliesPrincipal(other); } /** * Returns a new PermissionCollection object for storing * DmtPrincipalPermission objects. * * @return the new PermissionCollection */ public PermissionCollection newPermissionCollection() { return new DmtPrincipalPermissionCollection(); } /* * Returns true if the principal parameter of the given * DmtPrincipalPermission is implied by the principal of this permission, * i.e. this principal is a prefix of the other principal but ends with a *, * or the two principal strings are equal. */ boolean impliesPrincipal(DmtPrincipalPermission p) { return isPrefix ? p.principal.startsWith(principal) : !p.isPrefix && p.principal.equals(principal); } } /** * Represents a homogeneous collection of DmtPrincipalPermission objects. */ final class DmtPrincipalPermissionCollection extends PermissionCollection { private static final long serialVersionUID = -6692103535775802684L; private ArrayList perms; /** * Create an empty DmtPrincipalPermissionCollection object. */ public DmtPrincipalPermissionCollection() { perms = new ArrayList(); } /** * Adds a permission to the DmtPrincipalPermissionCollection. * * @param permission the Permission object to add * @exception IllegalArgumentException if the permission is not a * DmtPrincipalPermission * @exception SecurityException if this DmtPrincipalPermissionCollection * object has been marked readonly */ public void add(Permission permission) { if (!(permission instanceof DmtPrincipalPermission)) throw new IllegalArgumentException( "Cannot add permission, invalid permission type: " + permission); if (isReadOnly()) throw new SecurityException( "Cannot add permission, collection is marked read-only."); // only add new permission if it is not already implied by the // permissions in the collection if (!implies(permission)) { // remove all permissions that are implied by the new one Iterator i = perms.iterator(); while (i.hasNext()) if (permission.implies((DmtPrincipalPermission) i.next())) i.remove(); // no need to synchronize because all adds are done sequentially // before any implies() calls perms.add(permission); } } /** * Check whether this set of permissions implies the permission specified in * the parameter. * * @param permission the Permission object to compare * @return true if the parameter permission is a proper subset of the * permissions in the collection, false otherwise */ public boolean implies(Permission permission) { if (!(permission instanceof DmtPrincipalPermission)) return false; DmtPrincipalPermission other = (DmtPrincipalPermission) permission; Iterator i = perms.iterator(); while (i.hasNext()) if (((DmtPrincipalPermission) i.next()).impliesPrincipal(other)) return true; return false; } /** * Returns an enumeration of all the DmtPrincipalPermission objects in the * container. The returned value cannot be {@code null}. * * @return an enumeration of all the DmtPrincipalPermission objects */ public Enumeration elements() { // Convert Iterator into Enumeration return Collections.enumeration(perms); } } osgi-compendium-4.3.0/src/info/dmtree/security/DmtPermission.java0000644000175000017500000004044511466514064025040 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.security; import info.dmtree.Acl; import info.dmtree.Uri; import java.security.Permission; import java.security.PermissionCollection; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; import java.util.StringTokenizer; /** * Controls access to management objects in the Device Management Tree (DMT). It * is intended to control local access to the DMT. DmtPermission target string * identifies the management object URI and the action field lists the OMA DM * commands that are permitted on the management object. Example: * *

 * DmtPermission("./OSGi/bundles", "Add,Replace,Get");
 * 
* * This means that owner of this permission can execute Add, Replace and Get * commands on the ./OSGi/bundles management object. It is possible to use * wildcards in both the target and the actions field. Wildcard in the target * field means that the owner of the permission can access children nodes of the * target node. Example: * *
 * DmtPermission("./OSGi/bundles/*", "Get");
 * 
* * This means that owner of this permission has Get access on every child node * of ./OSGi/bundles. The asterix does not necessarily have to follow a '/' * character. For example the {@code "./OSGi/a*"} target matches * the {@code ./OSGi/applications} subtree. *

* If wildcard is present in the actions field, all legal OMA DM commands are * allowed on the designated nodes(s) by the owner of the permission. Action * names are interpreted case-insensitively, but the canonical action string * returned by {@link #getActions} uses the forms defined by the action * constants. * * @version $Id: b0e2d35af55ac4ed117b4988b2c3a3f57081ab6d $ */ public class DmtPermission extends Permission { private static final long serialVersionUID = -1910969921419407809L; /** * Holders of DmtPermission with the Add action present can create new nodes * in the DMT, that is they are authorized to execute the * createInteriorNode() and createLeafNode() methods of the DmtSession. This * action is also required for the copy() command, which needs to perform * node creation operations (among others). */ public static final String ADD = "Add"; /** * Holders of DmtPermission with the Delete action present can delete nodes * from the DMT, that is they are authorized to execute the deleteNode() * method of the DmtSession. */ public static final String DELETE = "Delete"; /** * Holders of DmtPermission with the Exec action present can execute nodes * in the DMT, that is they are authorized to call the execute() method of * the DmtSession. */ public static final String EXEC = "Exec"; /** * Holders of DmtPermission with the Get action present can query DMT node * value or properties, that is they are authorized to execute the * isLeafNode(), getNodeAcl(), getEffectiveNodeAcl(), getMetaNode(), * getNodeValue(), getChildNodeNames(), getNodeTitle(), getNodeVersion(), * getNodeTimeStamp(), getNodeSize() and getNodeType() methods of the * DmtSession. This action is also required for the copy() command, which * needs to perform node query operations (among others). */ public static final String GET = "Get"; /** * Holders of DmtPermission with the Replace action present can update DMT * node value or properties, that is they are authorized to execute the * setNodeAcl(), setNodeTitle(), setNodeValue(), setNodeType() and * renameNode() methods of the DmtSession. This action is also be required * for the copy() command if the original node had a title property (which * must be set in the new node). */ public static final String REPLACE = "Replace"; // does this permission have a wildcard at the end? private final boolean prefixPath; // the name without the wildcard on the end private final String path; // the actions mask private final int mask; // the canonical action string (redundant) private final String actions; /** * Creates a new DmtPermission object for the specified DMT URI with the * specified actions. The given URI can be: *

*

* Since the {@code *} character is itself a valid URI character, it * can appear as the last character of a valid absolute URI. To distinguish * this case from using {@code *} as a wildcard, the {@code *} * character at the end of the URI must be escaped with the {@code \} * charater. For example the URI {@code "./a*"} matches * {@code "./a"}, {@code "./aa"}, {@code "./a/b"} etc. while * {@code "./a\*"} matches {@code "./a*"} only. *

* The actions string must either be "*" to allow all actions, or it must * contain a non-empty subset of the valid actions, defined as constants in * this class. * * @param dmtUri URI of the management object (or subtree) * @param actions OMA DM actions allowed * @throws NullPointerException if any of the parameters are * {@code null} * @throws IllegalArgumentException if any of the parameters are invalid */ public DmtPermission(String dmtUri, String actions) { super(dmtUri); mask = getMask(actions); this.actions = canonicalActions(mask); if (dmtUri == null) throw new NullPointerException("'dmtUri' parameter must not be " + "null."); prefixPath = dmtUri.endsWith("*") && !dmtUri.endsWith("\\*"); if(prefixPath) { dmtUri = dmtUri.substring(0, dmtUri.length() - 1); // the single "*" as dmtUri is the only valid non-absolute URI param if(dmtUri.length() == 0) { path = ""; return; } } // if URI ends with "/*", remove it before the validity check if(prefixPath && dmtUri.endsWith("/") && !dmtUri.endsWith("\\/")) checkUri(dmtUri.substring(0, dmtUri.length() - 1)); else checkUri(dmtUri); // canonicalize URI: remove escapes from non-special characters StringBuffer sb = new StringBuffer(dmtUri); int i = 0; while(i < sb.length()) { // length can decrease during the loop! if(sb.charAt(i) == '\\') { // there must be a next character after a '\' in a valid URI char nextCh = sb.charAt(i+1); if(nextCh != '/' && nextCh != '\\') sb.deleteCharAt(i); // remove the extra '\' else i++; } i++; } path = sb.toString(); } private void checkUri(String dmtUri) throws IllegalArgumentException { if(!Uri.isValidUri(dmtUri)) throw new IllegalArgumentException("'dmtUri' parameter does not " + "contain a valid URI."); if(!Uri.isAbsoluteUri(dmtUri)) throw new IllegalArgumentException("'dmtUri' parameter does not " + "contain an absolute URI."); } /** * Checks whether the given object is equal to this DmtPermission instance. * Two DmtPermission instances are equal if they have the same target string * and the same action mask. The "*" action mask is considered equal to a * mask containing all actions. * * @param obj the object to compare to this DmtPermission instance * @return {@code true} if the parameter represents the same * permissions as this instance */ public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof DmtPermission)) return false; DmtPermission other = (DmtPermission) obj; return mask == other.mask && prefixPath == other.prefixPath && path.equals(other.path); } /** * Returns the String representation of the action list. The allowed actions * are listed in the following order: Add, Delete, Exec, Get, Replace. The * wildcard character is not used in the returned string, even if the class * was created using the "*" wildcard. * * @return canonical action list for this permission object */ public String getActions() { return actions; } /** * Returns the hash code for this permission object. If two DmtPermission * objects are equal according to the {@link #equals} method, then calling * this method on each of the two DmtPermission objects must produce the * same integer result. * * @return hash code for this permission object */ public int hashCode() { return new Integer(mask).hashCode() ^ new Boolean(prefixPath).hashCode() ^ path.hashCode(); } /** * Checks if this DmtPermission object "implies" the specified * permission. This method returns {@code false} if and only if at * least one of the following conditions are fulfilled for the specified * permission: *

* * @param p the permission to check for implication * @return true if this DmtPermission instance implies the specified * permission */ public boolean implies(Permission p) { if (!(p instanceof DmtPermission)) return false; DmtPermission other = (DmtPermission) p; if ((mask & other.mask) != other.mask) return false; return impliesPath(other); } /** * Returns a new PermissionCollection object for storing DmtPermission * objects. * * @return the new PermissionCollection */ public PermissionCollection newPermissionCollection() { return new DmtPermissionCollection(); } // parses the given action string, and returns the corresponding action mask private static int getMask(String actions) { int mask = 0; if (actions == null) throw new NullPointerException( "'actions' parameter cannot be null."); if (actions.equals("*")) return Acl.ALL_PERMISSION; // empty tokens (swallowed by StringTokenizer) are not considered errors StringTokenizer st = new StringTokenizer(actions, ","); while (st.hasMoreTokens()) { String action = st.nextToken().trim(); if (action.equalsIgnoreCase(GET)) { mask |= Acl.GET; } else if (action.equalsIgnoreCase(ADD)) { mask |= Acl.ADD; } else if (action.equalsIgnoreCase(REPLACE)) { mask |= Acl.REPLACE; } else if (action.equalsIgnoreCase(DELETE)) { mask |= Acl.DELETE; } else if (action.equalsIgnoreCase(EXEC)) { mask |= Acl.EXEC; } else throw new IllegalArgumentException("Invalid action '" + action + "'"); } if (mask == 0) throw new IllegalArgumentException("Action mask cannot be empty."); return mask; } // generates the canonical string representation of the action list private static String canonicalActions(int mask) { StringBuffer sb = new StringBuffer(); addAction(sb, mask, Acl.ADD, ADD); addAction(sb, mask, Acl.DELETE, DELETE); addAction(sb, mask, Acl.EXEC, EXEC); addAction(sb, mask, Acl.GET, GET); addAction(sb, mask, Acl.REPLACE, REPLACE); return sb.toString(); } // if 'flag' appears in 'mask', appends the 'action' string to the contents // of 'sb', separated by a comma if needed private static void addAction(StringBuffer sb, int mask, int flag, String action) { if ((mask & flag) != 0) { if (sb.length() > 0) sb.append(','); sb.append(action); } } // used by DmtPermissionCollection to retrieve the action mask int getMask() { return mask; } // returns true if the path parameter of the given DmtPermission is // implied by the path of this permission, i.e. this path is a prefix of the // other path, but ends with a *, or the two path strings are equal boolean impliesPath(DmtPermission p) { return prefixPath ? p.path.startsWith(path) : !p.prefixPath && p.path.equals(path); } } /** * Represents a homogeneous collection of DmtPermission objects. */ final class DmtPermissionCollection extends PermissionCollection { private static final long serialVersionUID = -4172481774562012941L; // OPTIMIZE keep a special flag for permissions of "*" path private ArrayList perms; /** * Create an empty DmtPermissionCollection object. */ public DmtPermissionCollection() { perms = new ArrayList(); } /** * Adds a permission to the DmtPermissionCollection. * * @param permission the Permission object to add * @exception IllegalArgumentException if the permission is not a * DmtPermission * @exception SecurityException if this DmtPermissionCollection object has * been marked readonly */ public void add(Permission permission) { if (!(permission instanceof DmtPermission)) throw new IllegalArgumentException( "Cannot add permission, invalid permission type: " + permission); if (isReadOnly()) throw new SecurityException( "Cannot add permission, collection is marked read-only."); // No need to synchronize because all adds are done sequentially // before any implies() calls perms.add(permission); } /** * Check whether this set of permissions implies the permission specified in * the parameter. * * @param permission the Permission object to compare * @return true if the parameter permission is a proper subset of the * permissions in the collection, false otherwise */ public boolean implies(Permission permission) { if (!(permission instanceof DmtPermission)) return false; DmtPermission other = (DmtPermission) permission; int required = other.getMask(); int available = 0; int needed = required; Iterator i = perms.iterator(); while (i.hasNext()) { DmtPermission p = (DmtPermission) i.next(); if (((needed & p.getMask()) != 0) && p.impliesPath(other)) { available |= p.getMask(); if ((available & required) == required) return true; needed = (required ^ available); } } return false; } /** * Returns an enumeration of all the DmtPermission objects in the container. * The returned value cannot be {@code null}. * * @return an enumeration of all the DmtPermission objects */ public Enumeration elements() { // Convert Iterator into Enumeration return Collections.enumeration(perms); } } osgi-compendium-4.3.0/src/info/dmtree/notification/0000755000175000017500000000000011632153414022201 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/info/dmtree/notification/package-info.java0000644000175000017500000000314311466514064025400 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Device Management Tree Notification Package Version 1.0. * *

* This package contains the public API of the Notification service. This service * enables the sending of asynchronous notifications to management servers. * Permission classes are provided by the {@code info.dmtree.security} package. * *

* Bundles wishing to use this package must list the package in the * Import-Package header of the bundle's manifest. This package has two types of * users: the consumers that use the API in this package and the providers that * implement the API in this package. * *

* Example import for consumers using the API in this package: *

* {@code Import-Package: info.dmtree.notification; version="[1.0,2.0)"} *

* Example import for providers implementing the API in this package: *

* {@code Import-Package: info.dmtree.notification; version="[1.0,1.1)"} * * @version $Id: f5805c2959795df8d5c39a3bd0a5634a424f9b47 $ */ package info.dmtree.notification; osgi-compendium-4.3.0/src/info/dmtree/notification/AlertItem.java0000644000175000017500000001473011466514064024746 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.notification; import info.dmtree.DmtData; import info.dmtree.Uri; /** * Immutable data structure carried in an alert (client initiated notification). * The {@code AlertItem} describes details of various notifications that * can be sent by the client, for example as alerts in the OMA DM protocol. The * use cases include the client sending a session request to the server (alert * 1201), the client notifying the server of completion of a software update * operation (alert 1226) or sending back results in response to an asynchronous * EXEC command. *

* The data syntax and semantics varies widely between various alerts, so does * the optionality of particular parameters of an alert item. If an item, such * as source or type, is not defined, the corresponding getter method returns * {@code null}. For example, for alert 1201 (client-initiated session) all * elements will be {@code null}. *

* The syntax used in {@code AlertItem} class corresponds to the OMA DM * alert format. {@link NotificationService} implementations on other management * protocols should map these constructs to the underlying protocol. * * @version $Id: 8ed4f9c425e774840eaaae00e924798be8b997f2 $ */ public class AlertItem { private final String source; private final String type; private final String mark; private final DmtData data; /** * Create an instance of the alert item. The constructor takes all possible * data entries as parameters. Any of these parameters can be * {@code null}. The semantics of the parameters may be refined by * the definition of a specific alert, identified by its alert code (see * {@link NotificationService#sendNotification}). In case of Generic Alerts * for example (code 1226), the {@code mark} parameter contains a * severity string. * * @param source the URI of the node which is the source of the alert item * @param type a MIME type or a URN that identifies the type of the data in * the alert item * @param data a {@code DmtData} object that contains the format and * value of the data in the alert item * @param mark the mark parameter of the alert item */ public AlertItem(String source, String type, String mark, DmtData data) { this.source = source; this.type = type; this.mark = mark; this.data = data; } /** * Create an instance of the alert item, specifying the source node URI as * an array of path segments. The constructor takes all possible data * entries as parameters. Any of these parameters can be {@code null}. * The semantics of the parameters may be refined by the definition of a * specific alert, identified by its alert code (see * {@link NotificationService#sendNotification}). In case of Generic Alerts * for example (code 1226), the {@code mark} parameter contains a * severity string. * * @param source the path of the node which is the source of the alert item * @param type a MIME type or a URN that identifies the type of the data in * the alert item * @param data a {@code DmtData} object that contains the format and * value of the data in the alert item * @param mark the mark parameter of the alert item */ public AlertItem(String[] source, String type, String mark, DmtData data) { if ((null == source)) { this.source = null; } else { this.source = Uri.toUri(source); } this.type = type; this.mark = mark; this.data = data; } /** * Get the node which is the source of the alert. There might be no source * associated with the alert item. * * @return the URI of the node which is the source of this alert, or * {@code null} if there is no source */ public String getSource() { return source; } /** * Get the type associated with the alert item. The type string is a MIME * type or a URN that identifies the type of the data in the alert item * (returned by {@link #getData}). There might be no type associated with * the alert item. * * @return the type type associated with the alert item, or * {@code null} if there is no type */ public String getType() { return type; } /** * Get the mark parameter associated with the alert item. The interpretation * of the mark parameter depends on the alert being sent, as identified by * the alert code in {@link NotificationService#sendNotification}. There * might be no mark associated with the alert item. * * @return the mark associated with the alert item, or {@code null} * if there is no mark */ public String getMark() { return mark; } /** * Get the data associated with the alert item. The returned * {@code DmtData} object contains the format and the value of the * data in the alert item. There might be no data associated with the alert * item. * * @return the data associated with the alert item, or {@code null} * if there is no data */ public DmtData getData() { return data; } /** * Returns the string representation of this alert item. The returned string * includes all parameters of the alert item, and has the following format: * *

     *   AlertItem(<source>, <type>, <mark>, <data>)
     * 
* * The last parameter is the string representation of the data value. The * format of the data is not explicitly included. * * @return the string representation of this alert item */ public String toString() { return "AlertItem(" + source + ", " + type + ", " + mark + ", " + data + ")"; } } osgi-compendium-4.3.0/src/info/dmtree/notification/NotificationService.java0000644000175000017500000001173211466514064027026 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.notification; import info.dmtree.DmtException; import info.dmtree.DmtSession; /** * NotificationService enables sending aynchronous notifications to a management * server. The implementation of {@code NotificationService} should * register itself in the OSGi service registry as a service. * * @version $Id: b7acf86bcc10a1d479456ba684e01ba8b18166cf $ */ public interface NotificationService { /** * Sends a notification to a named principal. It is the responsibility of * the {@code NotificationService} to route the notification to the * given principal using the registered * {@link info.dmtree.notification.spi.RemoteAlertSender} services. *

* In remotely initiated sessions the principal name identifies the remote * server that created the session, this can be obtained using the session's * {@link DmtSession#getPrincipal getPrincipal} call. *

* The principal name may be omitted if the client does not know the * principal name. Even in this case the routing might be possible if the * Notification Service finds an appropriate default destination (for * example if it is only connected to one protocol adapter, which is only * connected to one management server). *

* Since sending the notification and receiving acknowledgment for it is * potentially a very time-consuming operation, notifications are sent * asynchronously. This method should attempt to ensure that the * notification can be sent successfully, and should throw an exception if * it detects any problems. If the method returns without error, the * notification is accepted for sending and the implementation must make a * best-effort attempt to deliver it. *

* In case the notification is an asynchronous response to a previous * {@link DmtSession#execute(String, String, String) execute} command, a * correlation identifier can be specified to provide the association * between the execute and the notification. *

* In order to send a notification using this method, the caller must have * an {@code AlertPermission} with a target string matching the * specified principal name. If the {@code principal} parameter is * {@code null} (the principal name is not known), the target of the * {@code AlertPermission} must be "*". *

* When this method is called with all its parameters {@code null} or 0 * (except {@code principal}), it should send a protocol * specific default notification to initiate a management session. For * example, in case of OMA DM this is alert 1201 "Client Initiated Session". * The {@code principal} parameter can be used to determine the * recipient of the session initiation request. * * @param principal the principal name which is the recipient of this * notification, can be {@code null} * @param code the alert code, can be 0 if not needed * @param correlator optional field that contains the correlation identifier * of an associated exec command, can be {@code null} if not * needed * @param items the data of the alert items carried in this alert, can be * {@code null} or empty if not needed * @throws DmtException with the following possible error codes: *

* @throws SecurityException if the caller does not have the required * {@code AlertPermission} with a target matching the * {@code principal} parameter, as described above */ void sendNotification(String principal, int code, String correlator, AlertItem[] items) throws DmtException; } osgi-compendium-4.3.0/src/info/dmtree/notification/packageinfo0000644000175000017500000000001411405717676024404 0ustar drazzibdrazzibversion 1.0 osgi-compendium-4.3.0/src/info/dmtree/notification/spi/0000755000175000017500000000000011632153414022774 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/info/dmtree/notification/spi/package-info.java0000644000175000017500000000332611466514064026176 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Device Management Tree Notification SPI Package Version 1.0. * *

* This package contains the SPI (Service Provider Interface) of the Notification * service. These interfaces are implemented by Protocol Adapters capable of * delivering notifications to management servers on a specific protocol. Users of * the {@code NotificationService} interface do not interact directly with this * package. * *

* Bundles wishing to use this package must list the package in the * Import-Package header of the bundle's manifest. This package has two types of * users: the consumers that use the API in this package and the providers that * implement the API in this package. * *

* Example import for consumers using the API in this package: *

* {@code Import-Package: info.dmtree.notification.spi; version="[1.0,2.0)"} *

* Example import for providers implementing the API in this package: *

* {@code Import-Package: info.dmtree.notification.spi; version="[1.0,1.1)"} * * @version $Id: 2c273b00d322bca78476155dffb03e0e6344ea9b $ */ package info.dmtree.notification.spi; osgi-compendium-4.3.0/src/info/dmtree/notification/spi/packageinfo0000644000175000017500000000001411405717676025177 0ustar drazzibdrazzibversion 1.0 osgi-compendium-4.3.0/src/info/dmtree/notification/spi/RemoteAlertSender.java0000644000175000017500000001014211466514064027230 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.notification.spi; import info.dmtree.notification.AlertItem; /** * The RemoteAlertSender can be used to send notifications to (remote) entities * identified by principal names. This service is provided by Protocol Adapters, * and is used by the {@link info.dmtree.notification.NotificationService} when * sending alerts. Implementations of this interface have to be able to connect * and send alerts to one or more management servers in a protocol specific way. *

* The properties of the service registration should specify a list of * destinations (principals) where the service is capable of sending alerts. * This can be done by providing a {@code String} array of principal names * in the {@code principals} registration property. If this property is not * registered, the service will be treated as the default sender. The default * alert sender is only used when a more specific alert sender cannot be found. *

* The {@code principals} registration property is used when the * {@link info.dmtree.notification.NotificationService#sendNotification} method * is called, to find the proper {@code RemoteAlertSender} for the given * destination. If the caller does not specify a principal, the alert is only * sent if the Notification Sender finds a default alert sender, or if the * choice is unambiguous for some other reason (for example if only one alert * sender is registered). * * @version $Id: 885f0d730d8f9ff88b872f95dee8a91daf97e2d4 $ */ public interface RemoteAlertSender { /** * Sends an alert to a server identified by its principal name. In case the * alert is sent in response to a previous * {@link info.dmtree.DmtSession#execute(String, String, String) execute} * command, a correlation identifier can be specified to provide the * association between the execute and the alert. *

* The {@code principal} parameter specifies which server the alert * should be sent to. This parameter can be {@code null} if the * client does not know the name of the destination. The alert should still * be delivered if possible; for example if the alert sender is only * connected to one destination. *

* Any exception thrown on this method will be propagated to the original * sender of the event, wrapped in a {@code DmtException} with the * code {@code REMOTE_ERROR}. *

* Since sending the alert and receiving acknowledgment for it is * potentially a very time-consuming operation, alerts are sent * asynchronously. This method should attempt to ensure that the alert can * be sent successfully, and should throw an exception if it detects any * problems. If the method returns without error, the alert is accepted for * sending and the implementation must make a best-effort attempt to deliver * it. * * @param principal the name identifying the server where the alert should * be sent, can be {@code null} * @param code the alert code, can be 0 if not needed * @param correlator the correlation identifier of an associated EXEC * command, or {@code null} if there is no associated EXEC * @param items the data of the alert items carried in this alert, can be * empty or {@code null} if no alert items are needed * @throws Exception if the alert can not be sent to the server */ void sendAlert(String principal, int code, String correlator, AlertItem[] items) throws Exception; } osgi-compendium-4.3.0/src/info/dmtree/Acl.java0000644000175000017500000005477011466514064021101 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree; import java.util.Arrays; import java.util.Iterator; import java.util.Map; import java.util.TreeMap; import java.util.Vector; /** * {@code Acl} is an immutable class representing structured access to DMT * ACLs. Under OMA DM the ACLs are defined as strings with an internal syntax. *

* The methods of this class taking a principal as parameter accept remote * server IDs (as passed to {@link DmtAdmin#getSession(String, String, int) * DmtAdmin.getSession}), as well as " {@code *} " indicating any * principal. *

* The syntax for valid remote server IDs:
* <server-identifier> ::= All printable characters except * {@code '='}, {@code '&'}, {@code '*'}, {@code '+'} or white-space * characters. * * @version $Id: 13eb07de6924756e573ff2eb72db6b66e4e53cc7 $ */ public final class Acl { // ----- Public constants -----// /** * Principals holding this permission can issue GET command on the node * having this ACL. */ public static final int GET = 1; /** * Principals holding this permission can issue ADD commands on the node * having this ACL. */ public static final int ADD = 2; /** * Principals holding this permission can issue REPLACE commands on the node * having this ACL. */ public static final int REPLACE = 4; /** * Principals holding this permission can issue DELETE commands on the node * having this ACL. */ public static final int DELETE = 8; /** * Principals holding this permission can issue EXEC commands on the node * having this ACL. */ public static final int EXEC = 16; /** * Principals holding this permission can issue any command on the node * having this ACL. This permission is the logical OR of {@link #ADD}, * {@link #DELETE}, {@link #EXEC}, {@link #GET} and {@link #REPLACE} * permissions. */ public static final int ALL_PERMISSION = ADD | DELETE | EXEC | GET | REPLACE; // ----- Private constants -----// private static final int[] PERMISSION_CODES = new int[] { ADD, DELETE, EXEC, GET, REPLACE }; private static final String[] PERMISSION_NAMES = new String[] { "Add", "Delete", "Exec", "Get", "Replace" }; private static final String ALL_PRINCIPALS = "*"; // ----- Private fields -----// // the implementation takes advantage of this being a sorted map private final TreeMap principalPermissions; private final int globalPermissions; // ----- Public constructors -----// /** * Create an instance of the ACL from its canonic string representation. * * @param acl The string representation of the ACL as defined in OMA DM. If * {@code null} or empty then it represents an empty list of * principals with no permissions. * @throws IllegalArgumentException if acl is not a valid OMA DM ACL string */ public Acl(String acl) { if (acl == null || acl.equals("")) { // empty permission set principalPermissions = new TreeMap(); globalPermissions = 0; return; } TreeMap tempPrincipalPermissions = new TreeMap(); int tempGlobalPermissions = 0; String[] aclEntries = split(acl, '&', -1); for (int i = 0; i < aclEntries.length; i++) { if (aclEntries[i].length() == 0) throw new IllegalArgumentException( "Invalid ACL string: empty ACL entry."); String[] entryParts = split(aclEntries[i], '=', 2); if (entryParts.length == 1) throw new IllegalArgumentException( "Invalid ACL string: no '=' in ACL entry."); if (entryParts[1].length() == 0) throw new IllegalArgumentException( "Invalid ACL string: no server identifiers in ACL entry."); int command = parseCommand(entryParts[0]); String[] serverIds = split(entryParts[1], '+', -1); for (int j = 0; j < serverIds.length; j++) { if (serverIds[j].length() == 0) throw new IllegalArgumentException( "Invalid ACL string: empty server identifier."); if (serverIds[j].equals(ALL_PRINCIPALS)) tempGlobalPermissions |= command; else { checkServerId(serverIds[j], "Invalid ACL string: " + "server ID contains illegal character"); Integer n = (Integer) tempPrincipalPermissions .get(serverIds[j]); int oldPermission = (n != null) ? n.intValue() : 0; tempPrincipalPermissions.put(serverIds[j], new Integer( oldPermission | command)); } } } principalPermissions = tempPrincipalPermissions; globalPermissions = tempGlobalPermissions; } /** * Creates an instance with a specified list of principals and the * permissions they hold. The two arrays run in parallel, that is * {@code principals[i]} will hold {@code permissions[i]} in * the ACL. *

* A principal name may not appear multiple times in the 'principals' * argument. If the "*" principal appears in the array, the * corresponding permissions will be granted to all principals (regardless * of whether they appear in the array or not). * * @param principals The array of principals * @param permissions The array of permissions * @throws IllegalArgumentException if the length of the two arrays are not * the same, if any array element is invalid, or if a principal * appears multiple times in the {@code principals} array */ public Acl(String[] principals, int[] permissions) { if (principals.length != permissions.length) throw new IllegalArgumentException( "The lengths of the principal and permission arrays are not the same."); TreeMap tempPrincipalPermissions = new TreeMap(); int tempGlobalPermissions = 0; for (int i = 0; i < principals.length; i++) { // allow one * in 'principals' array, remove after loop if (!ALL_PRINCIPALS.equals(principals[i])) checkPrincipal(principals[i]); checkPermissions(permissions[i]); Integer permInt = new Integer(permissions[i]); Object old = tempPrincipalPermissions.put(principals[i], permInt); if (old != null) throw new IllegalArgumentException("Principal '" + principals[i] + "' appears multiple times in the principal array."); } // set the global permissions if there was a * in the array Object globalPermObj = tempPrincipalPermissions.remove(ALL_PRINCIPALS); if (globalPermObj != null) tempGlobalPermissions = ((Integer) globalPermObj).intValue(); principalPermissions = tempPrincipalPermissions; globalPermissions = tempGlobalPermissions; } // ----- Private constructors -----// /** * Creates an instance identical to the {@code base} ACL except for * the permissions of the given {@code principal}, which are * overwritten with the given {@code permissions}. *

* Assumes that the permissions parameter has been checked. All * modifications of an {@code Acl} (add, delete, set) are done * through this method. * * @param base The ACL that provides all permissions except for permissions * of the given principal. * @param principal The entity to which permission should be granted. * @param permissions The set of permissions to be given. The parameter can * be a logical {@code or} of the permission constants defined * in this class. */ private Acl(Acl base, String principal, int permissions) { // make a shallow copy of the permission table, the keys (String) and // values (Integer) are immutable anyway TreeMap tempPrincipalPermissions = (TreeMap) base.principalPermissions .clone(); int tempGlobalPermissions = base.globalPermissions; int deletedGlobalPerm = tempGlobalPermissions & ~permissions; if (ALL_PRINCIPALS.equals(principal)) { deleteFromAll(tempPrincipalPermissions, deletedGlobalPerm); tempGlobalPermissions = permissions; } else { checkPrincipal(principal); if (deletedGlobalPerm != 0) throw new IllegalArgumentException( "Cannot revoke globally set permissions (" + writeCommands(deletedGlobalPerm) + ") from a specific principal (" + principal + ")."); setPrincipalPermission(tempPrincipalPermissions, principal, permissions); } principalPermissions = tempPrincipalPermissions; globalPermissions = tempGlobalPermissions; } // ----- Public methods -----// /** * Checks whether the given object is equal to this {@code Acl} * instance. Two {@code Acl} instances are equal if they allow the * same set of permissions for the same set of principals. * * @param obj the object to compare with this {@code Acl} instance * @return {@code true} if the parameter represents the same ACL as * this instance */ public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof Acl)) return false; Acl other = (Acl) obj; if (globalPermissions != other.globalPermissions || principalPermissions.size() != other.principalPermissions .size()) return false; // principalPermissions sets cannot be easily compared, because they are // not canonical: the global permissions may or may not be present for // each principal, without changing the meaning of the Acl object. // Compare canonical string representations, inefficient but simple. return toString().equals(other.toString()); } /** * Returns the hash code for this ACL instance. If two {@code Acl} * instances are equal according to the {@link #equals} method, then calling * this method on each of them must produce the same integer result. * * @return hash code for this ACL */ public int hashCode() { // Using the hash code of the canonical string representation, because // the principalPermissions set is not canonical (see above). return toString().hashCode(); } /** * Use {@link #hashCode()} instead. * * @return Result of {@link #hashCode()} * @deprecated Use correct method {@link #hashCode()}; */ public int hashcode() { return hashCode(); } /** * Create a new {@code Acl} instance from this {@code Acl} with * the given permission added for the given principal. The already existing * permissions of the principal are not affected. * * @param principal The entity to which permissions should be granted, or * "*" to grant permissions to all principals. * @param permissions The permissions to be given. The parameter can be a * logical {@code or} of more permission constants defined in * this class. * @return a new {@code Acl} instance * @throws IllegalArgumentException if {@code principal} is not a * valid principal name or if {@code permissions} is not a * valid combination of the permission constants defined in this * class */ public synchronized Acl addPermission(String principal, int permissions) { checkPermissions(permissions); int oldPermissions = getPermissions(principal); return setPermission(principal, oldPermissions | permissions); } /** * Create a new {@code Acl} instance from this {@code Acl} with * the given permission revoked from the given principal. Other permissions * of the principal are not affected. *

* Note, that it is not valid to revoke a permission from a specific * principal if that permission is granted globally to all principals. * * @param principal The entity from which permissions should be revoked, or * "*" to revoke permissions from all principals. * @param permissions The permissions to be revoked. The parameter can be a * logical {@code or} of more permission constants defined in * this class. * @return a new {@code Acl} instance * @throws IllegalArgumentException if {@code principal} is not a * valid principal name, if {@code permissions} is not a * valid combination of the permission constants defined in this * class, or if a globally granted permission would have been * revoked from a specific principal */ public synchronized Acl deletePermission(String principal, int permissions) { checkPermissions(permissions); int oldPermissions = getPermissions(principal); return setPermission(principal, oldPermissions & ~permissions); } /** * Get the permissions associated to a given principal. * * @param principal The entity whose permissions to query, or "*" * to query the permissions that are granted globally, to all * principals * @return The permissions of the given principal. The returned * {@code int} is a bitmask of the permission constants defined * in this class * @throws IllegalArgumentException if {@code principal} is not a * valid principal name */ public synchronized int getPermissions(String principal) { int permissions = 0; if (!(ALL_PRINCIPALS.equals(principal))) { checkPrincipal(principal); Object po = principalPermissions.get(principal); if (po != null) permissions = ((Integer) po).intValue(); } return permissions | globalPermissions; } /** * Check whether the given permissions are granted to a certain principal. * The requested permissions are specified as a bitfield, for example * {@code (Acl.ADD | Acl.DELETE | Acl.GET)}. * * @param principal The entity to check, or "*" to check whether * the given permissions are granted to all principals globally * @param permissions The permissions to check * @return {@code true} if the principal holds all the given permissions * @throws IllegalArgumentException if {@code principal} is not a * valid principal name or if {@code permissions} is not a * valid combination of the permission constants defined in this * class */ public synchronized boolean isPermitted(String principal, int permissions) { checkPermissions(permissions); int hasPermissions = getPermissions(principal); return (permissions & hasPermissions) == permissions; } /** * Create a new {@code Acl} instance from this {@code Acl} where * all permissions for the given principal are overwritten with the given * permissions. *

* Note, that when changing the permissions of a specific principal, it is * not allowed to specify a set of permissions stricter than the global set * of permissions (that apply to all principals). * * @param principal The entity to which permissions should be granted, or * "*" to globally grant permissions to all principals. * @param permissions The set of permissions to be given. The parameter is * a bitmask of the permission constants defined in this class. * @return a new {@code Acl} instance * @throws IllegalArgumentException if {@code principal} is not a * valid principal name, if {@code permissions} is not a * valid combination of the permission constants defined in this * class, or if a globally granted permission would have been * revoked from a specific principal */ public synchronized Acl setPermission(String principal, int permissions) { checkPermissions(permissions); Acl newPermission = new Acl(this, principal, permissions); return newPermission; } /** * Get the list of principals who have any kind of permissions on this node. * The list only includes those principals that have been explicitly * assigned permissions (so "*" is never returned), globally set * permissions naturally apply to all other principals as well. * * @return The array of principals having permissions on this node. */ public String[] getPrincipals() { return (String[]) (principalPermissions.keySet().toArray(new String[0])); } /** * Give the canonic string representation of this ACL. The operations are in * the following order: {Add, Delete, Exec, Get, Replace}, principal names * are sorted alphabetically. * * @return The string representation as defined in OMA DM. */ public synchronized String toString() { String acl = null; for (int i = 0; i < PERMISSION_CODES.length; i++) acl = writeEntry(PERMISSION_CODES[i], acl); return (acl != null) ? acl : ""; } // ----- Private utility methods -----// private String writeEntry(int command, String acl) { String aclEntry = null; if ((command & globalPermissions) > 0) aclEntry = ALL_PRINCIPALS; else { // TreeMap guarantees alphabetical ordering of keys during traversal Iterator i = principalPermissions.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); if ((command & ((Integer) entry.getValue()).intValue()) > 0) aclEntry = appendEntry(aclEntry, '+', (String) entry .getKey()); } } if (aclEntry == null) return acl; return appendEntry(acl, '&', writeCommands(command) + '=' + aclEntry); } private static void deleteFromAll(TreeMap principalPermissions, int perm) { Iterator i = principalPermissions.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); setPrincipalPermission(principalPermissions, (String) entry .getKey(), ((Integer) entry.getValue()).intValue() & ~perm); } } private static void setPrincipalPermission(TreeMap principalPermissions, String principal, int perm) { if (perm == 0) principalPermissions.remove(principal); else principalPermissions.put(principal, new Integer(perm)); } private static String writeCommands(int command) { String commandStr = null; for (int i = 0; i < PERMISSION_CODES.length; i++) if ((command & PERMISSION_CODES[i]) != 0) commandStr = appendEntry(commandStr, ',', PERMISSION_NAMES[i]); return (commandStr != null) ? commandStr : ""; } private static String appendEntry(String base, char separator, String entry) { return (base != null) ? base + separator + entry : entry; } private static int parseCommand(String command) { int i = Arrays.asList(PERMISSION_NAMES).indexOf(command); if (i == -1) throw new IllegalArgumentException( "Invalid ACL string: unknown command '" + command + "'."); return PERMISSION_CODES[i]; } private static void checkPermissions(int perm) { if ((perm & ~ALL_PERMISSION) != 0) throw new IllegalArgumentException("Invalid ACL permission value: " + perm); } private static void checkPrincipal(String principal) { if (principal == null) throw new IllegalArgumentException("Principal is null."); checkServerId(principal, "Principal name contains illegal character"); } private static void checkServerId(String serverId, String errorText) { char[] chars = serverId.toCharArray(); for (int i = 0; i < chars.length; i++) if ("*=+&".indexOf(chars[i]) != -1 || Character.isWhitespace(chars[i])) throw new IllegalArgumentException(errorText + " '" + chars[i] + "'."); } private static String[] split(String input, char sep, int limit) { Vector v = new Vector(); boolean limited = (limit > 0); int applied = 0; int index = 0; StringBuffer part = new StringBuffer(); while (index < input.length()) { char ch = input.charAt(index); if (ch != sep) part.append(ch); else { ++applied; v.add(part.toString()); part = new StringBuffer(); } ++index; if (limited && applied == limit - 1) break; } while (index < input.length()) { char ch = input.charAt(index); part.append(ch); ++index; } v.add(part.toString()); int last = v.size(); if (0 == limit) { for (int j = v.size() - 1; j >= 0; --j) { String s = (String) v.elementAt(j); if ("".equals(s)) --last; else break; } } String[] ret = new String[last]; for (int i = 0; i < last; ++i) ret[i] = (String) v.elementAt(i); return ret; } } osgi-compendium-4.3.0/src/info/dmtree/DmtEventListener.java0000644000175000017500000000267211466514064023630 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree; /** * Registered implementations of this class are notified via {@link DmtEvent} * objects about important changes in the tree. Events are generated after every * successful DMT change, and also when sessions are opened or closed. If a * {@link DmtSession} is opened in atomic mode, DMT events are only sent when * the session is committed, when the changes are actually performed. * * @version $Id: 275675e7ed60b346c1081e1b5bacdfa348ad8350 $ */ public interface DmtEventListener { /** * {@code DmtAdmin} uses this method to notify the registered * listeners about the change. This method is called asynchronously from the * actual event occurrence. * * @param event the {@code DmtEvent} describing the change in detail */ void changeOccurred(DmtEvent event); } osgi-compendium-4.3.0/src/info/dmtree/DmtAdmin.java0000644000175000017500000003432611564442770022075 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree; /** * An interface providing methods to open sessions and register listeners. The * implementation of {@code DmtAdmin} should register itself in the OSGi * service registry as a service. {@code DmtAdmin} is the entry point for * applications to use the DMT API. *

* The {@code getSession} methods are used to open a session on a specified * subtree of the DMT. A typical way of usage: * *

 * serviceRef = context.getServiceReference(DmtAdmin.class.getName());
 * DmtAdmin admin = (DmtAdmin) context.getService(serviceRef);
 * DmtSession session = admin.getSession("./OSGi/Configuration");
 * session.createInteriorNode("./OSGi/Configuration/my.table");
 * 
*

* The methods for opening a session take a node URI (the session root) as a * parameter. All segments of the given URI must be within the segment length * limit of the implementation, and the special characters '/' and '\' must be * escaped (preceded by a '\'). Any string can be converted to a valid URI * segment using the {@link Uri#mangle(String)} method. *

* It is possible to specify a lock mode when opening the session (see lock type * constants in {@link DmtSession}). This determines whether the session can run * in parallel with other sessions, and the kinds of operations that can be * performed in the session. All Management Objects constituting the device * management tree must support read operations on their nodes, while support * for write operations depends on the Management Object. Management Objects * supporting write access may support transactional write, non-transactional * write or both. Users of {@code DmtAdmin} should consult the Management * Object specification and implementation for the supported update modes. If * Management Object definition permits, implementations are encouraged to * support both update modes. *

* This interface also contains methods for manipulating the set of * {@code DmtEventListener} objects that are called when the structure or * content of the tree is changed. These methods are not needed in an OSGi * environment, clients should register listeners through the Event Admin * service. * * @version $Id: d34854b75471e0738ef0458a6cf154f0bd3a581d $ */ public interface DmtAdmin { /** * Opens a {@code DmtSession} for local usage on a given subtree of * the DMT with non transactional write lock. This call is equivalent to the * following: * {@code getSession(null, subtreeUri, DmtSession.LOCK_TYPE_EXCLUSIVE)} *

* The {@code subtreeUri} parameter must contain an absolute URI. It * can also be {@code null}, in this case the session is opened with * the default session root, ".", that gives access to the whole * tree. *

* To perform this operation the caller must have {@code DmtPermission} * for the {@code subtreeUri} node with the Get action present. * * @param subtreeUri the subtree on which DMT manipulations can be performed * within the returned session * @return a {@code DmtSession} object for the requested subtree * @throws DmtException with the following possible error codes: *

* @throws SecurityException if the caller does not have * {@code DmtPermission} for the given root node with the Get * action present */ DmtSession getSession(String subtreeUri) throws DmtException; /** * Opens a {@code DmtSession} for local usage on a specific DMT * subtree with a given lock mode. This call is equivalent to the * following: {@code getSession(null, subtreeUri, lockMode)} *

* The {@code subtreeUri} parameter must contain an absolute URI. It * can also be {@code null}, in this case the session is opened with * the default session root, ".", that gives access to the whole * tree. *

* To perform this operation the caller must have {@code DmtPermission} * for the {@code subtreeUri} node with the Get action present. * * @param subtreeUri the subtree on which DMT manipulations can be performed * within the returned session * @param lockMode one of the lock modes specified in * {@code DmtSession} * @return a {@code DmtSession} object for the requested subtree * @throws DmtException with the following possible error codes: *

* @throws SecurityException if the caller does not have * {@code DmtPermission} for the given root node with the Get * action present */ DmtSession getSession(String subtreeUri, int lockMode) throws DmtException; /** * Opens a {@code DmtSession} on a specific DMT subtree using a * specific lock mode on behalf of a remote principal. If local management * applications are using this method then they should provide * {@code null} as the first parameter. Alternatively they can use * other forms of this method without providing a principal string. *

* The {@code subtreeUri} parameter must contain an absolute URI. It * can also be {@code null}, in this case the session is opened with * the default session root, ".", that gives access to the whole * tree. *

* This method is guarded by {@code DmtPrincipalPermission} in case of * remote sessions. In addition, the caller must have Get access rights * (ACL in case of remote sessions, {@code DmtPermission} in case of * local sessions) on the {@code subtreeUri} node to perform this * operation. * * @param principal the identifier of the remote server on whose behalf the * data manipulation is performed, or {@code null} for local * sessions * @param subtreeUri the subtree on which DMT manipulations can be performed * within the returned session * @param lockMode one of the lock modes specified in * {@code DmtSession} * @return a {@code DmtSession} object for the requested subtree * @throws DmtException with the following possible error codes: *

* @throws SecurityException in case of remote sessions, if the caller does * not have the required {@code DmtPrincipalPermission} with a * target matching the {@code principal} parameter, or in case * of local sessions, if the caller does not have * {@code DmtPermission} for the given root node with the Get * action present */ DmtSession getSession(String principal, String subtreeUri, int lockMode) throws DmtException; /** * Registers an event listener on behalf of a local application. The given * listener will receive notification on all changes affecting the specified * subtree. The subtree is specified by its root node URI. An event is * delivered to the registered listener if at least one affected node is * within this subtree. The events can also be filtered by specifying a * bitmask of relevant event types (e.g. * {@code DmtEvent.ADDED | DmtEvent.REPLACED | DmtEvent.SESSION_CLOSED}). * Only event types included in the bitmask will be delivered to the * listener. *

* The listener will only receive the change notifications of nodes for * which the registering application has the appropriate GET * {@link info.dmtree.security.DmtPermission}. *

* If the specified {@code listener} was already registered, calling * this method will update the registration. * * @param type a bitmask of event types the caller is interested in * @param uri the URI of the root node of a subtree, must not be * {@code null} * @param listener the listener to be registered, must not be * {@code null} * @throws SecurityException if the caller doesn't have the necessary GET * {@code DmtPermission} for the given URI * @throws NullPointerException if the {@code uri} or * {@code listener} parameter is {@code null} * @throws IllegalArgumentException if the {@code type} parameter * contains invalid bits (not corresponding to any event type * defined in {@code DmtEvent}), or if the {@code uri} * parameter is invalid (is not an absolute URI or is syntactically * incorrect) */ void addEventListener(int type, String uri, DmtEventListener listener); /** * Registers an event listener on behalf of a remote principal. The given * listener will receive notification on all changes affecting the specified * subtree. The subtree is specified by its root node URI. An event is * delivered to the registered listener if at least one affected node is * within this subtree. The events can also be filtered by specifying a * bitmask of relevant event types (e.g. * {@code DmtEvent.ADDED | DmtEvent.REPLACED | DmtEvent.SESSION_CLOSED}). * Only event types included in the bitmask will be delivered to the * listener. *

* The listener will only receive the change notifications of nodes for * which the node ACL grants GET access to the specified principal. *

* If the specified {@code listener} was already registered, calling * this method will update the registration. * * @param principal the management server identity the caller is acting on * behalf of, must not be {@code null} * @param type a bitmask of event types the caller is interested in * @param uri the URI of the root node of a subtree, must not be * {@code null} * @param listener the listener to be registered, must not be * {@code null} * @throws SecurityException if the caller doesn't have the necessary * {@code DmtPrincipalPermission} to use the specified * principal * @throws NullPointerException if the {@code principal}, * {@code uri} or {@code listener} parameter is * {@code null} * @throws IllegalArgumentException if the {@code type} parameter * contains invalid bits (not corresponding to any event type * defined in {@code DmtEvent}), or if the {@code uri} * parameter is invalid (is not an absolute URI or is syntactically * incorrect) */ void addEventListener(String principal, int type, String uri, DmtEventListener listener); /** * Remove a previously registered listener. After this call, the listener * will not receive change notifications. * * @param listener the listener to be unregistered, must not be * {@code null} * @throws NullPointerException if the {@code listener} parameter is * {@code null} */ void removeEventListener(DmtEventListener listener); } osgi-compendium-4.3.0/src/info/dmtree/DmtData.java0000644000175000017500000007406711564442770021724 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree; import java.util.Arrays; import java.util.Hashtable; // Possible enhancements to this class: // * new constructors and get/set methods for b64, to access the encoded value // * new constructors and get/set methods for date/time, for more convenient // Java access /** * An immutable data structure representing the contents of a leaf or interior * node. This structure represents only the value and the format property of the * node, all other properties (like MIME type) can be set and read using the * {@code DmtSession} interface. *

* Different constructors are available to create nodes with different formats. * Nodes of {@code null} format can be created using the static * {@link #NULL_VALUE} constant instance of this class. *

* {@link #FORMAT_RAW_BINARY} and {@link #FORMAT_RAW_STRING} enable the support * of future data formats. When using these formats, the actual format name is * specified as a {@code String}. The application is responsible for the * proper encoding of the data according to the specified format. * * @version $Id: 6c2015a5ae3d771d4d09128428373b61fe832523 $ */ public final class DmtData { /** * The node holds an OMA DM {@code int} value. */ public static final int FORMAT_INTEGER = 0x0001; /** * The node holds an OMA DM {@code float} value. */ public static final int FORMAT_FLOAT = 0x0002; /** * The node holds an OMA DM {@code chr} value. */ public static final int FORMAT_STRING = 0x0004; /** * The node holds an OMA DM {@code bool} value. */ public static final int FORMAT_BOOLEAN = 0x0008; /** * The node holds an OMA DM {@code date} value. */ public static final int FORMAT_DATE = 0x0010; /** * The node holds an OMA DM {@code time} value. */ public static final int FORMAT_TIME = 0x0020; /** * The node holds an OMA DM {@code bin} value. The value of the node * corresponds to the Java {@code byte[]} type. */ public static final int FORMAT_BINARY = 0x0040; /** * The node holds an OMA DM {@code b64} value. Like * {@link #FORMAT_BINARY}, this format is also represented by the Java * {@code byte[]} type, the difference is only in the corresponding * OMA DM format. */ public static final int FORMAT_BASE64 = 0x0080; /** * The node holds an OMA DM {@code xml} value. */ public static final int FORMAT_XML = 0x0100; /** * The node holds an OMA DM {@code null} value. This corresponds to * the Java {@code null} type. */ public static final int FORMAT_NULL = 0x0200; /** * Format specifier of an internal node. An interior node can hold a Java * object as value (see {@link DmtData#DmtData(Object)} and * {@link DmtData#getNode()}). This value can be used by Java programs that * know a specific URI understands the associated Java type. This type is * further used as a return value of the {@link MetaNode#getFormat} method * for interior nodes. */ public static final int FORMAT_NODE = 0x0400; /** * The node holds raw protocol data encoded as {@code String}. The * {@link #getFormatName()} method can be used to get the actual format * name. */ public static final int FORMAT_RAW_STRING = 0x0800; /** * The node holds raw protocol data encoded in binary format. The * {@link #getFormatName()} method can be used to get the actual format * name. */ public static final int FORMAT_RAW_BINARY = 0x1000; private static final Hashtable FORMAT_NAMES = new Hashtable(); static { FORMAT_NAMES.put(new Integer(FORMAT_BASE64), "b64"); FORMAT_NAMES.put(new Integer(FORMAT_BINARY), "bin"); FORMAT_NAMES.put(new Integer(FORMAT_BOOLEAN), "bool"); FORMAT_NAMES.put(new Integer(FORMAT_DATE), "date"); FORMAT_NAMES.put(new Integer(FORMAT_FLOAT), "float"); FORMAT_NAMES.put(new Integer(FORMAT_INTEGER), "int"); FORMAT_NAMES.put(new Integer(FORMAT_NODE), "node"); FORMAT_NAMES.put(new Integer(FORMAT_NULL), "null"); FORMAT_NAMES.put(new Integer(FORMAT_STRING), "chr"); FORMAT_NAMES.put(new Integer(FORMAT_TIME), "time"); FORMAT_NAMES.put(new Integer(FORMAT_XML), "xml"); } /** * Constant instance representing a leaf node of {@code null} format. */ public static final DmtData NULL_VALUE = new DmtData(); // FORMAT_NAMES must be initialized by the time the constr. is called private final String str; private final int integer; private final float flt; private final boolean bool; private final byte[] bytes; private final int format; private final String formatName; private final Object complex; /** * Create a {@code DmtData} instance of {@code null} format. * This constructor is private and used only to create the public * {@link #NULL_VALUE} constant. */ private DmtData() { format = FORMAT_NULL; formatName = getFormatName(format); this.str = null; this.integer = 0; this.flt = 0; this.bool = false; this.bytes = null; this.complex = null; } /** * Create a {@code DmtData} instance of {@code chr} format * with the given string value. The {@code null} string argument is * valid. * * @param str the string value to set */ public DmtData(String str) { format = FORMAT_STRING; formatName = getFormatName(format); this.str = str; this.integer = 0; this.flt = 0; this.bool = false; this.bytes = null; this.complex = null; } /** * Create a {@code DmtData} instance of {@code node} format * with the given object value. The value represents complex data associated * with an interior node. *

* Certain interior nodes can support access to their subtrees through such * complex values, making it simpler to retrieve or update all leaf nodes in * a subtree. *

* The given value must be a non-{@code null} immutable object. * * @param complex the complex data object to set */ public DmtData(Object complex) { if(complex == null) throw new NullPointerException("Complex data argument is null."); format = FORMAT_NODE; formatName = getFormatName(format); this.complex = complex; this.str = null; this.integer = 0; this.flt = 0; this.bool = false; this.bytes = null; } /** * Create a {@code DmtData} instance of the specified format and set * its value based on the given string. Only the following string-based * formats can be created using this constructor: *

* The {@code null} string argument is only valid if the format is * string or XML. * * @param value the string, XML, date or time value to set * @param format the format of the {@code DmtData} instance to be * created, must be one of the formats specified above * @throws IllegalArgumentException if {@code format} is not one of * the allowed formats, or {@code value} is not a valid * string for the given format * @throws NullPointerException if a date or time is constructed and * {@code value} is {@code null} */ public DmtData(String value, int format) { switch (format) { case FORMAT_DATE: checkDateFormat(value); break; case FORMAT_TIME: checkTimeFormat(value); break; case FORMAT_STRING: case FORMAT_XML: break; // nothing to do, all string values are accepted default: throw new IllegalArgumentException( "Invalid format in string constructor: " + format); } this.format = format; this.formatName = getFormatName(format); this.str = value; this.integer = 0; this.flt = 0; this.bool = false; this.bytes = null; this.complex = null; } /** * Create a {@code DmtData} instance of {@code int} format and * set its value. * * @param integer the integer value to set */ public DmtData(int integer) { format = FORMAT_INTEGER; formatName = getFormatName(format); this.integer = integer; this.str = null; this.flt = 0; this.bool = false; this.bytes = null; this.complex = null; } /** * Create a {@code DmtData} instance of {@code float} format * and set its value. * * @param flt the float value to set */ public DmtData(float flt) { format = FORMAT_FLOAT; formatName = getFormatName(format); this.flt = flt; this.str = null; this.integer = 0; this.bool = false; this.bytes = null; this.complex = null; } /** * Create a {@code DmtData} instance of {@code bool} format * and set its value. * * @param bool the boolean value to set */ public DmtData(boolean bool) { format = FORMAT_BOOLEAN; formatName = getFormatName(format); this.bool = bool; this.str = null; this.integer = 0; this.flt = 0; this.bytes = null; this.complex = null; } /** * Create a {@code DmtData} instance of {@code bin} format and * set its value. * * @param bytes the byte array to set, must not be {@code null} * @throws NullPointerException if {@code bytes} is {@code null} */ public DmtData(byte[] bytes) { if (bytes == null) throw new NullPointerException("Binary data argument is null."); format = FORMAT_BINARY; formatName = getFormatName(format); this.bytes = bytes; this.str = null; this.integer = 0; this.flt = 0; this.bool = false; this.complex = null; } /** * Create a {@code DmtData} instance of {@code bin} or * {@code b64} format and set its value. The chosen format is * specified by the {@code base64} parameter. * * @param bytes the byte array to set, must not be {@code null} * @param base64 if {@code true}, the new instance will have * {@code b64} format, if {@code false}, it will have * {@code bin} format * @throws NullPointerException if {@code bytes} is {@code null} */ public DmtData(byte[] bytes, boolean base64) { if (bytes == null) throw new NullPointerException("Binary data argument is null."); format = base64 ? FORMAT_BASE64 : FORMAT_BINARY; formatName = getFormatName(format); this.bytes = bytes; this.str = null; this.integer = 0; this.flt = 0; this.bool = false; this.complex = null; } /** * Create a {@code DmtData} instance in {@link #FORMAT_RAW_STRING} * format. The data is provided encoded as a {@code String}. The * actual data format is specified in {@code formatName}. The * encoding used in {@code data} must conform to this format. * * @param formatName the name of the format, must not be {@code null} * @param data the data encoded according to the specified format, must not * be {@code null} * @throws NullPointerException if {@code formatName} or * {@code data} is {@code null} */ public DmtData(String formatName, String data) { if(formatName == null) throw new NullPointerException("Format name argument is null."); if(data == null) throw new NullPointerException("Data argument is null."); format = FORMAT_RAW_STRING; this.formatName = formatName; this.str = data; this.bytes = null; this.integer = 0; this.flt = 0; this.bool = false; this.complex = null; } /** * Create a {@code DmtData} instance in {@link #FORMAT_RAW_BINARY} * format. The data is provided encoded as binary. The actual data format is * specified in {@code formatName}. The encoding used in * {@code data} must conform to this format. * * @param formatName the name of the format, must not be {@code null} * @param data the data encoded according to the specified format, must not * be {@code null} * @throws NullPointerException if {@code formatName} or * {@code data} is {@code null} */ public DmtData(String formatName, byte[] data) { if(formatName == null) throw new NullPointerException("Format name argument is null."); if(data == null) throw new NullPointerException("Data argument is null."); format = FORMAT_RAW_BINARY; this.formatName = formatName; this.bytes = (byte[]) data.clone(); this.str = null; this.integer = 0; this.flt = 0; this.bool = false; this.complex = null; } /** * Gets the value of a node with string ({@code chr}) format. * * @return the string value * @throws DmtIllegalStateException if the format of the node is not string */ public String getString() { if (format == FORMAT_STRING) return str; throw new DmtIllegalStateException("DmtData value is not string."); } /** * Gets the value of a node with date format. The returned date string is * formatted according to the ISO 8601 definition of a calendar date in * complete representation, basic format (pattern {@code CCYYMMDD}). * * @return the date value * @throws DmtIllegalStateException if the format of the node is not date */ public String getDate() { if (format == FORMAT_DATE) return str; throw new DmtIllegalStateException("DmtData value is not date."); } /** * Gets the value of a node with time format. The returned time string is * formatted according to the ISO 8601 definition of the time of day. The * exact format depends on the value the object was initialized with: either * local time, complete representation, basic format (pattern * {@code hhmmss}) or Coordinated Universal Time, basic format (pattern * {@code hhmmssZ}). * * @return the time value * @throws DmtIllegalStateException if the format of the node is not time */ public String getTime() { if (format == FORMAT_TIME) return str; throw new DmtIllegalStateException("DmtData value is not time."); } /** * Gets the value of a node with {@code xml} format. * * @return the XML value * @throws DmtIllegalStateException if the format of the node is not * {@code xml} */ public String getXml() { if (format == FORMAT_XML) return str; throw new DmtIllegalStateException("DmtData value is not XML."); } /** * Gets the value of a node with integer ({@code int}) format. * * @return the integer value * @throws DmtIllegalStateException if the format of the node is not integer */ public int getInt() { if (format == FORMAT_INTEGER) return integer; throw new DmtIllegalStateException("DmtData value is not integer."); } /** * Gets the value of a node with {@code float} format. * * @return the float value * @throws DmtIllegalStateException if the format of the node is not * {@code float} */ public float getFloat() { if (format == FORMAT_FLOAT) return flt; throw new DmtIllegalStateException("DmtData value is not float."); } /** * Gets the value of a node with boolean ({@code bool}) format. * * @return the boolean value * @throws DmtIllegalStateException if the format of the node is not boolean */ public boolean getBoolean() { if (format == FORMAT_BOOLEAN) return bool; throw new DmtIllegalStateException("DmtData value is not boolean."); } /** * Gets the value of a node with binary ({@code bin}) format. * * @return the binary value * @throws DmtIllegalStateException if the format of the node is not binary */ public byte[] getBinary() { if (format == FORMAT_BINARY) { byte[] bytesCopy = new byte[bytes.length]; for (int i = 0; i < bytes.length; i++) bytesCopy[i] = bytes[i]; return bytesCopy; } throw new DmtIllegalStateException("DmtData value is not a byte array."); } /** * Gets the value of a node in raw binary ({@link #FORMAT_RAW_BINARY}) * format. * * @return the data value in raw binary format * @throws DmtIllegalStateException if the format of the node is not raw binary */ public byte[] getRawBinary() { if (format == FORMAT_RAW_BINARY) return (byte[]) bytes.clone(); throw new DmtIllegalStateException( "DmtData value is not in raw binary format."); } /** * Gets the value of a node in raw {@code String} * ({@link #FORMAT_RAW_STRING}) format. * * @return the data value in raw {@code String} format * @throws DmtIllegalStateException if the format of the node is not raw * {@code String} */ public String getRawString() { if (format == FORMAT_RAW_STRING) return str; throw new DmtIllegalStateException( "DmtData value is not in raw string format."); } /** * Gets the value of a node with base 64 ({@code b64}) format. * * @return the binary value * @throws DmtIllegalStateException if the format of the node is not base 64. */ public byte[] getBase64() { if (format == FORMAT_BASE64) { byte[] bytesCopy = new byte[bytes.length]; for (int i = 0; i < bytes.length; i++) bytesCopy[i] = bytes[i]; return bytesCopy; } throw new DmtIllegalStateException( "DmtData value is not in base 64 format."); } /** * Gets the complex data associated with an interior node ({@code node} * format). *

* Certain interior nodes can support access to their subtrees through * complex values, making it simpler to retrieve or update all leaf nodes in * the subtree. * * @return the data object associated with an interior node * @throws DmtIllegalStateException if the format of the data is not * {@code node} */ public Object getNode() { if(format == FORMAT_NODE) return complex; throw new DmtIllegalStateException( "DmtData does not contain interior node data."); } /** * Get the node's format, expressed in terms of type constants defined in * this class. Note that the 'format' term is a legacy from OMA DM, it is * more customary to think of this as 'type'. * * @return the format of the node */ public int getFormat() { return format; } /** * Returns the format of this {@code DmtData} as {@code String}. * For the predefined data formats this is the OMA DM defined name of the * format. For {@link #FORMAT_RAW_STRING} and {@link #FORMAT_RAW_BINARY} * this is the format specified when the object was created. * * @return the format name as {@code String} */ public String getFormatName() { return formatName; } /** * Get the size of the data. The returned value depends on the format of * data in the node: *

* * @return the size of the data stored by this object */ public int getSize() { switch (format) { case FORMAT_STRING: case FORMAT_XML: case FORMAT_DATE: case FORMAT_TIME: case FORMAT_RAW_STRING: return str == null ? 0 : str.length(); case FORMAT_BINARY: case FORMAT_BASE64: case FORMAT_RAW_BINARY: return bytes.length; case FORMAT_INTEGER: case FORMAT_FLOAT: return 4; case FORMAT_BOOLEAN: return 1; case FORMAT_NODE: return -1; case FORMAT_NULL: return 0; } return 0; // never reached } /** * Gets the string representation of the {@code DmtData}. This * method works for all formats. *

* For string format data - including {@link #FORMAT_RAW_STRING} - the * string value itself is returned, while for XML, date, time, integer, * float, boolean and node formats the string form of the value is returned. * Binary - including {@link #FORMAT_RAW_BINARY} - and base64 data is * represented by two-digit hexadecimal numbers for each byte separated by * spaces. The {@link #NULL_VALUE} data has the string form of * "{@code null}". Data of string or XML format containing the Java * {@code null} value is represented by an empty string. * * @return the string representation of this {@code DmtData} instance */ public String toString() { switch (format) { case FORMAT_STRING: case FORMAT_XML: case FORMAT_DATE: case FORMAT_TIME: case FORMAT_RAW_STRING: return str == null ? "" : str; case FORMAT_INTEGER: return String.valueOf(integer); case FORMAT_FLOAT: return String.valueOf(flt); case FORMAT_BOOLEAN: return String.valueOf(bool); case FORMAT_BINARY: case FORMAT_BASE64: case FORMAT_RAW_BINARY: return getHexDump(bytes); case FORMAT_NODE: return complex.toString(); case FORMAT_NULL: return "null"; } return null; // never reached } /** * Compares the specified object with this {@code DmtData} instance. * Two {@code DmtData} objects are considered equal if their format * is the same, and their data (selected by the format) is equal. *

* In case of {@link #FORMAT_RAW_BINARY} and {@link #FORMAT_RAW_STRING} * the textual name of the data format - as returned by * {@link #getFormatName()} - must be equal as well. * * @param obj the object to compare with this {@code DmtData} * @return true if the argument represents the same {@code DmtData} * as this object */ public boolean equals(Object obj) { if (!(obj instanceof DmtData)) return false; DmtData other = (DmtData) obj; if (format != other.format) return false; switch (format) { case FORMAT_STRING: case FORMAT_XML: case FORMAT_DATE: case FORMAT_TIME: return str == null ? other.str == null : str.equals(other.str); case FORMAT_INTEGER: return integer == other.integer; case FORMAT_FLOAT: return flt == other.flt; case FORMAT_BOOLEAN: return bool == other.bool; case FORMAT_BINARY: case FORMAT_BASE64: return Arrays.equals(bytes, other.bytes); case FORMAT_NODE: return complex.equals(other.complex); case FORMAT_NULL: return true; case FORMAT_RAW_BINARY: return formatName.equals(other.formatName) && Arrays.equals(bytes, other.bytes); case FORMAT_RAW_STRING: // in this case str cannot be null return formatName.equals(other.formatName) && str.equals(other.str); } return false; // never reached } /** * Returns the hash code value for this {@code DmtData} instance. The * hash code is calculated based on the data (selected by the format) of * this object. * * @return the hash code value for this object */ public int hashCode() { switch (format) { case FORMAT_STRING: case FORMAT_XML: case FORMAT_DATE: case FORMAT_TIME: case FORMAT_RAW_STRING: return str == null ? 0 : str.hashCode(); case FORMAT_INTEGER: return new Integer(integer).hashCode(); case FORMAT_FLOAT: return new Float(flt).hashCode(); case FORMAT_BOOLEAN: return new Boolean(bool).hashCode(); case FORMAT_BINARY: case FORMAT_BASE64: case FORMAT_RAW_BINARY: return new String(bytes).hashCode(); case FORMAT_NODE: return complex.hashCode(); case FORMAT_NULL: return 0; } return 0; // never reached } private static void checkDateFormat(String value) { if(value.length() != 8) throw new IllegalArgumentException("Date string '" + value + "' does not follow the format 'CCYYMMDD'."); int year = checkNumber(value, "Date", 0, 4, 0, 9999); int month = checkNumber(value, "Date", 4, 2, 1, 12); int day = checkNumber(value, "Date", 6, 2, 1, 31); // Date checking is not prepared for all special rules (for example // historical leap years), production code could contain a full check. // Day 31 is invalid for April, June, September and November if((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) throw new IllegalArgumentException("Date string '" + value + "' contains an invalid date."); // February 29 is invalid except for leap years, Feb. 30-31 are invalid if(month == 2 && day > 28 && !(day == 29 && year%4 == 0 && (year%100 != 0 || year%400 == 0))) throw new IllegalArgumentException("Date string '" + value + "' contains an invalid date."); } private static void checkTimeFormat(String value) { if(value.length() > 0 && value.charAt(value.length()-1) == 'Z') value = value.substring(0, value.length()-1); if(value.length() != 6) throw new IllegalArgumentException("Time string '" + value + "' does not follow the format 'hhmmss' or 'hhmmssZ'."); // Time checking is not prepared for all special rules (for example // leap seconds), production code could contain a full check. // if hour is 24, only 240000 should be allowed checkNumber(value, "Time", 0, 2, 0, 24); checkNumber(value, "Time", 2, 2, 0, 59); checkNumber(value, "Time", 4, 2, 0, 59); if(value.startsWith("24") && !value.startsWith("240000")) throw new IllegalArgumentException("Time string is out of range."); } private static int checkNumber(String value, String name, int from, int length, int min, int max) { String part = value.substring(from, from+length); int number; try { number = Integer.parseInt(part); } catch(NumberFormatException e) { throw new IllegalArgumentException(name + " string '" + value + "' contains a non-numeric part."); } if(number < min || number > max) throw new IllegalArgumentException("A segment of the " + name + " string '" + value + "' is out of range."); return number; } // character array of hexadecimal digits, used for printing binary data private static char[] hex = "0123456789ABCDEF".toCharArray(); // generates a hexadecimal dump of the given binary data private static String getHexDump(byte[] bytes) { if (bytes.length == 0) return ""; StringBuffer buf = new StringBuffer(); appendHexByte(buf, bytes[0]); for (int i = 1; i < bytes.length; i++) appendHexByte(buf.append(' '), bytes[i]); return buf.toString(); } private static void appendHexByte(StringBuffer buf, byte b) { buf.append(hex[(b & 0xF0) >> 4]).append(hex[b & 0x0F]); } private static String getFormatName(int format) { return (String) FORMAT_NAMES.get(new Integer(format)); } } osgi-compendium-4.3.0/src/info/dmtree/DmtEvent.java0000644000175000017500000001216511564442770022123 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree; /** * Event class storing the details of a change in the tree. * {@code DmtEvent} is used by {@code DmtAdmin} to notify registered * {@link DmtEventListener EventListeners} about important changes. Events are * generated after every successful DMT change, and also when sessions are * opened or closed. If a {@link DmtSession} is opened in atomic mode, DMT * events are only sent when the session is committed, when the changes are * actually performed. *

* An event is generated for each group of nodes added, deleted, replaced, * renamed or copied, in this order. Events are also generated when sessions are * opened and closed. *

* The {@code type} of the event describes the change that triggered the * event delivery. Each event carries the unique identifier of the session in * which the described change happened. The events describing changes in the DMT * carry the list of affected nodes. In case of {@link #COPIED} or * {@link #RENAMED} events, the event carries the list of new nodes as well. *

* When a {@code DmtEvent} is delivered to a listener, the event contains * only those node URIs that the listener has access to. This access control * decision is based on the principal specified when the listener was * registered: *

* * @version $Id: 506872c6a60ee9170672b0e6cb2bc9688d70ad57 $ */ public interface DmtEvent { /** * Event type indicating nodes that were added. */ int ADDED = 0x01; /** * Event type indicating nodes that were copied. */ int COPIED = 0x02; /** * Event type indicating nodes that were deleted. */ int DELETED = 0x04; /** * Event type indicating nodes that were renamed. */ int RENAMED = 0x08; /** * Event type indicating nodes that were replaced. */ int REPLACED = 0x10; /** * Event type indicating that a new session was opened. */ int SESSION_OPENED = 0x20; /** * Event type indicating that a session was closed. This type of event is * sent when the session is closed by the client or becomes inactive for any * other reason (session timeout, fatal errors in business methods, etc.). */ int SESSION_CLOSED = 0x40; /** * This method returns the type of this event. * * @return the type of this event. */ int getType(); /** * This method returns the identifier of the session in which this event * took place. The ID is guaranteed to be unique on a machine. * * @return the unique indetifier of the session that triggered the event */ int getSessionId(); /** * This method can be used to query the subject nodes of this event. The * method returns {@code null} for {@link #SESSION_OPENED} and * {@link #SESSION_CLOSED}. *

* The method returns only those affected nodes that the caller has the GET * permission for (or in case of {@link #COPIED} or {@link #RENAMED} events, * where the caller has GET permissions for either the source or the * destination nodes). Therefore, it is possible that the method returns an * empty array. All returned URIs are absolute. * * @return the array of affected nodes * @see #getNewNodes */ String[] getNodes(); /** * This method can be used to query the new nodes, when the type of the * event is {@link #COPIED} or {@link #RENAMED}. For all other event types * this method returns {@code null}. *

* The array returned by this method runs parallel to the array returned by * {@link #getNodes}, the elements in the two arrays contain the source and * destination URIs for the renamed or copied nodes in the same order. All * returned URIs are absolute. *

* This method returns only those nodes where the caller has the GET * permission for the source or destination node of the operation. * Therefore, it is possible that the method returns an empty array. * * @return the array of newly created nodes */ String[] getNewNodes(); } osgi-compendium-4.3.0/src/info/dmtree/packageinfo0000644000175000017500000000001611405717676021720 0ustar drazzibdrazzibversion 1.0.2 osgi-compendium-4.3.0/src/info/dmtree/DmtSession.java0000644000175000017500000025276011466514064022471 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree; import java.util.Date; /** * DmtSession provides concurrent access to the DMT. All DMT manipulation * commands for management applications are available on the * {@code DmtSession} interface. The session is associated with a root node * which limits the subtree in which the operations can be executed within this * session. *

* Most of the operations take a node URI as parameter, which can be either an * absolute URI (starting with "./") or a URI relative to the root * node of the session. The empty string as relative URI means the root URI the * session was opened with. All segments of a URI must be within the segment * length limit of the implementation, and the special characters '/' and '\' * must be escaped (preceded by a '\'). Any string can be converted to a valid * URI segment using the {@link Uri#mangle(String)} method. *

* If the URI specified does not correspond to a legitimate node in the tree an * exception is thrown. The only exception is the {@link #isNodeUri(String)} * method which returns {@code false} in case of an invalid URI. *

* Each method of {@code DmtSession} that accesses the tree in any way can * throw {@code DmtIllegalStateException} if the session has been closed or * invalidated (due to timeout, fatal exceptions, or unexpectedly unregistered * plugins). * * @version $Id: 3e598cf3f60216bdc289e749ad8703710c0d990d $ */ public interface DmtSession { /** * Sessions created with {@code LOCK_TYPE_SHARED} lock allows * read-only access to the tree, but can be shared between multiple readers. */ int LOCK_TYPE_SHARED = 0; /** * {@code LOCK_TYPE_EXCLUSIVE} lock guarantees full access to the * tree, but can not be shared with any other locks. */ int LOCK_TYPE_EXCLUSIVE = 1; /** * {@code LOCK_TYPE_ATOMIC} is an exclusive lock with transactional * functionality. Commands of an atomic session will either fail or succeed * together, if a single command fails then the whole session will be rolled * back. */ int LOCK_TYPE_ATOMIC = 2; /** * The session is open, all session operations are available. */ int STATE_OPEN = 0; /** * The session is closed, DMT manipulation operations are not available, * they throw {@code DmtIllegalStateException} if tried. */ int STATE_CLOSED = 1; /** * The session is invalid because a fatal error happened. Fatal errors * include the timeout of the session, any DmtException with the 'fatal' * flag set, or the case when a plugin service is unregistered while in use * by the session. DMT manipulation operations are not available, they throw * {@code DmtIllegalStateException} if tried. */ int STATE_INVALID = 2; /** * Get the current state of this session. * * @return the state of the session, one of {@link #STATE_OPEN}, * {@link #STATE_CLOSED} and {@link #STATE_INVALID} */ int getState(); /** * Gives the type of lock the session has. * * @return the lock type of the session, one of {@link #LOCK_TYPE_SHARED}, * {@link #LOCK_TYPE_EXCLUSIVE} and {@link #LOCK_TYPE_ATOMIC} */ int getLockType(); /** * Gives the name of the principal on whose behalf the session was created. * Local sessions do not have an associated principal, in this case * {@code null} is returned. * * @return the identifier of the remote server that initiated the session, * or {@code null} for local sessions */ String getPrincipal(); /** * The unique identifier of the session. The ID is generated automatically, * and it is guaranteed to be unique on a machine. * * @return the session identification number */ int getSessionId(); /** * Get the root URI associated with this session. Gives "{@code .}" * if the session was created without specifying a root, which means that * the target of this session is the whole DMT. * * @return the root URI */ String getRootUri(); /** * Commits a series of DMT operations issued in the current atomic session * since the last transaction boundary. Transaction boundaries are the * creation of this object that starts the session, and all subsequent * {@link #commit} and {@link #rollback} calls. *

* This method can fail even if all operations were successful. This can * happen due to some multi-node semantic constraints defined by a specific * implementation. For example, node A can be required to always have * children A/B, A/C and A/D. If this condition is broken when * {@code commit()} is executed, the method will fail, and throw a * {@code METADATA_MISMATCH} exception. *

* An error situation can arise due to the lack of a two phase commit * mechanism in the underlying plugins. As an example, if plugin A has * committed successfully but plugin B failed, the whole session must fail, * but there is no way to undo the commit performed by A. To provide * predictable behaviour, the commit operation should continue with the * remaining plugins even after detecting a failure. All exceptions received * from failed commits are aggregated into one * {@code TRANSACTION_ERROR} exception thrown by this method. *

* In many cases the tree is not the only way to manage a given part of the * system. It may happen that while modifying some nodes in an atomic * session, the underlying settings are modified in parallel outside the * scope of the DMT. If this is detected during commit, an exception with * the code {@code CONCURRENT_ACCESS} is thrown. * * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was not opened using the * {@code LOCK_TYPE_ATOMIC} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ void commit() throws DmtException; /** * Rolls back a series of DMT operations issued in the current atomic * session since the last transaction boundary. Transaction boundaries are * the creation of this object that starts the session, and all subsequent * {@link #commit} and {@link #rollback} calls. * * @throws DmtException with the error code {@code ROLLBACK_FAILED} * in case the rollback did not succeed * @throws DmtIllegalStateException if the session was not opened using the * {@code LOCK_TYPE_ATOMIC} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ void rollback() throws DmtException; /** * Closes a session. If the session was opened with atomic lock mode, the * {@code DmtSession} must first persist the changes made to the DMT * by calling {@code commit()} on all (transactional) plugins * participating in the session. See the documentation of the * {@link #commit} method for details and possible errors during this * operation. *

* The state of the session changes to {@code DmtSession.STATE_CLOSED} * if the close operation completed successfully, otherwise it becomes * {@code DmtSession.STATE_INVALID}. * * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ void close() throws DmtException; /** * Executes a node. This corresponds to the EXEC operation in OMA DM. This * method cannot be called in a read-only session. *

* The semantics of an execute operation and the data parameter it takes * depends on the definition of the managed object on which the command is * issued. * * @param nodeUri the node on which the execute operation is issued * @param data the parameter of the execute operation, can be * {@code null} * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Exec action * present * * @see #execute(String, String, String) */ void execute(String nodeUri, String data) throws DmtException; /** * Executes a node, also specifying a correlation ID for use in response * notifications. This operation corresponds to the EXEC command in OMA DM. * This method cannot be called in a read-only session. *

* The semantics of an execute operation and the data parameter it takes * depends on the definition of the managed object on which the command is * issued. If a correlation ID is specified, it should be used as the * {@code correlator} parameter for notifications sent in response to this * execute operation. * * @param nodeUri the node on which the execute operation is issued * @param correlator an identifier to associate this operation with any * notifications sent in response to it, can be {@code null} if not * needed * @param data the parameter of the execute operation, can be * {@code null} * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Exec action * present * @see #execute(String, String) */ void execute(String nodeUri, String correlator, String data) throws DmtException; /** * Get the Access Control List associated with a given node. The returned * {@code Acl} object does not take inheritance into account, it * gives the ACL specifically given to the node. * * @param nodeUri the URI of the node * @return the Access Control List belonging to the node or * {@code null} if none defined * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException in case of local sessions, if the caller does * not have {@code DmtPermission} for the node with the Get * action present * @see #getEffectiveNodeAcl */ Acl getNodeAcl(String nodeUri) throws DmtException; /** * Gives the Access Control List in effect for a given node. The returned * {@code Acl} takes inheritance into account, that is if there is no * ACL defined for the node, it will be derived from the closest ancestor * having an ACL defined. * * @param nodeUri the URI of the node * @return the Access Control List belonging to the node * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException in case of local sessions, if the caller does * not have {@code DmtPermission} for the node with the Get * action present * @see #getNodeAcl */ Acl getEffectiveNodeAcl(String nodeUri) throws DmtException; /** * Set the Access Control List associated with a given node. To perform this * operation, the caller needs to have replace rights ({@code Acl.REPLACE} * or the corresponding Java permission depending on the session type) as * described below: * *

* If the given {@code acl} is {@code null} or an empty ACL * (not specifying any permissions for any principals), then the ACL of the * node is deleted, and the node will inherit the ACL from its parent node. * * @param nodeUri the URI of the node * @param acl the Access Control List to be set on the node, can be * {@code null} * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException in case of local sessions, if the caller does * not have {@code DmtPermission} for the node or its parent * (see above) with the Replace action present */ void setNodeAcl(String nodeUri, Acl acl) throws DmtException; /** * Create a copy of a node or a whole subtree. Beside the structure and * values of the nodes, most properties are also copied, with the exception * of the ACL (Access Control List), Timestamp and Version properties. *

* The copy method is essentially a convenience method that could be * substituted with a sequence of retrieval and update operations. This * determines the permissions required for copying. However, some * optimization can be possible if the source and target nodes are all * handled by DmtAdmin or by the same plugin. In this case, the handler * might be able to perform the underlying management operation more * efficiently: for example, a configuration table can be copied at once * instead of reading each node for each entry and creating it in the new * tree. *

* This method may result in any of the errors possible for the contributing * operations. Most of these are collected in the exception descriptions * below, but for the full list also consult the documentation of * {@link #getChildNodeNames(String)}, {@link #isLeafNode(String)}, * {@link #getNodeValue(String)}, {@link #getNodeType(String)}, * {@link #getNodeTitle(String)}, {@link #setNodeTitle(String, String)}, * {@link #createLeafNode(String, DmtData, String)} and * {@link #createInteriorNode(String, String)}. * * @param nodeUri the node or root of a subtree to be copied * @param newNodeUri the URI of the new node or root of a subtree * @param recursive {@code false} if only a single node is copied, * {@code true} if the whole subtree is copied * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the copied node(s) with the Get * action present, or for the parent of the target node with the Add * action */ void copy(String nodeUri, String newNodeUri, boolean recursive) throws DmtException; /** * Create an interior node. If the parent node does not exist, it is created * automatically, as if this method were called for the parent URI. This way * all missing ancestor nodes leading to the specified node are created. Any * exceptions encountered while creating the ancestors are propagated to the * caller of this method, these are not explicitly listed in the error * descriptions below. *

* If meta-data is available for the node, several checks are made before * creating it. The node must have {@code MetaNode.CMD_ADD} access * type, it must be defined as a non-permanent interior node, the node name * must conform to the valid names, and the creation of the new node must * not cause the maximum occurrence number to be exceeded. *

* If the meta-data cannot be retrieved because the given node cannot * possibly exist in the tree (it is not defined in the specification), the * {@code NODE_NOT_FOUND} error code is returned (see * {@link #getMetaNode(String)}). * * @param nodeUri the URI of the node to create * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the parent node with the Add * action present */ void createInteriorNode(String nodeUri) throws DmtException; /** * Create an interior node with a given type. The type of interior node, if * specified, is a URI identifying a DDF document. If the parent node does * not exist, it is created automatically, as if * {@link #createInteriorNode(String)} were called for the parent URI. This * way all missing ancestor nodes leading to the specified node are created. * Any exceptions encountered while creating the ancestors are propagated to * the caller of this method, these are not explicitly listed in the error * descriptions below. *

* If meta-data is available for the node, several checks are made before * creating it. The node must have {@code MetaNode.CMD_ADD} access * type, it must be defined as a non-permanent interior node, the node name * must conform to the valid names, and the creation of the new node must * not cause the maximum occurrence number to be exceeded. *

* If the meta-data cannot be retrieved because the given node cannot * possibly exist in the tree (it is not defined in the specification), the * {@code NODE_NOT_FOUND} error code is returned (see * {@link #getMetaNode(String)}). *

* Interior node type identifiers must follow the format defined in section * 7.7.7.2 of the OMA Device Management Tree and Description document. * Checking the validity of the type string does not have to be done by the * DmtAdmin, this can be left to the plugin handling the node (if any), to * avoid unnecessary double-checks. * * @param nodeUri the URI of the node to create * @param type the type URI of the interior node, can be {@code null} * if no node type is defined * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the parent node with the Add * action present * @see #createInteriorNode(String) * @see * OMA Device Management Tree and Description v1.2 draft */ void createInteriorNode(String nodeUri, String type) throws DmtException; /** * Create a leaf node with default value and MIME type. If a node does not * have a default value or MIME type, this method will throw a * {@code DmtException} with error code * {@code METADATA_MISMATCH}. Note that a node might have a default * value or MIME type even if there is no meta-data for the node or its * meta-data does not specify the default. *

* If the parent node does not exist, it is created automatically, as if * {@link #createInteriorNode(String)} were called for the parent URI. This * way all missing ancestor nodes leading to the specified node are created. * Any exceptions encountered while creating the ancestors are propagated to * the caller of this method, these are not explicitly listed in the error * descriptions below. *

* If meta-data is available for a node, several checks are made before * creating it. The node must have {@code MetaNode.CMD_ADD} access * type, it must be defined as a non-permanent leaf node, the node name must * conform to the valid names, and the creation of the new node must not * cause the maximum occurrence number to be exceeded. *

* If the meta-data cannot be retrieved because the given node cannot * possibly exist in the tree (it is not defined in the specification), the * {@code NODE_NOT_FOUND} error code is returned (see * {@link #getMetaNode(String)}). * * @param nodeUri the URI of the node to create * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the parent node with the Add * action present * @see #createLeafNode(String, DmtData) */ void createLeafNode(String nodeUri) throws DmtException; /** * Create a leaf node with a given value and the default MIME type. If the * specified value is {@code null}, the default value is taken. If * the node does not have a default MIME type or value (if needed), this * method will throw a {@code DmtException} with error code * {@code METADATA_MISMATCH}. Note that a node might have a default * value or MIME type even if there is no meta-data for the node or its * meta-data does not specify the default. *

* If the parent node does not exist, it is created automatically, as if * {@link #createInteriorNode(String)} were called for the parent URI. This * way all missing ancestor nodes leading to the specified node are created. * Any exceptions encountered while creating the ancestors are propagated to * the caller of this method, these are not explicitly listed in the error * descriptions below. *

* If meta-data is available for a node, several checks are made before * creating it. The node must have {@code MetaNode.CMD_ADD} access * type, it must be defined as a non-permanent leaf node, the node name must * conform to the valid names, the node value must conform to the value * constraints, and the creation of the new node must not cause the maximum * occurrence number to be exceeded. *

* If the meta-data cannot be retrieved because the given node cannot * possibly exist in the tree (it is not defined in the specification), the * {@code NODE_NOT_FOUND} error code is returned (see * {@link #getMetaNode(String)}). *

* Nodes of {@code null} format can be created by using * {@link DmtData#NULL_VALUE} as second argument. * * @param nodeUri the URI of the node to create * @param value the value to be given to the new node, can be * {@code null} * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the parent node with the Add * action present */ void createLeafNode(String nodeUri, DmtData value) throws DmtException; /** * Create a leaf node with a given value and MIME type. If the specified * value or MIME type is {@code null}, their default values are * taken. If the node does not have the necessary defaults, this method will * throw a {@code DmtException} with error code * {@code METADATA_MISMATCH}. Note that a node might have a default * value or MIME type even if there is no meta-data for the node or its * meta-data does not specify the default. *

* If the parent node does not exist, it is created automatically, as if * {@link #createInteriorNode(String)} were called for the parent URI. This * way all missing ancestor nodes leading to the specified node are created. * Any exceptions encountered while creating the ancestors are propagated to * the caller of this method, these are not explicitly listed in the error * descriptions below. *

* If meta-data is available for a node, several checks are made before * creating it. The node must have {@code MetaNode.CMD_ADD} access * type, it must be defined as a non-permanent leaf node, the node name must * conform to the valid names, the node value must conform to the value * constraints, the MIME type must be among the listed types, and the * creation of the new node must not cause the maximum occurrence number to * be exceeded. *

* If the meta-data cannot be retrieved because the given node cannot * possibly exist in the tree (it is not defined in the specification), the * {@code NODE_NOT_FOUND} error code is returned (see * {@link #getMetaNode(String)}). *

* Nodes of {@code null} format can be created by using * {@link DmtData#NULL_VALUE} as second argument. *

* The MIME type string must conform to the definition in RFC 2045. Checking * its validity does not have to be done by the DmtAdmin, this can be left * to the plugin handling the node (if any), to avoid unnecessary * double-checks. * * @param nodeUri the URI of the node to create * @param value the value to be given to the new node, can be * {@code null} * @param mimeType the MIME type to be given to the new node, can be * {@code null} * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the parent node with the Add * action present * @see #createLeafNode(String, DmtData) * @see RFC 2045 */ void createLeafNode(String nodeUri, DmtData value, String mimeType) throws DmtException; /** * Delete the given node. Deleting interior nodes is recursive, the whole * subtree under the given node is deleted. It is not allowed to delete * the root node of the session. *

* If meta-data is available for a node, several checks are made before * deleting it. The node must be non-permanent, it must have the * {@code MetaNode.CMD_DELETE} access type, and if zero occurrences * of the node are not allowed, it must not be the last one. * * @param nodeUri the URI of the node * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Delete action * present */ void deleteNode(String nodeUri) throws DmtException; /** * Rename a node. This operation only changes the name of the node (updating * the timestamp and version properties if they are supported), the value * and the other properties are not changed. The new name of the node must * be provided, the new URI is constructed from the base of the old URI and * the given name. It is not allowed to rename the root node of the session. *

* If available, the meta-data of the original and the new nodes are checked * before performing the rename operation. Neither node can be permanent, * their leaf/interior property must match, and the name change must not * violate any of the cardinality constraints. The original node must have * the {@code MetaNode.CMD_REPLACE} access type, and the name of the * new node must conform to the valid names. * * @param nodeUri the URI of the node to rename * @param newName the new name property of the node * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Replace action * present */ void renameNode(String nodeUri, String newName) throws DmtException; /** * Set the value of a leaf or interior node to its default. The default * can be defined by the node's {@code MetaNode}. The method throws a * {@code METADATA_MISMATCH} exception if the node does not have a * default value. * * @param nodeUri the URI of the node * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Replace action * present * @see #setNodeValue */ void setDefaultNodeValue(String nodeUri) throws DmtException; /** * Set the value of a leaf or interior node. The format of the node is * contained in the {@code DmtData} object. For interior nodes, the * format must be {@code FORMAT_NODE}, while for leaf nodes this * format must not be used. *

* If the specified value is {@code null}, the default value is taken. * In this case, if the node does not have a default value, this method will * throw a {@code DmtException} with error code * {@code METADATA_MISMATCH}. Nodes of {@code null} format can be * set by using {@link DmtData#NULL_VALUE} as second argument. *

* An Event of type REPLACE is sent out for a leaf node. A replaced interior * node sends out events for each of its children in depth first order * and node names sorted with Arrays.sort(String[]). When setting a value * on an interior node, the values of the leaf nodes under it can change, * but the structure of the subtree is not modified by the operation. * * @param nodeUri the URI of the node * @param data the data to be set, can be {@code null} * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Replace action * present */ void setNodeValue(String nodeUri, DmtData data) throws DmtException; /** * Set the title property of a node. The length of the title string in UTF-8 * encoding must not exceed 255 bytes. * * @param nodeUri the URI of the node * @param title the title text of the node, can be {@code null} * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Replace action * present */ void setNodeTitle(String nodeUri, String title) throws DmtException; /** * Set the type of a node. The type of leaf node is the MIME type of the * data it contains. The type of an interior node is a URI identifying a DDF * document. *

* For interior nodes, a {@code null} type string means that there is * no DDF document overriding the tree structure defined by the ancestors. * For leaf nodes, it requests that the default MIME type is used for the * given node. If the node does not have a default MIME type this method * will throw a {@code DmtException} with error code * {@code METADATA_MISMATCH}. Note that a node might have a default * MIME type even if there is no meta-data for the node or its meta-data * does not specify the default. *

* MIME types must conform to the definition in RFC 2045. Interior node type * identifiers must follow the format defined in section 7.7.7.2 of the OMA * Device Management Tree and Description document. Checking the validity of * the type string does not have to be done by the DmtAdmin, this can be * left to the plugin handling the node (if any), to avoid unnecessary * double-checks. * * @param nodeUri the URI of the node * @param type the type of the node, can be {@code null} * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session was opened using the * {@code LOCK_TYPE_SHARED} lock type, or if the session is * already closed or invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Replace action * present * @see RFC 2045 * @see * OMA Device Management Tree and Description v1.2 draft */ void setNodeType(String nodeUri, String type) throws DmtException; /** * Get the list of children names of a node. The returned array contains the * names - not the URIs - of the immediate children nodes of the given node. * The returned child names are mangled ({@link Uri#mangle(String)}). The elements * are in no particular order. The returned array must not contain * {@code null} entries. * * @param nodeUri the URI of the node * @return the list of child node names as a string array or an empty string * array if the node has no children * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Get action * present */ String[] getChildNodeNames(String nodeUri) throws DmtException; /** * Get the meta data which describes a given node. Meta data can only be * inspected, it can not be changed. *

* The {@code MetaNode} object returned to the client is the * combination of the meta data returned by the data plugin (if any) plus * the meta data returned by the DmtAdmin. If there are differences in the * meta data elements known by the plugin and the DmtAdmin then the plugin * specific elements take precedence. *

* Note, that a node does not have to exist for having meta-data associated * with it. This method may provide meta-data for any node that can possibly * exist in the tree (any node defined in the specification). For nodes that * are not defined, it may throw {@code DmtException} with the error * code {@code NODE_NOT_FOUND}. To allow easier implementation of * plugins that do not provide meta-data, it is allowed to return * {@code null} for any node, regardless of whether it is defined or * not. * * @param nodeUri the URI of the node * @return a MetaNode which describes meta data information, can be * {@code null} if there is no meta data available for the * given node * @throws DmtException with the following possible error codes: *

* @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Get action * present */ MetaNode getMetaNode(String nodeUri) throws DmtException; /** * Get the size of the data in a leaf node. The returned value depends on * the format of the data in the node, see the description of the * {@link DmtData#getSize()} method for the definition of node size for each * format. * * @param nodeUri the URI of the leaf node * @return the size of the data in the node * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Get action * present * @see DmtData#getSize */ int getNodeSize(String nodeUri) throws DmtException; /** * Get the timestamp when the node was created or last modified. * * @param nodeUri the URI of the node * @return the timestamp of the last modification * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Get action * present */ Date getNodeTimestamp(String nodeUri) throws DmtException; /** * Get the title of a node. There might be no title property set for a node. * * @param nodeUri the URI of the node * @return the title of the node, or {@code null} if the node has no * title * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Get action * present */ String getNodeTitle(String nodeUri) throws DmtException; /** * Get the type of a node. The type of leaf node is the MIME type of the * data it contains. The type of an interior node is a URI identifying a DDF * document; a {@code null} type means that there is no DDF document * overriding the tree structure defined by the ancestors. * * @param nodeUri the URI of the node * @return the type of the node, can be {@code null} * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Get action * present */ String getNodeType(String nodeUri) throws DmtException; /** * Get the data contained in a leaf or interior node. When retrieving the * value associated with an interior node, the caller must have rights to * read all nodes in the subtree under the given node. * * @param nodeUri the URI of the node to retrieve * @return the data of the node, can not be {@code null} * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node (and all its descendants * in case of interior nodes) with the Get action present */ DmtData getNodeValue(String nodeUri) throws DmtException; /** * Get the version of a node. The version can not be set, it is calculated * automatically by the device. It is incremented modulo 0x10000 at every * modification of the value or any other property of the node, for both * leaf and interior nodes. When a node is created the initial value is 0. * * @param nodeUri the URI of the node * @return the version of the node * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Get action * present */ int getNodeVersion(String nodeUri) throws DmtException; /** * Tells whether a node is a leaf or an interior node of the DMT. * * @param nodeUri the URI of the node * @return true if the given node is a leaf node * @throws DmtException with the following possible error codes: * * @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Get action * present */ boolean isLeafNode(String nodeUri) throws DmtException; /** * Check whether the specified URI corresponds to a valid node in the DMT. * * @param nodeUri the URI to check * @return true if the given node exists in the DMT * @throws DmtIllegalStateException if the session is already closed or * invalidated * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation, or, * in case of local sessions, if the caller does not have * {@code DmtPermission} for the node with the Get action * present */ boolean isNodeUri(String nodeUri); } osgi-compendium-4.3.0/src/info/dmtree/Uri.java0000644000175000017500000005121611564442770021134 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.List; /** * This class contains static utility methods to manipulate DMT URIs. *

* Syntax of valid DMT URIs: *

* * @version $Id: 5289414c7bb0af15b3db2b8d2174181321f739c4 $ */ public final class Uri { /* * NOTE: An implementor may also choose to replace this class in * their distribution with a class that directly interfaces with the * info.dmtree implementation. This replacement class MUST NOT alter the * public/protected signature of this class. */ /* * This class will load the class named * by the org.osgi.vendor.dmtree.DigestDelegate property. This class will call * the public static byte[] digest(byte[]) method on that class. */ private static class ImplHolder implements PrivilegedAction { // the name of the system property containing the digest delegate class name private static final String DIGEST_DELEGATE_PROPERTY = "org.osgi.vendor.dmtree.DigestDelegate"; // the Method where message digest requests can be delegated static final Method digestMethod; static { digestMethod = (Method) AccessController.doPrivileged(new ImplHolder()); } private ImplHolder() { } public Object run() { String className = System .getProperty(DIGEST_DELEGATE_PROPERTY); if (className == null) { throw new NoClassDefFoundError("Digest " + "delegate class property '" + DIGEST_DELEGATE_PROPERTY + "' must be set to a " + "class which implements a " + "public static byte[] digest(byte[]) method."); } Class delegateClass; try { delegateClass = Class.forName(className); } catch (ClassNotFoundException e) { throw new NoClassDefFoundError(e.toString()); } Method result; try { result = delegateClass.getMethod("digest", new Class[] {byte[].class}); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.toString()); } if (!Modifier.isStatic(result.getModifiers())) { throw new NoSuchMethodError( "digest method must be static"); } return result; } } // the name of the system property containing the URI segment length limit private static final String SEGMENT_LENGTH_LIMIT_PROPERTY = "org.osgi.impl.service.dmt.uri.limits.segmentlength"; // the smallest valid value for the URI segment length limit private static final int MINIMAL_SEGMENT_LENGTH_LIMIT = 32; // contains the maximum length of node names private static final int segmentLengthLimit; static { segmentLengthLimit = ((Integer) AccessController .doPrivileged(new PrivilegedAction() { public Object run() { String limitString = System.getProperty(SEGMENT_LENGTH_LIMIT_PROPERTY); int limit = MINIMAL_SEGMENT_LENGTH_LIMIT; // min. used as default try { int limitInt = Integer.parseInt(limitString); if(limitInt >= MINIMAL_SEGMENT_LENGTH_LIMIT) limit = limitInt; } catch(NumberFormatException e) {} return new Integer(limit); } })).intValue(); } // base64 encoding table, modified for use in node name mangling private static final char BASE_64_TABLE[] = { 'A','B','C','D','E','F','G','H', 'I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X', 'Y','Z','a','b','c','d','e','f', 'g','h','i','j','k','l','m','n', 'o','p','q','r','s','t','u','v', 'w','x','y','z','0','1','2','3', '4','5','6','7','8','9','+','_', // !!! this differs from base64 }; /** * A private constructor to suppress the default public constructor. */ private Uri() {} /** * Returns a node name that is valid for the tree operation methods, based * on the given node name. This transformation is not idempotent, so it must * not be called with a parameter that is the result of a previous * {@code mangle} method call. *

* Node name mangling is needed in the following cases: *

*

* A node name that does not suffer from either of these problems is * guaranteed to remain unchanged by this method. Therefore the client may * skip the mangling if the node name is known to be valid (though it is * always safe to call this method). *

* The method returns the normalized {@code nodeName} as described * below. Invalid node names are normalized in different ways, depending on * the cause. If the length of the name does not exceed the limit, but the * name contains '/' or '\' characters, then these are simply escaped by * inserting an additional '\' before each occurrence. If the length of the * name does exceed the limit, the following mechanism is used to normalize * it: *

* * @param nodeName the node name to be mangled (if necessary), must not be * {@code null} or empty * @return the normalized node name that is valid for tree operations * @throws NullPointerException if {@code nodeName} is * {@code null} * @throws IllegalArgumentException if {@code nodeName} is empty */ public static String mangle(String nodeName) { return mangle(nodeName, getMaxSegmentNameLength()); } /** * Construct a URI from the specified URI segments. The segments must * already be mangled. *

* If the specified path is an empty array then an empty URI * ({@code ""}) is returned. * * @param path a possibly empty array of URI segments, must not be * {@code null} * @return the URI created from the specified segments * @throws NullPointerException if the specified path or any of its * segments are {@code null} * @throws IllegalArgumentException if the specified path contains too many * or malformed segments or the resulting URI is too long */ public static String toUri(String[] path) { if (0 == path.length) { return ""; } if (path.length > getMaxUriSegments()) { throw new IllegalArgumentException( "Path contains too many segments."); } StringBuffer uri = new StringBuffer(); int uriLength = 0; for (int i = 0; i < path.length; ++i) { // getSegmentLength throws exceptions on malformed segments. int segmentLength = getSegmentLength(path[i]); if (segmentLength > getMaxSegmentNameLength()) { throw new IllegalArgumentException("URI segment too long."); } if (i > 0) { uri.append('/'); uriLength++; } uriLength += segmentLength; uri.append(path[i]); } if (uriLength > getMaxUriLength()) { throw new IllegalArgumentException("URI too long."); } return uri.toString(); } /** * This method returns the length of a URI segment. The length of the URI * segment is defined as the number of bytes in the unescaped, UTF-8 encoded * represenation of the segment. *

* The method verifies that the URI segment is well-formed. * * @param segment the URI segment * @return URI segment length * @throws NullPointerException if the specified segment is * {@code null} * @throws IllegalArgumentException if the specified URI segment is * malformed */ private static int getSegmentLength(String segment) { if (segment.length() == 0) throw new IllegalArgumentException("URI segment is empty."); StringBuffer newsegment = new StringBuffer(segment); int i = 0; while (i < newsegment.length()) { // length can decrease during the loop! if (newsegment.charAt(i) == '\\') { if (i == newsegment.length() - 1) // last character cannot be a '\' throw new IllegalArgumentException( "URI segment ends with the escape character."); newsegment.deleteCharAt(i); // remove the extra '\' } else if (newsegment.charAt(i) == '/') throw new IllegalArgumentException( "URI segment contains an unescaped '/' character."); i++; } if (newsegment.toString().equals("..")) throw new IllegalArgumentException( "URI segment must not be \"..\"."); try { return newsegment.toString().getBytes("UTF-8").length; } catch (UnsupportedEncodingException e) { // This should never happen. All implementations must support // UTF-8 encoding; throw new RuntimeException(e.toString()); } } /** * Split the specified URI along the path separator '/' charaters and return * an array of URI segments. Special characters in the returned segments are * escaped. The returned array may be empty if the specifed URI was empty. * * @param uri the URI to be split, must not be {@code null} * @return an array of URI segments created by splitting the specified URI * @throws NullPointerException if the specified URI is {@code null} * @throws IllegalArgumentException if the specified URI is malformed */ public static String[] toPath(String uri) { if (uri == null) throw new NullPointerException("'uri' parameter is null."); if (!isValidUri(uri)) throw new IllegalArgumentException("Malformed URI: " + uri); if (uri.length() == 0) return new String[] {}; List segments = new ArrayList(); StringBuffer segment = new StringBuffer(); boolean escape = false; for (int i = 0; i < uri.length(); i++) { char ch = uri.charAt(i); if (escape) { if(ch == '/' || ch == '\\') segment.append('\\'); segment.append(ch); escape = false; } else if (ch == '/') { segments.add(segment.toString()); segment = new StringBuffer(); } else if (ch == '\\') { escape = true; } else segment.append(ch); } if (segment.length() > 0) { segments.add(segment.toString()); } return (String[]) segments.toArray(new String[segments.size()]); } /** * Returns the maximum allowed number of URI segments. The returned value is * implementation specific. *

* The return value of {@code Integer.MAX_VALUE} indicates that there * is no upper limit on the number of URI segments. * * @return maximum number of URI segments supported by the implementation */ public static int getMaxUriSegments() { return Integer.MAX_VALUE; } /** * Returns the maximum allowed length of a URI. The value is implementation * specific. The length of the URI is defined as the number of bytes in the * unescaped, UTF-8 encoded represenation of the URI. *

* The return value of {@code Integer.MAX_VALUE} indicates that there * is no upper limit on the length of URIs. * * @return maximum URI length supported by the implementation */ public static int getMaxUriLength() { return Integer.MAX_VALUE; } /** * Returns the maximum allowed length of a URI segment. The value is * implementation specific. The length of the URI segment is defined as the * number of bytes in the unescaped, UTF-8 encoded represenation of the * segment. *

* The return value of {@code Integer.MAX_VALUE} indicates that there * is no upper limit on the length of segment names. * * @return maximum URI segment length supported by the implementation */ public static int getMaxSegmentNameLength() { return segmentLengthLimit; } /** * Checks whether the specified URI is an absolute URI. An absolute URI * contains the complete path to a node in the DMT starting from the DMT * root ("."). * * @param uri the URI to be checked, must not be {@code null} and must * contain a valid URI * @return whether the specified URI is absolute * @throws NullPointerException if the specified URI is {@code null} * @throws IllegalArgumentException if the specified URI is malformed */ public static boolean isAbsoluteUri(String uri) { if( null == uri ) { throw new NullPointerException("'uri' parameter is null."); } if( !isValidUri(uri) ) throw new IllegalArgumentException("Malformed URI: " + uri); return uri.equals(".") || uri.equals("\\.") || uri.startsWith("./") || uri.startsWith("\\./"); } /** * Checks whether the specified URI is valid. A URI is considered valid if * it meets the following constraints: *

* The exact definition of the length of a URI and its segments is * given in the descriptions of the {@code getMaxUriLength()} and * {@code getMaxSegmentNameLength()} methods. * * @param uri the URI to be validated * @return whether the specified URI is valid */ public static boolean isValidUri(String uri) { if (null == uri) return false; int paramLen = uri.length(); if( paramLen == 0 ) return true; if( uri.charAt(0) == '/' || uri.charAt(paramLen-1) == '\\' ) return false; int processedUriLength = 0; int segmentNumber = 0; // append a '/' to indicate the end of the last segment (the URI in the // parameter must not end with a '/') uri += '/'; paramLen++; int start = 0; for(int i = 1; i < paramLen; i++) { // first character is not a '/' if(uri.charAt(i) == '/' && uri.charAt(i-1) != '\\') { segmentNumber++; String segment = uri.substring(start, i); if(segmentNumber > 1 && segment.equals(".")) return false; // the URI contains the "." node name at a // position other than the beginning of the URI int segmentLength; try { // also checks that the segment is valid segmentLength = getSegmentLength(segment); } catch(IllegalArgumentException e) { return false; } if(segmentLength > getMaxSegmentNameLength()) return false; // the extra byte is for the separator '/' (will be deducted // again for the last segment of the URI) processedUriLength += segmentLength + 1; start = i+1; } } processedUriLength--; // remove the '/' added to the end of the URI return segmentNumber <= getMaxUriSegments() && processedUriLength <= getMaxUriLength(); } // Non-public fields and methods // package private method for testing purposes static String mangle(String nodeName, int limit) { if(nodeName == null) throw new NullPointerException( "The 'nodeName' parameter must not be null."); if(nodeName.equals("")) throw new IllegalArgumentException( "The 'nodeName' parameter must not be empty."); if(nodeName.length() > limit) // create node name hash return getHash(nodeName); // escape any '/' and '\' characters in the node name StringBuffer nameBuffer = new StringBuffer(nodeName); for(int i = 0; i < nameBuffer.length(); i++) // 'i' can increase in loop if(nameBuffer.charAt(i) == '\\' || nameBuffer.charAt(i) == '/') nameBuffer.insert(i++, '\\'); return nameBuffer.toString(); } private static String getHash(String from) { byte[] byteStream; try { byteStream = from.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { // There's no way UTF-8 encoding is not implemented... throw new IllegalStateException("there's no UTF-8 encoder here!"); } byte[] digest = digestMessage(byteStream); // very dumb base64 encoder code. There is no need for multiple lines // or trailing '='-s.... // also, we hardcoded the fact that sha-1 digests are 20 bytes long StringBuffer sb = new StringBuffer(digest.length*2); for(int i=0;i<6;i++) { int d0 = digest[i*3]&0xff; int d1 = digest[i*3+1]&0xff; int d2 = digest[i*3+2]&0xff; sb.append(BASE_64_TABLE[d0>>2]); sb.append(BASE_64_TABLE[(d0<<4|d1>>4)&63]); sb.append(BASE_64_TABLE[(d1<<2|d2>>6)&63]); sb.append(BASE_64_TABLE[d2&63]); } int d0 = digest[18]&0xff; int d1 = digest[19]&0xff; sb.append(BASE_64_TABLE[d0>>2]); sb.append(BASE_64_TABLE[(d0<<4|d1>>4)&63]); sb.append(BASE_64_TABLE[(d1<<2)&63]); return sb.toString(); } private static byte[] digestMessage(byte[] byteStream) { try { try { return (byte[]) ImplHolder.digestMethod.invoke(null, new Object[] { byteStream}); } catch (InvocationTargetException e) { throw e.getTargetException(); } } catch (Error e) { throw e; } catch (RuntimeException e) { throw e; } catch (Throwable e) { throw new RuntimeException(e.toString()); } } } osgi-compendium-4.3.0/src/info/dmtree/spi/0000755000175000017500000000000011632153414020306 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/info/dmtree/spi/package-info.java0000644000175000017500000000311311564442770023505 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Device Management Tree SPI Package Version 1.0. * *

* This package contains the interface classes that compose the Device Management * SPI (Service Provider Interface). These interfaces are implemented by DMT plugins; * users of the {@code DmtAdmin} interface do not interact directly with these. * *

* Bundles wishing to use this package must list the package in the * Import-Package header of the bundle's manifest. This package has two types of * users: the consumers that use the API in this package and the providers that * implement the API in this package. * *

* Example import for consumers using the API in this package: *

* {@code Import-Package: info.dmtree.spi; version="[1.0,2.0)"} *

* Example import for providers implementing the API in this package: *

* {@code Import-Package: info.dmtree.spi; version="[1.0,1.1)"} * * @version $Id: d606bdeacd82efe829ce829dabbf5eedb1ae4b42 $ */ package info.dmtree.spi; osgi-compendium-4.3.0/src/info/dmtree/spi/DataPlugin.java0000644000175000017500000001467611564442770023231 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.spi; import info.dmtree.DmtException; import info.dmtree.DmtSession; /** * An implementation of this interface takes the responsibility of handling data * requests in a subtree of the DMT. *

* In an OSGi environment such implementations should be registered at the OSGi * service registry specifying the list of root node URIs in a * {@code String} array in the {@code dataRootURIs} registration * parameter. *

* When the first reference in a session is made to a node handled by this * plugin, the DmtAdmin calls one of the {@code open...} methods to * retrieve a plugin session object for processing the request. The called * method depends on the lock type of the current session. In case of * {@link #openReadWriteSession(String[], DmtSession)} and * {@link #openAtomicSession(String[], DmtSession)}, the plugin may return * {@code null} to indicate that the specified lock type is not supported. * In this case the DmtAdmin may call * {@link #openReadOnlySession(String[], DmtSession)} to start a read-only * plugin session, which can be used as long as there are no write operations on * the nodes handled by this plugin. *

* The {@code sessionRoot} parameter of each method is a String array * containing the segments of the URI pointing to the root of the session. This * is an absolute path, so the first segment is always ".". Special * characters appear escaped in the segments. *

* * @version $Id: 9c832c44be569dfd63ef66eb5a40bae7b283b81f $ */ public interface DataPlugin { /** * This method is called to signal the start of a read-only session when the * first reference is made within a {@code DmtSession} to a node * which is handled by this plugin. Session information is given as it is * needed for sending alerts back from the plugin. *

* The plugin can assume that there are no writing sessions open on any * subtree that has any overlap with the subtree of this session. * * @param sessionRoot the path to the subtree which is accessed in the * current session, must not be {@code null} * @param session the session from which this plugin instance is accessed, * must not be {@code null} * @return a plugin session capable of executing read operations * @throws DmtException with the following possible error codes: *

* @throws SecurityException if some underlying operation failed because of * lack of permissions */ ReadableDataSession openReadOnlySession(String[] sessionRoot, DmtSession session) throws DmtException; /** * This method is called to signal the start of a non-atomic read-write * session when the first reference is made within a {@code DmtSession} * to a node which is handled by this plugin. Session information is given * as it is needed for sending alerts back from the plugin. *

* The plugin can assume that there are no other sessions open on any * subtree that has any overlap with the subtree of this session. * * @param sessionRoot the path to the subtree which is locked in the current * session, must not be {@code null} * @param session the session from which this plugin instance is accessed, * must not be {@code null} * @return a plugin session capable of executing read-write operations, or * {@code null} if the plugin does not support non-atomic * read-write sessions * @throws DmtException with the following possible error codes: *

* @throws SecurityException if some underlying operation failed because of * lack of permissions */ ReadWriteDataSession openReadWriteSession(String[] sessionRoot, DmtSession session) throws DmtException; /** * This method is called to signal the start of an atomic read-write session * when the first reference is made within a {@code DmtSession} to a * node which is handled by this plugin. Session information is given as it * is needed for sending alerts back from the plugin. *

* The plugin can assume that there are no other sessions open on any * subtree that has any overlap with the subtree of this session. * * @param sessionRoot the path to the subtree which is locked in the current * session, must not be {@code null} * @param session the session from which this plugin instance is accessed, * must not be {@code null} * @return a plugin session capable of executing read-write operations in an * atomic block, or {@code null} if the plugin does not * support atomic read-write sessions * @throws DmtException with the following possible error codes: *

* @throws SecurityException if some underlying operation failed because of * lack of permissions */ TransactionalDataSession openAtomicSession(String[] sessionRoot, DmtSession session) throws DmtException; } osgi-compendium-4.3.0/src/info/dmtree/spi/ExecPlugin.java0000644000175000017500000000644711564442770023241 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.spi; import info.dmtree.DmtException; import info.dmtree.DmtSession; /** * An implementation of this interface takes the responsibility of handling node * execute requests requests in a subtree of the DMT. *

* In an OSGi environment such implementations should be registered at the OSGi * service registry specifying the list of root node URIs in a * {@code String} array in the {@code execRootURIs} registration * parameter. * * @version $Id: c79828948f304c0f55a835af04f01d5861adeb1d $ */ public interface ExecPlugin { /** * Execute the given node with the given data. This operation corresponds to * the EXEC command in OMA DM. *

* The semantics of an execute operation and the data parameter it takes * depends on the definition of the managed object on which the command is * issued. Session information is given as it is needed for sending alerts * back from the plugin. If a correlation ID is specified, it should be used * as the {@code correlator} parameter for alerts sent in response to * this execute operation. *

* The {@code nodePath} parameter contains an array of path segments * identifying the node to be executed in the subtree of this plugin. This * is an absolute path, so the first segment is always ".". * Special characters appear escaped in the segments. * * @param session a reference to the session in which the operation was * issued, must not be {@code null} * @param nodePath the absolute path of the node to be executed, must not be * {@code null} * @param correlator an identifier to associate this operation with any * alerts sent in response to it, can be {@code null} * @param data the parameter of the execute operation, can be * {@code null} * @throws DmtException with the following possible error codes: *

* @see DmtSession#execute(String, String) * @see DmtSession#execute(String, String, String) */ void execute(DmtSession session, String[] nodePath, String correlator, String data) throws DmtException; } osgi-compendium-4.3.0/src/info/dmtree/spi/ReadableDataSession.java0000644000175000017500000004401211466514064025016 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.spi; import info.dmtree.DmtData; import info.dmtree.DmtException; import info.dmtree.MetaNode; import java.util.Date; /** * Provides read-only access to the part of the tree handled by the plugin that * created this session. *

* Since the {@link ReadWriteDataSession} and {@link TransactionalDataSession} * interfaces inherit from this interface, some of the method descriptions do * not apply for an instance that is only a {@code ReadableDataSession}. * For example, the {@link #close} method description also contains information * about its behaviour when invoked as part of a transactional session. *

* The {@code nodePath} parameters appearing in this interface always * contain an array of path segments identifying a node in the subtree of this * plugin. This parameter contains an absolute path, so the first segment is * always ".". Special characters appear escaped in the segments. *

* Error handling *

* When a tree access command is called on the DmtAdmin service, it must perform * an extensive set of checks on the parameters and the authority of the caller * before delegating the call to a plugin. Therefore plugins can take certain * circumstances for granted: that the path is valid and is within the subtree * of the plugin and the session, the command can be applied to the given node * (e.g. the target of {@code getChildNodeNames} is an interior node), etc. * All errors described by the error codes {@link DmtException#INVALID_URI}, * {@link DmtException#URI_TOO_LONG}, {@link DmtException#PERMISSION_DENIED}, * {@link DmtException#COMMAND_NOT_ALLOWED} and * {@link DmtException#TRANSACTION_ERROR} are fully filtered out before control * reaches the plugin. *

* If the plugin provides meta-data for a node, the DmtAdmin service must also * check the constraints specified by it, as described in {@link MetaNode}. If * the plugin does not provide meta-data, it must perform the necessary checks * for itself and use the {@link DmtException#METADATA_MISMATCH} error code to * indicate such discrepancies. *

* The DmtAdmin also ensures that the targeted nodes exist before calling the * plugin (except, of course, before the {@code isNodeUri} call). However, * some small amount of time elapses between the check and the call, so in case * of plugins where the node structure can change independantly from the DMT, * the target node might disappear in that time. For example, a whole subtree * can disappear when a Monitorable application is unregistered, which might * happen in the middle of a DMT session accessing it. Plugins managing such * nodes always need to check whether they still exist and throw * {@link DmtException#NODE_NOT_FOUND} as necessary, but for more static * subtrees there is no need for the plugin to use this error code. *

* The plugin can use the remaining error codes as needed. If an error does not * fit into any other category, the {@link DmtException#COMMAND_FAILED} code * should be used. * * @version $Id: fdc501943df679cda179475a1f1257112d8fadfd $ */ public interface ReadableDataSession { /** * Notifies the plugin that the given node has changed outside the scope of * the plugin, therefore the Version and Timestamp properties must be * updated (if supported). This method is needed because the ACL property of * a node is managed by the DmtAdmin instead of the plugin. The DmtAdmin * must call this method whenever the ACL property of a node changes. * * @param nodePath the absolute path of the node that has changed * @throws DmtException with the following possible error codes: *

*/ void nodeChanged(String[] nodePath) throws DmtException; /** * Closes a session. This method is always called when the session ends for * any reason: if the session is closed, if a fatal error occurs in any * method, or if any error occurs during commit or rollback. In case the * session was invalidated due to an exception during commit or rollback, it * is guaranteed that no methods are called on the plugin until it is * closed. In case the session was invalidated due to a fatal exception in * one of the tree manipulation methods, only the rollback method is called * before this (and only in atomic sessions). *

* This method should not perform any data manipulation, only cleanup * operations. In non-atomic read-write sessions the data manipulation * should be done instantly during each tree operation, while in atomic * sessions the {@code DmtAdmin} always calls * {@link TransactionalDataSession#commit} automatically before the session * is actually closed. * * @throws DmtException with the error code {@code COMMAND_FAILED} if * the plugin failed to close for any reason */ void close() throws DmtException; /** * Get the list of children names of a node. The returned array contains the * names - not the URIs - of the immediate children nodes of the given node. * The returned child names must be mangled ({@link info.dmtree.Uri#mangle(String)}). * The returned array may contain {@code null} entries, but these are * removed by the DmtAdmin before returning it to the client. * * @param nodePath the absolute path of the node * @return the list of child node names as a string array or an empty string * array if the node has no children * @throws DmtException with the following possible error codes: *

* @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ String[] getChildNodeNames(String[] nodePath) throws DmtException; /** * Get the meta data which describes a given node. Meta data can be only * inspected, it can not be changed. *

* Meta data support by plugins is an optional feature. It can be used, for * example, when a data plugin is implemented on top of a data store or * another API that has their own metadata, such as a relational database, * in order to avoid metadata duplication and inconsistency. The meta data * specific to the plugin returned by this method is complemented by meta * data from the DmtAdmin before returning it to the client. If there are * differences in the meta data elements known by the plugin and the * {@code DmtAdmin} then the plugin specific elements take * precedence. *

* Note, that a node does not have to exist for having meta-data associated * with it. This method may provide meta-data for any node that can possibly * exist in the tree (any node defined by the Management Object provided by * the plugin). For nodes that are not defined, a {@code DmtException} * may be thrown with the {@code NODE_NOT_FOUND} error code. To allow * easier implementation of plugins that do not provide meta-data, it is * allowed to return {@code null} for any node, regardless of whether * it is defined or not. * * @param nodePath the absolute path of the node * @return a MetaNode which describes meta data information, can be * {@code null} if there is no meta data available for the * given node * @throws DmtException with the following possible error codes: *

* @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ MetaNode getMetaNode(String[] nodePath) throws DmtException; /** * Get the size of the data in a leaf node. The value to return depends on * the format of the data in the node, see the description of the * {@link DmtData#getSize()} method for the definition of node size for each * format. * * @param nodePath the absolute path of the leaf node * @return the size of the data in the node * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation * @see DmtData#getSize */ int getNodeSize(String[] nodePath) throws DmtException; /** * Get the timestamp when the node was last modified. * * @param nodePath the absolute path of the node * @return the timestamp of the last modification * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ Date getNodeTimestamp(String[] nodePath) throws DmtException; /** * Get the title of a node. There might be no title property set for a node. * * @param nodePath the absolute path of the node * @return the title of the node, or {@code null} if the node has no * title * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ String getNodeTitle(String[] nodePath) throws DmtException; /** * Get the type of a node. The type of leaf node is the MIME type of the * data it contains. The type of an interior node is a URI identifying a DDF * document; a {@code null} type means that there is no DDF document * overriding the tree structure defined by the ancestors. * * @param nodePath the absolute path of the node * @return the type of the node, can be {@code null} * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ String getNodeType(String[] nodePath) throws DmtException; /** * Check whether the specified path corresponds to a valid node in the DMT. * * @param nodePath the absolute path to check * @return true if the given node exists in the DMT */ boolean isNodeUri(String[] nodePath); /** * Tells whether a node is a leaf or an interior node of the DMT. * * @param nodePath the absolute path of the node * @return true if the given node is a leaf node * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ boolean isLeafNode(String[] nodePath) throws DmtException; /** * Get the data contained in a leaf or interior node. * * @param nodePath the absolute path of the node to retrieve * @return the data of the leaf node, must not be {@code null} * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ DmtData getNodeValue(String[] nodePath) throws DmtException; /** * Get the version of a node. The version can not be set, it is calculated * automatically by the device. It is incremented modulo 0x10000 at every * modification of the value or any other property of the node, for both * leaf and interior nodes. When a node is created the initial value is 0. * * @param nodePath the absolute path of the node * @return the version of the node * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ int getNodeVersion(String[] nodePath) throws DmtException; } osgi-compendium-4.3.0/src/info/dmtree/spi/packageinfo0000644000175000017500000000001411405717676022511 0ustar drazzibdrazzibversion 1.0 osgi-compendium-4.3.0/src/info/dmtree/spi/TransactionalDataSession.java0000644000175000017500000000674311466514064026132 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.spi; import info.dmtree.DmtException; /** * Provides atomic read-write access to the part of the tree handled by the * plugin that created this session. * * @version $Id: fa17127995f9e650baec161d4d767a9aef510cb9 $ */ public interface TransactionalDataSession extends ReadWriteDataSession { /** * Commits a series of DMT operations issued in the current atomic session * since the last transaction boundary. Transaction boundaries are the * creation of this object that starts the session, and all subsequent * {@link #commit} and {@link #rollback} calls. *

* This method can fail even if all operations were successful. This can * happen due to some multi-node semantic constraints defined by a specific * implementation. For example, node A can be required to always have * children A/B, A/C and A/D. If this condition is broken when * {@code commit()} is executed, the method will fail, and throw a * {@code METADATA_MISMATCH} exception. *

* In many cases the tree is not the only way to manage a given part of the * system. It may happen that while modifying some nodes in an atomic * session, the underlying settings are modified parallelly outside the * scope of the DMT. If this is detected during commit, an exception with * the code {@code CONCURRENT_ACCESS} is thrown. * * @throws DmtException with the following possible error codes *

* @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ void commit() throws DmtException; /** * Rolls back a series of DMT operations issued in the current atomic * session since the last transaction boundary. Transaction boundaries are * the creation of this object that starts the session, and all subsequent * {@link #commit} and {@link #rollback} calls. * * @throws DmtException with the error code {@code ROLLBACK_FAILED} * in case the rollback did not succeed * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation */ void rollback() throws DmtException; } osgi-compendium-4.3.0/src/info/dmtree/spi/ReadWriteDataSession.java0000644000175000017500000003574111466514064025216 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.dmtree.spi; import info.dmtree.DmtData; import info.dmtree.DmtException; import info.dmtree.DmtSession; import info.dmtree.MetaNode; /** * Provides non-atomic read-write access to the part of the tree handled by the * plugin that created this session. *

* The {@code nodePath} parameters appearing in this interface always * contain an array of path segments identifying a node in the subtree of this * plugin. This parameter contains an absolute path, so the first segment is * always ".". Special characters appear escaped in the segments. *

* Error handling *

* When a tree manipulation command is called on the DmtAdmin service, it must * perform an extensive set of checks on the parameters and the authority of the * caller before delegating the call to a plugin. Therefore plugins can take * certain circumstances for granted: that the path is valid and is within the * subtree of the plugin and the session, the command can be applied to the * given node (e.g. the target of {@code setNodeValue} is a leaf node), * etc. All errors described by the error codes {@link DmtException#INVALID_URI}, {@link DmtException#URI_TOO_LONG}, {@link DmtException#PERMISSION_DENIED}, * {@link DmtException#COMMAND_NOT_ALLOWED} and * {@link DmtException#TRANSACTION_ERROR} are fully filtered out before control * reaches the plugin. *

* If the plugin provides meta-data for a node, the DmtAdmin service must also * check the constraints specified by it, as described in {@link MetaNode}. If * the plugin does not provide meta-data, it must perform the necessary checks * for itself and use the {@link DmtException#METADATA_MISMATCH} error code to * indicate such discrepancies. *

* The DmtAdmin also ensures that the targeted nodes exist before calling the * plugin (or that they do not exist, in case of node creation). However, some * small amount of time elapses between the check and the call, so in case of * plugins where the node structure can change independantly from the DMT, the * target node might appear/disappear in that time. For example, a whole subtree * can disappear when a Monitorable application is unregistered, which might * happen in the middle of a DMT session accessing it. Plugins managing such * nodes always need to check the existance or non-existance of nodes and throw * {@link DmtException#NODE_NOT_FOUND} or * {@link DmtException#NODE_ALREADY_EXISTS} as necessary, but for more static * subtrees there is no need for the plugin to use these error codes. *

* The plugin can use the remaining error codes as needed. If an error does not * fit into any other category, the {@link DmtException#COMMAND_FAILED} code * should be used. * * @version $Id: fbde6c1121240b239e8a907c6427eeb242e78322 $ */ public interface ReadWriteDataSession extends ReadableDataSession { /** * Create a copy of a node or a whole subtree. Beside the structure and * values of the nodes, most properties managed by the plugin must also be * copied, with the exception of the Timestamp and Version properties. * * @param nodePath an absolute path specifying the node or the root of a * subtree to be copied * @param newNodePath the absolute path of the new node or root of a subtree * @param recursive {@code false} if only a single node is copied, * {@code true} if the whole subtree is copied * @throws DmtException with the following possible error codes: *

* @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation * @see DmtSession#copy(String, String, boolean) */ void copy(String[] nodePath, String[] newNodePath, boolean recursive) throws DmtException; /** * Create an interior node with a given type. The type of interior node, if * specified, is a URI identifying a DDF document. * * @param nodePath the absolute path of the node to create * @param type the type URI of the interior node, can be {@code null} * if no node type is defined * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation * @see DmtSession#createInteriorNode(String) * @see DmtSession#createInteriorNode(String, String) */ void createInteriorNode(String[] nodePath, String type) throws DmtException; /** * Create a leaf node with a given value and MIME type. If the specified * value or MIME type is {@code null}, their default values must be * taken. * * @param nodePath the absolute path of the node to create * @param value the value to be given to the new node, can be * {@code null} * @param mimeType the MIME type to be given to the new node, can be * {@code null} * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation * @see DmtSession#createLeafNode(String) * @see DmtSession#createLeafNode(String, DmtData) * @see DmtSession#createLeafNode(String, DmtData, String) */ void createLeafNode(String[] nodePath, DmtData value, String mimeType) throws DmtException; /** * Delete the given node. Deleting interior nodes is recursive, the whole * subtree under the given node is deleted. * * @param nodePath the absolute path of the node to delete * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation * @see DmtSession#deleteNode(String) */ void deleteNode(String[] nodePath) throws DmtException; /** * Rename a node. This operation only changes the name of the node (updating * the timestamp and version properties if they are supported), the value * and the other properties are not changed. The new name of the node must * be provided, the new path is constructed from the base of the old path * and the given name. * * @param nodePath the absolute path of the node to rename * @param newName the new name property of the node * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation * @see DmtSession#renameNode(String, String) */ void renameNode(String[] nodePath, String newName) throws DmtException; /** * Set the title property of a node. The length of the title is guaranteed * not to exceed the limit of 255 bytes in UTF-8 encoding. * * @param nodePath the absolute path of the node * @param title the title text of the node, can be {@code null} * @throws DmtException with the following possible error codes: * * @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation * @see DmtSession#setNodeTitle(String, String) */ void setNodeTitle(String[] nodePath, String title) throws DmtException; /** * Set the type of a node. The type of leaf node is the MIME type of the * data it contains. The type of an interior node is a URI identifying a DDF * document. *

* For interior nodes, the {@code null} type should remove the * reference (if any) to a DDF document overriding the tree structure * defined by the ancestors. For leaf nodes, it requests that the default * MIME type is used for the given node. * * @param nodePath the absolute path of the node * @param type the type of the node, can be {@code null} * @throws DmtException with the following possible error codes: *

* @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation * @see DmtSession#setNodeType(String, String) */ void setNodeType(String[] nodePath, String type) throws DmtException; /** * Set the value of a leaf or interior node. The format of the node is * contained in the {@code DmtData} object. For interior nodes, the * format is {@code FORMAT_NODE}, while for leaf nodes this format is * never used. *

* If the specified value is {@code null}, the default value must be * taken; if there is no default value, a {@code DmtException} with * error code {@code METADATA_MISMATCH} must be thrown. * * @param nodePath the absolute path of the node * @param data the data to be set, can be {@code null} * @throws DmtException with the following possible error codes: *

* @throws SecurityException if the caller does not have the necessary * permissions to execute the underlying management operation * @see DmtSession#setNodeValue(String, DmtData) */ void setNodeValue(String[] nodePath, DmtData data) throws DmtException; } osgi-compendium-4.3.0/src/org/0000755000175000017500000000000011632153414016067 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/org/osgi/0000755000175000017500000000000011632153414017030 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/org/osgi/application/0000755000175000017500000000000011632153414021333 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/org/osgi/application/package-info.java0000644000175000017500000000251611466514064024535 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Foreign Application Package Version 1.0. * *

* Bundles wishing to use this package must list the package in the * Import-Package header of the bundle's manifest. This package has two types of * users: the consumers that use the API in this package and the providers that * implement the API in this package. * *

* Example import for consumers using the API in this package: *

* {@code Import-Package: org.osgi.application; version="[1.0,2.0)"} *

* Example import for providers implementing the API in this package: *

* {@code Import-Package: org.osgi.application; version="[1.0,1.1)"} * * @version $Id: cd35b66cfa49a385a5650be5ceecad454d65e7b9 $ */ package org.osgi.application; osgi-compendium-4.3.0/src/org/osgi/application/Framework.java0000644000175000017500000000477011466514064024152 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2005, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.osgi.application; import java.util.Hashtable; /** * Using this class, OSGi-aware applications can obtain their * {@link ApplicationContext}. * * @version $Id: 68f0c39e8c8c0ea02ae2c20154bba8bf1e6ba7bc $ */ public final class Framework { private Framework() { } private static Hashtable appContextHash; /** * This method needs an argument, an object that represents the application instance. * An application consists of a set of object, however there is a single object, which * is used by the corresponding application container to manage the lifecycle on the * application instance. The lifetime of this object equals the lifetime of * the application instance; therefore, it is suitable to represent the instance. *

* The returned {@link ApplicationContext} object is singleton for the * specified application instance. Subsequent calls to this method with the same * application instance must return the same context object * * @param applicationInstance is the activator object of an application instance * @throws java.lang.NullPointerException If {@code applicationInstance} * is {@code null} * @throws java.lang.IllegalArgumentException if called with an object that is not * the activator object of an application. * @return the {@link ApplicationContext} of the specified application instance. */ public static ApplicationContext getApplicationContext(Object applicationInstance) { if( applicationInstance == null ) throw new NullPointerException( "Instance cannot be null!" ); ApplicationContext appContext = (ApplicationContext)appContextHash.get( applicationInstance ); if( appContext == null ) throw new IllegalArgumentException( "ApplicationContext not found!" ); return appContext; } } osgi-compendium-4.3.0/src/org/osgi/application/ApplicationServiceEvent.java0000644000175000017500000000650411466514064027000 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2005, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.osgi.application; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceReference; /** * An event from the Framework describing a service lifecycle change. *

* {@code ApplicationServiceEvent} objects are delivered to a * {@code ApplicationServiceListener} objects when a change occurs in this service's * lifecycle. The delivery of an {@code ApplicationServiceEvent} is * always triggered by a {@link org.osgi.framework.ServiceEvent}. * {@code ApplicationServiceEvent} extends the content of {@code ServiceEvent} * with the service object the event is referring to as applications has no means to * find the corresponding service object for a {@link org.osgi.framework.ServiceReference}. * A type code is used to identify the event type for future * extendability. The available type codes are defined in {@link org.osgi.framework.ServiceEvent}. * *

* OSGi Alliance reserves the right to extend the set of types. * * @see org.osgi.framework.ServiceEvent * @see ApplicationServiceListener * * @version $Id: bf3629f6023fe5a3897d1cfdcd441630187c3909 $ */ public class ApplicationServiceEvent extends ServiceEvent { private static final long serialVersionUID = -4762149286971897323L; final Object serviceObject; /** * Creates a new application service event object. * * @param type The event type. Available type codes are defines in * {@link org.osgi.framework.ServiceEvent} * @param reference A {@code ServiceReference} object to the service * that had a lifecycle change. This reference will be used as the {@code source} * in the {@link java.util.EventObject} baseclass, therefore, it must not be * null. * @param serviceObject The service object bound to this application instance. It can * be {@code null} if this application is not bound to this service yet. * @throws IllegalArgumentException if the specified {@code reference} is null. */ public ApplicationServiceEvent(int type, ServiceReference reference, Object serviceObject) { super(type, reference); this.serviceObject = serviceObject; } /** * This method returns the service object of this service bound to the listener * application instance. A service object becomes bound to the application when it * first obtains a service object reference to that service by calling the * {@code ApplicationContext.locateService} or {@code locateServices} * methods. If the application is not bound to the service yet, this method returns * {@code null}. * * @return the service object bound to the listener application or {@code null} * if it isn't bound to this service yet. */ public Object getServiceObject() { return this.serviceObject; } } osgi-compendium-4.3.0/src/org/osgi/application/packageinfo0000644000175000017500000000001411405717702023524 0ustar drazzibdrazzibversion 1.0 osgi-compendium-4.3.0/src/org/osgi/application/ApplicationContext.java0000644000175000017500000004153011632147274026020 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2005, 2011). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.osgi.application; import java.util.Dictionary; import java.util.Map; import org.osgi.framework.Constants; import org.osgi.framework.ServiceRegistration; /** * {@code ApplicationContext} is the access point for an OSGi-aware application * to the features of the OSGi Service Platform. Each application instance will * have its own {@code ApplicationContext} instance, which will not be reused * after destroying the corresponding application instance. *

* Application instances can obtain their {@code ApplicationContext} using the * {@link Framework#getApplicationContext(Object)} method. *

* The lifecycle of an {@code ApplicationContext} instance is bound to the * lifecycle of the corresponding application instance. The * {@code ApplicationContext} becomes available when the application is started * and it is invalidated when the application instance is stopped (i.e. the * "stop" method of the application activator object returned). All method calls * (except {@link #getApplicationId()} and {@link #getInstanceId()}) to an * invalidated context object result an {@code IllegalStateException}. * * @see org.osgi.application.Framework * * @version $Id: b86dd158983b7a8aafa2a8023d76ef15b3e68125 $ */ public interface ApplicationContext { /** * Adds the specified {@link ApplicationServiceListener} object to this context * application instance's list of listeners. The specified {@code referenceName} is a * reference name specified in the descriptor of the corresponding application. The registered * {@code listener} will only receive the {@link ApplicationServiceEvent}s related to the referred service. *

* If the {@code listener} was already added, calling this method will overwrite the previous * registration. *

* * @param listener * The {@link org.osgi.application.ApplicationServiceListener} to be added. It must * not be {@code null} * @param referenceName the reference name of a service from the descriptor of the corresponding * application. It must not be {@code null}. * @throws java.lang.IllegalStateException * If this context application instance has stopped. * @throws java.lang.NullPointerException If {@code listener} or {@code referenceName} * is {@code null} * @throws java.lang.IllegalArgumentException If there is no service in the * application descriptor with the specified {@code referenceName}. */ public void addServiceListener(ApplicationServiceListener listener, String referenceName) throws java.lang.IllegalArgumentException; /** * Adds the specified {@link ApplicationServiceListener} object to this context * application instance's list of listeners. The {@code referenceNames} parameter is an * array of reference name specified in the descriptor of the corresponding application. The registered * {@code listener} will only receive the {@link ApplicationServiceEvent}s related to the referred * services. *

* If the {@code listener} was already added, calling this method will overwrite the previous * registration. *

* * @param listener * The {@link org.osgi.application.ApplicationServiceListener} to be added. It must not * be {@code null} * @param referenceNames and array of service reference names from the descriptor of the corresponding * application. It must not be {@code null} and it must not be empty. * @throws java.lang.IllegalStateException * If this context application instance has stopped. * @throws java.lang.NullPointerException If {@code listener} or {@code referenceNames} * is {@code null} * @throws java.lang.IllegalArgumentException If {@code referenceNames} array is empty or it * contains unknown references */ public void addServiceListener(ApplicationServiceListener listener, String[] referenceNames) throws java.lang.IllegalArgumentException; /** * Removes the specified {@link org.osgi.application.ApplicationServiceListener} object from this * context application instances's list of listeners. *

* If {@code listener} is not contained in this context application * instance's list of listeners, this method does nothing. * * @param listener * The {@link org.osgi.application.ApplicationServiceListener} object to be removed. * @throws java.lang.IllegalStateException * If this context application instance has stopped. */ public void removeServiceListener(ApplicationServiceListener listener); /** * This method returns the identifier of the corresponding application * instance. This identifier is guaranteed to be unique within the scope of * the device. * * Note: this method can safely be called on an invalid * {@code ApplicationContext} as well. * * @see org.osgi.service.application.ApplicationHandle#getInstanceId() * * @return the unique identifier of the corresponding application instance */ public String getInstanceId(); /** * This method return the identifier of the corresponding application type. This identifier * is the same for the different instances of the same application but it is different for * different application type. *

* Note: this method can safely be called on an invalid * {@code ApplicationContext} as well. * * @see org.osgi.service.application.ApplicationDescriptor#getApplicationId() * * @return the identifier of the application type. */ public String getApplicationId(); /** * This method returns the service object for the specified * {@code referenceName}. If the cardinality of the reference is * 0..n or 1..n and multiple services are bound to the reference, the * service with the highest ranking (as specified in its * {@link org.osgi.framework.Constants#SERVICE_RANKING} property) is returned. If there * is a tie in ranking, the service with the lowest service ID (as specified * in its {@link org.osgi.framework.Constants#SERVICE_ID} property); that is, the * service that was registered first is returned. * * @param referenceName * The name of a reference as specified in a reference element in * this context applications's description. It must not be {@code null} * @return A service object for the referenced service or {@code null} * if the reference cardinality is 0..1 or 0..n and no bound service * is available. * @throws java.lang.NullPointerException If {@code referenceName} is {@code null}. * @throws java.lang.IllegalArgumentException If there is no service in the * application descriptor with the specified {@code referenceName}. * @throws java.lang.IllegalStateException * If this context application instance has stopped. */ public Object locateService(String referenceName); /** * This method returns the service objects for the specified * {@code referenceName}. * * @param referenceName * The name of a reference as specified in a reference element in * this context applications's description. It must not be * {@code null}. * @return An array of service object for the referenced service or * {@code null} if the reference cardinality is 0..1 or 0..n * and no bound service is available. * @throws java.lang.NullPointerException If {@code referenceName} is {@code null}. * @throws java.lang.IllegalArgumentException If there is no service in the * application descriptor with the specified {@code referenceName}. * @throws java.lang.IllegalStateException * If this context application instance has stopped. */ public Object[] locateServices(String referenceName); /** * Returns the startup parameters specified when calling the * {@code org.osgi.service.application.ApplicationDescriptor#launch(Map)} * method. *

* Startup arguments can be specified as name, value pairs. The name must be * of type {@link java.lang.String}, which must not be {@code null} or empty * {@link java.lang.String} ({@code ""}), the value can be any object * including {@code null}. * * @return a {@link java.util.Map} containing the startup arguments. It can * be {@code null}. * @throws java.lang.IllegalStateException If this context application * instance has stopped. */ public Map getStartupParameters(); /** * Application can query the service properties of a service object * it is bound to. Application gets bound to a service object when * it first obtains a reference to the service by calling * {@code locateService} or {@code locateServices} methods. * * @param serviceObject A service object the application is bound to. * It must not be null. * @return The service properties associated with the specified service * object. * @throws NullPointerException if the specified {@code serviceObject} * is {@code null} * @throws IllegalArgumentException if the application is not * bound to the specified service object or it is not a service * object at all. * @throws java.lang.IllegalStateException * If this context application instance has stopped. */ public Map getServiceProperties(Object serviceObject); /** * Registers the specified service object with the specified properties * under the specified class names into the Framework. A * {@link org.osgi.framework.ServiceRegistration} object is returned. The * {@link org.osgi.framework.ServiceRegistration} object is for the private * use of the application registering the service and should not be shared * with other applications. The registering application is defined to be the * context application. Bundles can locate the service by using either the * {@link org.osgi.framework.BundleContext#getServiceReferences(String, String)} * or {@link org.osgi.framework.BundleContext#getServiceReference(String)} * method. Other applications can locate this service by using * {@link #locateService(String)} or {@link #locateServices(String)} method, * if they declared their dependence on the registered service. * *

* An application can register a service object that implements the * {@link org.osgi.framework.ServiceFactory} interface to have more * flexibility in providing service objects to other applications or * bundles. * *

* The following steps are required to register a service: *

    *
  1. If {@code service} is not a {@code ServiceFactory}, an * {@code IllegalArgumentException} is thrown if {@code service} is not an * {@code instanceof} all the classes named. *
  2. The Framework adds these service properties to the specified * {@code Dictionary} (which may be {@code null}): a property named * {@link org.osgi.framework.Constants#SERVICE_ID} identifying the * registration number of the service and a property named * {@link org.osgi.framework.Constants#OBJECTCLASS} containing all the * specified classes. If any of these properties have already been specified * by the registering bundle, their values will be overwritten by the * Framework. *
  3. The service is added to the Framework service registry and may now be * used by others. *
  4. A service event of type * {@link org.osgi.framework.ServiceEvent#REGISTERED} is fired. This event * triggers the corresponding {@link ApplicationServiceEvent} to be * delivered to the applications that registered the appropriate listener. *
  5. A {@code ServiceRegistration} object for this registration is * returned. *
* * @param clazzes The class names under which the service can be located. * The class names in this array will be stored in the service's * properties under the key * {@link org.osgi.framework.Constants#OBJECTCLASS}. This parameter * must not be {@code null}. * @param service The service object or a {@code ServiceFactory} object. * @param properties The properties for this service. The keys in the * properties object must all be {@code String} objects. See * {@link org.osgi.framework.Constants} for a list of standard * service property keys. Changes should not be made to this object * after calling this method. To update the service's properties the * {@link org.osgi.framework.ServiceRegistration#setProperties(Dictionary)} * method must be called. The set of properties may be {@code null} * if the service has no properties. * * @return A {@link org.osgi.framework.ServiceRegistration} object for use * by the application registering the service to update the * service's properties or to unregister the service. * * @throws java.lang.IllegalArgumentException If one of the following is * true: * * @throws NullPointerException if {@code clazzes} is {@code null} * * @throws java.lang.SecurityException If the caller does not have the * {@code ServicePermission} to register the service for all the * named classes and the Java Runtime Environment supports * permissions. * * @throws java.lang.IllegalStateException If this ApplicationContext is no * longer valid. * * @see org.osgi.framework.BundleContext#registerService(java.lang.String[], * java.lang.Object, java.util.Dictionary) * @see org.osgi.framework.ServiceRegistration * @see org.osgi.framework.ServiceFactory */ public ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties); /** * Registers the specified service object with the specified properties * under the specified class name with the Framework. * *

* This method is otherwise identical to * {@link #registerService(java.lang.String[], java.lang.Object, * java.util.Dictionary)} and is provided as a convenience when * {@code service} will only be registered under a single class name. * Note that even in this case the value of the service's * {@link Constants#OBJECTCLASS} property will be an array of strings, * rather than just a single string. * * @param clazz The class name under which the service can be located. It * must not be {@code null} * @param service The service object or a {@code ServiceFactory} * object. * @param properties The properties for this service. * * @return A {@code ServiceRegistration} object for use by the application * registering the service to update the service's properties or to * unregister the service. * * @throws java.lang.IllegalArgumentException If one of the following is * true: *

* @throws NullPointerException if {@code clazz} is {@code null} * * @throws java.lang.SecurityException If the caller does not have the * {@code ServicePermission} to register the service * the named class and the Java Runtime Environment supports * permissions. * * @throws java.lang.IllegalStateException If this ApplicationContext is no * longer valid. * @see #registerService(java.lang.String[], java.lang.Object, * java.util.Dictionary) */ public ServiceRegistration registerService(String clazz, Object service, Dictionary properties); } osgi-compendium-4.3.0/src/org/osgi/application/ApplicationServiceListener.java0000644000175000017500000000525711466514064027510 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2005, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.osgi.application; import java.util.EventListener; import org.osgi.framework.*; /** * An {@code ApplicationServiceEvent} listener. When a * {@code ServiceEvent} is * fired, it is converted to an {@code ApplictionServiceEvent} * and it is synchronously delivered to an {@code ApplicationServiceListener}. * *

* {@code ApplicationServiceListener} is a listener interface that may be * implemented by an application developer. *

* An {@code ApplicationServiceListener} object is registered with the Framework * using the {@code ApplicationContext.addServiceListener} method. * {@code ApplicationServiceListener} objects are called with an * {@code ApplicationServiceEvent} object when a service is registered, modified, or * is in the process of unregistering. * *

* {@code ApplicationServiceEvent} object delivery to * {@code ApplicationServiceListener} * objects is filtered by the filter specified when the listener was registered. * If the Java Runtime Environment supports permissions, then additional * filtering is done. {@code ApplicationServiceEvent} objects are only delivered to * the listener if the application which defines the listener object's class has the * appropriate {@code ServicePermission} to get the service using at * least one of the named classes the service was registered under, and the application * specified its dependence on the corresponding service in the application metadata. * *

* {@code ApplicationServiceEvent} object delivery to {@code ApplicationServiceListener} * objects is further filtered according to package sources as defined in * {@link ServiceReference#isAssignableTo(Bundle, String)}. * * @version $Id: fdd38c556d5784e412d68175a59f6f83c92aa4cc $ * @see ApplicationServiceEvent * @see ServicePermission */ public interface ApplicationServiceListener extends EventListener { /** * Receives notification that a service has had a lifecycle change. * * @param event The {@code ApplicationServiceEvent} object. */ public void serviceChanged(ApplicationServiceEvent event); } osgi-compendium-4.3.0/src/org/osgi/service/0000755000175000017500000000000011632153414020470 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/org/osgi/service/log/0000755000175000017500000000000011632153414021251 5ustar drazzibdrazzibosgi-compendium-4.3.0/src/org/osgi/service/log/package-info.java0000644000175000017500000000250611466514064024452 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Log Service Package Version 1.3. * *

* Bundles wishing to use this package must list the package in the * Import-Package header of the bundle's manifest. This package has two types of * users: the consumers that use the API in this package and the providers that * implement the API in this package. * *

* Example import for consumers using the API in this package: *

* {@code Import-Package: org.osgi.service.log; version="[1.3,2.0)"} *

* Example import for providers implementing the API in this package: *

* {@code Import-Package: org.osgi.service.log; version="[1.3,1.4)"} * * @version $Id: 5c4120fc17628d242e1641557eacb9581b08c920 $ */ package org.osgi.service.log; osgi-compendium-4.3.0/src/org/osgi/service/log/LogListener.java0000644000175000017500000000335711466514064024362 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2000, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.osgi.service.log; import java.util.EventListener; /** * Subscribes to {@code LogEntry} objects from the {@code LogReaderService}. * *

* A {@code LogListener} object may be registered with the Log Reader Service * using the {@code LogReaderService.addLogListener} method. After the * listener is registered, the {@code logged} method will be called for each * {@code LogEntry} object created. The {@code LogListener} object may be * unregistered by calling the {@code LogReaderService.removeLogListener} * method. * * @ThreadSafe * @version $Id: 9b1ea6645e00027d03684b74745f47a42fb9ad30 $ * @see LogReaderService * @see LogEntry * @see LogReaderService#addLogListener(LogListener) * @see LogReaderService#removeLogListener(LogListener) */ public interface LogListener extends EventListener { /** * Listener method called for each LogEntry object created. * *

* As with all event listeners, this method should return to its caller as * soon as possible. * * @param entry A {@code LogEntry} object containing log information. * @see LogEntry */ public void logged(LogEntry entry); } osgi-compendium-4.3.0/src/org/osgi/service/log/LogEntry.java0000644000175000017500000000677011466514064023700 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2000, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.osgi.service.log; import org.osgi.framework.Bundle; import org.osgi.framework.ServiceReference; /** * Provides methods to access the information contained in an individual Log * Service log entry. * *

* A {@code LogEntry} object may be acquired from the * {@code LogReaderService.getLog} method or by registering a * {@code LogListener} object. * * @ThreadSafe * @noimplement * @version $Id: e20fd66ff9e0264d77f7b7ea19212b305d1b3a40 $ * @see LogReaderService#getLog * @see LogListener */ public interface LogEntry { /** * Returns the bundle that created this {@code LogEntry} object. * * @return The bundle that created this {@code LogEntry} object; * {@code null} if no bundle is associated with this * {@code LogEntry} object. */ public Bundle getBundle(); /** * Returns the {@code ServiceReference} object for the service associated * with this {@code LogEntry} object. * * @return {@code ServiceReference} object for the service associated * with this {@code LogEntry} object; {@code null} if no * {@code ServiceReference} object was provided. */ public ServiceReference getServiceReference(); /** * Returns the severity level of this {@code LogEntry} object. * *

* This is one of the severity levels defined by the {@code LogService} * interface. * * @return Severity level of this {@code LogEntry} object. * * @see LogService#LOG_ERROR * @see LogService#LOG_WARNING * @see LogService#LOG_INFO * @see LogService#LOG_DEBUG */ public int getLevel(); /** * Returns the human readable message associated with this {@code LogEntry} * object. * * @return {@code String} containing the message associated with this * {@code LogEntry} object. */ public String getMessage(); /** * Returns the exception object associated with this {@code LogEntry} * object. * *

* In some implementations, the returned exception may not be the original * exception. To avoid references to a bundle defined exception class, thus * preventing an uninstalled bundle from being garbage collected, the Log * Service may return an exception object of an implementation defined * Throwable subclass. The returned object will attempt to provide as much * information as possible from the original exception object such as the * message and stack trace. * * @return {@code Throwable} object of the exception associated with this * {@code LogEntry};{@code null} if no exception is * associated with this {@code LogEntry} object. */ public Throwable getException(); /** * Returns the value of {@code currentTimeMillis()} at the time this * {@code LogEntry} object was created. * * @return The system time in milliseconds when this {@code LogEntry} * object was created. * @see "System.currentTimeMillis()" */ public long getTime(); } osgi-compendium-4.3.0/src/org/osgi/service/log/packageinfo0000644000175000017500000000001411405717704023444 0ustar drazzibdrazzibversion 1.3 osgi-compendium-4.3.0/src/org/osgi/service/log/LogReaderService.java0000644000175000017500000000652211466514064025315 0ustar drazzibdrazzib/* * Copyright (c) OSGi Alliance (2000, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.osgi.service.log; import java.util.Enumeration; /** * Provides methods to retrieve {@code LogEntry} objects from the log. *

* There are two ways to retrieve {@code LogEntry} objects: *