jafs-library-20020725
[openafs.git] / src / JAVA / libjafs / Group.c
1 /*
2  * Copyright (c) 2001-2002 International Business Machines Corp.
3  * All rights reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  * 
9  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
12  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
13  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
15  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
16  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
17  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
18  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20  */
21
22 #include "Internal.h"
23 #include "org_openafs_jafs_Group.h"
24
25 #include <stdio.h>
26 #include <afs_ptsAdmin.h>
27 #include <afs_AdminPtsErrors.h>
28 #include <afs_AdminClientErrors.h>
29 #include <afs_AdminCommonErrors.h>
30 #include <pterror.h>
31
32 /////  definitions in Internal.c ///////////////
33
34 extern jclass userCls;
35 //extern jfieldID user_cellHandleField;
36 extern jfieldID user_nameField;
37 extern jfieldID user_cachedInfoField;
38
39 extern jclass groupCls;
40 extern jfieldID group_nameField;
41 extern jfieldID group_nameUidField;
42 extern jfieldID group_ownerUidField;
43 extern jfieldID group_creatorUidField;
44 extern jfieldID group_listStatusField;
45 extern jfieldID group_listGroupsOwnedField;
46 extern jfieldID group_listMembershipField;
47 extern jfieldID group_listAddField;
48 extern jfieldID group_listDeleteField;
49 extern jfieldID group_membershipCountField;
50 extern jfieldID group_ownerField;
51 extern jfieldID group_creatorField;
52
53 //////////////////////////////////////////////////////
54
55
56 /**
57  * Creates the PTS entry for a new group.  Pass in 0 for the uid if PTS is to
58  * automatically assign the group id.
59  *
60  * env      the Java environment
61  * cls      the current Java class
62  * cellHandle    the handle of the cell to which the group belongs
63  * jgroupName      the name of the group to create
64  * jownerName      the owner of this group
65  * gid     the group id to assign to the group (0 to have one 
66  *                automatically assigned)
67  */
68 JNIEXPORT void JNICALL 
69 Java_org_openafs_jafs_Group_create
70   (JNIEnv *env, jclass cls, jint cellHandle, jstring jgroupName, 
71    jstring jownerName, jint gid )
72 {
73   afs_status_t ast;
74   // convert java strings
75   const char *groupName;
76   const char *ownerName;
77
78   if( jgroupName != NULL ) {
79     groupName = (*env)->GetStringUTFChars(env, jgroupName, 0);
80     if( !groupName ) {
81         throwAFSException( env, JAFSADMNOMEM );
82         return;    
83     }
84   } else {
85     groupName = NULL;
86   }
87
88   if( jownerName != NULL ) {
89     ownerName = (*env)->GetStringUTFChars(env, jownerName, 0);
90     if( !ownerName ) {
91         throwAFSException( env, JAFSADMNOMEM );
92         return;    
93     }
94   } else {
95     ownerName = NULL;
96   }
97
98   // make sure the name is within the allowed bounds
99   if( groupName != NULL && strlen( groupName ) > PTS_MAX_NAME_LEN ) {
100     // release converted java strings
101     if( groupName != NULL ) {
102       (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
103     }
104     if( ownerName != NULL ) {
105       (*env)->ReleaseStringUTFChars(env, jownerName, ownerName);
106     }
107     throwAFSException( env, ADMPTSGROUPNAMETOOLONG );
108     return;
109   }
110   
111   if( !pts_GroupCreate( (void *) cellHandle, groupName, ownerName, 
112                         (int *) &gid, &ast ) ) {
113     // release converted java strings
114     if( groupName != NULL ) {
115       (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
116     }
117     if( ownerName != NULL ) {
118       (*env)->ReleaseStringUTFChars(env, jownerName, ownerName);
119     }
120     throwAFSException( env, ast );
121     return;
122   }
123
124   // release converted java strings
125   if( groupName != NULL ) {
126     (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
127   }
128   if( ownerName != NULL ) {
129     (*env)->ReleaseStringUTFChars(env, jownerName, ownerName);
130   }
131
132 }
133
134 /**
135  * Deletes the PTS entry for a group.  Deletes this group from the 
136  * membership list of the users that belonged to it, but does not delete 
137  * the groups owned by this group.
138  *
139  * env      the Java environment
140  * cls      the current Java class
141  * cellHandle    the handle of the cell to which the group belongs
142  * jgroupName      the name of the group to delete
143  */
144 JNIEXPORT void JNICALL 
145 Java_org_openafs_jafs_Group_delete
146   (JNIEnv *env, jclass cls, jint cellHandle, jstring jgroupName )
147 {
148   afs_status_t ast;
149   // convert java strings
150   const char *groupName;
151
152   if( jgroupName != NULL ) {
153     groupName = (*env)->GetStringUTFChars(env, jgroupName, 0);
154     if( !groupName ) {
155         throwAFSException( env, JAFSADMNOMEM );
156         return;    
157     }
158   } else {
159     groupName = NULL;
160   }
161
162   if( !pts_GroupDelete( (void *) cellHandle, groupName, &ast ) ) {
163     if( groupName != NULL ) {
164       (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
165     }
166     throwAFSException( env, ast );
167     return;
168   }
169   
170   // release converted java strings
171   if( groupName != NULL ) {
172     (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
173   }
174
175 }
176
177 /**
178  * Retrieve the information for the specified group and populate the
179  * given object
180  *
181  * env      the Java environment
182  * cellHandle    the handle of the cell to which the user belongs
183  * name      the name of the group for which to get the info
184  * group      the Group object to populate with the info
185  */
186 void getGroupInfoChar
187   ( JNIEnv *env, jint cellHandle, const char *name, jobject group )
188 {
189
190   jstring jowner;
191   jstring jcreator;
192   pts_GroupEntry_t entry;
193   afs_status_t ast;
194   // get the field ids if you haven't already
195   if( groupCls == 0 ) {
196     internal_getGroupClass( env, group );
197   }
198
199   if ( !pts_GroupGet( (void *) cellHandle, name, &entry, &ast ) ) {
200     throwAFSException( env, ast );
201     return;
202   }
203
204   // set the fields
205   (*env)->SetIntField(env, group, group_nameUidField, entry.nameUid);
206   (*env)->SetIntField(env, group, group_ownerUidField, entry.ownerUid);
207   (*env)->SetIntField(env, group, group_creatorUidField, entry.creatorUid);
208   (*env)->SetIntField(env, group, group_membershipCountField, 
209                       entry.membershipCount);
210
211   if( entry.listStatus == PTS_GROUP_OWNER_ACCESS ) {
212       (*env)->SetIntField(env, group, group_listStatusField, 
213                           org_openafs_jafs_Group_GROUP_OWNER_ACCESS);
214   } else if( entry.listStatus == PTS_GROUP_ACCESS ) {
215       (*env)->SetIntField(env, group, group_listStatusField, 
216                           org_openafs_jafs_Group_GROUP_GROUP_ACCESS);
217   } else {
218       (*env)->SetIntField(env, group, group_listStatusField, 
219                           org_openafs_jafs_Group_GROUP_ANYUSER_ACCESS);
220   }
221
222   if( entry.listGroupsOwned == PTS_GROUP_OWNER_ACCESS ) {
223       (*env)->SetIntField(env, group, group_listGroupsOwnedField, 
224                           org_openafs_jafs_Group_GROUP_OWNER_ACCESS);
225   } else if( entry.listGroupsOwned == PTS_GROUP_ACCESS ) {
226       (*env)->SetIntField(env, group, group_listGroupsOwnedField, 
227                           org_openafs_jafs_Group_GROUP_GROUP_ACCESS);
228   } else {
229       (*env)->SetIntField(env, group, group_listGroupsOwnedField, 
230                           org_openafs_jafs_Group_GROUP_ANYUSER_ACCESS);
231   }
232
233   if( entry.listMembership == PTS_GROUP_OWNER_ACCESS ) {
234       (*env)->SetIntField(env, group, group_listMembershipField, 
235                           org_openafs_jafs_Group_GROUP_OWNER_ACCESS);
236   } else if( entry.listMembership == PTS_GROUP_ACCESS ) {
237       (*env)->SetIntField(env, group, group_listMembershipField, 
238                           org_openafs_jafs_Group_GROUP_GROUP_ACCESS);
239   } else {
240       (*env)->SetIntField(env, group, group_listMembershipField, 
241                           org_openafs_jafs_Group_GROUP_ANYUSER_ACCESS);
242   }
243
244   if( entry.listAdd == PTS_GROUP_OWNER_ACCESS ) {
245       (*env)->SetIntField(env, group, group_listAddField, 
246                           org_openafs_jafs_Group_GROUP_OWNER_ACCESS);
247   } else if( entry.listAdd == PTS_GROUP_ACCESS ) {
248       (*env)->SetIntField(env, group, group_listAddField, 
249                           org_openafs_jafs_Group_GROUP_GROUP_ACCESS);
250   } else {
251       (*env)->SetIntField(env, group, group_listAddField, 
252                           org_openafs_jafs_Group_GROUP_ANYUSER_ACCESS);
253   }
254
255   if( entry.listDelete == PTS_GROUP_OWNER_ACCESS ) {
256       (*env)->SetIntField(env, group, group_listDeleteField, 
257                           org_openafs_jafs_Group_GROUP_OWNER_ACCESS);
258   } else if( entry.listDelete == PTS_GROUP_ACCESS ) {
259       (*env)->SetIntField(env, group, group_listDeleteField, 
260                           org_openafs_jafs_Group_GROUP_GROUP_ACCESS);
261   } else {
262       (*env)->SetIntField(env, group, group_listDeleteField, 
263                           org_openafs_jafs_Group_GROUP_ANYUSER_ACCESS);
264   }
265
266   jowner = (*env)->NewStringUTF(env, entry.owner);
267   jcreator =  (*env)->NewStringUTF(env, entry.creator);
268
269   (*env)->SetObjectField(env, group, group_ownerField, jowner);
270   (*env)->SetObjectField(env, group, group_creatorField, jcreator);
271
272 }
273
274 /**
275  * Fills in the information fields of the provided Group.  
276  * Fills in values based on the current PTS information of the group.
277  *
278  * env      the Java environment
279  * cls      the current Java class
280  * cellHandle    the handle of the cell to which the group belongs
281  * name     the name of the group for which to get the information
282  * group     the Group object in which to fill in the 
283  *                  information
284  */
285 JNIEXPORT void JNICALL 
286 Java_org_openafs_jafs_Group_getGroupInfo
287   (JNIEnv *env, jclass cls, jint cellHandle, jstring jname, jobject group)
288 {
289
290   const char *name;
291
292   if( jname != NULL ) {
293     name = (*env)->GetStringUTFChars(env, jname, 0);
294     if( !name ) {
295         throwAFSException( env, JAFSADMNOMEM );
296         return;    
297     }
298   } else {
299     name = NULL;
300   }
301   getGroupInfoChar( env, cellHandle, name, group );
302
303   // get class fields if need be
304   if( groupCls == 0 ) {
305     internal_getGroupClass( env, group );
306   }
307
308   // set name in case blank object
309   (*env)->SetObjectField(env, group, group_nameField, jname);
310
311   if( name != NULL ) {
312     (*env)->ReleaseStringUTFChars(env, jname, name);
313   }
314
315 }
316
317 /**
318  * Sets the information values of this AFS group to be the parameter values.
319  *
320  * env      the Java environment
321  * cls      the current Java class
322  * cellHandle    the handle of the cell to which the user belongs
323  * name     the name of the user for which to set the information
324  * theGroup   the group object containing the desired information
325  */
326 JNIEXPORT void JNICALL 
327 Java_org_openafs_jafs_Group_setGroupInfo
328   (JNIEnv *env, jclass cls, jint cellHandle, jstring jname, jobject group)
329 {
330   const char *name;
331   pts_GroupUpdateEntry_t ptsEntry;
332   afs_status_t ast;
333
334   jint jlistStatus;
335   jint jlistGroupsOwned;
336   jint jlistMembership;
337   jint jlistAdd;
338   jint jlistDelete;
339
340   // get the field ids if you haven't already
341   if( groupCls == 0 ) {
342     internal_getGroupClass( env, group );
343   }
344
345   jlistStatus = (*env)->GetIntField(env, group, group_listStatusField);
346   jlistGroupsOwned = (*env)->GetIntField(env, group, 
347                                          group_listGroupsOwnedField);
348   jlistMembership = (*env)->GetIntField(env, group, group_listMembershipField);
349   jlistAdd = (*env)->GetIntField(env, group, group_listAddField);
350   jlistDelete = (*env)->GetIntField(env, group, group_listDeleteField);
351
352   if( jname != NULL ) {
353     name = (*env)->GetStringUTFChars(env, jname, 0);
354     if( !name ) {
355         throwAFSException( env, JAFSADMNOMEM );
356         return;    
357     }
358   } else {
359     name = NULL;
360   }
361
362   if( jlistStatus == org_openafs_jafs_Group_GROUP_OWNER_ACCESS ) {
363     ptsEntry.listStatus = PTS_GROUP_OWNER_ACCESS;
364   } else if( jlistStatus == org_openafs_jafs_Group_GROUP_GROUP_ACCESS ) {
365     ptsEntry.listStatus = PTS_GROUP_ACCESS;
366   } else {
367     ptsEntry.listStatus = PTS_GROUP_ANYUSER_ACCESS;
368   }
369   if( jlistGroupsOwned == org_openafs_jafs_Group_GROUP_OWNER_ACCESS ) {
370     ptsEntry.listGroupsOwned = PTS_GROUP_OWNER_ACCESS;
371   } else if( jlistGroupsOwned == 
372              org_openafs_jafs_Group_GROUP_GROUP_ACCESS ) {
373     ptsEntry.listGroupsOwned = PTS_GROUP_ACCESS;
374   } else {
375     ptsEntry.listGroupsOwned = PTS_GROUP_ANYUSER_ACCESS;
376   }
377   if( jlistMembership == org_openafs_jafs_Group_GROUP_OWNER_ACCESS ) {
378     ptsEntry.listMembership = PTS_GROUP_OWNER_ACCESS;
379   } else if( jlistMembership == 
380              org_openafs_jafs_Group_GROUP_GROUP_ACCESS ) {
381     ptsEntry.listMembership = PTS_GROUP_ACCESS;
382   } else {
383     ptsEntry.listMembership = PTS_GROUP_ANYUSER_ACCESS;
384   }
385   if( jlistAdd == org_openafs_jafs_Group_GROUP_OWNER_ACCESS ) {
386     ptsEntry.listAdd = PTS_GROUP_OWNER_ACCESS;
387   } else if( jlistAdd == org_openafs_jafs_Group_GROUP_GROUP_ACCESS ) {
388     ptsEntry.listAdd = PTS_GROUP_ACCESS;
389   } else {
390     ptsEntry.listAdd = PTS_GROUP_ANYUSER_ACCESS;
391   }
392   if( jlistDelete == org_openafs_jafs_Group_GROUP_OWNER_ACCESS ) {
393     ptsEntry.listDelete = PTS_GROUP_OWNER_ACCESS;
394   } else if( jlistDelete == org_openafs_jafs_Group_GROUP_GROUP_ACCESS ) {
395     ptsEntry.listDelete = PTS_GROUP_ACCESS;
396   } else {
397     ptsEntry.listDelete = PTS_GROUP_ANYUSER_ACCESS;
398   }
399   if( !pts_GroupModify( (void *) cellHandle, name, &ptsEntry, &ast ) ) {
400     if( name != NULL ) {
401       (*env)->ReleaseStringUTFChars(env, jname, name);
402     }
403     throwAFSException( env, ast );
404     return;    
405   }
406
407   if( name != NULL ) {
408     (*env)->ReleaseStringUTFChars(env, jname, name);
409   }
410
411 }
412
413 /**
414  * Begin the process of getting the users that belong to the group.  Returns 
415  * an iteration ID to be used by subsequent calls to 
416  * getGroupMembersNext and getGroupMembersDone.  
417  *
418  * env      the Java environment
419  * cls      the current Java class
420  * cellHandle    the handle of the cell to which the group belongs
421  * jname          the name of the group for which to get the members
422  * returns an iteration ID
423  */
424 JNIEXPORT jint JNICALL 
425 Java_org_openafs_jafs_Group_getGroupMembersBegin
426   (JNIEnv *env, jclass cls, jint cellHandle, jstring jname)
427 {
428   const char *name;
429   afs_status_t ast;
430   void *iterationId;
431
432   if( jname != NULL ) {
433     name = (*env)->GetStringUTFChars(env, jname, 0);
434     if( !name ) {
435         throwAFSException( env, JAFSADMNOMEM );
436         return;    
437     }
438   } else {
439     name = NULL;
440   }
441
442   if( !pts_GroupMemberListBegin( (void *) cellHandle, name, &iterationId, 
443                                  &ast ) ) {
444     if( name != NULL ) {
445       (*env)->ReleaseStringUTFChars(env, jname, name);
446     }
447     throwAFSException( env, ast );
448     return;
449   }
450
451   if( name != NULL ) {
452     (*env)->ReleaseStringUTFChars(env, jname, name);
453   }
454
455   return (jint) iterationId;
456
457 }
458
459 /**
460  * Returns the next members that belongs to the group.  Returns 
461  * null if there are no more members.
462  *
463  * env      the Java environment
464  * cls      the current Java class
465  * iterationId   the iteration ID of this iteration
466  * returns the name of the next member
467  */
468 JNIEXPORT jstring JNICALL 
469 Java_org_openafs_jafs_Group_getGroupMembersNextString
470   (JNIEnv *env, jclass cls, jint iterationId)
471 {
472   afs_status_t ast;
473   char *userName = (char *) malloc( sizeof(char)*PTS_MAX_NAME_LEN);
474   jstring juser;
475
476   if( !userName ) {
477     throwAFSException( env, JAFSADMNOMEM );
478     return;    
479   }
480
481   if( !pts_GroupMemberListNext( (void *) iterationId, userName, &ast ) ) {
482     free( userName );
483     if( ast == ADMITERATORDONE ) {
484       return NULL;
485     } else {
486       throwAFSException( env, ast );
487       return;
488     }
489   }
490   
491   juser = (*env)->NewStringUTF(env, userName);
492   free( userName );
493   return juser;
494 }
495
496 /**
497  * Fills the next user object belonging to that group.  Returns 0 if there
498  * are no more users, != 0 otherwise.
499  *
500  * env      the Java environment
501  * cls      the current Java class
502  * cellHandle    the handle of the cell to which the users belong
503  * iterationId   the iteration ID of this iteration
504  * juserObject   a User object to be populated with the values of the 
505  *                  next user
506  * returns 0 if there are no more users, != 0 otherwise
507  */
508 JNIEXPORT jint JNICALL 
509 Java_org_openafs_jafs_Group_getGroupMembersNext
510   (JNIEnv *env, jclass cls, jint cellHandle, jint iterationId,
511    jobject juserObject)
512 {
513   afs_status_t ast;
514   char *userName;
515   jstring juser;
516
517   userName = (char *) malloc( sizeof(char)*PTS_MAX_NAME_LEN);
518
519   if( !userName ) {
520     throwAFSException( env, JAFSADMNOMEM );
521     return;    
522   }
523
524   if( !pts_GroupMemberListNext( (void *) iterationId, userName, &ast ) ) {
525     free( userName );
526     if( ast == ADMITERATORDONE ) {
527       return 0;
528     } else {
529       throwAFSException( env, ast );
530       return 0;
531     }
532   }
533
534   juser = (*env)->NewStringUTF(env, userName);
535
536   if( userCls == 0 ) {
537     internal_getUserClass( env, juserObject );
538   }
539
540   (*env)->SetObjectField(env, juserObject, user_nameField, juser);
541
542   getUserInfoChar( env, (void *) cellHandle, userName, juserObject );
543   (*env)->SetBooleanField( env, juserObject, user_cachedInfoField, TRUE );
544
545   free( userName );
546   return 1;
547
548 }
549
550 /**
551  * Signals that the iteration is complete and will not be accessed anymore.
552  *
553  * env      the Java environment
554  * cls      the current Java class
555  * iterationId   the iteration ID of this iteration
556  */
557 JNIEXPORT void JNICALL 
558 Java_org_openafs_jafs_Group_getGroupMembersDone
559   (JNIEnv *env, jclass cls, jint iterationId)
560 {
561   afs_status_t ast;
562
563   if( !pts_GroupMemberListDone( (void *) iterationId, &ast ) ) {
564     throwAFSException( env, ast );
565     return;
566   }
567
568 }
569
570 /**
571  * Adds a user to the specified group. 
572  *
573  * env      the Java environment
574  * cls      the current Java class
575  * cellHandle    the handle of the cell to which the group belongs
576  * jgroupName          the name of the group to which to add a member
577  * juserName      the name of the user to add
578  */
579 JNIEXPORT void JNICALL 
580 Java_org_openafs_jafs_Group_addMember
581   (JNIEnv *env, jclass cls, jint cellHandle, jstring jgroupName,
582    jstring juserName )
583 {
584   afs_status_t ast;
585   const char *groupName;
586   const char *userName;
587
588   if( jgroupName != NULL ) {
589     groupName = (*env)->GetStringUTFChars(env, jgroupName, 0);
590     if( !groupName ) {
591         throwAFSException( env, JAFSADMNOMEM );
592         return;    
593     }
594   } else {
595     groupName = NULL;
596   }
597
598   if( juserName != NULL ) {
599     userName = (*env)->GetStringUTFChars(env, juserName, 0);
600     if( !userName ) {
601       if( groupName != NULL ) {
602         (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
603       }
604       throwAFSException( env, JAFSADMNOMEM );
605       return;    
606     }
607   } else {
608     userName = NULL;
609   }
610
611   if( !pts_GroupMemberAdd( (void *) cellHandle, userName, groupName, &ast ) ) {
612     if( groupName != NULL ) {
613       (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
614     }
615     if( userName != NULL ) {
616       (*env)->ReleaseStringUTFChars(env, juserName, userName);
617     }
618     throwAFSException( env, ast );
619     return;
620   }
621
622   if( groupName != NULL ) {
623     (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
624   }
625   if( userName != NULL ) {
626     (*env)->ReleaseStringUTFChars(env, juserName, userName);
627   }
628 }
629
630 /**
631  * Removes a user from the specified group. 
632  *
633  * env      the Java environment
634  * cls      the current Java class
635  * cellHandle    the handle of the cell to which the group belongs
636  * jgroupName          the name of the group from which to remove a 
637  *                           member
638  * juserName      the name of the user to remove
639  */
640 JNIEXPORT void JNICALL 
641 Java_org_openafs_jafs_Group_removeMember
642   (JNIEnv *env, jclass cls, jint cellHandle, jstring jgroupName,
643    jstring juserName)
644 {
645   afs_status_t ast;
646   const char *groupName;
647   const char *userName;
648
649   if( jgroupName != NULL ) {
650     groupName = (*env)->GetStringUTFChars(env, jgroupName, 0);
651     if( !groupName ) {
652         throwAFSException( env, JAFSADMNOMEM );
653         return;    
654     }
655   } else {
656     groupName = NULL;
657   }
658
659   if( juserName != NULL ) {
660     userName = (*env)->GetStringUTFChars(env, juserName, 0);
661     if( !userName ) {
662       if( groupName != NULL ) {
663         (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
664       }
665       throwAFSException( env, JAFSADMNOMEM );
666       return;    
667     }
668   } else {
669     userName = NULL;
670   }
671
672   if( !pts_GroupMemberRemove( (void *)cellHandle, userName, 
673                               groupName, &ast ) ) {
674     if( groupName != NULL ) {
675       (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
676     }
677     if( userName != NULL ) {
678       (*env)->ReleaseStringUTFChars(env, juserName, userName);
679     }
680     throwAFSException( env, ast );
681     return;
682   }
683   
684   if( groupName != NULL ) {
685     (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
686   }
687   if( userName != NULL ) {
688     (*env)->ReleaseStringUTFChars(env, juserName, userName);
689   }
690 }
691
692 /**
693  * Change the owner of the specified group. 
694  *
695  * env      the Java environment
696  * cls      the current Java class
697  * cellHandle    the handle of the cell to which the group belongs
698  * jgroupName          the name of the group of which to change the 
699  *                           owner
700  * jownerName      the name of the new owner
701  */
702 JNIEXPORT void JNICALL 
703 Java_org_openafs_jafs_Group_changeOwner
704   (JNIEnv *env, jclass cls, jint cellHandle, jstring jgroupName,
705    jstring jownerName )
706 {
707   afs_status_t ast;
708   const char *groupName;
709   const char *ownerName;
710
711   if( jgroupName != NULL ) {
712     groupName = (*env)->GetStringUTFChars(env, jgroupName, 0);
713     if( !groupName ) {
714         throwAFSException( env, JAFSADMNOMEM );
715         return;    
716     }
717   } else {
718     groupName = NULL;
719   }
720
721   if( jownerName != NULL ) {
722     ownerName = (*env)->GetStringUTFChars(env, jownerName, 0);
723     if( !ownerName ) {
724       if( groupName != NULL ) {
725         (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
726       }
727       throwAFSException( env, JAFSADMNOMEM );
728       return;    
729     }
730   } else {
731     ownerName = NULL;
732   }
733
734   if( !pts_GroupOwnerChange( (void *)cellHandle, groupName, 
735                              ownerName, &ast ) ) {
736     if( groupName != NULL ) {
737       (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
738     }
739     if( ownerName != NULL ) {
740     (*env)->ReleaseStringUTFChars(env, jownerName, ownerName);
741     }
742     throwAFSException( env, ast );
743     return; 
744   }
745
746   if( groupName != NULL ) {
747     (*env)->ReleaseStringUTFChars(env, jgroupName, groupName);
748   }
749   if( ownerName != NULL ) {
750     (*env)->ReleaseStringUTFChars(env, jownerName, ownerName);
751   }
752   
753 }
754
755 /**
756  * Change the name of the specified group. 
757  *
758  * env      the Java environment
759  * cls      the current Java class
760  * cellHandle    the handle of the cell to which the group belongs
761  * joldGroupName          the old name of the group
762  * jnewGroupName      the new name for the group
763  */
764 JNIEXPORT void JNICALL 
765 Java_org_openafs_jafs_Group_rename
766   (JNIEnv *env, jclass cls, jint cellHandle, jstring jgroupOldName, 
767    jstring jgroupNewName )
768 {
769   afs_status_t ast;
770   const char *groupOldName;
771   const char *groupNewName;
772
773   if( jgroupOldName != NULL ) {
774     groupOldName = (*env)->GetStringUTFChars(env, jgroupOldName, 0);
775     if( !groupOldName ) {
776         throwAFSException( env, JAFSADMNOMEM );
777         return;    
778     }
779   } else {
780     groupOldName = NULL;
781   }
782
783   if( jgroupNewName != NULL ) {
784     groupNewName = (*env)->GetStringUTFChars(env, jgroupNewName, 0);
785     if( !groupNewName ) {
786       if( groupOldName != NULL ) {
787         (*env)->ReleaseStringUTFChars(env, jgroupOldName, groupOldName);
788       }
789       throwAFSException( env, JAFSADMNOMEM );
790       return;    
791     }
792   } else {
793     groupNewName = NULL;
794   }
795
796   if( !pts_GroupRename( (void *)cellHandle, groupOldName, 
797                         groupNewName, &ast ) ) {
798     if( groupOldName != NULL ) {
799       (*env)->ReleaseStringUTFChars(env, jgroupOldName, groupOldName);
800     }
801     if( groupNewName != NULL ) {
802       (*env)->ReleaseStringUTFChars(env, jgroupNewName, groupNewName);
803     }
804     throwAFSException( env, ast );
805     return;
806   }
807
808   if( groupOldName != NULL ) {
809     (*env)->ReleaseStringUTFChars(env, jgroupOldName, groupOldName);
810   }
811   if( groupNewName != NULL ) {
812     (*env)->ReleaseStringUTFChars(env, jgroupNewName, groupNewName);
813   }
814 }
815
816 // reclaim global memory used by this portion
817 JNIEXPORT void JNICALL 
818 Java_org_openafs_jafs_Group_reclaimGroupMemory (JNIEnv *env, jclass cls)
819 {
820   if( groupCls ) {
821       (*env)->DeleteGlobalRef(env, groupCls);
822       groupCls = 0;
823   }
824 }
825
826
827