r20569: Web Application Framework
authorDerrell Lipman <derrell@samba.org>
Fri, 5 Jan 2007 21:20:11 +0000 (21:20 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:37:02 +0000 (14:37 -0500)
- Fix handling of predicates in finite state machine

- Make use of predicates to handle a specific PermissionDenied failure, vs
  some other generic failure

- Add JSON-RPC error constants
(This used to be commit 38ae9658cb52149d66f910582d8b55fe954650fb)

webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/State.js
webapps/swat/source/class/swat/module/AbstractModuleFsm.js

index fc054e304aa24f9063461954bd19f14e0510ec31..718961d0b58b2fd887c77986710f681c3207fd10 100644 (file)
@@ -493,14 +493,17 @@ qx.Proto._checkEvents = function(propValue, propData)
       for (action_e in action)
       {
         if (typeof(action[action_e]) == "number" &&
-            action != qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE &&
-            action != qx.util.fsm.FiniteStateMachine.EventHandling.BLOCKED)
+            action[action_e] !=
+              qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE &&
+            action[action_e] !=
+              qx.util.fsm.FiniteStateMachine.EventHandling.BLOCKED)
         {
           throw new Error("Invalid numeric value in events object " +
                           "(" + e + "): " +
                           action_e + ": " + action[action_e]);
         }
-        else if (typeof(action[action_e]) != "string")
+        else if (typeof(action[action_e]) != "string" &&
+                 typeof(action[action_e]) != "number")
         {
           throw new Error("Invalid value in events object " +
                           "(" + e + "): " +
@@ -508,7 +511,7 @@ qx.Proto._checkEvents = function(propValue, propData)
         }
       }
     }
-    else if (typeof(action) != "string")
+    else if (typeof(action) != "string" && typeof(action) != "number")
     {
       throw new Error("Invalid value in events object: " +
                       e + ": " + propValue[e]);
index a2564e708a9a901ede1d7879d66694e5e6cd09a9..2b54b4fab46aac405b1957b9f601ee960eabfc88 100644 (file)
@@ -131,30 +131,40 @@ qx.Proto.addAwaitRpcResultState = function(module)
           "Transition_AwaitRpcResult_to_PopStack_via_complete",
 
         "failed" :
-          "Transition_AwaitRpcResult_to_PopStack_via_failed"
+          qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE
       }
     });
   fsm.addState(state);
 
+  /*** Transitions that use a PREDICATE appear first ***/
+
   /*
-   * Transition: AwaitRpcResult to AwaitRpcResult
+   * Transition: AwaitRpcResult to GetAuthInfo
    *
-   * Cause: "execute" on swat.module.fsmUtils.abort_rpc
+   * Cause: "failed" (on RPC) where reason is PermissionDenied
    */
   var trans = new qx.util.fsm.Transition(
-    "Transition_AwaitRpcResult_to_AwaitRpcResult_via_button_abort",
+    "Transition_AwaitRpcResult_to_GetAuthInfo",
     {
       "nextState" :
-        "State_AwaitRpcResult",
+        qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK,
 
-      "ontransition" :
+      "predicate" :
         function(fsm, event)
         {
-          // Get the request object
-          var rpcRequest = _this.getCurrentRpcRequest();
+          var error = event.getData(); // retrieve the JSON-RPC error
 
-          // Issue an abort for the pending request
-          rpcRequest.request.abort();
+          // Did we get get origin=Server, code=PermissionDenied ?
+          var origins = swat.module.AbstractModuleFsm.JsonRpc_Origin;
+          var serverErrors = swat.module.AbstractModuleFsm.JsonRpc_ServerError;
+          if (error.origin == origins.Server &&
+              error.code == serverErrors.PermissionDenied)
+          {
+            return true;
+          }
+
+          // fall through to next transition, also for "failed"
+          return false;
         }
     });
   state.addTransition(trans);
@@ -162,10 +172,10 @@ qx.Proto.addAwaitRpcResultState = function(module)
   /*
    * Transition: AwaitRpcResult to PopStack
    *
-   * Cause: "complete" (on RPC)
+   * Cause: "failed" (on RPC)
    */
   var trans = new qx.util.fsm.Transition(
-    "Transition_AwaitRpcResult_to_PopStack_via_complete",
+    "Transition_AwaitRpcResult_to_PopStack_via_failed",
     {
       "nextState" :
         qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK,
@@ -179,20 +189,45 @@ qx.Proto.addAwaitRpcResultState = function(module)
           // Generate the result for a completed request
           rpcRequest.setUserData("result",
                                   {
-                                      type : "complete",
+                                      type : "failed",
                                       data : event.getData()
                                   });
         }
     });
   state.addTransition(trans);
 
+  /*** Remaining transitions are accessed via the jump table ***/
+
+  /*
+   * Transition: AwaitRpcResult to AwaitRpcResult
+   *
+   * Cause: "execute" on swat.module.fsmUtils.abort_rpc
+   */
+  var trans = new qx.util.fsm.Transition(
+    "Transition_AwaitRpcResult_to_AwaitRpcResult_via_button_abort",
+    {
+      "nextState" :
+        "State_AwaitRpcResult",
+
+      "ontransition" :
+        function(fsm, event)
+        {
+          // Get the request object
+          var rpcRequest = _this.getCurrentRpcRequest();
+
+          // Issue an abort for the pending request
+          rpcRequest.request.abort();
+        }
+    });
+  state.addTransition(trans);
+
   /*
    * Transition: AwaitRpcResult to PopStack
    *
-   * Cause: "failed" (on RPC)
+   * Cause: "complete" (on RPC)
    */
   var trans = new qx.util.fsm.Transition(
-    "Transition_AwaitRpcResult_to_PopStack_via_failed",
+    "Transition_AwaitRpcResult_to_PopStack_via_complete",
     {
       "nextState" :
         qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK,
@@ -206,7 +241,7 @@ qx.Proto.addAwaitRpcResultState = function(module)
           // Generate the result for a completed request
           rpcRequest.setUserData("result",
                                   {
-                                      type : "failed",
+                                      type : "complete",
                                       data : event.getData()
                                   });
         }
@@ -317,3 +352,104 @@ qx.Proto.getCurrentRpcRequest = function()
   return this._requests[this._requests.length - 1];
 };
 
+
+/**
+ * JSON-RPC error origins
+ */
+qx.Class.JsonRpc_Origin =
+{
+  Server              : 1,
+  Application         : 2,
+  Transport           : 3,
+  Client              : 4
+};
+
+
+/**
+ * JSON-RPC Errors for origin == Server
+ */
+qx.Class.JsonRpc_ServerError =
+{
+  /**
+   * Error code, value 0: Unknown Error
+   *
+   * The default error code, used only when no specific error code is passed
+   * to the JsonRpcError constructor.  This code should generally not be used.
+   */
+  Unknown               : 0,
+
+  /**
+   * Error code, value 1: Illegal Service
+   *
+   * The service name contains illegal characters or is otherwise deemed
+   * unacceptable to the JSON-RPC server.
+   */
+  IllegalService        : 1,
+
+  /**
+   * Error code, value 2: Service Not Found
+   *
+   * The requested service does not exist at the JSON-RPC server.
+   */
+  ServiceNotFound       : 2,
+
+  /**
+   * Error code, value 3: Class Not Found
+   *
+   * If the JSON-RPC server divides service methods into subsets (classes),
+   * this indicates that the specified class was not found.  This is slightly
+   * more detailed than "Method Not Found", but that error would always also
+   * be legal (and true) whenever this one is returned. (Not used in this
+   * implementation)
+   */
+  ClassNotFound         : 3, // not used in this implementation
+
+  /**
+   * Error code, value 4: Method Not Found
+   *
+   * The method specified in the request is not found in the requested
+   * service.
+   */
+  MethodNotFound        : 4,
+
+  /*
+   * Error code, value 5: Parameter Mismatch
+   *
+   * If a method discovers that the parameters (arguments) provided to it do
+   * not match the requisite types for the method's parameters, it should
+   * return this error code to indicate so to the caller.
+   *
+   * This error is also used to indicate an illegal parameter value, in server
+   * scripts.
+   */
+  ParameterMismatch     : 5,
+
+  /**
+   * Error code, value 6: Permission Denied
+   *
+   * A JSON-RPC service provider can require authentication, and that
+   * authentication can be implemented such the method takes authentication
+   * parameters, or such that a method or class of methods requires prior
+   * authentication.  If the caller has not properly authenticated to use the
+   * requested method, this error code is returned.
+   */
+  PermissionDenied      : 6,
+
+  /*
+   * Error code, value 7: Unexpected Output
+   *
+   * The called method illegally generated output to the browser, which would
+   * have preceeded the JSON-RPC data.
+   */
+  UnexpectedOutput      : 7,
+
+  /*
+   * Error code, value 8: Resource Error
+   *
+   * Too many resources were requested, a system limitation on the total
+   * number of resources has been reached, or a resource or resource id was
+   * misused.
+   */
+  ResourceError         : 8
+
+};