text:
<?xml version="1.0" encoding="utf-8"?>

<chapter label="107"
         revision="$Id$"
         version="5.0" xml:id="service.useradmin"
         xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:ns5="http://www.w3.org/2000/svg"
         xmlns:ns4="http://www.w3.org/1998/Math/MathML"
         xmlns:ns3="http://www.w3.org/1999/xhtml"
         xmlns:ns="http://docbook.org/ns/docbook">
  <title>User Admin Service Specification</title>

  <info>
    <releaseinfo><xref endterm="org.osgi.service.useradmin-version"
    linkend="org.osgi.service.useradmin"/></releaseinfo>
  </info>

    <title>Introduction</title>

    <para>OSGi frameworks are often used in places where end users or devices
    initiate actions. These kinds of actions inevitably create a need for
    authenticating the initiator. Authenticating can be done in many different
    ways, including with passwords, one-time token cards, biometrics, and
    certificates.</para>

    <para>Once the initiator is authenticated, it is necessary to verify that
    this principal is authorized to perform the requested action. This
    authorization can only be decided by the operator of the OSGi environment,
    and thus requires administration.</para>

    <para>The User Admin service provides this type of functionality. Bundles
    can use the User Admin service to authenticate an initiator and represent
    this authentication as an Authorization object. Bundles that
    execute actions on behalf of this user can use the
    Authorization object to verify if that user is
    authorized.</para>

    <para>The User Admin service provides authorization based on who runs the
    code, instead of using the Java code-based permission model. See <xref
    linkend="i1307817"/>. It performs a role similar to <xref
    linkend="i1307810"/>.</para>

      <title>Essentials</title>

      <itemizedlist>
        <listitem>
          <para><emphasis>Authentication</emphasis> - A large number of
          authentication schemes already exist, and more will be developed.
          The User Admin service must be flexible enough to adapt to the many
          different authentication schemes that can be run on a computer
          system.</para>
        </listitem>

        <listitem>
          <para><emphasis>Authorization</emphasis> - All bundles should use
          the User Admin service to authenticate users and to find out if
          those users are authorized. It is therefore paramount that a bundle
          can find out authorization information with little effort.</para>
        </listitem>

        <listitem>
          <para><emphasis>Security</emphasis> - Detailed security, based on
          the Framework security model, is needed to provide safe access to
          the User Admin service. It should allow limited access to the
          credentials and other properties.</para>
        </listitem>

        <listitem>
          <para><emphasis>Extensibility</emphasis> - Other bundles should be
          able to build on the User Admin service. It should be possible to
          examine the information from this service and get real-time
          notifications of changes.</para>
        </listitem>

        <listitem>
          <para><emphasis>Properties</emphasis> - The User Admin service must
          maintain a persistent database of users. It must be possible to use
          this database to hold more information about this user.</para>
        </listitem>

        <listitem>
          <para><emphasis>Administration</emphasis> - Administering
          authorizations for each possible action and initiator is
          time-consuming and error-prone. It is therefore necessary to have
          mechanisms to group end users and make it simple to assign
          authorizations to all members of a group at one time.</para>
        </listitem>
      </itemizedlist>

      <title>Entities</title>

      <para>This Specification defines the following User Admin service
      entities:</para>

      <itemizedlist>
        <listitem>
          <para><emphasis>User Admin</emphasis> - This interface manages a
          database of named roles which can be used for authorization and
          authentication purposes.</para>
        </listitem>

        <listitem>
          <para><emphasis>Role</emphasis> - This interface exposes the
          characteristics shared by all roles: a name, a type, and a set of
          properties.</para>
        </listitem>

        <listitem>
          <para><emphasis>User</emphasis> - This interface (which extends
          Role) is used to represent any entity which may have
          credentials associated with it. These credentials can be used to
          authenticate an initiator.</para>
        </listitem>

        <listitem>
          <para><emphasis>Group</emphasis> - This interface (which extends
          User) is used to contain an aggregation of named
          Role objects (Group or User
          objects).</para>
        </listitem>

        <listitem>
          <para><emphasis>Authorization</emphasis> - This interface
          encapsulates an authorization context on which bundles can base
          authorization decisions.</para>
        </listitem>

        <listitem>
          <para><emphasis>User Admin Event</emphasis> - This class is used to
          represent a role change event.</para>
        </listitem>

        <listitem>
          <para><emphasis>User Admin Listener</emphasis> - This interface
          provides a listener for events of type UserAdminEvent
          that can be registered as a service.</para>
        </listitem>

        <listitem>
          <para><emphasis>User Admin Permission</emphasis> - This permission
          is needed to configure and access the roles managed by a User Admin
          service.</para>
        </listitem>

        <listitem>
          <para><emphasis>Role.USER_ANYONE</emphasis> - This is a special User
          object that represents <emphasis>any</emphasis> user, it implies all
          other User objects. It is also used when a Group is used with only
          basic members. The Role.USER_ANYONE is then the only
          required member.</para>
        </listitem>
      </itemizedlist>

        <title>User Admin Service, org.osgi.service.useradmin</title>

        <mediaobject>
          <imageobject>
            <imagedata align="center" contentdepth="4.681in"
                       contentwidth="6.500in" fileref="useradmin-classes.svg"/>
          </imageobject>
        </mediaobject>

      <title>Operation</title>

      <para>An Operator uses the User Admin service to define OSGi framework
      users and configure them with properties, credentials, and
      <emphasis>roles</emphasis>.</para>

      <para>A Role object represents the initiator of a request
      (human or otherwise). This specification defines two types of
      roles:</para>

      <itemizedlist>
        <listitem>
          <para><emphasis>User</emphasis> - A User object can be
          configured with credentials, such as a password, and properties,
          such as address, telephone number, and so on.</para>
        </listitem>

        <listitem>
          <para><emphasis>Group</emphasis> - A Group object is an
          aggregation of <emphasis>basic</emphasis> and
          <emphasis>required</emphasis> roles. Basic and required roles are
          used in the authorization phase.</para>
        </listitem>
      </itemizedlist>

      <para>An OSGi framework can have several entry points, each of which
      will be responsible for authenticating incoming requests. An example of
      an entry point is the Http Service, which delegates authentication of
      incoming requests to the handleSecurity method of the
      HttpContext object that was specified when the target
      servlet or resource of the request was registered.</para>

      <para>The OSGi framework entry points should use the information in the
      User Admin service to authenticate incoming requests, such as a password
      stored in the private credentials or the use of a certificate.</para>

      <para>A bundle can determine if a request for an action is authorized by
      looking for a Role object that has the name of the
      requested action.</para>

      <para>The bundle may execute the action if the Role object
      representing the initiator <emphasis>implies</emphasis> the
      Role object representing the requested action.</para>

      <para>For example, an initiator Role object
      <emphasis>X</emphasis> implies an action Group object
      <emphasis>A</emphasis> if:</para>

      <itemizedlist>
        <listitem>
          <para><emphasis>X</emphasis> implies at least one of
          <emphasis>A</emphasis>'s basic members, and</para>
        </listitem>

        <listitem>
          <para><emphasis>X</emphasis> implies all of <emphasis>A</emphasis>'s
          required members.</para>
        </listitem>
      </itemizedlist>

      <para>An initiator Role object <emphasis>X</emphasis>
      implies an action User object <emphasis>A</emphasis>
      if:</para>

      <itemizedlist>
        <listitem>
          <para><emphasis>A</emphasis> and <emphasis>X</emphasis> are
          equal.</para>
        </listitem>
      </itemizedlist>

      <para>The Authorization class handles this non-trivial
      logic. The User Admin service can capture the privileges of an
      authenticated User object into an
      Authorization object. The
      Authorization.hasRole method checks if the authenticate
      User object has (or implies) a specified action
      Role object.</para>

      <para>For example, in the case of a web application, a server component
      like a servlet filter can authenticate the initiator and place
      an Authorization object in the request. The servlet
      calls the hasRole method on this Authorization
      object to verify that the initiator has the authority to perform a
      certain action.</para>

    <title>Authentication</title>

    <para>The authentication phase determines if the initiator is actually the
    one it says it is. Mechanisms to authenticate always need some information
    related to the user or the OSGi framework to authenticate an external
    user. This information can consist of the following:</para>

    <itemizedlist>
      <listitem>
        <para>A secret known only to the initiator.</para>
      </listitem>

      <listitem>
        <para>Knowledge about cards that can generate a unique token.</para>
      </listitem>

      <listitem>
        <para>Public information like certificates of trusted signers.</para>
      </listitem>

      <listitem>
        <para>Information about the user that can be measured in a trusted
        way.</para>
      </listitem>

      <listitem>
        <para>Other specific information.</para>
      </listitem>
    </itemizedlist>

      <title>Repository</title>

      <para>The User Admin service offers a repository of Role
      objects. Each Role object has a unique name and a set of
      properties that are readable by anyone, and are changeable when the
      changer has the UserAdminPermission. Additionally,
      User objects, a sub-interface of Role, also
      have a set of private protected properties called credentials.
      Credentials are an extra set of properties that are used to authenticate
      users and that are protected by UserAdminPermission.</para>

      <para>Properties are accessed with the Role.getProperties()
      method and credentials with the User.getCredentials()
      method. Both methods return a Dictionary object containing
      key/value pairs. The keys are String objects and the values
      of the Dictionary object are limited to String
      or byte[ ] objects.</para>

      <para>This specification does not define any standard keys for the
      properties or credentials. The keys depend on the implementation of the
      authentication mechanism and are not formally defined by OSGi
      specifications.</para>

      <para>The repository can be searched for objects that have a unique
      property (key/value pair) with the method
      UserAdmin.getUser(String,String). This makes it easy to
      find a specific user related to a specific authentication mechanism. For
      example, a secure card mechanism that generates unique tokens could have
      a serial number identifying the user. The owner of the card could be
      found with the method</para>

      <programlisting>User owner = useradmin.getUser(
    "secure-card-serial", "132456712-1212" );</programlisting>

      <para>If multiple User objects have the same property (key
      <emphasis>and</emphasis> value), a null is returned.</para>

      <para>There is a convenience method to verify that a user has a
      credential without actually getting the credential. This is the
      User.hasCredential(String,Object) method.</para>

      <para>Access to credentials is protected on a name basis by
      UserAdminPermission. Because properties can be read by
      anyone with access to a User object,
      UserAdminPermission only protects change access to
      properties.</para>

      <title>Basic Authentication</title>

      <para>The following example shows a very simple authentication algorithm
      based on passwords.</para>

      <para>The vendor of the authentication bundle uses the property
      "com.acme.basic-id" to contain the name of a user as it
      logs in. This property is used to locate the User object in
      the repository. Next, the credential "com.acme.password"
      contains the password and is compared to the entered password. If the
      password is correct, the User object is returned. In all
      other cases a SecurityException is thrown.</para>

      <programlisting>public User authenticate(
        UserAdmin ua, String name, String pwd )
    throws SecurityException {
    User user = ua.getUser("com.acme.basicid",
        username);
    if (user == null)
        throw new SecurityException( "No such user" );

    if (!user.hasCredential("com.acme.password", pwd))
        throw new SecurityException(
            "Invalid password" );
    return user;
}</programlisting>

      <title>Certificates</title>

      <para>Authentication based on certificates does not require a shared
      secret. Instead, a certificate contains a name, a public key, and the
      signature of one or more signers.</para>

      <para>The name in the certificate can be used to locate a
      User object in the repository. Locating a User
      object, however, only identifies the initiator and does not authenticate
      it.</para>

      <orderedlist>
        <listitem>
          <para>The first step to authenticate the initiator is to verify that
          it has the private key of the certificate.</para>
        </listitem>

        <listitem>
          <para>Next, the User Admin service must verify that it has a
          User object with the right property, for example
          "com.acme.certificate"="Fudd".</para>
        </listitem>

        <listitem>
          <para>The next step is to see if the certificate is signed by a
          trusted source. The bundle could use a central list of trusted
          signers and only accept certificates signed by those sources.
          Alternatively, it could require that the certificate itself is
          already stored in the repository under a unique key as a
          byte[] in the credentials.</para>
        </listitem>

        <listitem>
          <para>In any case, once the certificate is verified, the associated
          User object is authenticated.</para>
        </listitem>
      </orderedlist>

    <title>Authorization</title>

    <para>The User Admin service authorization architecture is a
    <emphasis>role-based model</emphasis>. In this model, every action that
    can be performed by a bundle is associated with a
    <emphasis>role</emphasis>. Such a role is a Group object
    (called group from now on) from the User Admin service repository. For
    example, if a servlet could be used to activate the alarm system, there
    should be a group named AlarmSystemActivation.</para>

    <para>The operator can administrate authorizations by populating the group
    with User objects (users) and other groups. Groups are used
    to minimize the amount of administration required. For example, it is
    easier to create one Administrators group and add
    administrative roles to it rather than individually administer all users
    for each role. Such a group requires only one action to remove or add a
    user as an administrator.</para>

    <para>The authorization decision can now be made in two fundamentally
    different ways:</para>

    <para>An initiator could be allowed to carry out an action (represented by
    a Group object) if it implied any of the Group
    object's members. For example, the AlarmSystemActivation
    Group object contains an Administrators and a
    Family Group object:</para>

    <programlisting>    Administrators        = { Elmer, Pepe,Bugs }
    Family                = { Elmer, Pepe, Daffy }

    AlarmSystemActivation = { Administrators, Family}</programlisting>

    <para>Any of the four members Elmer, Pepe,
    Daffy, or Bugs can activate the alarm
    system.</para>

    <para>Alternatively, an initiator could be allowed to perform an action
    (represented by a Group object) if it implied
    <emphasis>all</emphasis> the Group object's members. In this
    case, using the same AlarmSystemActivation group, only
    Elmer and Pepe would be authorized to activate
    the alarm system, since Daffy and Bugs are
    <emphasis>not</emphasis> members of <emphasis>both</emphasis> the
    Administrators and Family Group objects.</para>

    <para>The User Admin service supports a combination of both strategies by
    defining both a set of <emphasis>basic members</emphasis> (any) and a set
    of <emphasis>required members</emphasis> (all).</para>

    <programlisting>Administrators            = { Elmer, Pepe, Bugs}
Family                    = { Elmer, Pepe, Daffy }

AlarmSystemActivation
    required              = { Administrators }
    basic                 = { Family }</programlisting>

    <para>The difference is made when Role objects are added to
    the Group object. To add a basic member, use the
    Group.addMember(Role) method. To add a required member, use
    the Group.addRequiredMember(Role) method.</para>

    <para>Basic members define the set of members that can get access and
    required members reduce this set by requiring the initiator to
    <emphasis>imply</emphasis> each required member.</para>

    <para>A User object implies a Group object if it
    implies the following:</para>

    <itemizedlist>
      <listitem>
        <para><emphasis>All</emphasis> of the Group's required members,
        and</para>
      </listitem>

      <listitem>
        <para>At <emphasis>least</emphasis> one of the Group's basic
        members</para>
      </listitem>
    </itemizedlist>

    <para>A User object always implies itself.</para>

    <para>If only required members are used to qualify the implication, then
    the standard user Role.<xref
    linkend="org.osgi.service.useradmin.Role.USER_ANYONE"
    xrefstyle="hyperlink"/> can be obtained from the User Admin service and
    added to the Group object. This Role object is
    implied by anybody and therefore does not affect the required
    members.</para>

      <title>The Authorization Object</title>

      <para>The complexity of authorization is hidden in an
      Authorization class. Normally, the authenticator should
      retrieve an Authorization object from the User Admin
      service by passing the authenticated User object as an
      argument. This Authorization object is then passed to the
      bundle that performs the action. This bundle checks the authorization
      with the Authorization.hasRole(String) method. The
      performing bundle must pass the name of the action as an argument. The
      Authorization object checks whether the authenticated user
      implies the Role object, specifically a Group
      object, with the given name. This is shown in the following
      example.</para>

      <programlisting>public void activateAlarm(Authorization auth) {
    if ( auth.hasRole( "AlarmSystemActivation" ) ) {
        // activate the alarm
        ...
    }
    else throw new SecurityException(
        "Not authorized to activate alarm" );
}</programlisting>

      <title>Authorization Example</title>

      <para>This section demonstrates a possible use of the User Admin
      service. The service has a flexible model and many other schemes are
      possible.</para>

      <para>Assume an Operator installs an OSGi framework. Bundles in this
      environment have defined the following action groups:</para>

      <programlisting>AlarmSystemControl
InternetAccess
TemperatureControl
PhotoAlbumEdit
PhotoAlbumView
PortForwarding</programlisting>

      <para>Installing and uninstalling bundles could potentially extend this
      set. Therefore, the Operator also defines a number of groups that can be
      used to contain the different types of system users.</para>

      <programlisting>Administrators
Buddies
Children
Adults
Residents</programlisting>

      <para>In a particular instance, the Operator installs it in a household
      with the following residents and buddies:</para>

      <programlisting>Residents:      Elmer, Fudd, Marvin, Pepe
Buddies:        Daffy, Foghorn</programlisting>

      <para>First, the residents and buddies are assigned to the system user
      groups. Second, the user groups need to be assigned to the action
      groups.</para>

      <para>The following tables show how the groups could be assigned.</para>

        <title>Example Groups with Basic and Required Members</title>

        <tgroup cols="7">
          <colspec colnum="1" colwidth="1.5*"/>

          <colspec colnum="2" colwidth="1*"/>

          <colspec colnum="3" colwidth="1*"/>

          <colspec colnum="4" colwidth="1*"/>

          <colspec colnum="5" colwidth="1*"/>

          <colspec colnum="6" colwidth="1*"/>

          <colspec colnum="7" colwidth="1*"/>

            <row>
              <entry>Groups</entry>

              <entry>Elmer</entry>

              <entry>Fudd</entry>

              <entry>Marvin</entry>

              <entry>Pepe</entry>

              <entry>Daffy</entry>

              <entry>Foghorn</entry>
            </row>

            <row>
              <entry>Residents</entry>

              <entry>Basic</entry>

              <entry>Basic</entry>

              <entry>Basic</entry>

              <entry>Basic</entry>

              <entry>-</entry>

              <entry>-</entry>
            </row>

            <row>
              <entry>Buddies</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>Basic</entry>

              <entry>Basic</entry>
            </row>

            <row>
              <entry>Children</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>Basic</entry>

              <entry>Basic</entry>

              <entry>-</entry>

              <entry>-</entry>
            </row>

            <row>
              <entry>Adults</entry>

              <entry>Basic</entry>

              <entry>Basic</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>-</entry>
            </row>

            <row>
              <entry>Administrators</entry>

              <entry>Basic</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>-</entry>
            </row>

        </tgroup>

        <title>Example Action Groups with their Basic and Required
        Members</title>

        <tgroup cols="6">
          <colspec colnum="1" colwidth="2*"/>

          <colspec colnum="2" colwidth="1*"/>

          <colspec colnum="3" colwidth="1*"/>

          <colspec colnum="4" colwidth="1*"/>

          <colspec colnum="5" colwidth="1*"/>

          <colspec colnum="6" colwidth="1*"/>

            <row>
              <entry>Groups</entry>

              <entry>Residents</entry>

              <entry>Buddies</entry>

              <entry>Children</entry>

              <entry>Adults</entry>

              <entry>Admin</entry>
            </row>

            <row>
              <entry>AlarmSystemControl</entry>

              <entry>Basic</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>Required</entry>
            </row>

            <row>
              <entry>InternetAccess</entry>

              <entry>Basic</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>Required</entry>

              <entry>-</entry>
            </row>

            <row>
              <entry>TemperatureControl</entry>

              <entry>Basic</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>Required</entry>

              <entry>-</entry>
            </row>

            <row>
              <entry>PhotoAlbumEdit</entry>

              <entry>Basic</entry>

              <entry>-</entry>

              <entry>Basic</entry>

              <entry>Basic</entry>

              <entry>-</entry>
            </row>

            <row>
              <entry>PhotoAlbumView</entry>

              <entry>Basic</entry>

              <entry>Basic</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>-</entry>
            </row>

            <row>
              <entry>PortForwarding</entry>

              <entry>Basic</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>-</entry>

              <entry>Required</entry>
            </row>

        </tgroup>

    <title>Repository Maintenance</title>

    <para>The UserAdmin interface is a straightforward API to
    maintain a repository of User and Group objects.
    It contains methods to create new Group and User
    objects with the createRole(String,int) method. The method is
    prepared so that the same signature can be used to create new types of
    roles in the future. The interface also contains a method to remove a
    Role object.</para>

    <para>The existing configuration can be obtained with methods that list
    all Role objects using a filter argument. This filter, which
    has the same syntax as the Framework filter, must only return the
    Role objects for which the filter matches the
    properties.</para>

    <para>Several utility methods simplify getting User objects
    depending on their properties.</para>

    <title>User Admin Events</title>

    <para>Changes in the User Admin service can be determined in real time.
    Each User Admin service implementation must send a
    UserAdminEvent object to any service in the Framework service
    registry that is registered under the UserAdminListener
    interface. This event must be send asynchronously from the cause of the
    event. The way events must be delivered is the same as described in
    <emphasis>Delivering Events</emphasis> of <xref
    linkend="intro.core.release" xrefstyle="template:%t"/>.</para>

    <para>This procedure is demonstrated in the following code sample.</para>

    <programlisting>class Listener implements UserAdminListener{
    public void roleChanged( UserAdminEvent event ) {
        ...
    }
}
public class MyActivator
    implements BundleActivator {
    public void start( BundleContext context ) {
        context.registerService(
            UserAdminListener.class.getName(),
            new Listener(), null );
    }
    public void stop( BundleContext context ) {}
}</programlisting>

    <para>It is not necessary to unregister the listener object when the
    bundle is stopped because the Framework automatically unregisters it. Once
    registered, the UserAdminListener object must be notified of
    all changes to the role repository.</para>

      <title>Event Admin and User Admin Change Events</title>

      <para>User Admin events must be delivered asynchronously to the Event
      Admin service by the implementation, if present. The topic of a User
      Admin Event is:</para>

      <programlisting>org/osgi/service/useradmin/UserAdmin/<eventtype></programlisting>

      <para>The following event types are supported:</para>

      <programlisting>ROLE_CREATED
ROLE_CHANGED
ROLE_REMOVED</programlisting>

      <para>All User Admin Events must have the following properties:</para>

      <itemizedlist>
        <listitem>
          <para>event - (UserAdminEvent) The event
          that was broadcast by the User Admin service.</para>
        </listitem>

        <listitem>
          <para>role - (Role) The Role
          object that was created, modified or removed.</para>
        </listitem>

        <listitem>
          <para>role.name - (String) The name of the
          role.</para>
        </listitem>

        <listitem>
          <para>role.type - (Integer) One of
          ROLE, USER or GROUP.</para>
        </listitem>

        <listitem>
          <para>service - (ServiceReference) The
          Service Reference of the User Admin service.</para>
        </listitem>

        <listitem>
          <para>service.id - (Long) The User Admin
          service's ID.</para>
        </listitem>

        <listitem>
          <para>service.objectClass - (String[]) The
          User Admin service's object class (which must include
          org.osgi.service.useradmin.UserAdmin)</para>
        </listitem>

        <listitem>
          <para>service.pid - (String) The User
          Admin service's persistent identity</para>
        </listitem>
      </itemizedlist>

    <title>Security</title>

    <para>The User Admin service is related to the security model of the OSGi
    framework, but is complementary to the <xref linkend="i1307817"/>. The
    final permission of most code should be the intersection of the Java 2
    Permissions, which are based on the code that is executing, and the User
    Admin service authorization, which is based on the user for whom the code
    runs.</para>

      <title>User Admin Permission</title>

      <para>The User Admin service defines the
      UserAdminPermission class that can be used to restrict
      bundles in accessing credentials. This permission class has the
      following actions:</para>

      <itemizedlist>
        <listitem>
          <para>changeProperty - This permission is required to
          modify properties. The name of the permission is the prefix of the
          property name.</para>
        </listitem>

        <listitem>
          <para>changeCredential - This action permits changing
          credentials. The name of the permission is the prefix of the name of
          the credential.</para>
        </listitem>

        <listitem>
          <para>getCredential - This action permits getting
          credentials. The name of the permission is the prefix of the
          credential.</para>
        </listitem>
      </itemizedlist>

      <para>If the name of the permission is "admin", it allows
      the owner to administer the repository. No action is associated with the
      permission in that case.</para>

      <para>Otherwise, the permission name is used to match the property name.
      This name may end with a ".*" string to indicate a
      wildcard. For example, com.acme.* matches
      com.acme.fudd.elmer and com.acme.bugs.</para>

    <title>Relation to JAAS</title>

    <para>At a glance, the Java Authorization and Authentication Service
    (JAAS) seems to be a very suitable model for user administration. The OSGi
    organization, however, decided to develop an independent User Admin
    service because JAAS was not deemed applicable. The reasons for this
    include dependency on Java SE version 1.3 ("JDK 1.3") and existing
    mechanisms in the previous OSGi Service Gateway 1.0 specification.</para>

      <title>JDK 1.3 Dependencies</title>

      <para>The authorization component of JAAS relies on the
      java.security.DomainCombiner interface, which provides a
      means to dynamically update the ProtectionDomain objects
      affiliated with an AccessControlContext object.</para>

      <para>This interface was added in JDK 1.3. In the context of JAAS, the
      SubjectDomainCombiner object, which implements the
      DomainCombiner interface, is used to update
      ProtectionDomain objects. The permissions of
      ProtectionDomain objects depend on where code came from and
      who signed it, with permissions based on who is running the code.</para>

      <para>Leveraging JAAS would have resulted in user-based access control
      on the OSGi framework being available only with JDK 1.3, which was not
      deemed acceptable.</para>

      <title>Existing OSGi Mechanism</title>

      <para>JAAS provides a plugable authentication architecture, which
      enables applications and their underlying authentication services to
      remain independent from each other.</para>

      <para>The Http Service already provides a similar feature by allowing
      servlet and resource registrations to be supported by an
      HttpContext object, which uses a callback mechanism to
      perform any required authentication checks before granting access to the
      servlet or resource. This way, the registering bundle has complete
      control on a per-servlet and per-resource basis over which
      authentication protocol to use, how the credentials presented by the
      remote requester are to be validated, and who should be granted access
      to the servlet or resource.</para>

      <title>Future Road Map</title>

      <para>In the future, the main barrier of 1.3 compatibility will be
      removed. JAAS could then be implemented in an OSGi environment. At that
      time, the User Admin service will still be needed and will provide
      complementary services in the following ways:</para>

      <itemizedlist>
        <listitem>
          <para>The authorization component relies on group membership
          information to be stored and managed outside JAAS. JAAS does not
          manage persistent information, so the User Admin service can be a
          provider of group information when principals are assigned to a
          Subject object.</para>
        </listitem>

        <listitem>
          <para>The authorization component allows for credentials to be
          collected and verified, but a repository is needed to actually
          validate the credentials.</para>
        </listitem>
      </itemizedlist>

      <para>In the future, the User Admin service can act as the back-end
      database to JAAS. The only aspect JAAS will remove from the User Admin
      service is the need for the Authorization interface.</para>

  <xi:include href="../../generated/javadoc/docbook/org.osgi.service.useradmin.xml"/>

    <title>References</title>

    <bibliolist>
      <bibliomixed xml:id="i1307817"><title>The Java Security Architecture for
      JDK 1.2</title>Version 1.0, Sun Microsystems, October 1998</bibliomixed>

      <bibliomixed xml:id="i1307810"><title>Java Authentication and
      Authorization Service</title><biblioid class="uri"><link
      xlink:href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/jaas/JAASRefGuide.html"/></biblioid></bibliomixed>
    </bibliolist>

</chapter>


text:
bower install
#sass --update assets/sass:app/css

redpajama_set_name: RedPajamaGithub


text:
package org.neo4j.kernel.impl.store;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.neo4j.cursor.GenericCursor;
import org.neo4j.helpers.Pair;
import org.neo4j.helpers.collection.Iterables;
import org.neo4j.helpers.collection.IteratorUtil;
import org.neo4j.io.pagecache.PageCache;
import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.io.pagecache.PagedFile;
import org.neo4j.kernel.IdGeneratorFactory;
import org.neo4j.kernel.IdType;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.store.id.IdGenerator;
import org.neo4j.kernel.impl.store.record.DynamicRecord;
import org.neo4j.kernel.impl.store.record.Record;
import org.neo4j.logging.LogProvider;

import static org.neo4j.io.pagecache.PagedFile.PF_EXCLUSIVE_LOCK;
import static org.neo4j.io.pagecache.PagedFile.PF_SHARED_LOCK;

/**
 * An abstract representation of a dynamic store. The difference between a
 * normal {@link AbstractStore} and a AbstractDynamicStore is
 * that the size of a record/entry can be dynamic.
 *

 * Instead of a fixed record this class uses blocks to store a record. If a
 * record size is greater than the block size the record will use one or more
 * blocks to store its data.
 *

 * A dynamic store don't have a {@link IdGenerator} because the position of a
 * record can't be calculated just by knowing the id. Instead one should use a
 * {@link AbstractStore} and store the start block of the record located in the
 * dynamic store. Note: This class makes use of an id generator internally for
 * managing free and non free blocks.
 *

 * Note, the first block of a dynamic store is reserved and contains information
 * about the store.
 */
public abstract class AbstractDynamicStore extends CommonAbstractStore implements RecordStore<DynamicRecord>,
        DynamicBlockSize, DynamicRecordAllocator
{
    private static final byte[] NO_DATA = new byte[0];
    // (in_use+next high)(1 byte)+nr_of_bytes(3 bytes)+next_block(int)
    public static final int BLOCK_HEADER_SIZE = 1 + 3 + 4; // = 8

    private final int blockSizeFromConfiguration;
    private int blockSize;

    public AbstractDynamicStore(
            File fileName,
            Config conf,
            IdType idType,
            IdGeneratorFactory idGeneratorFactory,
            PageCache pageCache,
            LogProvider logProvider,
            int blockSizeFromConfiguration )
    {
        super( fileName, conf, idType, idGeneratorFactory, pageCache, logProvider );
        this.blockSizeFromConfiguration = blockSizeFromConfiguration;
    }

    /**
     * Calculate the size of a dynamic record given the size of the data block.
     *
     * @param dataSize the size of the data block in bytes.
     * @return the size of a dynamic record.
     */
    public static int getRecordSize( int dataSize )
    {
        return dataSize + BLOCK_HEADER_SIZE;
    }

    @Override
    protected void initialiseNewStoreFile( PagedFile file ) throws IOException
    {
        int blockSize = blockSizeFromConfiguration;
        if ( blockSize < 1 || blockSize > 0xFFFF )
        {
            throw new IllegalArgumentException( "Illegal block size[" + blockSize + "], limit is 65535" );
        }

        blockSize += BLOCK_HEADER_SIZE;

        try ( PageCursor pageCursor = file.io( 0, PagedFile.PF_EXCLUSIVE_LOCK ) )
        {
            if ( pageCursor.next() )
            {
                do
                {
                    pageCursor.putInt( blockSize );
                }
                while ( pageCursor.shouldRetry() );
            }
        }

        File idFileName = new File( storageFileName.getPath() + ".id" );
        idGeneratorFactory.create( idFileName, 0, true );
        // TODO highestIdInUse = 0 works now, but not when slave can create store files.
        IdGenerator idGenerator = idGeneratorFactory.open( idFileName, idType, 0 );
        idGenerator.nextId(); // reserve first for blockSize
        idGenerator.close();
    }

    public static void allocateRecordsFromBytes(
            Collection<DynamicRecord> recordList, byte src[], Iterator<DynamicRecord> recordsToUseFirst,
            DynamicRecordAllocator dynamicRecordAllocator )
    {
        assert src != null : "Null src argument";
        DynamicRecord nextRecord = dynamicRecordAllocator.nextUsedRecordOrNew( recordsToUseFirst );
        int srcOffset = 0;
        int dataSize = dynamicRecordAllocator.dataSize();
        do
        {
            DynamicRecord record = nextRecord;
            record.setStartRecord( srcOffset == 0 );
            if ( src.length - srcOffset > dataSize )
            {
                byte data[] = new byte[dataSize];
                System.arraycopy( src, srcOffset, data, 0, dataSize );
                record.setData( data );
                nextRecord = dynamicRecordAllocator.nextUsedRecordOrNew( recordsToUseFirst );
                record.setNextBlock( nextRecord.getId() );
                srcOffset += dataSize;
            }
            else
            {
                byte data[] = new byte[src.length - srcOffset];
                System.arraycopy( src, srcOffset, data, 0, data.length );
                record.setData( data );
                nextRecord = null;
                record.setNextBlock( Record.NO_NEXT_BLOCK.intValue() );
            }
            recordList.add( record );
            assert !record.isLight();
            assert record.getData() != null;
        }
        while ( nextRecord != null );
    }

    /**
     * @return a {@link ByteBuffer#slice() sliced} {@link ByteBuffer} wrapping {@code target} or,
     * if necessary a new larger {@code byte[]} and containing exactly all concatenated data read from records
     */
    public static ByteBuffer concatData( Collection<DynamicRecord> records, byte[] target )
    {
        int totalLength = 0;
        for ( DynamicRecord record : records )
        {
            totalLength += record.getLength();
        }

        if ( target.length < totalLength )
        {
            target = new byte[totalLength];
        }

        ByteBuffer buffer = ByteBuffer.wrap( target, 0, totalLength );
        for ( DynamicRecord record : records )
        {
            buffer.put( record.getData() );
        }
        buffer.position( 0 );
        return buffer;
    }

    /**
     * @return Pair< header-in-first-record , all-other-bytes >
     */
    public static Pair<byte[], byte[]> readFullByteArrayFromHeavyRecords(
            Iterable<DynamicRecord> records, PropertyType propertyType )
    {
        byte[] header = null;
        List<byte[]> byteList = new ArrayList<>();
        int totalSize = 0, i = 0;
        for ( DynamicRecord record : records )
        {
            int offset = 0;
            if ( i++ == 0 )
            {   // This is the first one, read out the header separately
                header = propertyType.readDynamicRecordHeader( record.getData() );
                offset = header.length;
            }

            byteList.add( record.getData() );
            totalSize += (record.getData().length - offset);
        }
        byte[] bArray = new byte[totalSize];
        assert header != null :
                "header should be non-null since records should not be empty: " + Iterables.toString( records, ", " );
        int sourceOffset = header.length;
        int offset = 0;
        for ( byte[] currentArray : byteList )
        {
            System.arraycopy( currentArray, sourceOffset, bArray, offset,
                    currentArray.length - sourceOffset );
            offset += (currentArray.length - sourceOffset);
            sourceOffset = 0;
        }
        return Pair.of( header, bArray );
    }

    @Override
    public DynamicRecord nextUsedRecordOrNew( Iterator<DynamicRecord> recordsToUseFirst )
    {
        DynamicRecord record;
        if ( recordsToUseFirst.hasNext() )
        {
            record = recordsToUseFirst.next();
            if ( !record.inUse() )
            {
                record.setCreated();
            }
        }
        else
        {
            record = new DynamicRecord( nextId() );
            record.setCreated();
        }
        record.setInUse( true );
        return record;
    }

    @Override
    public int dataSize()
    {
        return getBlockSize() - AbstractDynamicStore.BLOCK_HEADER_SIZE;
    }

    @Override
    public int getRecordSize()
    {
        return getBlockSize();
    }

    @Override
    public int getRecordHeaderSize()
    {
        return BLOCK_HEADER_SIZE;
    }

    /**
     * We reserve the first record, record 0, to contain an integer saying how big the record size of
     * this store is. Record size of a dynamic store can be specified at creation time, and will be
     * put here and read every time the store is loaded.
     */
    @Override
    public int getNumberOfReservedLowIds()
    {
        return 1;
    }

    @Override
    protected void readAndVerifyBlockSize() throws IOException
    {
        blockSize = getHeaderRecord();
    }

    /**
     * Returns the byte size of each block for this dynamic store
     *
     * @return The block size of this store
     */
    @Override
    public int getBlockSize()
    {
        return blockSize;
    }

    @Override
    public void updateRecord( DynamicRecord record )
    {
        long blockId = record.getId();
        long pageId = pageIdForRecord( blockId );
        try ( PageCursor cursor = storeFile.io( pageId, PF_EXCLUSIVE_LOCK ) )
        {
            if ( cursor.next() )
            {
                do
                {
                    writeRecord( cursor, record );
                }
                while ( cursor.shouldRetry() );
            }
        }
        catch ( IOException e )
        {
            throw new UnderlyingStorageException( e );
        }
    }

    // [next][type][data]

    private void writeRecord( PageCursor cursor, DynamicRecord record )
    {
        long recordId = record.getId();
        int offset = offsetForId( recordId );
        cursor.setOffset( offset );
        if ( record.inUse() )
        {
            long nextBlock = record.getNextBlock();
            int highByteInFirstInteger = nextBlock == Record.NO_NEXT_BLOCK.intValue() ? 0
                    : (int) ((nextBlock & 0xF00000000L) >> 8);
            highByteInFirstInteger |= (Record.IN_USE.byteValue() << 28);
            highByteInFirstInteger |= (record.isStartRecord() ? 0 : 1) << 31;

            /*
             * First 4b
             * [x   ,    ][    ,    ][    ,    ][    ,    ] 0: start record, 1: linked record
             * [   x,    ][    ,    ][    ,    ][    ,    ] inUse
             * [    ,xxxx][    ,    ][    ,    ][    ,    ] high next block bits
             * [    ,    ][xxxx,xxxx][xxxx,xxxx][xxxx,xxxx] nr of bytes in the data field in this record
             *
             */
            int firstInteger = record.getLength();
            assert firstInteger < (1 << 24) - 1;

            firstInteger |= highByteInFirstInteger;

            cursor.putInt( firstInteger );
            cursor.putInt( (int) nextBlock );
            if ( !record.isLight() )
            {
                cursor.putBytes( record.getData() );
            }
        }
        else
        {
            cursor.putByte( Record.NOT_IN_USE.byteValue() );
            freeId( recordId );
        }
    }

    @Override
    public void forceUpdateRecord( DynamicRecord record )
    {
        updateRecord( record );
    }

    public void allocateRecordsFromBytes( Collection<DynamicRecord> target, byte src[] )
    {
        allocateRecordsFromBytes( target, src, IteratorUtil.<DynamicRecord>emptyIterator(), this );
    }

    public Collection<DynamicRecord> getLightRecords( long startBlockId )
    {
        return getRecords( startBlockId, false );
    }

    private Collection<DynamicRecord> getRecords( long startBlockId, boolean readBothHeaderAndData )
    {
        // TODO we should instead be passed in a consumer of records, so we don't have to spend memory building up
        // this list
        List<DynamicRecord> recordList = new LinkedList<>();
        long blockId = startBlockId;
        int noNextBlock = Record.NO_NEXT_BLOCK.intValue();

        try ( PageCursor cursor = storeFile.io( 0, PF_SHARED_LOCK ) )
        {
            while ( blockId != noNextBlock && cursor.next( pageIdForRecord( blockId ) ) )
            {
                DynamicRecord record = new DynamicRecord( blockId );
                HeaderReadResult headerReadResult;
                do
                {
                    cursor.setOffset( offsetForId( blockId ) );
                    headerReadResult = readRecordHeader( cursor, record, false );
                    if ( headerReadResult == HeaderReadResult.DATA && readBothHeaderAndData )
                    {
                        readRecordData( cursor, record );
                    }
                }
                while ( cursor.shouldRetry() );

                checkForInUse( headerReadResult, record );
                checkForIllegalSize( headerReadResult, record );
                recordList.add( record );
                blockId = record.getNextBlock();
            }
            return recordList;
        }
        catch ( IOException e )
        {
            throw new UnderlyingStorageException( e );
        }
    }

    public DynamicRecordCursor newDynamicRecordCursor()
    {
        return new DynamicRecordCursor();
    }

    DynamicRecordCursor getRecordsCursor( long startBlockId )
    {
        return getRecordsCursor( startBlockId, newDynamicRecordCursor() );
    }

    public DynamicRecordCursor getRecordsCursor( long startBlockId, DynamicRecordCursor dynamicRecordCursor )
    {
        try
        {
            PageCursor cursor = storeFile.io( 0, PF_SHARED_LOCK );
            dynamicRecordCursor.init( startBlockId, cursor );
            return dynamicRecordCursor;
        }
        catch ( IOException e )
        {
            throw new UnderlyingStorageException( e );
        }
    }

    private void checkForInUse( HeaderReadResult headerReadResult, DynamicRecord record )
    {
        if ( headerReadResult == HeaderReadResult.NOT_IN_USE )
        {
            throw new InvalidRecordException( "DynamicRecord not in use, blockId[" + record.getId() + "]" );
        }
    }

    private void checkForIllegalSize( HeaderReadResult headerReadResult, DynamicRecord record )
    {
        if ( headerReadResult == HeaderReadResult.ILLEGAL_SIZE )
        {
            int dataSize = getBlockSize() - AbstractDynamicStore.BLOCK_HEADER_SIZE;
            throw new InvalidRecordException( "Next block set[" + record.getNextBlock()
                    + "] current block illegal size[" + record.getLength() + "/" + dataSize +
                    "]" );
        }
    }

    /**
     * Reads data from the cursor into the given record, and returns one of the signals specified above.
     */
    private HeaderReadResult readRecordHeader( PageCursor cursor, DynamicRecord record, boolean force )
    {
        /*
         * First 4b
         * [x   ,    ][    ,    ][    ,    ][    ,    ] 0: start record, 1: linked record
         * [   x,    ][    ,    ][    ,    ][    ,    ] inUse
         * [    ,xxxx][    ,    ][    ,    ][    ,    ] high next block bits
         * [    ,    ][xxxx,xxxx][xxxx,xxxx][xxxx,xxxx] nr of bytes in the data field in this record
         *
         */
        long firstInteger = cursor.getUnsignedInt();
        boolean isStartRecord = (firstInteger & 0x80000000) == 0;
        long maskedInteger = firstInteger & ~0x80000000;
        int highNibbleInMaskedInteger = (int) ((maskedInteger) >> 28);
        boolean inUse = highNibbleInMaskedInteger == Record.IN_USE.intValue();
        if ( !inUse && !force )
        {
            return HeaderReadResult.NOT_IN_USE;
        }
        int dataSize = getBlockSize() - AbstractDynamicStore.BLOCK_HEADER_SIZE;

        int nrOfBytes = (int) (firstInteger & 0xFFFFFF);

        /*
         * Pointer to next block 4b (low bits of the pointer)
         */
        long nextBlock = cursor.getUnsignedInt();
        long nextModifier = (firstInteger & 0xF000000L) << 8;

        long longNextBlock = CommonAbstractStore.longFromIntAndMod( nextBlock, nextModifier );
        boolean hasDataToRead = true;
        record.setInUse( inUse );
        record.setStartRecord( isStartRecord );
        record.setLength( nrOfBytes );
        record.setNextBlock( longNextBlock );
        if ( longNextBlock != Record.NO_NEXT_BLOCK.intValue()
                && nrOfBytes < dataSize || nrOfBytes > dataSize )
        {
            hasDataToRead = false;
            if ( !force )
            {
                return HeaderReadResult.ILLEGAL_SIZE;
            }
        }
        return hasDataToRead ? HeaderReadResult.DATA : HeaderReadResult.NO_DATA;
    }

    private void readRecordData( PageCursor cursor, DynamicRecord record )
    {
        int len = record.getLength();
        byte[] data = record.getData();
        if ( data == null || data.length != len )
        {
            data = new byte[len];
        }
        cursor.getBytes( data );
        record.setData( data );
    }

    public void ensureHeavy( DynamicRecord record )
    {
        if ( !record.isLight() )
        {
            return;
        }
        if ( record.getLength() == 0 ) // don't go though the trouble of acquiring the window if we would read nothing
        {
            record.setData( NO_DATA );
            return;
        }

        long pageId = pageIdForRecord( record.getId() );
        try ( PageCursor cursor = storeFile.io( pageId, PF_SHARED_LOCK ) )
        {
            if ( cursor.next() )
            {
                int offset = offsetForId( record.getId() );
                do
                {
                    // Add the BLOCK_HEADER_SIZE to the offset, since we don't read it
                    cursor.setOffset( offset + BLOCK_HEADER_SIZE );
                    readRecordData( cursor, record );
                }
                while ( cursor.shouldRetry() );
            }
        }
        catch ( IOException e )
        {
            throw new UnderlyingStorageException( e );
        }
    }

    @Override
    public DynamicRecord getRecord( long id )
    {
        DynamicRecord record = new DynamicRecord( id );
        long pageId = pageIdForRecord( id );
        try ( PageCursor cursor = storeFile.io( pageId, PF_SHARED_LOCK ) )
        {
            HeaderReadResult headerReadResult = HeaderReadResult.NOT_IN_USE;
            if ( cursor.next() )
            {
                int offset = offsetForId( record.getId() );
                do
                {
                    cursor.setOffset( offset );
                    headerReadResult = readRecordHeader( cursor, record, false );
                    if ( headerReadResult == HeaderReadResult.DATA )
                    {
                        readRecordData( cursor, record );
                    }
                }
                while ( cursor.shouldRetry() );
            }

            checkForInUse( headerReadResult, record );
            checkForIllegalSize( headerReadResult, record );
            return record;
        }
        catch ( IOException e )
        {
            throw new UnderlyingStorageException( e );
        }
    }

    @Override
    public DynamicRecord forceGetRecord( long id )
    {
        DynamicRecord record = new DynamicRecord( id );
        long pageId = pageIdForRecord( id );
        try ( PageCursor cursor = storeFile.io( pageId, PF_SHARED_LOCK ) )
        {
            if ( cursor.next() )
            {
                int offset = offsetForId( record.getId() );
                HeaderReadResult headerReadResult;
                do
                {
                    cursor.setOffset( offset );
                    headerReadResult = readRecordHeader( cursor, record, true );
                    if ( headerReadResult == HeaderReadResult.DATA )
                    {
                        readRecordData( cursor, record );
                    }
                }
                while ( cursor.shouldRetry() );
                checkForIllegalSize( headerReadResult, record );
            }
            return record;
        }
        catch ( IOException e )
        {
            throw new UnderlyingStorageException( e );
        }
    }

    @Override
    public Collection<DynamicRecord> getRecords( long startBlockId )
    {
        return getRecords( startBlockId, true );
    }

    @Override
    protected boolean isInUse( byte inUseByte )
    {
        return ((inUseByte & (byte) 0x10) >> 4) == Record.IN_USE.byteValue();
    }

    @Override
    public String toString()
    {
        return super.toString() + "[fileName:" + storageFileName.getName() +
                ", blockSize:" + (getRecordSize() - getRecordHeaderSize()) + "]";
    }

    public Pair<byte[]/*header in the first record*/, byte[]/*all other bytes*/> readFullByteArray(
            Iterable<DynamicRecord> records, PropertyType propertyType )
    {
        for ( DynamicRecord record : records )
        {
            ensureHeavy( record );
        }

        return readFullByteArrayFromHeavyRecords( records, propertyType );
    }

    public class DynamicRecordCursor extends GenericCursor<DynamicRecord>
    {
        private PageCursor cursor;
        long blockId;
        int noNextBlock;

        private final DynamicRecord record = new DynamicRecord( blockId );

        public void init( long startBlockId, PageCursor cursor )
        {
            this.cursor = cursor;
            blockId = startBlockId;
            noNextBlock = Record.NO_NEXT_BLOCK.intValue();
        }

        @Override
        public boolean next()
        {
            try
            {
                if ( blockId != noNextBlock && cursor.next( pageIdForRecord( blockId ) ) )
                {
                    record.setId( blockId );

                    HeaderReadResult headerReadResult;
                    do
                    {
                        cursor.setOffset( offsetForId( blockId ) );
                        headerReadResult = readRecordHeader( cursor, record, true );
                        if ( headerReadResult == HeaderReadResult.DATA )
                        {
                            readRecordData( cursor, record );
                        }
                    }
                    while ( cursor.shouldRetry() );

                    checkForIllegalSize( headerReadResult, record );
                    current = record;
                    blockId = record.getNextBlock();
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch ( IOException e )
            {
                throw new UnderlyingStorageException( e );
            }
        }

        @Override
        public void close()
        {
            cursor.close();
            cursor = null;
        }
    }

    private enum HeaderReadResult
    {
        DATA, NO_DATA, NOT_IN_USE, ILLEGAL_SIZE
    }
}


text:
namespace messages {

MockMessageDispatcherBridge::MockMessageDispatcherBridge() = default;
MockMessageDispatcherBridge::~MockMessageDispatcherBridge() = default;

int MockMessageDispatcherBridge::MapToJavaDrawableId(int resource_id) {
  return -1;
}

void MockMessageDispatcherBridge::SetMessagesEnabledForEmbedder(
    bool messages_enabled_for_embedder) {
  messages_enabled_for_embedder_ = messages_enabled_for_embedder;
}

}  // namespace messages


text:
require 'thread'

module Puppet::Util::Puppetdb
  class Atom
    def initialize(value)
      @value = value
      @mutex = Mutex.new
    end

    def deref()
      @mutex.synchronize {
        @value
      }
    end

    def reset(value)
      @mutex.synchronize {
        @value = value
      }
    end
  end
end


text:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <parent>
    <artifactId>project</artifactId>
    <groupId>org.mortbay.jetty</groupId>
    <version>6.1.22</version>
    <relativePath>../../pom.xml</relativePath>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.mortbay.jetty</groupId>
  <artifactId>maven-jetty-jspc-plugin</artifactId>
  <packaging>maven-plugin</packaging>
  <name>Maven Jetty JSPC Plugin</name>
  <developers>
    <developer>
      <id>janb</id>
      <name>Jan Bartel</name>
      <email>janb@webtide.com</email>
      <organization>Webtide</organization>
      <organizationUrl>http://www.webtide.com</organizationUrl>
    </developer>
  </developers>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <skip>true</skip>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-plugin-plugin</artifactId>
        <executions>
          <execution>
            <id>exec-plugin-doc</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>xdoc</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-site-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>site</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
           <descriptors>
            <descriptor>src/main/assembly/site-component.xml</descriptor>
          </descriptors>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>jetty-util</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-project</artifactId>
      <version>2.0.3</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-plugin-api</artifactId>
      <version>2.0.3</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-artifact</artifactId>
      <version>2.0.3</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-plugin-tools-api</artifactId>
    </dependency>
    <dependency>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>servlet-api</artifactId>
      <version>${servlet-version}</version>
    </dependency>
  </dependencies>

  <profiles>
    <profile>
      <id>jdk1.4</id>
      <!-- Default, use JSP-2.0 and use slf4j logging. -->
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <dependencies>
        <dependency>
          <groupId>org.mortbay.jetty</groupId>
          <artifactId>jsp-2.0</artifactId>
          <version>${project.version}</version>
          <type>pom</type>
        </dependency>
      </dependencies>
    </profile>
    <profile>
      <id>jdk1.5</id>
      <!-- activated on JDK 5 and above -->
      <activation>
        <jdk>!1.4</jdk>
      </activation>
      <dependencies>
        <dependency>
          <groupId>org.mortbay.jetty</groupId>
          <artifactId>jsp-2.1-jetty</artifactId>
          <version>${project.version}</version>
        </dependency>
      </dependencies>
    </profile>
  </profiles>
</project>


text:
import AssertAgainstDynamicHelpersModifiers from './assert-against-dynamic-helpers-modifiers';
import AssertAgainstNamedBlocks from './assert-against-named-blocks';
import AssertInputHelperWithoutBlock from './assert-input-helper-without-block';
import AssertReservedNamedArguments from './assert-reserved-named-arguments';
import AssertSplattributeExpressions from './assert-splattribute-expression';
import DeprecateSendAction from './deprecate-send-action';
import DeprecateWith from './deprecate-with';
import TransformActionSyntax from './transform-action-syntax';
import TransformAttrsIntoArgs from './transform-attrs-into-args';
import TransformEachInIntoEach from './transform-each-in-into-each';
import TransformEachTrackArray from './transform-each-track-array';
import TransformHasBlockSyntax from './transform-has-block-syntax';
import TransformInElement from './transform-in-element';
import TransformLinkTo from './transform-link-to';
import TransformOldClassBindingSyntax from './transform-old-class-binding-syntax';
import TransformQuotedBindingsIntoJustBindings from './transform-quoted-bindings-into-just-bindings';
import TransformResolutions from './transform-resolutions';
import TransformWrapMountAndOutlet from './transform-wrap-mount-and-outlet';

import { EMBER_DYNAMIC_HELPERS_AND_MODIFIERS, EMBER_NAMED_BLOCKS } from '@ember/canary-features';
import { SEND_ACTION } from '@ember/deprecated-features';

// order of plugins is important
export const RESOLUTION_MODE_TRANSFORMS = Object.freeze(
  [
    TransformOldClassBindingSyntax,
    TransformQuotedBindingsIntoJustBindings,
    AssertReservedNamedArguments,
    TransformActionSyntax,
    TransformAttrsIntoArgs,
    TransformEachInIntoEach,
    TransformHasBlockSyntax,
    TransformLinkTo,
    AssertInputHelperWithoutBlock,
    TransformInElement,
    AssertSplattributeExpressions,
    TransformEachTrackArray,
    TransformWrapMountAndOutlet,
    DeprecateWith,
    SEND_ACTION ? DeprecateSendAction : null,
    !EMBER_NAMED_BLOCKS ? AssertAgainstNamedBlocks : null,
    EMBER_DYNAMIC_HELPERS_AND_MODIFIERS
      ? TransformResolutions
      : AssertAgainstDynamicHelpersModifiers,
  ].filter(notNull)
);

export const STRICT_MODE_TRANSFORMS = Object.freeze(
  [
    TransformQuotedBindingsIntoJustBindings,
    AssertReservedNamedArguments,
    TransformActionSyntax,
    TransformEachInIntoEach,
    TransformInElement,
    AssertSplattributeExpressions,
    TransformEachTrackArray,
    TransformWrapMountAndOutlet,
    DeprecateWith,
    SEND_ACTION ? DeprecateSendAction : null,
    !EMBER_NAMED_BLOCKS ? AssertAgainstNamedBlocks : null,
    !EMBER_DYNAMIC_HELPERS_AND_MODIFIERS ? AssertAgainstDynamicHelpersModifiers : null,
  ].filter(notNull)
);

function notNull<TValue>(value: TValue | null): value is TValue {
  return value !== null;
}


text:
package org.elasticsearch.indices;

import org.elasticsearch.tasks.TaskResultsService;
import org.elasticsearch.test.ESTestCase;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.elasticsearch.tasks.TaskResultsService.TASK_INDEX;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;

public class SystemIndicesTests extends ESTestCase {

    public void testBasicOverlappingPatterns() {
        SystemIndexDescriptor broadPattern = new SystemIndexDescriptor(".a*c*", "test");
        SystemIndexDescriptor notOverlapping = new SystemIndexDescriptor(".bbbddd*", "test");
        SystemIndexDescriptor overlapping1 = new SystemIndexDescriptor(".ac*", "test");
        SystemIndexDescriptor overlapping2 = new SystemIndexDescriptor(".aaaabbbccc", "test");
        SystemIndexDescriptor overlapping3 = new SystemIndexDescriptor(".aaabb*cccddd*", "test");

        // These sources have fixed prefixes to make sure they sort in the same order, so that the error message is consistent
        // across tests
        String broadPatternSource = "AAA" + randomAlphaOfLength(5);
        String otherSource = "ZZZ" + randomAlphaOfLength(6);
        Map<String, Collection<SystemIndexDescriptor>> descriptors = new HashMap<>();
        descriptors.put(broadPatternSource, List.of(broadPattern));
        descriptors.put(otherSource, List.of(notOverlapping, overlapping1, overlapping2, overlapping3));

        IllegalStateException exception = expectThrows(IllegalStateException.class,
            () -> SystemIndices.checkForOverlappingPatterns(descriptors));
        assertThat(exception.getMessage(), containsString("a system index descriptor [" + broadPattern +
            "] from [" + broadPatternSource + "] overlaps with other system index descriptors:"));
        String fromPluginString = " from [" + otherSource + "]";
        assertThat(exception.getMessage(), containsString(overlapping1.toString() + fromPluginString));
        assertThat(exception.getMessage(), containsString(overlapping2.toString() + fromPluginString));
        assertThat(exception.getMessage(), containsString(overlapping3.toString() + fromPluginString));
        assertThat(exception.getMessage(), not(containsString(notOverlapping.toString())));

        IllegalStateException constructorException = expectThrows(IllegalStateException.class, () -> new SystemIndices(descriptors));
        assertThat(constructorException.getMessage(), equalTo(exception.getMessage()));
    }

    public void testComplexOverlappingPatterns() {
        // These patterns are slightly more complex to detect because pattern1 does not match pattern2 and vice versa
        SystemIndexDescriptor pattern1 = new SystemIndexDescriptor(".a*c", "test");
        SystemIndexDescriptor pattern2 = new SystemIndexDescriptor(".ab*", "test");

        // These sources have fixed prefixes to make sure they sort in the same order, so that the error message is consistent
        // across tests
        String source1 = "AAA" + randomAlphaOfLength(5);
        String source2 = "ZZZ" + randomAlphaOfLength(6);
        Map<String, Collection<SystemIndexDescriptor>> descriptors = new HashMap<>();
        descriptors.put(source1, List.of(pattern1));
        descriptors.put(source2, List.of(pattern2));

        IllegalStateException exception = expectThrows(IllegalStateException.class,
            () -> SystemIndices.checkForOverlappingPatterns(descriptors));
        assertThat(exception.getMessage(), containsString("a system index descriptor [" + pattern1 +
            "] from [" + source1 + "] overlaps with other system index descriptors:"));
        assertThat(exception.getMessage(), containsString(pattern2.toString() + " from [" + source2 + "]"));

        IllegalStateException constructorException = expectThrows(IllegalStateException.class, () -> new SystemIndices(descriptors));
        assertThat(constructorException.getMessage(), equalTo(exception.getMessage()));
    }

    public void testBuiltInSystemIndices() {
        SystemIndices systemIndices = new SystemIndices(Map.of());
        assertTrue(systemIndices.isSystemIndex(".tasks"));
        assertTrue(systemIndices.isSystemIndex(".tasks1"));
        assertTrue(systemIndices.isSystemIndex(".tasks-old"));
    }

    public void testPluginCannotOverrideBuiltInSystemIndex() {
        Map<String, Collection<SystemIndexDescriptor>> pluginMap = Map.of(
            TaskResultsService.class.getName(), List.of(new SystemIndexDescriptor(TASK_INDEX, "Task Result Index"))
        );
        IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> new SystemIndices(pluginMap));
        assertThat(e.getMessage(), containsString("plugin or module attempted to define the same source"));
    }

    public void testPatternWithSimpleRange() {

        final SystemIndices systemIndices = new SystemIndices(Map.of("test", List.of(new SystemIndexDescriptor(".test-[abc]", ""))));

        assertThat(systemIndices.isSystemIndex(".test-a"), equalTo(true));
        assertThat(systemIndices.isSystemIndex(".test-b"), equalTo(true));
        assertThat(systemIndices.isSystemIndex(".test-c"), equalTo(true));

        assertThat(systemIndices.isSystemIndex(".test-aa"), equalTo(false));
        assertThat(systemIndices.isSystemIndex(".test-d"), equalTo(false));
        assertThat(systemIndices.isSystemIndex(".test-"), equalTo(false));
        assertThat(systemIndices.isSystemIndex(".test-="), equalTo(false));
    }

    public void testPatternWithSimpleRangeAndRepeatOperator() {
        final SystemIndices systemIndices = new SystemIndices(Map.of("test", List.of(new SystemIndexDescriptor(".test-[a]+", ""))));

        assertThat(systemIndices.isSystemIndex(".test-a"), equalTo(true));
        assertThat(systemIndices.isSystemIndex(".test-aa"), equalTo(true));
        assertThat(systemIndices.isSystemIndex(".test-aaa"), equalTo(true));

        assertThat(systemIndices.isSystemIndex(".test-b"), equalTo(false));
    }

    public void testPatternWithComplexRange() {
        final SystemIndices systemIndices = new SystemIndices(Map.of("test", List.of(new SystemIndexDescriptor(".test-[a-c]", ""))));

        assertThat(systemIndices.isSystemIndex(".test-a"), equalTo(true));
        assertThat(systemIndices.isSystemIndex(".test-b"), equalTo(true));
        assertThat(systemIndices.isSystemIndex(".test-c"), equalTo(true));

        assertThat(systemIndices.isSystemIndex(".test-aa"), equalTo(false));
        assertThat(systemIndices.isSystemIndex(".test-d"), equalTo(false));
        assertThat(systemIndices.isSystemIndex(".test-"), equalTo(false));
        assertThat(systemIndices.isSystemIndex(".test-="), equalTo(false));
    }

    public void testOverlappingDescriptorsWithRanges() {
        String source1 = "source1";
        String source2 = "source2";

        SystemIndexDescriptor pattern1 = new SystemIndexDescriptor(".test-[ab]*", "");
        SystemIndexDescriptor pattern2 = new SystemIndexDescriptor(".test-a*", "");

        Map<String, Collection<SystemIndexDescriptor>> descriptors = new HashMap<>();
        descriptors.put(source1, List.of(pattern1));
        descriptors.put(source2, List.of(pattern2));

        IllegalStateException exception = expectThrows(IllegalStateException.class,
            () -> SystemIndices.checkForOverlappingPatterns(descriptors));

        assertThat(exception.getMessage(), containsString("a system index descriptor [" + pattern1 +
            "] from [" + source1 + "] overlaps with other system index descriptors:"));

        assertThat(exception.getMessage(), containsString(pattern2.toString() + " from [" + source2 + "]"));
    }
}


text:
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Code generated by Microsoft (R) AutoRest Code Generator.

package com.azure.resourcemanager.consumption.fluent;

import com.azure.core.annotation.ReturnType;
import com.azure.core.annotation.ServiceMethod;
import com.azure.core.http.rest.PagedIterable;
import com.azure.core.util.Context;
import com.azure.resourcemanager.consumption.fluent.models.ReservationRecommendationInner;

/** An instance of this class provides access to all the operations defined in ReservationRecommendationsClient. */
public interface ReservationRecommendationsClient {
    /**
     * List of recommendations for purchasing reserved instances.
     *
     * @param scope The scope associated with reservation recommendations operations. This includes
     *     '/subscriptions/{subscriptionId}/' for subscription scope,
     *     '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}' for resource group scope,
     *     '/providers/Microsoft.Billing/billingAccounts/{billingAccountId}' for BillingAccount scope, and
     *     '/providers/Microsoft.Billing/billingAccounts/{billingAccountId}/billingProfiles/{billingProfileId}' for
     *     billingProfile scope.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws com.azure.core.management.exception.ManagementException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return result of listing reservation recommendations.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    PagedIterable<ReservationRecommendationInner> list(String scope);

    /**
     * List of recommendations for purchasing reserved instances.
     *
     * @param scope The scope associated with reservation recommendations operations. This includes
     *     '/subscriptions/{subscriptionId}/' for subscription scope,
     *     '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}' for resource group scope,
     *     '/providers/Microsoft.Billing/billingAccounts/{billingAccountId}' for BillingAccount scope, and
     *     '/providers/Microsoft.Billing/billingAccounts/{billingAccountId}/billingProfiles/{billingProfileId}' for
     *     billingProfile scope.
     * @param filter May be used to filter reservationRecommendations by: properties/scope with allowed values
     *     ['Single', 'Shared'] and default value 'Single'; properties/resourceType with allowed values
     *     ['VirtualMachines', 'SQLDatabases', 'PostgreSQL', 'ManagedDisk', 'MySQL', 'RedHat', 'MariaDB', 'RedisCache',
     *     'CosmosDB', 'SqlDataWarehouse', 'SUSELinux', 'AppService', 'BlockBlob', 'AzureDataExplorer',
     *     'VMwareCloudSimple'] and default value 'VirtualMachines'; and properties/lookBackPeriod with allowed values
     *     ['Last7Days', 'Last30Days', 'Last60Days'] and default value 'Last7Days'.
     * @param context The context to associate with this operation.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws com.azure.core.management.exception.ManagementException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return result of listing reservation recommendations.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    PagedIterable<ReservationRecommendationInner> list(String scope, String filter, Context context);
}


text:
namespace shp {

VALUE dbf::_klass = Qnil;

VALUE dbf::klass() {
  return dbf::_klass;
}

dbf::dbf(DBFHandle handle)
  : _handle(handle)
{
}

dbf::~dbf() {
  if (_handle) {
    DBFClose(_handle);
    _handle = NULL;
  }
}

VALUE dbf::create(VALUE klass, VALUE filename)
{
  CHECK_ARGUMENT_STRING(filename);

  DBFHandle handle = DBFCreate(RSTRING_PTR(filename));

  if (handle == NULL) {
    SHP_FATAL("Failed to create dbf file.");
    return Qnil;
  }

  dbf *file = new dbf(handle);

  return file->wrapped();
}

VALUE dbf::open(VALUE klass, VALUE filename, VALUE access)
{
  CHECK_ARGUMENT_STRING(filename);
  CHECK_ARGUMENT_STRING(access);

  DBFHandle handle = DBFOpen(RSTRING_PTR(filename), RSTRING_PTR(access));

  if (handle == NULL) {
    SHP_FATAL("Failed to open dbf file.");
    return Qnil;
  }

  dbf *file = new dbf(handle);

  return file->wrapped();
}

VALUE dbf::add_field(VALUE self, VALUE fieldName, VALUE fieldType, VALUE fieldWidth, VALUE fieldDecimals)
{
  CHECK_ARGUMENT_STRING(fieldName);
  CHECK_ARGUMENT_FIXNUM(fieldType);
  CHECK_ARGUMENT_FIXNUM(fieldWidth);
  CHECK_ARGUMENT_FIXNUM(fieldDecimals);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  std::string theFieldName(RSTRING_PTR(fieldName));

  int result = DBFAddField(db->value(),
                           theFieldName.c_str(),
                           (DBFFieldType)FIX2INT(fieldType),
                           FIX2INT(fieldWidth),
                           FIX2INT(fieldDecimals));

  if (result == -1) {
    SHP_FATAL("Failed to add new field");
    return Qnil;
  }

  return INT2FIX(result);
}

VALUE dbf::write_integer_attribute(VALUE self, VALUE recordNumber, VALUE fieldIndex, VALUE fieldValue)
{
  CHECK_ARGUMENT_FIXNUM(recordNumber);
  CHECK_ARGUMENT_FIXNUM(fieldIndex);
  CHECK_ARGUMENT_FIXNUM(fieldValue);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  int result = DBFWriteIntegerAttribute(db->value(),
                                        FIX2INT(recordNumber),
                                        FIX2INT(fieldIndex),
                                        FIX2INT(fieldValue));

  if (result == 0) {
    SHP_FATAL("Failed to write new attribute.");
    return Qnil;
  }

  return INT2FIX(result);
}

VALUE dbf::write_double_attribute(VALUE self, VALUE recordNumber, VALUE fieldIndex, VALUE fieldValue)
{
  CHECK_ARGUMENT_FIXNUM(recordNumber);
  CHECK_ARGUMENT_FIXNUM(fieldIndex);
  CHECK_ARGUMENT_FLOAT(fieldValue);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  int result = DBFWriteDoubleAttribute(db->value(),
                                       FIX2INT(recordNumber),
                                       FIX2INT(fieldIndex),
                                       NUM2DBL(fieldValue));

  if (result == 0) {
    SHP_FATAL("Failed to write new attribute.");
    return Qnil;
  }

  return INT2FIX(result);
}

VALUE dbf::write_string_attribute(VALUE self, VALUE recordNumber, VALUE fieldIndex, VALUE fieldValue)
{
  CHECK_ARGUMENT_FIXNUM(recordNumber);
  CHECK_ARGUMENT_FIXNUM(fieldIndex);
  CHECK_ARGUMENT_STRING(fieldValue);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  int result = DBFWriteStringAttribute(db->value(),
                                       FIX2INT(recordNumber),
                                       FIX2INT(fieldIndex),
                                       RSTRING_PTR(fieldValue));

  if (result == 0) {
    SHP_FATAL("Failed to write new attribute.");
    return Qnil;
  }

  return INT2FIX(result);
}

VALUE dbf::write_null_attribute(VALUE self, VALUE recordNumber, VALUE fieldIndex)
{
  CHECK_ARGUMENT_FIXNUM(recordNumber);
  CHECK_ARGUMENT_FIXNUM(fieldIndex);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  int result = DBFWriteNULLAttribute(db->value(),
                                     FIX2INT(recordNumber),
                                     FIX2INT(fieldIndex));

  if (result == 0) {
    SHP_FATAL("Failed to write new attribute.");
    return Qnil;
  }

  return INT2FIX(result);
}

VALUE dbf::read_integer_attribute(VALUE self, VALUE recordIndex, VALUE fieldIndex)
{
  CHECK_ARGUMENT_FIXNUM(recordIndex);
  CHECK_ARGUMENT_FIXNUM(fieldIndex);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  int result = DBFReadIntegerAttribute(db->value(),
                                       FIX2INT(recordIndex),
                                       FIX2INT(fieldIndex));

  return INT2FIX(result);
}

VALUE dbf::read_double_attribute(VALUE self, VALUE recordIndex, VALUE fieldIndex)
{
  CHECK_ARGUMENT_FIXNUM(recordIndex);
  CHECK_ARGUMENT_FIXNUM(fieldIndex);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  double result = DBFReadDoubleAttribute(db->value(),
                                         FIX2INT(recordIndex),
                                         FIX2INT(fieldIndex));

  return rb_float_new(result);
}

VALUE dbf::read_string_attribute(VALUE self, VALUE recordIndex, VALUE fieldIndex)
{
  CHECK_ARGUMENT_FIXNUM(recordIndex);
  CHECK_ARGUMENT_FIXNUM(fieldIndex);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  const char *result = DBFReadStringAttribute(db->value(),
                                              FIX2INT(recordIndex),
                                              FIX2INT(fieldIndex));

  return rb_str_new2(result);
}

VALUE dbf::is_attribute_null(VALUE self, VALUE recordIndex, VALUE fieldIndex)
{
  CHECK_ARGUMENT_FIXNUM(recordIndex);
  CHECK_ARGUMENT_FIXNUM(fieldIndex);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  int result = DBFIsAttributeNULL(db->value(),
                                  FIX2INT(recordIndex),
                                  FIX2INT(fieldIndex));

  return INT2NUM(result);
}

VALUE dbf::close(VALUE self)
{
  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  DBFClose(db->value());

  db->_handle = NULL;

  return Qnil;
}

VALUE dbf::get_field_count(VALUE self)
{
  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  int fieldCount = DBFGetFieldCount(db->value());

  return INT2FIX(fieldCount);
}

VALUE dbf::get_record_count(VALUE self)
{
  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  int recordCount = DBFGetRecordCount(db->value());

  return INT2FIX(recordCount);
}

VALUE dbf::get_field_index(VALUE self, VALUE fieldName)
{
  CHECK_ARGUMENT_STRING(fieldName);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  int fieldIndex = DBFGetFieldIndex(db->value(), RSTRING_PTR(fieldName));

  return INT2FIX(fieldIndex);
}

VALUE dbf::get_field_info(VALUE self, VALUE fieldIndex)
{
  CHECK_ARGUMENT_FIXNUM(fieldIndex);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  char fieldName[12];
  int fieldWidth = -1;
  int fieldDecimals = -1;

  DBFFieldType type = DBFGetFieldInfo(db->value(),
                                      FIX2INT(fieldIndex),
                                      fieldName,
                                      &fieldWidth,
                                      &fieldDecimals);

  VALUE hash = rb_hash_new();

  rb_hash_aset(hash, ID2SYM(rb_intern("name")), rb_str_new2(fieldName));
  rb_hash_aset(hash, ID2SYM(rb_intern("type")), INT2FIX((int)type));
  rb_hash_aset(hash, ID2SYM(rb_intern("width")), INT2FIX(fieldWidth));
  rb_hash_aset(hash, ID2SYM(rb_intern("decimals")), INT2FIX(fieldDecimals));

  return hash;
}

VALUE dbf::is_record_deleted(VALUE self, VALUE recordIndex)
{
  CHECK_ARGUMENT_FIXNUM(recordIndex);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  int result = DBFIsRecordDeleted(db->value(), FIX2INT(recordIndex));

  return INT2FIX(result);
}

VALUE dbf::mark_record_deleted(VALUE self, VALUE recordIndex, VALUE isDeleted)
{
  CHECK_ARGUMENT_FIXNUM(recordIndex);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  int result = DBFMarkRecordDeleted(db->value(), FIX2INT(recordIndex), FIX2INT(isDeleted));

  return INT2FIX(result);
}

VALUE dbf::get_native_field_type(VALUE self, VALUE fieldIndex)
{
  CHECK_ARGUMENT_FIXNUM(fieldIndex);

  dbf *db = unwrap(self);

  CHECK_VALID_HANDLE(db->value());

  char result = DBFGetNativeFieldType(db->value(), FIX2INT(fieldIndex));

  char resultAsString[2] = { result, '\0' };

  return rb_str_new2(resultAsString);
}

void dbf::define(VALUE module)
{
  dbf::_klass = rb_define_class_under(module, "DBF", rb_cObject);
  base::define(dbf::_klass, false);
  rb_define_singleton_method(dbf::_klass, "create", SHP_METHOD(dbf::create), 1);
  rb_define_singleton_method(dbf::_klass, "open", SHP_METHOD(dbf::open), 2);
  rb_define_method(dbf::_klass, "add_field", SHP_METHOD(dbf::add_field), 4);
  rb_define_method(dbf::_klass, "write_integer_attribute", SHP_METHOD(dbf::write_integer_attribute), 3);
  rb_define_method(dbf::_klass, "write_double_attribute", SHP_METHOD(dbf::write_double_attribute), 3);
  rb_define_method(dbf::_klass, "write_string_attribute", SHP_METHOD(dbf::write_string_attribute), 3);
  rb_define_method(dbf::_klass, "write_null_attribute", SHP_METHOD(dbf::write_null_attribute), 2);
  rb_define_method(dbf::_klass, "read_integer_attribute", SHP_METHOD(dbf::read_integer_attribute), 2);
  rb_define_method(dbf::_klass, "read_double_attribute", SHP_METHOD(dbf::read_double_attribute), 2);
  rb_define_method(dbf::_klass, "read_string_attribute", SHP_METHOD(dbf::read_string_attribute), 2);
  rb_define_method(dbf::_klass, "is_attribute_null", SHP_METHOD(dbf::is_attribute_null), 2);
  rb_define_method(dbf::_klass, "close", SHP_METHOD(dbf::close), 0);
  rb_define_method(dbf::_klass, "get_field_count", SHP_METHOD(dbf::get_field_count), 0);
  rb_define_method(dbf::_klass, "get_record_count", SHP_METHOD(dbf::get_record_count), 0);
  rb_define_method(dbf::_klass, "get_field_index", SHP_METHOD(dbf::get_field_index), 1);
  rb_define_method(dbf::_klass, "get_field_info", SHP_METHOD(dbf::get_field_info), 1);
  rb_define_method(dbf::_klass, "is_record_deleted", SHP_METHOD(dbf::is_record_deleted), 1);
  rb_define_method(dbf::_klass, "mark_record_deleted", SHP_METHOD(dbf::mark_record_deleted), 2);
  rb_define_method(dbf::_klass, "get_native_field_type", SHP_METHOD(dbf::get_native_field_type), 1);
}

}


text:
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/main</item>
        <item name="colorPrimaryDark">@color/darkGray</item>
        <item name="colorAccent">@color/gray</item>
        <item name="actionMenuTextColor">@color/white</item>
    </style>

    <style name="AppTheme.NoActionBar" parent="AppTheme">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.NoActionBar.TransparentStatusBar">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowContentOverlay">@null</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

    <style name="PagerTabStripText">
        <item name="android:textSize">18sp</item>
        <item name="android:textStyle">bold</item>
        <item name="android:fontFamily">@font/montserrat_extra_bold_ttf</item>
        <item name="android:textColor">@color/white</item>
    </style>

    <style name="PrefTitleText">
        <item name="android:fontFamily">@font/roboto_medium</item>
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/black</item>
    </style>

    <style name="PrefSecondaryText">
        <item name="android:fontFamily">@font/montserrat</item>
        <item name="android:textSize">12sp</item>
    </style>

    <style name="PrefSecondaryTextState">
        <item name="android:fontFamily">@font/montserrat</item>
        <item name="android:textSize">12sp</item>
        <item name="android:textColor">@color/mainDark</item>
    </style>

    <style name="WelcomeText">
        <item name="android:fontFamily">@font/muli</item>
        <item name="android:textSize">@dimen/title_font_size</item>
        <item name="android:lineHeight">20dp</item>
        <item name="android:textColor">@color/white</item>
        <item name="android:textStyle">bold</item>
        <item name="android:gravity">center</item>
        <item name="android:textAlignment">center</item>
        <item name="android:layout_width">300dp</item>
    </style>

    <style name="SplashTheme" parent="AppTheme.NoActionBar.TransparentStatusBar">
        <item name="android:windowBackground">@drawable/splash</item>
    </style>

    <style name="checkBoxStyle" parent="Base.Theme.AppCompat">
        <item name="colorAccent">@color/main</item>
        <item name="android:textColorSecondary">@color/inactive</item>
    </style>

    <style name="TextViewLink">
        <item name="android:autoLink">web</item>
        <item name="android:linksClickable">true</item>
        <item name="android:textColorLink">@color/href</item>
    </style>

    <style name="roundButton">
        <item name="android:background">@drawable/button_rounded_corners</item>
        <item name="android:textColor">@color/white</item>
        <item name="android:fontFamily">@font/montserrat_bold</item>
        <item name="android:paddingLeft">8dp</item>
        <item name="android:paddingRight">8dp</item>
        <item name="android:textSize">12sp</item>
    </style>

    <style name="sensorSettingInfoTitleStyle">
        <item name="android:fontFamily">@font/roboto_medium</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">wrap_content</item>
        <item name="android:padding">@dimen/tag_settings_text_padding</item>
        <item name="android:textAppearance">@style/TextAppearance.AppCompat.Title</item>
        <item name="android:textSize">16sp</item>
    </style>

    <style name="sensorSettingInfoValueStyle">
        <item name="android:gravity">end</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">0dp</item>
        <item name="android:padding">@dimen/tag_settings_text_padding</item>
        <item name="android:textSize">16sp</item>
    </style>

    <style name="CustomAlertDialog" parent="Theme.AppCompat.Light.Dialog.Alert">
        <item name="android:windowBackground">@drawable/rounded_layout</item>
    </style>
</resources>


text:
#include <stdio.h>
#include <stdlib.h>

#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>

#include <string.h>

int
readn(int sfd, char * const data, size_t* dsize)
{
    ssize_t n;
    size_t total = 0;
    size_t bytesleft = *dsize;

    while(total < *dsize)
    {
        n = recv(sfd, data + total, bytesleft, MSG_NOSIGNAL);
        if(-1 == n || 0 == n)
        {
            break;
        }
        total += n;
        bytesleft -= n;
    }

    *dsize = total;
    data[total] = '\0';

    return n > 0 ? (int) total : n;
}

int main(void) {
    int sockfd, newsockfd;
    uint16_t portno;
    unsigned int clilen;
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    ssize_t n;

    /* First call to socket() function */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if (sockfd < 0) {
        perror("ERROR opening socket");
        exit(1);
    }

    /* Initialize socket structure */
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = 5001;

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);

    /* Now bind the host address using bind() call.*/
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        perror("ERROR on binding");
        exit(1);
    }

    /* Now start listening for the clients, here process will
       * go in sleep mode and will wait for the incoming connection
    */

    listen(sockfd, 5);
    clilen = sizeof(cli_addr);

    /* Accept actual connection from the client */
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    shutdown(sockfd, SHUT_RDWR);
    close(sockfd);

    if (newsockfd < 0) {
        perror("ERROR on accept");
        exit(1);
    }

    /* If connection is established then start communicating */
    size_t limit = 255;
    if(-1 == readn(newsockfd, buffer, &limit))
    {
        fprintf(stderr, "Was read %ld bytes, but recv() failed:\n\t ", limit);
        perror("");
        exit(1);
    }
    shutdown(newsockfd, SHUT_RD);

    printf("Here is the message: %s\n", buffer);

    /* Write a response to the client */
    n = write(newsockfd, "I got your message", 18); // send on Windows
    shutdown(newsockfd, SHUT_WR);

    if (n < 0) {
        perror("ERROR writing to socket");
        exit(1);
    }

    close(newsockfd);

    return 0;
}


text:
<?php

namespace RunOpenCode\AssetsInjection\Resource;

use RunOpenCode\AssetsInjection\Contract\ResourceInterface;

abstract class AbstractResource implements ResourceInterface
{
    /**
     * @var string
     */
    protected $source;

    /**
     * @var string
     */
    protected $sourceRoot;

    /**
     * @var array
     */
    protected $options;

    /**
     * @var integer
     */
    protected $lastModified;

    /**
     * Default constructor.
     *
     * @param string $source Source for this resource.
     * @param array $options Options related to this resource.
     * @param string|null $sourceRoot Resource root path.
     * @param integer|null $lastModified Unix timestamp of last modification date of this resource.
     */
    public function __construct($source, array $options = [], $sourceRoot = null, $lastModified = null)
    {
        $this->source = $source;
        $this->sourceRoot = $sourceRoot;
        $this->options = $options;
        $this->lastModified = $lastModified;
    }

    public function getKey()
    {
        return md5($this->source);
    }

    /**
     * {@inheritdoc}
     */
    public function getSource()
    {
        return $this->source;
    }

    /**
     * {@inheritdoc}
     */
    public function getSourceRoot()
    {
        return $this->sourceRoot;
    }

    /**
     * {@inheritdoc}
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * {@inheritdoc}
     */
    public function getLastModified()
    {
        return $this->lastModified;
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        return $this->getSource();
    }
}


text:
package ca.fiset.dirdup.copy;

import java.io.File;
import java.util.List;

public interface DirectoryItem {

	List<String> getPath();

	String getName();

	File getEntry();

	String getPathAndName();

	String getSourcePathAndName();
}