1 var Class = require("../lib/mootools/mootools-node.js").Class;
  2 
  3 var RenderingController = require("../lib/RenderingController.js").RenderingController;
  4 
  5 /**
  6  * @class RequestProcessor
  7  * @requires Class
  8  * @requires RenderingController
  9  * @param {http.ServerRequest} request
 10  * @param {http.ServerResponse} response
 11  * @throws {RequestProcessor.Exception.INVALID_REQUEST_RESPONSE} if constructor parameters are invalid or null.
 12  */
 13 var RequestProcessor = function(){
 14     /**
 15      * Request object
 16      * @public 
 17      * @type {http.ServerRequest}
 18      */
 19     this.request = null;
 20     /**
 21      * Response object
 22      * @public
 23      * @type {http.ServerResponse}
 24      */
 25     this.response = null;
 26     /**
 27      * holds the request id
 28      * @private 
 29      * @type {mixed}
 30      */
 31     this._id;
 32     
 33     /** @ignore */
 34     this.initialize = function(request, response){
 35         if(!request || !response){
 36             throw RequestProcessor.Exception.INVALID_REQUEST_RESPONSE;
 37         }
 38 
 39         console.time('   -- REQUEST TIME');
 40         this.request = request;
 41         this.response = response;
 42     };
 43     /**
 44      * Starts processing the request. Creates and dispatches rendering flow.
 45      * @public
 46      */
 47     this.process = function(){
 48         //FIXME: dodac sprawdzanie czy format zapytania jest zgodny z jsonrpc - dla zapewnienia kompatybilnosci ze standardem
 49         //sprawdzam czy podanego json da sie sparsowac
 50         try{
 51             var request = JSON.parse(this.request.data);
 52         } catch(error){
 53             this.sendResponse({
 54                 error: {
 55                     code: -32700,
 56                     message: "Invalid JSON. An error occurred on the server while parsing the JSON text.",
 57                     data: error
 58                 }
 59             });
 60             return;
 61         }
 62         //weryfikuje poprawnosc zapytania
 63         if(!request.hasOwnProperty("method") ||
 64            !request.hasOwnProperty("jsonrpc") || request.jsonrpc != "2.0" ||
 65            !request.hasOwnProperty("params") ||
 66            !request.hasOwnProperty("id") || request.id == ""){
 67             this.sendResponse({
 68                 error: {
 69                     code: -32600,
 70                     message: "The received JSON is not a valid JSON-RPC Request."
 71                 }
 72             });
 73             return;
 74         }else{
 75             this._id = request.id;
 76         }
 77         
 78         //weryfikuje metode
 79         if(request.method != "render"){
 80             this.sendResponse({
 81                 error: {
 82                     code: -32601,
 83                     message: "The requested remote-procedure does not exist / is not available."
 84                 }
 85             });
 86             return;
 87         }
 88         
 89         //weryfikuje poprawnosc konfiguracji
 90         try{
 91             var controller = new RenderingController(request.params);            
 92         }catch(e){
 93             this.sendResponse({
 94                 error: {
 95                     code: -32602,
 96                     message: "Invalid method parameters.",
 97                     data: e
 98                 }
 99             });
100             return;            
101         }
102 
103         //wywalam ogolny blad jesli nie zostal przez nic glebiej przechwycony
104         try{
105             controller.addEventListener(RenderingController.RENDERED, this._onRenderingSuccess, this);
106             controller.addEventListener(RenderingController.ERROR, this._onRenderingError, this);
107             controller.render();
108         }catch(e){
109             this.sendResponse({
110                 error: {
111                     code: -32603,
112                     message: "Internal JSON-RPC error.",
113                     data: e
114                 }
115             });
116             return;  
117         }
118     };
119     /**
120      * Called on rendering success
121      * 
122      * @param {Event} e
123      * @private
124      */
125     this._onRenderingSuccess = function(e){
126         this.sendResponse({
127             result: e.data
128         });
129     };
130     /**
131      * Called on rendering error
132      * 
133      * @param {ErrorEvent} e
134      * @private
135      */
136     this._onRenderingError = function(e){
137         this.sendResponse({
138             error: {
139                 code: -123,
140                 message: e.toHtmlString()
141             }
142         });
143     };
144     /**
145      * Sends response
146      *
147      * @param {Object} data Response data.
148      */
149     this.sendResponse = function(data){
150         console.timeEnd('   -- REQUEST TIME');
151         this.response.writeHead(200, {
152             'Content-Type': 'application/json; charset=utf-8',
153             'Access-Control-Allow-Origin': '*'
154         });
155 
156         this.response.end(new Buffer(JSON.stringify(this._merge({
157             id: this._id,
158             jsonrpc: "2.0"
159         }, data))));
160         console.log('-- request ended with Success: 200');
161     };
162     
163     /**
164      * helper method, merges two or more object into one
165      * 
166      * @param {object}
167      * @private
168      * 
169      * @returns {object} merged object
170      */
171     this._merge = function(){
172         if(!arguments.length){
173             return;
174         }
175         
176         var tmp = {};
177         
178         for(var i = 0, l = arguments.length; i < l; i++){
179             for(var key in arguments[i]){
180                 if(arguments[i].hasOwnProperty(key)){
181                     tmp[key] = arguments[i][key];
182                 }
183             }
184         }
185         
186         return tmp;
187     };
188 };
189 
190 RequestProcessor = new Class( new RequestProcessor() );
191 
192 /**
193  * Namespace for exeptions messages.
194  * @static
195  * @constant
196  * @namespace
197  */
198 RequestProcessor.Exception = {};
199 /**
200  * @static
201  * @constant
202  */
203 RequestProcessor.Exception.INVALID_REQUEST_RESPONSE = "Invalid Request and/or Response objects";
204 
205 exports.RequestProcessor = RequestProcessor;