com.microsoft.tfs.core.checkinpolicies
Class PolicyBase

java.lang.Object
  extended by com.microsoft.tfs.core.checkinpolicies.PolicyBase
All Implemented Interfaces:
PolicyInstance, com.microsoft.tfs.util.Closable

public abstract class PolicyBase
extends java.lang.Object
implements PolicyInstance

A convenient base class for checkin policy implementers.

Events

Policy implementations can fire an event (PolicyStateChangedEvent) to indicate to upper layers in the framework that that policy has re-evaluated itself, and has built a new set of failures (perhaps an empty set).

Simple policies that do not respond to external events like timers or events from other components do not need to fire this event. More complicated policies might re-evaluate their rules because of events fired by other components , so methods to register listeners and fire the event have been implemented for your convenience.

To fire the event, simply invoke firePolicyStateChangedEvent(PolicyFailure[]) with the new array of failures (an empty array signifies no failures).

Event Example

A policy for the Plug-in for Eclipse wants to return policy failures if unit tests for the pending checkin do not pass. In this example, the unit tests are managed by a long-running component that fires events when the user runs the tests.

  1. Eclipse starts (no unit tests have been run) and the user views the Check-in Policies results view.
  2. The framework loads the policy and calls initialize(PendingCheckin, PolicyContext) with the current pending check-in.
  3. initialize(PendingCheckin, PolicyContext) finds the running unit test component, and registers itself to handle test pass/failure events.
  4. The policy immediately fires the PolicyStateChangedEvent with failures describing the current test state ("Unit tests have not completed"). These failures prevent prevent a check-in.
  5. If the user attempts to check-in his changes, the policy framework invokes evaluate(PolicyContext) on the policy, and it re-queries the test component for results, returning the appropriate failures.
  6. Some time later, when the user runs the unit tests, the pass/fail event fires, and the policy handles this event by firing its own PolicyStateChangedEvent with a new set of failures (or an empty array when all tests pass).

Later, when close() is called, event handlers are removed from the unit test component.

Declaring Editable

Make sure to override canEdit() to return false if your policy does not support user configuration (i.e. it has no settings to configure). If canEdit() returns true (the default), the "Edit" button or UI element is enabled when a policy is displayed in user interfaces. If it returns false, the user is prevented from editing the policy definition ( edit(PolicyEditArgs) will not be invoked).

Thread Safety

This class is thread-safe, but implementations are not required to be. The policy framework will not invoke policy methods from multiple threads concurrently. Policies that run in the Eclipse environment and interact with other components or Eclipse plug-ins with events should ensure their error handlers interact with policy data in a thread-safe way.

The framework does not guarantee which thread will be used to invoke evaluate(PolicyContext). Implementations must marshall any thread-sensitive work in this method (for example, user interface work in SWT/Eclipse) to the correct thread manually. See the thread policy notice in PolicyInstance for important information.

Since:
TEE-SDK-10.1
Thread-safety:
thread-compatible

Constructor Summary
PolicyBase()
           All policy implementations must include a zero-argument constructor, so they can be dynamically created by the policy framework.
 
Method Summary
 void activate(PolicyFailure failure, PolicyContext context)
           Called when the user activates (by double-clicking or some other user interface) a failure generated by a previous call to PolicyInstance.evaluate(PolicyContext).
 void addPolicyStateChangedListener(PolicyStateChangedListener listener)
          Adds a policy state changed listener that receives a PolicyStateChangedEvent whenever this policy is evaluated and a new set of failures is generated.
 boolean canEdit()
          
 void close()
          Removes all event listeners from this policy instance.
 void displayHelp(PolicyFailure failure, PolicyContext context)
           Shows help about the given failure if it was selected for help in the user interface.
abstract  boolean edit(PolicyEditArgs policyEditArgs)
           Edits the policy's configuration by interacting with the graphical user interface, if appropriate, or by other means.
abstract  PolicyFailure[] evaluate(PolicyContext context)
           Evaluates the pending checkin for policy compliance and returns any failures encountered.
protected  void firePolicyStateChangedEvent(PolicyFailure[] failures)
          Fires the PolicyStateChangedEvent with the given event failures, filling in the other PolicyStateChangedEvent fields automatically.
protected  void firePolicyStateChangedEvent(PolicyStateChangedEvent event)
          Fires the given PolicyStateChangedEvent, which must be constructed manually.
protected  PendingCheckin getPendingCheckin()
           
abstract  PolicyType getPolicyType()
          
 void initialize(PendingCheckin pendingCheckin, PolicyContext context)
           Prepares a PolicyInstance for policy evaluation.
abstract  void loadConfiguration(Memento configurationMemento)
           Loads run-time configuration information from the given Memento, which was previously build by a call to PolicyInstance.saveConfiguration(Memento).
 void removePolicyStateChangedListener(PolicyStateChangedListener listener)
          Removes a policy state changed listener that was previously added via PolicyInstance.addPolicyStateChangedListener(PolicyStateChangedListener).
abstract  void saveConfiguration(Memento configurationMemento)
           Saves the run-time configuration of this instance to the given (empty except for name) Memento object, which will be persisted by the framework in the policy definition in the Team Foundation Server.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

PolicyBase

public PolicyBase()

All policy implementations must include a zero-argument constructor, so they can be dynamically created by the policy framework.

Policies should prefer to hook up evaluation-specific events to other objects in initialize(PendingCheckin, PolicyContext) instead of in the constructor, and unhook them in close(). This is because policy instances are constructed during configuration, when no evaluation will be performed. Policies should also assure that events are only hooked up as many times as needed in initialize(PendingCheckin, PolicyContext), since it may be called multiple times during a policy instance's lifetime.

Method Detail

addPolicyStateChangedListener

public void addPolicyStateChangedListener(PolicyStateChangedListener listener)
Adds a policy state changed listener that receives a PolicyStateChangedEvent whenever this policy is evaluated and a new set of failures is generated.

Policies being evaluated in a graphical context (in an application like the Plug-in for Eclipse, or Explorer) can fire this event to cause the graphical display of their state (including failures) to be updated.

Specified by:
addPolicyStateChangedListener in interface PolicyInstance
Parameters:
listener - the listener to add (must not be null)

removePolicyStateChangedListener

public void removePolicyStateChangedListener(PolicyStateChangedListener listener)
Removes a policy state changed listener that was previously added via PolicyInstance.addPolicyStateChangedListener(PolicyStateChangedListener). changes.

Specified by:
removePolicyStateChangedListener in interface PolicyInstance
Parameters:
listener - the listener to remove (must not be null)
See Also:
PolicyInstance.addPolicyStateChangedListener(PolicyStateChangedListener)

firePolicyStateChangedEvent

protected void firePolicyStateChangedEvent(PolicyFailure[] failures)
Fires the PolicyStateChangedEvent with the given event failures, filling in the other PolicyStateChangedEvent fields automatically.

This is the preferred way to fire the PolicyStateChangedEvent.

Parameters:
failures - the failures to include with other event information (may be null: will be converted to an empty failure array).

firePolicyStateChangedEvent

protected void firePolicyStateChangedEvent(PolicyStateChangedEvent event)
Fires the given PolicyStateChangedEvent, which must be constructed manually.

firePolicyStateChangedEvent(PolicyFailure[]) fills in some fields automatically, and is preferred to this method.

Parameters:
event - the event to fire (must not be null)
See Also:
firePolicyStateChangedEvent(PolicyFailure[])

getPendingCheckin

protected PendingCheckin getPendingCheckin()
Returns:
the pending checkin this PolicyInstance was configured with. Never returns null.
Throws:
java.lang.IllegalStateException - if initialize(PendingCheckin, PolicyContext) has not yet been called on this object.

canEdit

public boolean canEdit()

Specified by:
canEdit in interface PolicyInstance
Returns:
true if this policy's run-time configuration can be edited, false if editing should be disallowed by the user interface.

activate

public void activate(PolicyFailure failure,
                     PolicyContext context)

Called when the user activates (by double-clicking or some other user interface) a failure generated by a previous call to PolicyInstance.evaluate(PolicyContext). Implementations should further explain the failure, perhaps presenting additional information or proposing a solution.

Always called after the framework has called PolicyInstance.initialize(PendingCheckin, PolicyContext).

Thread Policy

The policy framework always invokes this method on the user-interface thread, if the graphical environment where the framework is hosted requires it. Implementations may use the graphical interface context objects directly, without marhsalling calls to the UI thread.

Specified by:
activate in interface PolicyInstance
Parameters:
failure - the failure to activate or display (must not be null)
context - contextual settings that may include information about the user interface, etc. (must not be null)

displayHelp

public void displayHelp(PolicyFailure failure,
                        PolicyContext context)

Shows help about the given failure if it was selected for help in the user interface.

Always called after the framework has called PolicyInstance.initialize(PendingCheckin, PolicyContext).

Thread Policy

The policy framework always invokes this method on the user-interface thread, if the graphical environment where the framework is hosted requires it. Implementations may use the graphical interface context objects directly, without marhsalling calls to the UI thread.

Specified by:
displayHelp in interface PolicyInstance
Parameters:
failure - the failure to display help for (must not be null)
context - contextual settings that may include information about the user interface, etc. (must not be null)

initialize

public void initialize(PendingCheckin pendingCheckin,
                       PolicyContext context)

Prepares a PolicyInstance for policy evaluation. The framework tries to keep PolicyInstance instances around as long as possible, for performance reasons, so it will invoke this method repeatedly to re-configure the object for a new pending checkin.

If you allocate resources in this method, Closable.close() is a good place to release them.

Implementations should not save the PolicyContext object for later use, because the framework may pass a different context to PolicyInstance.evaluate(PolicyContext).

Implementations should not perform user interface work in this method because the framework tries to initialize a policy as lazily as it can, but also must call initialize many times as the checkin data changes.

Specified by:
initialize in interface PolicyInstance
Parameters:
pendingCheckin - the pending changes that will be evaluated by this PolicyInstance (must not be null)
context - contextual settings that may include information about the user interface, etc. (must not be null)

close

public void close()
Removes all event listeners from this policy instance. Do not use this object after calling close(). Extending classes should make sure to call super.close() if they override this method.

Specified by:
close in interface com.microsoft.tfs.util.Closable

loadConfiguration

public abstract void loadConfiguration(Memento configurationMemento)

Loads run-time configuration information from the given Memento, which was previously build by a call to PolicyInstance.saveConfiguration(Memento).

Implementations should not perform user interface work in this method.

Specified by:
loadConfiguration in interface PolicyInstance
Parameters:
configurationMemento - the Memento to load settings from (must not be null)

saveConfiguration

public abstract void saveConfiguration(Memento configurationMemento)

Saves the run-time configuration of this instance to the given (empty except for name) Memento object, which will be persisted by the framework in the policy definition in the Team Foundation Server.

Implementations should not perform user interface work in this method.

Memento Notes

Implementations should not store text data directly inside the given memento node (via Memento.putTextData(String), but instead they should create child nodes to store text data. Any text data stored on the given node will be discarded when it is saved. Implementations are encouraged to set other types of attributes (Integer, String, Boolean, etc.) directly on the given node or any child nodes they create.

Specified by:
saveConfiguration in interface PolicyInstance
Parameters:
configurationMemento - the empty (except for name) Memento to save settings to (must not be null)

edit

public abstract boolean edit(PolicyEditArgs policyEditArgs)

Edits the policy's configuration by interacting with the graphical user interface, if appropriate, or by other means. Implementations should obtain references to user interface objects from the PolicyEditArgs map. This object's configuration is later retrieved by the framework (via PolicyInstance.saveConfiguration(Memento)) and saved in the policy definition on the Team Foundation Server.

The policy framework will always invoke this method from the UI thread when running in Eclipse and Explorer.

Thread Policy

The policy framework always invokes this method on the user-interface thread, if the graphical environment where the framework is hosted requires it. Implementations may use the graphical interface context objects directly, without marhsalling calls to the UI thread.

Specified by:
edit in interface PolicyInstance
Parameters:
policyEditArgs - a map of strings to objects that can be used as context for interface building.
Returns:
true if the user made changes to this policy's configuration, false if the edit operation was cancelled and no changes were made.

getPolicyType

public abstract PolicyType getPolicyType()

Specified by:
getPolicyType in interface PolicyInstance
Returns:
the PolicyType information for this instance.

evaluate

public abstract PolicyFailure[] evaluate(PolicyContext context)
                                  throws PolicyEvaluationCancelledException

Evaluates the pending checkin for policy compliance and returns any failures encountered. Called by the checkin policy framework at various times during the life of the PolicyInstance object, but always after PolicyInstance.initialize(PendingCheckin, PolicyContext) was called with a pending checkin and contextual information.

Implementations should not save the PolicyContext object for later use, becuase the objects inside it are not guaranteed to persist after PolicyInstance.evaluate(PolicyContext) returns. This restriction means that policies which call their own PolicyInstance.evaluate(PolicyContext) method (as a result of an external event or some other design decision) must create their own PolicyContext instances for this call. They can re-use the values from the original, framework-called PolicyInstance.evaluate(PolicyContext) at their own risk--these objects may become stale or invalid.

Thread Policy

Implementations must not assume this method will be invoked on any specific thread. More specifically, if the framework is running in an application with a graphical user interface, any user-interface work done in the policy (through objects obtained in the context, for example) must be marshalled to the correct thread, if required by the interface toolkit in use. For Eclipse plug-ins, this means access to all user-interface objects should be done by by org.eclipse.swt.widgets.Display's asyncExec(Runnable) or syncExec(Runnable) methods.

Specified by:
evaluate in interface PolicyInstance
Parameters:
context - contextual settings that may include information about the user interface, etc. (must not be null)
Returns:
any failures encounterd by this policy, or an empty PolicyFailure array if none encountered.
Throws:
PolicyEvaluationCancelledException - if the user cancelled the policy evaluation.


© 2015 Microsoft. All rights reserved.