Well basically, I was coding earlier and I encountered this

for(int i = 0; i<acl.size();i++){
            //System.out.println(acl.get(i));
            if(acl.get(i).contains(role)){
                permissions = acl.get(i).split(":");
                if(permissions[operation].equals("yes")) return true;
            }
        }

and I was getting index out of boundary exception, but I knew that wasn't the case so I decided to use a for loop to print out the entire content of permissions. Well surprisingly it worked ... so I did this instead to fix my code because I had no better idea what is the reason for my earlier version to fail

for(int i = 0; i<acl.size();i++){
            //System.out.println(acl.get(i));
            if(acl.get(i).contains(role)){
                permissions = acl.get(i).split(":");
                for(int j = 0; j<permissions.length;j++)
                    if(j==operation)
                        //System.out.println(permissions[operation]);
                        if(permissions[operation].equals("yes")) return true;
            }
        }

I would say that the problem was that the compiler wasn't sure whether permissions would have a value at position operation? And using the loop which loops through the array(permissions is String[]) ensures that a value at position will be available if the last if statement is true. Still not sure maybe someone could give me an insight?

This is nothing to do with the compiler. The compiler has no way to know whether the array reference will be valid at run time. It's the Java runtime that checks every actual array index and throws the exception if it finds one out of range.

What is the value of "operation"? It looks like it can be >= length of the permissions array.
The code change you made will ensure that the permissions[operation] will never be evaluated for an out-of-bounds value of operation, so that supresses the exception, but may not be the result you intended.

Hey James,

Yep, the permission array holds strings of yes/no and I have another array referencing on which position is what operation. Say we are looking at operation "Print". What I am doing is in different class I pass "Print" into a method, which returns the value of operating,from an array which has stuff such as {"Print", "Start,"Stop" etc you get the idea} and it retuns the position of it, that returned value is then passed as operation. A bit weird was that if I used static values instead of operation, it only worked if the value was 0, and index out of boundary if anything else unless I loop through it

Time for a bit more debugging!
Try printing the important values (eg. the contents of permissions, the value of operation) and see what tells us.
ps: why not simply store the permissions as pairs of strings (operation:permission) and avoid all that indexing and array referencing?

Hey James,
The reason behind using the permissions as the way that I have them now is because I am implementing Access control List and the same project with Role based access control list. In the first case I have the following:

Operations:Start:Stop:Restart:Status:readConfig:setConfig:Print:Queue:topQueue
Alice:yes:yes:yes:yes:yes:yes:yes:yes:yes
Bob:yes:yes:yes:yes:yes:yes:no:no:no
Cecilia:no:no:yes:no:no:no:yes:yes:yes
David:no:no:no:no:no:no:yes:yes:no
Erica:no:no:no:no:no:no:yes:yes:no
Fred:no:no:no:no:no:no:yes:yes:no
George:no:no:no:no:no:no:yes:yes:no

where, I pass a username, based on that username I get the entire line from the text, in other words if the line contains the username, get the line, split it by ":" and save it into an array. Then use the operation to see if that particuliar permission is going to be granted(it is granted if at the position it has "yes")

For the second case, I have something similiar, one file which contains names and their roles in the company, and another file which has roles mapped to permissions. The problem that I faced here was during the second case using Role based access control. Okay, here is debugging (operation is always a value representing one of the operations in the text file)

As far as debugging goes:

for(int i = 0; i<acl.size();i++){
            //System.out.println(acl.get(i));
            if(acl.get(i).contains(role)){
                permissions = acl.get(i).split(":");
                //
                for(int j = 0; j<permissions.length;j++){
                    //System.out.println(permissions[j]);
                    //System.out.println(operation);
                    if(j==operation){
                        //System.out.println(permissions[j]);
                        System.out.println(permissions[operation]);
                        System.out.println(operation);
                        if(permissions[operation].equals("yes")) return true;
                    }
                }
            }
        }

and the output is

no
4
false

as it should be but if I try the original thing like this

for(int i = 0; i<acl.size();i++){
            //System.out.println(acl.get(i));
            if(acl.get(i).contains(role)){
                permissions = acl.get(i).split(":");
                //
                //for(int j = 0; j<permissions.length;j++){
                    //System.out.println(permissions[j]);
                    //System.out.println(operation);
                    //if(j==operation){
                        //System.out.println(permissions[j]);
                        System.out.println(permissions[operation]);
                        System.out.println(operation);
                        if(permissions[operation].equals("yes")) return true;
                    //}
                //}
            }
        }

I still get error, which is

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
    at server.CheckPermission.checkPermissions(CheckPermission.java:44)
    at server.CheckPermission.checkUserPermission(CheckPermission.java:70)
    at server.CheckPermission.main(CheckPermission.java:20)

where line 44 is System.out.println(permissions[operation]);

The idea would be to print permissions and operation just BEFORE the exception, so you can see their values. But the message implies that operation == 4 and permissions.length <= 4
Looks like the permissions array isn't what you expected it to be?

ps Did you consider holding the permissions like this...

Alice:Start:Stop:Restart:Status:readConfig:setConfig:Print:Queue:topQueue
George:Print:Queue

I think the code would be a lot simpler (especially if you read that at startup into a Map user -> permissions, so a permissions check looks like

   aclMap.getOrDefault(userName, "").contains(operation)

Edited 2 Years Ago by JamesCherrill

Hello James,
I didn't think of doing it that way perhaps I should implement in might be easier to see who has what permissions. Anyhow permissions is always the same size Alice:yes:yes:yes:yes:yes:yes:yes:yes:yes , which is 10 items so 4 shoudn't be a problem but then again even if I don't use operation but just normal numbers, it works only if the number is 0 and it prints Alice, if its 1 or bigger gives exception, bit of a mistary still

I keep saying "print the permissions array"!
It's obviously not what you expect, but if you see what it really is then you can work out why it's wrong.

for(int i = 0; i<acl.size();i++){
            //System.out.println(acl.get(i));
            if(acl.get(i).contains(role)){
                permissions = acl.get(i).split(":");
            }
        }
        for (int i = 0; i<permissions.length;i++) System.out.println(permissions[i]);

Output is:

Manager
yes
yes
yes
yes
yes
yes
yes
yes
yes

It is all "yes" because the test was ran for the admin

Hmm, if instead using the for loop I just use System.out.println(permissions[4])
like outside of the loop now it works. Is permissions not initialized completely at this point?

if(acl.get(i).contains(role)){
                permissions = acl.get(i).split(":");

I would expect permissions at that point to contain

    Manager
    yes
    yes
    yes
    yes
    yes
    yes
    yes
    yes
    yes

is that not the case?

"now it works"?
With the data you just posted there's no way permissions[operation] will fail with operation == 4.
Anyway, earlier you said permissions[0] gives "Alice", but that data is "Manager", and from what you said earlier people and roles have different files and (presumably) code.

You need to identify a test case that fails, and print permissions for that exact test case, not some other case that does work.

Edited 2 Years Ago by JamesCherrill

My bad, its Manager not Alice earlier as I mentioned. See this works

for(int i = 0; i<acl.size();i++){
            //System.out.println(acl.get(i));
            if(acl.get(i).contains(role)){
                permissions = acl.get(i).split(":");
            }
        }
        if(permissions[operation].equals("yes")) return true;
        return false;

but this doesnt

for(int i = 0; i<acl.size();i++){
            //System.out.println(acl.get(i));
            if(acl.get(i).contains(role)){
                permissions = acl.get(i).split(":");
                if(permissions[operation].equals("yes")) return true;
            }
        }
        return false;




Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
    at server.CheckPermission.checkPermissions(CheckPermission.java:38)
    at server.CheckPermission.checkUserPermission(CheckPermission.java:74)
    at server.CheckPermission.main(CheckPermission.java:20)

I swear I haven't changed anything else in the code other than move that if statement inside, if i move it out, works great again

Edited 2 Years Ago by Slavi

Omg James,
it just hit me :D, fixed and works now, the actual error was that I've used acl for reading both files, and when checking for roles let's say manager, it also has Manager on the file Alice Manager and there, it doesn't have length of 4 or more ... Well, took me quite a while to see it I guess lol, Thank you for your help

This question has already been answered. Start a new discussion instead.