View Javadoc

1   /* 
2    * Copyright (c) 2007, Fraunhofer-Gesellschaft
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are
7    * met:
8    * 
9    * (1) Redistributions of source code must retain the above copyright
10   *     notice, this list of conditions and the disclaimer at the end.
11   *     Redistributions in binary form must reproduce the above copyright
12   *     notice, this list of conditions and the following disclaimer in
13   *     the documentation and/or other materials provided with the
14   *     distribution.
15   * 
16   * (2) Neither the name of Fraunhofer nor the names of its
17   *     contributors may be used to endorse or promote products derived
18   *     from this software without specific prior written permission.
19   * 
20   * DISCLAIMER
21   * 
22   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   *  
34   */
35  package org.ogf.graap.wsag.server.monitoring;
36  
37  import java.text.MessageFormat;
38  import java.util.HashMap;
39  import java.util.Iterator;
40  import java.util.Map;
41  import java.util.Vector;
42  
43  import org.apache.log4j.Logger;
44  import org.apache.xmlbeans.XmlObject;
45  import org.ogf.graap.wsag.api.logging.LogMessage;
46  import org.ogf.graap.wsag.api.types.AbstractAgreementType;
47  import org.ogf.graap.wsag4j.types.engine.GuaranteeEvaluationResultType;
48  import org.ogf.graap.wsag4j.types.engine.SLAMonitoringNotificationEventType;
49  import org.ogf.schemas.graap.wsAgreement.AgreementPropertiesDocument;
50  import org.ogf.schemas.graap.wsAgreement.AgreementPropertiesType;
51  import org.ogf.schemas.graap.wsAgreement.AgreementStateDefinition;
52  import org.ogf.schemas.graap.wsAgreement.AgreementStateType;
53  import org.ogf.schemas.graap.wsAgreement.GuaranteeTermStateDefinition;
54  import org.ogf.schemas.graap.wsAgreement.GuaranteeTermStateType;
55  import org.ogf.schemas.graap.wsAgreement.GuaranteeTermType;
56  import org.ogf.schemas.graap.wsAgreement.ServicePropertiesType;
57  import org.ogf.schemas.graap.wsAgreement.ServiceSelectorType;
58  import org.ogf.schemas.graap.wsAgreement.ServiceTermStateDefinition;
59  import org.ogf.schemas.graap.wsAgreement.ServiceTermStateType;
60  
61  /**
62   * WSAG4JAgreementMonitor
63   * 
64   * Monitors the service term states of an agreement instance and evaluates the guarantee term states for
65   * guarantees defined in the agreement instance.
66   * 
67   * @author Oliver Waeldrich
68   * 
69   */
70  public class AgreementMonitor
71  {
72  
73      private static final String XPATH_NS_DECL_WSAG =
74          "declare namespace wsag='http://schemas.ggf.org/graap/2007/03/ws-agreement';";
75  
76      private static final String XPATH_QUERY_GUARANTEE_TERM =
77          "$this/wsag:Terms/wsag:All//wsag:GuaranteeTerm[ @wsag:Name = ''{0}'']";
78  
79      private static final String XPATH_QUERY_SERVICE_PROPERTIES =
80          "$this/wsag:Terms/wsag:All//wsag:ServiceProperties[ @wsag:ServiceName = ''{0}'']";
81  
82      //
83      // static variable definitions
84      //
85      private static final Logger LOG = Logger.getLogger( AgreementMonitor.class );
86  
87      //
88      // private variable definitions
89      //
90      private AbstractAgreementType agreementInstance;
91  
92      private IMonitoringContext monitoringContext;
93  
94      private ServiceTermStateMonitor stateMonitor = new ServiceTermStateMonitor();
95  
96      //
97      // message code definitions
98      //
99      static final String ERR_UPDATE_GUARANTEE_STATE = "AgreementMonitor.ERR_UPDATE_GUARANTEE_STATE"; //$NON-NLS-1$ 
100 
101     static final String ERR_UPDATE_AGREEMENT_STATE = "AgreementMonitor.ERR_UPDATE_AGREEMENT_STATE"; //$NON-NLS-1$
102 
103     static final String ERR_GET_STD_STATES = "AgreementMonitor.ERR_GET_STD_STATES"; //$NON-NLS-1$
104 
105     static final String ERR_INIT_SDT_STATES = "AgreementMonitor.ERR_INIT_SDT_STATES"; //$NON-NLS-1$
106 
107     static final String ERR_UPD_STD_STATES = "AgreementMonitor.ERR_UPD_STD_STATES"; //$NON-NLS-1$
108 
109     private static final String ERR_GET_GUARANTEE_STATES = "AgreementMonitor.ERR_GET_GUARANTEE_STATES"; //$NON-NLS-1$
110 
111     static final String WARN_MULTIPLE_GUARANTEES = "AgreementMonitor.WARN_MULTIPLE_GUARANTEE_OCCOURENCES"; //$NON-NLS-1$
112 
113     static final String WARN_SP_DEF_NOT_FOUND = "AgreementMonitor.WARN_SP_DEF_NOT_FOUND"; //$NON-NLS-1$
114 
115     static final String WARN_MULTIPLE_SP_DEFS = "AgreementMonitor.WARN_SP_DEF_MULTIPLE_OCCURENCES"; //$NON-NLS-1$
116 
117     static final String WARN_GURANTEE_NOT_FOUND = "AgreementMonitor.WARN_GURANTEE_TERM_NOT_FOUND"; //$NON-NLS-1$
118 
119     static final String DBG_EVAL_GUARANTEE_STATE = "AgreementMonitor.DBG_EVAL_GUARANTEE_STATE"; //$NON-NLS-1$
120 
121     static final String DBG_SERVICE_PROPERTIES = "AgreementMonitor.DBG_SERVICE_PROPERTIES"; //$NON-NLS-1$
122 
123     static final String DBG_DUPLICATE_VAR_DEF = "AgreementMonitor.DEBUG_DUPLICATE_VAR_DEF"; //$NON-NLS-1$
124 
125     //
126     // method implementations
127     //
128 
129     /**
130      * @return the agreementInstance
131      */
132     public AbstractAgreementType getAgreementInstance()
133     {
134         return agreementInstance;
135     }
136 
137     /**
138      * @param agreementInstance
139      *            the agreementInstance to set
140      */
141     public void setAgreementInstance( AbstractAgreementType agreementInstance )
142     {
143         this.agreementInstance = agreementInstance;
144     }
145 
146     /**
147      * @return the monitoringContext
148      */
149     public IMonitoringContext getMonitoringContext()
150     {
151         return monitoringContext;
152     }
153 
154     /**
155      * @param monitoringContext
156      *            the monitoringContext to set
157      */
158     public void setMonitoringContext( IMonitoringContext monitoringContext )
159     {
160         this.monitoringContext = monitoringContext;
161     }
162 
163     /**
164      * Updates the states of the associated agreement instance. First, the service term states are updated by
165      * using the registered monitoring handler. In a second step, all guarantee terms are evaluated and
166      * updated. When the monitoring cycle is completed, the resource property document of the agreement
167      * instance is updated with the results.
168      * 
169      * The monitoring handler are invoked in the same order as they are registered.
170      * 
171      * @throws Exception
172      *             indicates an error while updating the states
173      */
174     public void updateStates() throws Exception
175     {
176         //
177         // synchronize the monitoring process
178         //
179         IMonitoringContext mutex = monitoringContext;
180 
181         synchronized ( mutex )
182         {
183             //
184             // Monitoring of an agreement instance is only performed
185             // in observed or in observed and terminating state
186             //
187 
188             //
189             // For the agreement processing we create a copy of the agreement resource properties document.
190             // First we must make sure that the agreement properties object has a DOM element representation
191             // (important for XPath queries), not a DOM document fragment representation.
192             //
193             AgreementPropertiesDocument apDoc = AgreementPropertiesDocument.Factory.newInstance();
194             AgreementPropertiesType apCopy =
195                 (AgreementPropertiesType) getAgreementInstance().getXMLObject().copy();
196             apDoc.setAgreementProperties( apCopy );
197 
198             //
199             // now this agreement properties object is an element, no document fragment anymore
200             //
201             AgreementPropertiesType agreementProperties = apDoc.getAgreementProperties();
202 
203             AgreementStateType agreementState = agreementProperties.getAgreementState();
204             if ( ( agreementState.getState() == AgreementStateDefinition.OBSERVED )
205                 || ( agreementState.getState() == AgreementStateDefinition.OBSERVED_AND_TERMINATING ) )
206             {
207 
208                 doUpdateStates( agreementProperties );
209 
210                 //
211                 // set the updated state at once and update the agreement execution properties
212                 //
213                 synchronized ( getAgreementInstance().getXMLObject() )
214                 {
215                     getAgreementInstance().setState( agreementProperties.getAgreementState() );
216                     getAgreementInstance().setServiceTermStates(
217                         agreementProperties.getServiceTermStateArray() );
218                     getAgreementInstance().setGuaranteeTermStates(
219                         agreementProperties.getGuaranteeTermStateArray() );
220 
221                     getAgreementInstance().getExecutionContext().putAll( monitoringContext.getProperties() );
222 
223                 }
224             }
225 
226             getAgreementInstance().notifyObservers();
227         }
228     }
229 
230     private void doUpdateStates( AgreementPropertiesType agreementProperties ) throws Exception
231     {
232         try
233         {
234             //
235             // first we update the state of the service terms
236             //
237             boolean monitoringResult = updateServiceTermStates( agreementProperties );
238 
239             //
240             // Now we evaluate the guarantees defined in this agreement
241             //
242             GuaranteeTermStateType[] gStates = new GuaranteeTermStateType[0];
243 
244             try
245             {
246                 //
247                 // Get the auto generated service term state documents.
248                 //
249                 gStates = agreementProperties.getGuaranteeTermStateArray();
250             }
251             catch ( Exception e )
252             {
253                 String error = Messages.formatString( ERR_GET_GUARANTEE_STATES, e.getMessage() );
254                 throw new Exception( error, e );
255             }
256 
257             //
258             // If the service term states were updated, the guarantees are evaluated.
259             // Otherwise, all guarantees are in the state not determined. This is an
260             // error of the system and human intervention is required.
261             //
262             if ( monitoringResult )
263             {
264                 Vector<GuaranteeEvaluationResultType> evalResults =
265                     new Vector<GuaranteeEvaluationResultType>();
266                 //
267                 // Now evaluate the guarantee term state
268                 //
269                 for ( int i = 0; i < gStates.length; i++ )
270                 {
271                     try
272                     {
273                         GuaranteeEvaluationResultType result =
274                             updateGuaranteeTermState( gStates[i].getTermName(), agreementProperties );
275                         evalResults.add( result );
276                     }
277                     catch ( Exception e )
278                     {
279                         String error =
280                             Messages.formatString( ERR_UPDATE_GUARANTEE_STATE, gStates[i].getTermName(),
281                                 e.getMessage() );
282                         throw new Exception( error, e );
283                     }
284                 }
285 
286                 //
287                 // create the notification event, update the states and notify the accounting system
288                 //
289                 SLAMonitoringNotificationEventType monitoringEvent =
290                     SLAMonitoringNotificationEventType.Factory.newInstance();
291 
292                 monitoringEvent.setAgreementId( getAgreementInstance().getAgreementId() );
293 
294                 for ( int i = 0; i < gStates.length; i++ )
295                 {
296                     GuaranteeEvaluationResultType result = evalResults.get( i );
297                     gStates[i] = result.getDetails().getGuaranteeState();
298                     monitoringEvent.addNewGuaranteeEvaluationResult().set( result );
299                 }
300 
301                 getMonitoringContext().getAccountingSystem().issueCompensation( monitoringEvent );
302             }
303             else
304             {
305                 for ( int i = 0; i < gStates.length; i++ )
306                 {
307                     gStates[i].setState( GuaranteeTermStateDefinition.NOT_DETERMINED );
308                 }
309             }
310             //
311             // update the agreement property document at once and update the overall agreement state
312             //
313             agreementProperties.setGuaranteeTermStateArray( gStates );
314             updateAgreementState( agreementProperties );
315 
316         }
317         catch ( Exception e )
318         {
319             LOG.error( e.getMessage() );
320             throw e;
321         }
322     }
323 
324     private void updateAgreementState( AgreementPropertiesType agreementProperties )
325     {
326         try
327         {
328             AgreementStateType state = agreementProperties.getAgreementState();
329 
330             ServiceTermStateType[] sdtstates = agreementProperties.getServiceTermStateArray();
331             for ( int i = 0; i < sdtstates.length; i++ )
332             {
333                 if ( ( sdtstates[i].getState() == ServiceTermStateDefinition.NOT_READY )
334                     || ( sdtstates[i].getState() == ServiceTermStateDefinition.READY ) )
335                 {
336                     if ( state.getState() == AgreementStateDefinition.OBSERVED_AND_TERMINATING )
337                     {
338                         //
339                         // if the agreement is currently terminating we keep this state
340                         //
341                         return;
342                     }
343                     else
344                     {
345                         //
346                         // in all other cases (pending, ...) we change to observed state
347                         //
348                         state.setState( AgreementStateDefinition.OBSERVED );
349                     }
350                     return;
351                 }
352             }
353 
354             //
355             // only if all service term states are completed, the overall agreement is completed
356             //
357             state.setState( AgreementStateDefinition.COMPLETE );
358         }
359         catch ( Exception e )
360         {
361             LOG.error( LogMessage.getMessage( ERR_UPDATE_AGREEMENT_STATE, e.getMessage() ) );
362             LOG.debug( e );
363         }
364     }
365 
366     private boolean updateServiceTermStates( AgreementPropertiesType agreementProperties ) throws Exception
367     {
368         try
369         {
370             //
371             // Get the auto generated service term state documents.
372             //
373             ServiceTermStateType[] states = new ServiceTermStateType[0];
374             try
375             {
376                 states = agreementProperties.getServiceTermStateArray();
377             }
378             catch ( Exception e )
379             {
380                 String error = Messages.formatString( ERR_GET_STD_STATES, e.getMessage() );
381                 throw new Exception( error, e );
382             }
383 
384             //
385             // Initialize the current monitoring context
386             //
387             IMonitoringContext currentMonitoringContext = (IMonitoringContext) monitoringContext.clone();
388 
389             try
390             {
391                 currentMonitoringContext.setServiceTemState( new ServiceTermStateType[0] );
392 
393                 //
394                 // we copy of the service term states and set the for the current monitoring context
395                 //
396                 for ( int i = 0; i < states.length; i++ )
397                 {
398                     states[i] = (ServiceTermStateType) states[i].copy();
399                 }
400 
401                 currentMonitoringContext.setServiceTemState( states );
402             }
403             catch ( Exception e )
404             {
405                 throw new IllegalStateException( Messages.getString( ERR_INIT_SDT_STATES ), e );
406             }
407 
408             //
409             // do the state monitoring
410             //
411             boolean monitoringResult = stateMonitor.monitor( currentMonitoringContext );
412 
413             //
414             // finally update the agreement monitoring context
415             // and the service term states in the agreement
416             //
417             agreementProperties.setServiceTermStateArray( currentMonitoringContext.getServiceTermStates() );
418             monitoringContext = currentMonitoringContext;
419 
420             return monitoringResult;
421         }
422         catch ( Exception e )
423         {
424             String message = LogMessage.format( ERR_UPD_STD_STATES, e.getMessage() );
425             throw new Exception( message, e );
426         }
427     }
428 
429     private GuaranteeTermType loadGuaranteeTerm( String name, AgreementPropertiesType agreementProperties )
430     {
431         String xpath = XPATH_NS_DECL_WSAG + MessageFormat.format( XPATH_QUERY_GUARANTEE_TERM, name );
432         XmlObject[] result = agreementProperties.selectPath( xpath );
433 
434         if ( result.length == 0 )
435         {
436             LOG.warn( Messages.formatString( WARN_GURANTEE_NOT_FOUND, name ) );
437             return null;
438         }
439 
440         if ( result.length > 1 )
441         {
442             LOG.warn( Messages.formatString( WARN_MULTIPLE_GUARANTEES, name ) );
443         }
444 
445         return (GuaranteeTermType) result[0];
446     }
447 
448     private ServicePropertiesType loadServiceProperties( String serviceName,
449                                                          AgreementPropertiesType agreementProperties )
450     {
451         String xpath =
452             XPATH_NS_DECL_WSAG + MessageFormat.format( XPATH_QUERY_SERVICE_PROPERTIES, serviceName );
453 
454         XmlObject[] result = agreementProperties.selectPath( xpath );
455 
456         if ( result.length == 0 )
457         {
458             LOG.warn( Messages.formatString( WARN_SP_DEF_NOT_FOUND, serviceName ) );
459             ServicePropertiesType empty = ServicePropertiesType.Factory.newInstance();
460             empty.setName( "empty" ); //$NON-NLS-1$
461             empty.setServiceName( serviceName );
462             empty.addNewVariableSet();
463             return empty;
464         }
465 
466         if ( result.length > 1 )
467         {
468             String warn = Messages.formatString( WARN_MULTIPLE_SP_DEFS, serviceName );
469             LOG.warn( warn );
470         }
471 
472         return (ServicePropertiesType) result[0];
473     }
474 
475     private GuaranteeEvaluationResultType
476         updateGuaranteeTermState( String termName, AgreementPropertiesType agreementProperties )
477             throws Exception
478     {
479         GuaranteeTermType guarantee = loadGuaranteeTerm( termName, agreementProperties );
480 
481         LOG.debug( LogMessage.getMessage( DBG_EVAL_GUARANTEE_STATE, termName ) );
482 
483         Map<String, Object> variableMap = new HashMap<String, Object>();
484 
485         for ( int i = 0; i < guarantee.getServiceScopeArray().length; i++ )
486         {
487             //
488             // for each service we should only have one instance
489             // of service properties defined
490             //
491             ServiceSelectorType scope = guarantee.getServiceScopeArray( i );
492             ServicePropertiesType properties =
493                 loadServiceProperties( scope.getServiceName(), agreementProperties );
494 
495             LOG.debug( LogMessage.getMessage( DBG_SERVICE_PROPERTIES, properties.getServiceName(),
496                 properties.getName() ) );
497 
498             ServicePropertyResolver resolver = new ServicePropertyResolver( properties, agreementProperties );
499             Map<String, Object> var = resolver.resolveServiceProperties();
500 
501             Iterator<String> keys = var.keySet().iterator();
502             while ( keys.hasNext() )
503             {
504                 String variableName = (String) keys.next();
505                 if ( variableMap.containsKey( variableName ) )
506                 {
507                     LOG.debug( LogMessage.getMessage( DBG_DUPLICATE_VAR_DEF, variableName ) );
508                 }
509                 else
510                 {
511                     variableMap.put( variableName, var.get( variableName ) );
512                 }
513             }
514         }
515 
516         IGuaranteeEvaluator evaluator = new SimpleGuaranteeEvaluator();
517         return evaluator.evaluate( guarantee, variableMap );
518     }
519 
520 }