Search.java
/*
** Module : Search.java
** Abstract : Represents open rights searches.
**
** Copyright (c) 2004-2023, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- ----------------Description----------------------
** 001 NVS 20050322 @20455 Created the initial version. This class
** represents open rights searches.
** 002 NVS 20061009 @30250 Resource instance names are assumed to be
** case insensitive for now, if they are given
** as EXACT.
** 003 CA 20090610 @42630 Bindings with 'all-others' as subject have
** lower priority then bindings with an explicit
** subject ID.
** 004 NVS 20090625 @42943 Opening a search collects all relevant bindings,
** according to the new ACL style.
** 005 CA 20110105 Fixed handle calculation in c'tor (it must sync
** on the class object not on the new instance).
** 006 IAS 20150217 Added check for null acls
** 007 GES 20160222 Fix for NPE.
** 008 HC 20230427 Implemented management for file-system resource. This includes Admin
** and server directory changes.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.security;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
/**
* Represents open seaches initiated by calls to openRightsSearch().
*/
class Search
{
/** handle generator */
private static int handles = 0;
/** handle of this instance */
private int handle = 0;
/** resource instance name */
private String instanceName = null;
/** access mode AKA requested rights */
private int mode = 0;
/** array of subject IDs associated with this search */
private int[] checkList = null;
/** list of bindings found for this resource */
private List bindings = null;
/** index of the last returned item from the array or -1 if never */
private int lastUsed = -1;
/**
* Package private constructor.
*
* @param instance
* resource instance name
*
* @param mode
* resource access mode
*
* @param checkList
* array of subject IDs to open this search with
*
* @param acls
* stream of ACLs to find the resource instance
*/
Search(String instance,
int mode,
int[] checkList,
Stream<AccessControlList> acls)
{
synchronized(Search.class)
{
if (handles == Integer.MAX_VALUE)
{
handles = 1;
}
else
{
handles++;
}
this.handle = handles;
}
this.instanceName = instance;
this.mode = mode;
this.checkList = checkList;
// denied if there are no ACLs to process
if (acls == null)
{
return;
}
bindings = new LinkedList();
acls.forEach(acl -> bindings.addAll(acl.getBindings()));
}
/**
* Gets the handle of this search.
*
* @return handle of this search
*/
int getHandle()
{
return handle;
}
/**
* Gets the resource instance name of this search.
*
* @return resource instance name
*/
String getInstanceName()
{
return instanceName;
}
/**
* Gets the resource access mode of this search.
*
* @return resource access mode
*/
int getMode()
{
return mode;
}
/**
* Gets the next Rights object from the list of bindings.
* <p>
* Search is done in the order of subject IDs in the check list. The next
* unchecked ID is selected and the whole list of bindings is searched for
* a matching subject ID. If no matching entry exists, the next subject ID
* from the check list is checked and so on until either a matching ID
* is found or the end of the check list is reached.
* <p>
* If a matching binding is found for an ID, its index is saved so that the
* next call would start the search from the next unchecked ID.
* <p>
* When determining if a binding matches the current subject, bindings with
* 'all-others' among their subjects (-2 subject ID) have lower priority
* then bindings with explicit checklist subject. If no explicit binding
* found, it will return the first binding with 'all-others' among its
* subjects.
*
* @return <code>Rights</code> object or null
*/
Rights next()
{
if (bindings == null || bindings.isEmpty())
return null;
// loop through the array of subject IDs
int startPos = lastUsed + 1;
int sid = 0;
Binding bind = null;
int i = 0;
Iterator iter = null;
Rights allOthersRights = null;
for (i = startPos; i < checkList.length; i ++)
{
sid = checkList[i];
iter = bindings.iterator();
while (iter.hasNext())
{
bind = (Binding)iter.next();
if (bind.matches(sid))
{
if (bind.matches(-2))
{
if (allOthersRights == null)
{
// save only first encountered binding which matches
// 'all-others'
lastUsed = i;
allOthersRights = bind.getRights();
}
// if this is not the first binding with 'all-others',
// ignore it
}
else
{
// if some binding doesn't match all-others, get the rights
lastUsed = i;
return bind.getRights();
}
}
}
}
// return the first binding with 'all-others' as subject or null, if
// none found
return allOthersRights;
}
}