View Javadoc

1   package fr.in2p3.jsaga.impl.permissions;
2   
3   import fr.in2p3.jsaga.adaptor.data.DataAdaptor;
4   import fr.in2p3.jsaga.adaptor.data.permission.*;
5   import fr.in2p3.jsaga.adaptor.data.read.DataReaderAdaptor;
6   import fr.in2p3.jsaga.adaptor.data.read.FileAttributes;
7   import fr.in2p3.jsaga.helpers.StringArray;
8   import fr.in2p3.jsaga.impl.AbstractSagaObjectImpl;
9   import fr.in2p3.jsaga.impl.task.AbstractThreadedTask;
10  import fr.in2p3.jsaga.impl.url.AbstractURLImpl;
11  import fr.in2p3.jsaga.sync.namespace.SyncNSEntry;
12  import org.ogf.saga.SagaObject;
13  import org.ogf.saga.error.*;
14  import org.ogf.saga.namespace.NSEntry;
15  import org.ogf.saga.permissions.Permission;
16  import org.ogf.saga.permissions.Permissions;
17  import org.ogf.saga.session.Session;
18  import org.ogf.saga.task.Task;
19  import org.ogf.saga.task.TaskMode;
20  import org.ogf.saga.url.URL;
21  
22  /* ***************************************************
23  * *** Centre de Calcul de l'IN2P3 - Lyon (France) ***
24  * ***             http://cc.in2p3.fr/             ***
25  * ***************************************************
26  * File:   AbstractDataPermissionsImpl
27  * Author: Sylvain Reynaud (sreynaud@in2p3.fr)
28  * Date:   17 sept. 2007
29  * ***************************************************
30  * Description:                                      */
31  /**
32   *
33   */
34  public abstract class AbstractDataPermissionsImpl extends AbstractSagaObjectImpl implements Permissions<NSEntry>, SyncNSEntry {
35      protected URL m_url;
36      protected DataAdaptor m_adaptor;
37  
38      /** constructor */
39      public AbstractDataPermissionsImpl(Session session, URL url, DataAdaptor adaptor) throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, DoesNotExistException, TimeoutException, NoSuccessException {
40          super(session);
41  
42          // set URL
43          m_url = url;
44          String scheme = adaptor.getType();
45          if (! url.getScheme().equals(scheme)) {
46              m_url.setScheme(scheme);
47          }
48  
49          // set adaptor
50          m_adaptor = adaptor;
51      }
52  
53      /** clone */
54      public SagaObject clone() throws CloneNotSupportedException {
55          AbstractDataPermissionsImpl clone = (AbstractDataPermissionsImpl) super.clone();
56          clone.m_url = m_url;
57          clone.m_adaptor = m_adaptor;
58          return clone;
59      }
60  
61      //////////////////////////////////////////// Synchronous ////////////////////////////////////////////
62  
63      public void permissionsAllow(String id, int permissions) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, TimeoutException, NoSuccessException {
64          if (m_adaptor instanceof PermissionAdaptor) {
65              PermissionAdaptor adaptor = (PermissionAdaptor) m_adaptor;
66              if (isSupportedScope(adaptor, id)) {
67                  int _scope = getPermissionsScope(id);
68                  String _identifier = getPermissionsIdentifier(id);
69                  PermissionBytes _permissions = new PermissionBytes(permissions);
70  
71                  // set OWNER permission
72                  if (_permissions.contains(Permission.OWNER)) {
73                      switch (_scope) {
74                          case PermissionAdaptor.SCOPE_USER:
75                              if (adaptor instanceof PermissionAdaptorFull) {
76                                  ((PermissionAdaptorFull)adaptor).setOwner(m_url.getPath(), _identifier);
77                              } else {
78                                  throw new BadParameterException("Not supported for this protocol: "+m_url.getScheme(), this);
79                              }
80                              break;
81                          case PermissionAdaptor.SCOPE_GROUP:
82  						    try {
83  							    adaptor.setGroup(m_url.getPath(), _identifier);
84  						    } catch (DoesNotExistException e) {
85  							    throw new NoSuccessException("File not found: " +m_url.getPath(), this);
86  						    }
87                              break;
88                          case PermissionAdaptor.SCOPE_ANY:
89                              throw new BadParameterException("Setting * as OWNER is not allowed");
90                      }
91                      // remove flag OWNER
92                      _permissions = new PermissionBytes(permissions - Permission.OWNER.getValue());
93                  }
94  
95                  // set other permissions
96                  if (adaptor instanceof PermissionAdaptorFull) {
97                      // set them
98                      ((PermissionAdaptorFull)adaptor).permissionsAllow(
99                              m_url.getPath(), _scope, _permissions, _identifier);
100                 } else if (adaptor instanceof PermissionAdaptorBasic) {
101                     // get cache
102                     FileAttributes attrs;
103                     try{attrs=this._getFileAttributes();} catch(IncorrectStateException e){throw new NoSuccessException(e);}
104 
105                     // may throw exception for unsupported use-cases
106                     if (_identifier!=null && _scope==PermissionAdaptor.SCOPE_USER &&
107                             (attrs.getOwner()==null || !attrs.getOwner().equals(_identifier)))
108                     {
109                         throw new BadParameterException("Not supported for this protocol: "+m_url.getScheme(), this);
110                     }
111 
112                     // set them
113                     ((PermissionAdaptorBasic)adaptor).permissionsAllow(
114                             m_url.getPath(), _scope, _permissions);
115                 } else {
116                     throw new NotImplementedException("Not supported for this protocol: "+ m_url.getScheme(), this);
117                 }
118             } else {
119                 throw new BadParameterException("Not supported for this protocol: "+ m_url.getScheme(), this);
120             }
121             // reset file attributes from cache
122             ((AbstractURLImpl)m_url).setCache(null);
123         } else {
124             throw new NotImplementedException("Not supported for this protocol: "+ m_url.getScheme(), this);
125         }
126     }
127 
128     public void permissionsDeny(String id, int permissions) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, TimeoutException, NoSuccessException {
129         if (m_adaptor instanceof PermissionAdaptor) {
130             PermissionAdaptor adaptor = (PermissionAdaptor) m_adaptor;
131             if (isSupportedScope(adaptor, id)) {
132                 int _scope = getPermissionsScope(id);
133                 String _identifier = getPermissionsIdentifier(id);
134                 PermissionBytes _permissions = new PermissionBytes(permissions);
135 
136                 // set OWNER permission
137                 if (_permissions.contains(Permission.OWNER)) {
138                     throw new BadParameterException("Unsetting OWNER permission is not allowed");
139                 }
140 
141                 // set other permissions
142                 if (adaptor instanceof PermissionAdaptorFull) {
143                     // set them
144                     ((PermissionAdaptorFull)adaptor).permissionsDeny(
145                             m_url.getPath(), _scope, _permissions, _identifier);
146                 } else if (adaptor instanceof PermissionAdaptorBasic) {
147                     // get cache
148                     FileAttributes attrs;
149                     try{attrs=this._getFileAttributes();} catch(IncorrectStateException e){throw new NoSuccessException(e);}
150 
151                     // may throw exception for unsupported use-cases
152                     if (_identifier != null) {
153                         switch (_scope) {
154                             case PermissionAdaptor.SCOPE_USER:
155                                 if (attrs.getOwner()==null || !attrs.getOwner().equals(_identifier)) {
156                                     throw new BadParameterException("Not supported for this protocol: "+m_url.getScheme(), this);
157                                 }
158                                 break;
159                             case PermissionAdaptor.SCOPE_GROUP:
160                                 if (attrs.getGroup()==null || !attrs.getGroup().equals(_identifier)) {
161                                     throw new BadParameterException("Not supported for this protocol: "+m_url.getScheme(), this);
162                                 }
163                                 break;
164                         }
165                     }
166 
167                     // set them
168                     ((PermissionAdaptorBasic)adaptor).permissionsDeny(
169                             m_url.getPath(), _scope, _permissions);
170                 } else {
171                     throw new NotImplementedException("Not supported for this protocol: "+ m_url.getScheme(), this);
172                 }
173             } else {
174                 throw new BadParameterException("Not supported for this protocol: "+ m_url.getScheme(), this);
175             }
176         } else {
177             throw new NotImplementedException("Not supported for this protocol: "+ m_url.getScheme(), this);
178         }
179         // reset file attributes from cache
180         ((AbstractURLImpl)m_url).setCache(null);
181     }
182 
183     public boolean permissionsCheck(String id, int permissions) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, TimeoutException, NoSuccessException {
184         boolean checked = true;
185 
186         final String ctxUserID = null;  //todo: get UserID from context
187         int _scope = getPermissionsScope(id);
188         String _identifier = getPermissionsIdentifier(id);
189         PermissionBytes _permissions = new PermissionBytes(permissions);
190 
191         // get cache
192         FileAttributes attrs;
193         try{attrs=this._getFileAttributes();} catch(IncorrectStateException e){throw new NoSuccessException(e);}
194 
195         // check OWNER permission
196         if (_permissions.contains(Permission.OWNER)) {
197             switch (_scope) {
198                 case PermissionAdaptor.SCOPE_USER:
199                     if (attrs.getOwner() != null) {
200                         checked = attrs.getOwner().equals(_identifier);
201                     } else {
202                         throw new BadParameterException("Not supported for this protocol: "+m_url.getScheme(), this);
203                     }
204                     break;
205                 case PermissionAdaptor.SCOPE_GROUP:
206                     if (attrs.getGroup() != null) {
207                         checked = attrs.getGroup().equals(_identifier);
208                     } else {
209                         throw new BadParameterException("Not supported for this protocol: "+m_url.getScheme(), this);
210                     }
211                     break;
212                 case PermissionAdaptor.SCOPE_ANY:
213                     throw new BadParameterException("* can not be OWNER of an entry");
214             }
215             // remove flag OWNER
216             _permissions = new PermissionBytes(permissions - Permission.OWNER.getValue());
217         }
218 
219         // check scope
220         if (m_adaptor instanceof PermissionAdaptor && !isSupportedScope((PermissionAdaptor)m_adaptor, id)) {
221             throw new BadParameterException("Not supported for this protocol: "+ m_url.getScheme(), this);
222         }
223 
224         // get permissions from cache
225         PermissionBytes cachedPerms;
226         if (id==null || id==ctxUserID ||
227             (_scope==PermissionAdaptor.SCOPE_USER && _identifier.equals(attrs.getOwner())))
228             cachedPerms = attrs.getUserPermission();
229         else if ((_scope==PermissionAdaptor.SCOPE_GROUP && _identifier.equals(attrs.getGroup())) ||
230                  (_scope==PermissionAdaptor.SCOPE_USER && this.isMemberOf(_identifier, attrs.getGroup())))
231             cachedPerms = attrs.getGroupPermission();
232         else
233             cachedPerms = attrs.getAnyPermission();
234         
235         // check other permissions
236         if (m_adaptor instanceof PermissionAdaptorFull) {
237             return checked && ((PermissionAdaptorFull)m_adaptor).permissionsCheck(
238                     m_url.getPath(), _scope, _permissions, _identifier);
239         } else if (cachedPerms != FileAttributes.PERMISSION_UNKNOWN) {
240             return checked && cachedPerms.containsAll(_permissions.getValue());
241         } else {
242             throw new NotImplementedException("Not supported for this protocol: "+ m_url.getScheme(), this);
243         }
244     }
245     private boolean isMemberOf(String id, String groupOwner) throws BadParameterException, NoSuccessException {
246         if (m_adaptor instanceof PermissionAdaptorBasic) {
247             String[] groups = ((PermissionAdaptorBasic)m_adaptor).getGroupsOf(id);
248             return StringArray.arrayContains(groups, groupOwner);
249         } else {
250             return false;
251         }
252     }
253 
254     private static boolean isSupportedScope(PermissionAdaptor adaptor, String id) {
255         int scope = getPermissionsScope(id);
256         for (int s : adaptor.getSupportedScopes()) {
257             if (scope == s) {
258                 return true;
259             }
260         }
261         return false;
262     }
263     private static int getPermissionsScope(String id) {
264         if (id != null) {
265             if (id.equals("*")) {
266                 return PermissionAdaptor.SCOPE_ANY;
267             } else if (id.startsWith("group-")) {
268                 return PermissionAdaptor.SCOPE_GROUP;
269             }
270         }
271         return PermissionAdaptor.SCOPE_USER;
272     }
273     private static String getPermissionsIdentifier(String id) {
274         if (id != null) {
275             if (id.startsWith("group-") || id.startsWith("user-")) {
276                 String realIdentifier = id.substring(id.indexOf('-')+1);
277                 if (realIdentifier.equals("null")) {
278                     return null;
279                 } else {
280                     return realIdentifier;
281                 }
282             }
283         }
284         return id;
285     }
286 
287     public String getOwner() throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, TimeoutException, NoSuccessException {
288         try {
289             FileAttributes attrs = this._getFileAttributes();
290             String owner = attrs.getOwner();
291             if (owner != null) {
292                 return owner;
293             }
294         } catch (IncorrectStateException e) {
295             throw new NoSuccessException(e);
296         }
297         throw new NotImplementedException("Not supported for this protocol: "+ m_url.getScheme(), this);
298     }
299 
300     public String getGroup() throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, TimeoutException, NoSuccessException {
301         try {
302             FileAttributes attrs = this._getFileAttributes();
303             String group = attrs.getGroup();
304             if (group != null) {
305                 return group;
306             }
307         } catch (IncorrectStateException e) {
308             throw new NoSuccessException(e);
309         }
310         throw new NotImplementedException("Not supported for this protocol: "+ m_url.getScheme(), this);
311     }
312 
313     //////////////////////////////////////////// Asynchronous ////////////////////////////////////////////
314 
315     public Task<NSEntry, Void> permissionsAllow(TaskMode mode, final String id, final int permissions) throws NotImplementedException {
316         return new AbstractThreadedTask<NSEntry,Void>(mode) {
317             public Void invoke() throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, DoesNotExistException, TimeoutException, NoSuccessException {
318                 AbstractDataPermissionsImpl.this.permissionsAllow(id, permissions);
319                 return null;
320             }
321         };
322     }
323 
324     public Task<NSEntry, Void> permissionsDeny(TaskMode mode, final String id, final int permissions) throws NotImplementedException {
325         return new AbstractThreadedTask<NSEntry,Void>(mode) {
326             public Void invoke() throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, DoesNotExistException, TimeoutException, NoSuccessException {
327                 AbstractDataPermissionsImpl.this.permissionsDeny(id, permissions);
328                 return null;
329             }
330         };
331     }
332 
333     public Task<NSEntry, Boolean> permissionsCheck(TaskMode mode, final String id, final int permissions) throws NotImplementedException {
334         return new AbstractThreadedTask<NSEntry,Boolean>(mode) {
335             public Boolean invoke() throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, DoesNotExistException, TimeoutException, NoSuccessException {
336                 return AbstractDataPermissionsImpl.this.permissionsCheck(id, permissions);
337             }
338         };
339     }
340 
341     public Task<NSEntry, String> getOwner(TaskMode mode) throws NotImplementedException {
342         return new AbstractThreadedTask<NSEntry,String>(mode) {
343             public String invoke() throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, DoesNotExistException, TimeoutException, NoSuccessException {
344                 return AbstractDataPermissionsImpl.this.getOwner();
345             }
346         };
347     }
348 
349     public Task<NSEntry, String> getGroup(TaskMode mode) throws NotImplementedException {
350         return new AbstractThreadedTask<NSEntry,String>(mode) {
351             public String invoke() throws NotImplementedException, IncorrectURLException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, BadParameterException, IncorrectStateException, AlreadyExistsException, DoesNotExistException, TimeoutException, NoSuccessException {
352                 return AbstractDataPermissionsImpl.this.getGroup();
353             }
354         };
355     }
356 
357     protected FileAttributes _getFileAttributes() throws NotImplementedException, PermissionDeniedException, IncorrectStateException, TimeoutException, NoSuccessException {
358         FileAttributes attrs;
359         if ( ((AbstractURLImpl)m_url).hasCache() ) {
360             // get file attributes from cache
361             attrs = ((AbstractURLImpl)m_url).getCache();
362         } else if (m_adaptor instanceof DataReaderAdaptor) {
363             // query file attributes
364             try {
365                 attrs = ((DataReaderAdaptor)m_adaptor).getAttributes(
366                         m_url.getPath(),
367                         m_url.getQuery());
368             } catch (DoesNotExistException doesNotExist) {
369                 throw new IncorrectStateException("Entry does not exist: "+m_url, doesNotExist);
370             }
371 
372             // set file attributes to cache
373             ((AbstractURLImpl)m_url).setCache(attrs);
374         } else {
375             throw new NotImplementedException("Not supported for this protocol: "+m_url.getScheme(), this);
376         }
377         return attrs;
378     }
379 }