View Javadoc

1   package fr.in2p3.jsaga.impl.context;
2   
3   import fr.in2p3.jsaga.adaptor.base.defaults.Default;
4   import fr.in2p3.jsaga.adaptor.base.usage.Usage;
5   import fr.in2p3.jsaga.adaptor.security.*;
6   import fr.in2p3.jsaga.engine.factories.SecurityAdaptorFactory;
7   import fr.in2p3.jsaga.engine.session.SessionConfiguration;
8   import fr.in2p3.jsaga.impl.attributes.AbstractAttributesImpl;
9   import fr.in2p3.jsaga.impl.job.service.JobServiceImpl;
10  import org.apache.log4j.Logger;
11  import org.ogf.saga.SagaObject;
12  import org.ogf.saga.context.Context;
13  import org.ogf.saga.error.*;
14  
15  import java.io.ByteArrayOutputStream;
16  import java.io.FileNotFoundException;
17  import java.io.PrintStream;
18  import java.util.*;
19  
20  /* ***************************************************
21  * *** Centre de Calcul de l'IN2P3 - Lyon (France) ***
22  * ***             http://cc.in2p3.fr/             ***
23  * ***************************************************
24  * File:   ContextImpl
25  * Author: Sylvain Reynaud (sreynaud@in2p3.fr)
26  * Date:   17 sept. 2007
27  * ***************************************************
28  * Description:                                      */
29  /**
30   *
31   */
32  public class ContextImpl extends AbstractAttributesImpl implements Context {
33      public static final String URL_PREFIX = "UrlPrefix";
34      public static final String BASE_URL_INCLUDES = "BaseUrlIncludes";
35      public static final String BASE_URL_EXCLUDES = "BaseUrlExcludes";
36      public static final String JOB_SERVICE_ATTRIBUTES = "JobServiceAttributes";
37      public static final String DATA_SERVICE_ATTRIBUTES = "DataServiceAttributes";
38  
39      private static Logger s_logger = Logger.getLogger(ContextImpl.class);
40      
41      private ContextAttributes m_attributes;
42      private SecurityAdaptor m_adaptor;
43      private SecurityCredential m_credential;
44      private WeakHashMap<JobServiceImpl,Object> m_jobServices;
45      private SessionConfiguration m_config;
46      private SecurityAdaptorFactory m_adaptorFactory;
47  
48      /** constructor */
49      public ContextImpl(String type, SessionConfiguration config, SecurityAdaptorFactory adaptorFactory) throws IncorrectStateException, TimeoutException, NoSuccessException {
50          super(null, true);  //not attached to a session, isExtensible=true
51          m_attributes = new ContextAttributes(this);
52          m_adaptor = null;
53          m_credential = null;
54          m_jobServices = new WeakHashMap<JobServiceImpl,Object>();
55          m_config = config;
56          m_adaptorFactory = adaptorFactory;
57          if (type!=null && !type.equals("")) {
58              try {
59                  this.setAttribute(Context.TYPE, type);
60              }
61              catch (IncorrectStateException e) {throw e;}
62              catch (TimeoutException e) {throw e;}
63              catch (NoSuccessException e) {throw e;}
64              catch (SagaException e) {throw new NoSuccessException(e);}
65          }
66      }
67  
68      /** clone */
69      public SagaObject clone() throws CloneNotSupportedException {
70          ContextImpl clone = (ContextImpl) super.clone();
71          clone.m_attributes = m_attributes;
72          clone.m_adaptor = m_adaptor;
73          clone.m_credential = m_credential;
74          clone.m_jobServices = m_jobServices;
75          clone.m_config = m_config;
76          clone.m_adaptorFactory = m_adaptorFactory;
77          return clone;
78      }
79  
80      ////////////////////////// override some AbstractAttributesImpl methods //////////////////////////
81  
82      /** override super.setAttribute() */
83      public void setAttribute(String key, String value) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, BadParameterException, DoesNotExistException, TimeoutException, NoSuccessException {
84          // set attribute
85          try {
86              m_attributes.getScalarAttribute(key).setValue(value);
87          } catch (DoesNotExistException e) {
88              super.setAttribute(key, value);
89          }
90          
91          // instanciate adaptor
92          if (Context.TYPE.equals(key)) {
93              // instanciate
94              m_adaptor = m_adaptorFactory.getSecurityAdaptor(value);
95  
96              // set PLUG-IN defaults
97              Default[] defaults = m_adaptor.getDefaults(new HashMap());
98              if (defaults != null) {
99                  for (int i=0; i<defaults.length; i++) {
100                     if (defaults[i].getValue() != null) {
101                         super.setAttribute(defaults[i].getName(), defaults[i].getValue());
102                     }
103                 }
104             }
105 
106             // set CONFIGURATION defaults (/jsaga-defaults/contexts)
107             if (m_config != null) {
108                 m_config.setDefaultContext(this);
109             }
110         }
111 
112         // reset credential
113         m_credential = null;
114     }
115 
116     /** override super.getAttribute() */
117     public String getAttribute(String key) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, DoesNotExistException, TimeoutException, NoSuccessException {
118         // get attribute
119         try {
120             return m_attributes.getScalarAttribute(key).getValue();
121         } catch (DoesNotExistException e) {
122             // try to get from credential
123             SecurityCredential credential = null;
124             try{credential=this.getCredential();} catch(IncorrectStateException e2){/* ignore "Missing attribute" */}
125             if (credential != null) {
126                 if (Context.USERID.equals(key)) {
127                     try {
128                         // try to get from credential
129                         return credential.getUserID();
130                     } catch (Exception e2) {
131                         throw new NoSuccessException(e2);
132                     }
133                 } else {
134                 	try{return credential.getAttribute(key);} catch(NotImplementedException e2){/* ignore "Unsupported attribute" */}
135                 }
136             }
137             // else try to get from parent class
138             try {
139                 return super.getAttribute(key);
140             } catch (DoesNotExistException dnee) {
141                 if (m_adaptor.getUsage().toString().contains(key)) {
142                     throw dnee;
143                 } else if (Context.USERID.equals(key)) {
144                     throw new IncorrectStateException("Attribute not yet initialized. Please first add context to a session.");
145                 } else {
146                     throw new NoSuccessException("Attribute not supported for this adaptor (or not yet initialized)");
147                 }
148             }
149         }
150     }
151 
152     /** override super.setVectorAttribute() */
153     public void setVectorAttribute(String key, String[] values) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, BadParameterException, DoesNotExistException, TimeoutException, NoSuccessException {
154         // set attribute
155         try {
156             m_attributes.getVectorAttribute(key).setValues(values);
157         } catch (DoesNotExistException e) {
158             super.setVectorAttribute(key, values);
159         }
160 
161         // reset credential
162         m_credential = null;
163     }
164 
165     /** override super.getVectorAttribute() */
166     public String[] getVectorAttribute(String key) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, DoesNotExistException, TimeoutException, NoSuccessException {
167         // get attribute
168         try {
169             return m_attributes.getVectorAttribute(key).getValues();
170         } catch (DoesNotExistException e) {
171             if (Context.USERID.equals(key)) {
172                 throw new IncorrectStateException("Operation not allowed on scalar attribute: "+key, this);
173             } else {
174                 // try to get from parent class
175                 return super.getVectorAttribute(key);
176             }
177         }
178     }
179 
180     private String getAttributeFromCredential(String key, SecurityCredential credential) throws NotImplementedException, DoesNotExistException, NoSuccessException {
181         try {
182             return credential.getAttribute(key);
183         } catch (NotImplementedException e) {
184             Usage usage = m_adaptor.getUsage();
185             if (usage!=null && usage.getKeys().contains(key)) {
186                 throw new DoesNotExistException("Attribute not set: "+key);
187             } else {
188                 throw new NotImplementedException("Attribute not supported: "+key);
189             }
190         }
191     }
192 
193     ///////////////////////////////////////// implementation /////////////////////////////////////////
194 
195     /**
196      * @see org.ogf.saga.session.Session
197      */
198     public void close() {
199         if (m_credential!= null) {
200             try {
201                 m_credential.close();
202             } catch (Exception e) {
203                 s_logger.warn("Failed to close security adaptor", e);
204             }
205             // reset credential
206             m_credential = null;
207         }
208     }
209 
210     /**
211      * This method is specific to JSAGA implementation.
212      */
213     public void destroy() throws IncorrectStateException, NoSuccessException {
214         if (m_adaptor== null) {
215             throw new IncorrectStateException("Attribute MUST be set before destroying context: "+Context.TYPE, this);
216         }
217         if (m_adaptor instanceof ExpirableSecurityAdaptor) {
218             try {
219                 ((ExpirableSecurityAdaptor) m_adaptor).destroySecurityAdaptor(
220                         super._getAttributesMap(), m_attributes.m_type.getValue());
221             } catch (Exception e) {
222                 throw new NoSuccessException(e);
223             }
224         }
225         // reset credential
226         m_credential = null;
227     }
228 
229     /**
230      * This method is specific to JSAGA implementation.
231      */
232     public String toString() {
233         ByteArrayOutputStream stream = new ByteArrayOutputStream();
234         PrintStream out = new PrintStream(stream);
235         if (m_credential!= null) {
236             try {
237                 m_credential.dump(out);
238             } catch (Exception e) {
239                 e.printStackTrace(out);
240             }
241         } else {
242             out.println("Not yet initialized");
243         }
244         out.close();
245         return stream.toString();
246     }
247 
248     /**
249      * This method is specific to JSAGA implementation.
250      */
251     public synchronized Class getCredentialClass() throws BadParameterException {
252         if (m_adaptor== null) {
253             throw new BadParameterException("Attribute MUST be set before using context: "+Context.TYPE, this);
254         }
255         return m_adaptor.getSecurityCredentialClass();
256     }
257 
258     /**
259      * This method is specific to JSAGA implementation.
260      */
261     public synchronized SecurityCredential getCredential() throws NotImplementedException, IncorrectStateException, TimeoutException, NoSuccessException {
262         if (m_adaptor== null) {
263             throw new IncorrectStateException("Attribute MUST be set before using context: "+Context.TYPE, this);
264         }
265 
266         return m_credential;
267     }
268 
269     public synchronized SecurityCredential createCredential() throws NotImplementedException, IncorrectStateException, TimeoutException, NoSuccessException {
270         Usage usage = m_adaptor.getUsage();
271         Map attributes = super._getAttributesMap();
272         int matching;
273         try {
274             matching = (usage!=null ? usage.getFirstMatchingUsage(attributes) : -1);
275         } catch(DoesNotExistException e) {
276             Usage missing = (usage!=null ? usage.getMissingValues(attributes) : null);
277             if (missing != null) {
278                 throw new IncorrectStateException("Missing attribute(s): "+missing.toString(), this);
279             } else {
280                 throw new NoSuccessException("[INTERNAL ERROR] Unexpected exception", this);
281             }
282         } catch (BadParameterException e) {
283             throw new IncorrectStateException("Invalid attribute(s): " + e.getMessage(), e);
284         } catch (FileNotFoundException e) {
285             // Should not happen
286             throw new IncorrectStateException("Invalid attribute(s): " + e.getMessage(), e);
287         }
288         m_credential = m_adaptor.createSecurityCredential(
289                 matching, attributes, m_attributes.m_type.getValue());
290         if (m_credential== null) {
291             throw new NotImplementedException("[INTERNAL ERROR] Method createSecurityCredential should never return 'null'");
292         }
293 
294         // reset the job services using this context
295         Set<JobServiceImpl> jobServices = new HashSet<JobServiceImpl>();
296         jobServices.addAll(m_jobServices.keySet());
297         new Thread(new JobServiceReset(jobServices, m_credential)).start();
298         return m_credential;
299     }
300     
301     /**
302      * This method is specific to JSAGA implementation.
303      */
304     public String getSchemeFromAlias(String alias) throws NotImplementedException, NoSuccessException {
305         String urlPrefix;
306         try{urlPrefix=m_attributes.m_urlPrefix.getValue()+"-";} catch(IncorrectStateException e){throw new NoSuccessException(e);}
307         if (alias.startsWith(urlPrefix)) {
308             return alias.substring(urlPrefix.length());
309         } else {
310             String scheme = m_attributes.m_baseUrlIncludes.getSchemeFromAlias(alias);
311             if (scheme != null) {
312                 return scheme;
313             } else {
314                 return alias;
315             }
316         }
317     }
318 
319     /**
320      * This method is specific to JSAGA implementation.
321      */
322     public Properties getServiceConfig(String serviceType, String scheme) {
323     	if (JOB_SERVICE_ATTRIBUTES.equals(serviceType)) {
324     		return m_attributes.m_jobServiceAttributes.getServiceConfig(scheme);
325     	} else if (DATA_SERVICE_ATTRIBUTES.equals(serviceType)) {
326     		return m_attributes.m_dataServiceAttributes.getServiceConfig(scheme);
327     	} else {
328     		return null;
329     	}
330     }
331 
332     /**
333      * This method is specific to JSAGA implementation.
334      */
335     public void throwIfConflictsWith(ContextImpl ref) throws NoSuccessException {
336         try {
337             m_attributes.m_baseUrlIncludes.throwIfConflictsWith(
338                     m_attributes.m_urlPrefix.getValue(),
339                     ref.m_attributes.m_urlPrefix.getValue(),
340                     ref.m_attributes.m_baseUrlIncludes,
341                     ref.m_attributes.m_baseUrlExcludes,
342                     m_attributes.m_baseUrlExcludes);
343         }
344         catch (NoSuccessException e) {throw e;}
345         catch (SagaException e) {throw new NoSuccessException(e);}
346     }
347 
348     /**
349      * This method is specific to JSAGA implementation.
350      */
351     public boolean matches(String url) {
352         // returns false if matches an excluded pattern
353         if (m_attributes.m_baseUrlExcludes.matches(url)) {
354             return false;
355         }
356         // returns true if matches an included pattern
357         return m_attributes.m_baseUrlIncludes.matches(url);
358     }
359 
360     /**
361      * This method is specific to JSAGA implementation.
362      */
363     public void setUrlPrefix(int position) throws NoSuccessException {
364         try {
365             if (m_attributes.m_urlPrefix.getValue() == null) {
366                 m_attributes.m_urlPrefix.setValue(m_attributes.m_type.getValue()+position);
367             }
368         }
369         catch (NoSuccessException e) {throw e;}
370         catch (SagaException e) {throw new NoSuccessException(e);}
371     }
372 
373     /**
374      * This method is specific to JSAGA implementation.
375      */
376     public synchronized void registerJobService(JobServiceImpl jobService) {
377         m_jobServices.put(jobService, new Object());
378     }
379 
380     /** This method is specific to JSAGA implementation. It should be used for debugging purpose only. */
381     public String getUsage() {
382         Usage usage = m_adaptor.getUsage();
383         if (usage != null) {
384             return usage.toString();
385         }
386         return null;
387     }
388     /** This method is specific to JSAGA implementation. It should be used for debugging purpose only. */
389     public String getDefault(String key) throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, IncorrectStateException, DoesNotExistException, TimeoutException, NoSuccessException {
390         // do not try to get attribute from credential
391         if (super.isVectorAttribute(key)) {
392             return Arrays.toString(super.getVectorAttribute(key));
393         } else {
394             return super.getAttribute(key);
395         }
396     }
397     /** This method is specific to JSAGA implementation. It should be used for debugging purpose only. */
398     public String getMissings() throws NotImplementedException, AuthenticationFailedException, AuthorizationFailedException, PermissionDeniedException, DoesNotExistException, IncorrectStateException, TimeoutException, NoSuccessException {
399         Map<String,String> defaults = new HashMap<String,String>();
400         for (String key : this.listAttributes()) {
401             defaults.put(key, this.getDefault(key));
402         }
403         Usage usage = m_adaptor.getUsage();
404         if (usage != null) {
405             Usage missing = usage.getMissingValues(defaults);
406             if (missing != null) {
407                 return missing.toString();
408             }
409         }
410         return null;
411     }
412 }