Compare commits

..

195 Commits

Author SHA1 Message Date
Jocelyn Fiat eaa99c9c61 Used object test 2011-10-19 00:40:04 +02:00
Jocelyn Fiat 5f492d6fb6 removed useless local variable 2011-10-19 00:35:32 +02:00
Jocelyn Fiat c3f5376ef5 fixed cgi and libfcgi connectors due to recent changes from WGI_APPLICATION 2011-10-14 14:27:54 +02:00
Jocelyn Fiat 21e973f8a4 Removed handling of internal error from WGI_APPLICATION
And for now added it into nino connector
2011-10-14 14:15:23 +02:00
Jocelyn Fiat dec1958909 Fixed issue with index in uri template matcher 2011-10-14 14:14:13 +02:00
Jocelyn Fiat 1453873b6c Added HTTP_FILE_EXTENSION_MIME_MAPPING
Added REQUEST_FILE_SYSTEM_HANDLER to the router library
Added file system handler in "hello_routed_world" example
2011-10-14 14:13:40 +02:00
Jocelyn Fiat 4c36d75ef3 Using Transfer-Encoding: chunked in example to send response progressively 2011-10-12 17:23:24 +02:00
Jocelyn Fiat 09030a27d9 sync with submodules 2011-10-12 17:22:46 +02:00
Jocelyn Fiat b9ca22006b removed unwanted code 2011-10-12 15:38:45 +02:00
Jocelyn Fiat 593b48fe90 applied recent changes on HTTP_REQUEST_METHOD_CONSTANTS 2011-10-12 11:56:25 +02:00
Jocelyn Fiat 735730b5a0 cosmetic 2011-10-12 11:52:00 +02:00
Jocelyn Fiat 035a133b5b Addition to "http" library, separated constants into
- HTTP_MIME_TYPES
 - HTTP_HEADER_NAMES
 - HTTP_REQUEST_METHODS
 - HTTP_STATUS_CODE   (already exists)

Do not set the "Status" header when using WGI_RESPONSE_BUFFER.write_header (...)
Cosmetic
2011-10-12 11:51:49 +02:00
Jocelyn Fiat 0144e97d69 Merge branch 'master' of https://github.com/jvelilla/Eiffel-Web-Framework
Conflicts:	examples/restbucks/src/domain/json_order_converter.e
Cosmetics
2011-10-11 14:25:22 +02:00
Jocelyn Fiat 26bfd72f5f Fixed errors recently introduced 2011-10-11 14:16:08 +02:00
Jocelyn Fiat 88542c2762 Merge branch 'master' of github.com:Eiffel-World/Eiffel-Web-Framework 2011-10-11 14:09:10 +02:00
Jocelyn Fiat 12fc54a403 sync with latest JSON 2011-10-11 14:08:41 +02:00
jvelilla eb44eef885 Update order_handler, fix json_order_converter 2011-10-11 08:18:46 -03:00
Jocelyn Fiat c2b66d6ca6 Use local curl if compiler is < 7.0.8.7340
otherwise, use ISE_LIBRARY cURL
2011-10-11 11:09:00 +02:00
Jocelyn Fiat 6758c4aef4 Temporary fixed issue of using modified cURL (which is cURL provided with EiffelStudio 7.0)
This changes will be reverted in the future
2011-10-11 10:46:56 +02:00
Jocelyn Fiat 6408bec628 Updated readme related to mirrored Eiffel cURL library 2011-10-10 17:56:09 +02:00
Jocelyn Fiat f77ba9ccd8 added submodule ext/ise_library/curl to use the updated Eiffel cURL from ISE. 2011-10-10 17:48:18 +02:00
Jocelyn Fiat c105c267e7 cosmetic 2011-10-10 16:09:44 +02:00
Jocelyn Fiat 19da4d6fd0 added http diagrams found on the web 2011-10-07 16:05:39 +02:00
Jocelyn Fiat a9e2dc1135 Added the possibility to specify the supported content types
Added FIXME
2011-10-07 15:39:04 +02:00
Jocelyn Fiat 142dbc39b4 Cosmetic 2011-10-07 14:11:03 +02:00
Jocelyn Fiat b17887d634 Added "Date:" helper feature in EWF_HEADER
Added license.lic to restbuck example, and mainly copyright to Javier
Use HTTP_STATUS_CODES
Minor improvements using object tests
Cosmetic (indentation, ..)
2011-10-07 14:03:31 +02:00
Jocelyn Fiat f443087e71 Added a first simple test client to test the restbuck client 2011-10-06 19:09:56 +02:00
Jocelyn Fiat e5eb11b4e7 added support for data in POST request 2011-10-06 19:09:17 +02:00
Jocelyn Fiat 720d8be08a Merge branch 'master' of https://github.com/jvelilla/Eiffel-Web-Framework 2011-10-06 17:37:41 +02:00
jvelilla ed04b7fba0 Added REQUEST_RESOURCE_HANDLER_HELPER class to contain
common http method behavior.
Updated ORDER_HANLDER to use this new class.
2011-10-06 09:54:20 -03:00
Jocelyn Fiat 4c9e7a4331 Added `base_url' for REQUEST_ROUTER (and descendants)
Fixed implementation of REST_REQUEST_AGENT_HANDLER to avoid wrong path in inherited routine.
Allow to build a URI_TEMPLATE from another URI TEMPLATE,
   this way, if later we have more attribute (status or settings) to URI_TEMPLATE,
   we'll be able to change the `template' without breaking the settings
2011-10-05 17:09:16 +02:00
Jocelyn Fiat cc6992a6fc added missing call to pre_execute and post_execute 2011-10-05 14:47:59 +02:00
Jocelyn Fiat 71c851ca39 Fixed missing http:// in absolute URL 2011-10-05 14:47:30 +02:00
Jocelyn Fiat 900ed8baea remove pre_execute, and post_execute, and make process_request frozen
this way, the user won't be tempted to redefine feature not being part of pure EWSGI interface.
2011-10-05 14:46:39 +02:00
Jocelyn Fiat dba55fcfd9 better argument name, to precise the timeout is in second
also in comment.
2011-10-05 14:45:47 +02:00
Jocelyn Fiat 456299ccdf Fixed agent handler for rest library 2011-10-04 17:33:15 +02:00
Jocelyn Fiat 810208f176 Merge branch 'master' of github.com:jocelyn/Eiffel-Web-Framework 2011-10-04 16:19:36 +02:00
Jocelyn Fiat 27c637b066 fixed inheritance and precursor bad usage. 2011-10-04 16:19:09 +02:00
Jocelyn Fiat a0df04a7f2 Merge branch 'master' of github.com:jocelyn/Eiffel-Web-Framework 2011-10-04 09:50:14 +02:00
Jocelyn Fiat bc5d20b221 Merge branch 'master' of https://github.com/jvelilla/Eiffel-Web-Framework 2011-10-04 09:49:20 +02:00
jvelilla 7ba3eb9ecd Updated support for PUT. Now the example support
GET, POST, PUT, DELETE.
2011-10-03 09:26:01 -03:00
Jocelyn Fiat 2b14a40898 fixed compilation for ewsgi/tests/tests.ecf file 2011-09-28 17:08:28 +02:00
Jocelyn Fiat aa20a1423f Made WGI_VALUE.name as READABLE_STRING_32 .. otherwise it is a pain to manipulate.
Changed return type of meta_variable to be WGI_STRING_VALUE ... since the meta variable can not be anything else.
Made sure REQUEST_URI starts with one and only one slash
Internal implementation: the _table now compares object
Removed SELF variable ... at least for now
Be sure to provide a REQUEST_URI even if the underlying connector does not.
2011-09-28 16:41:22 +02:00
Jocelyn Fiat 34c8cfa427 cleaned http_client configuration files 2011-09-28 14:53:34 +02:00
Jocelyn Fiat f7dcadccd5 Added library/library.index 2011-09-28 14:42:53 +02:00
Jocelyn Fiat f24df1d745 restructured ewsgi to avoid too many sub cluster 2011-09-28 14:42:34 +02:00
jvelilla 5adf40a9ed Updated Restbucks examples, handle not method allowed
in a better way, added the readme file.
2011-09-28 08:54:12 -03:00
jvelilla f20bc42b76 Merge remote-tracking branch 'jocelynEWF/master' 2011-09-28 07:36:35 -03:00
Jocelyn Fiat a4df57a7ac fixed compilation of rest example 2011-09-26 20:54:04 +02:00
Jocelyn Fiat df59ae579b fixed typo 2011-09-26 17:19:37 +02:00
Jocelyn Fiat 738eb7555f Changed ITERATION_CURSOR [WGI_VALUE] into ITERABLE [WGI_VALUE] for WGI_REQUEST.*parameters* and similar
Applied recent changes on EWF_HEADER
2011-09-26 17:10:05 +02:00
Jocelyn Fiat d397d4e35d Updated changelogs.txt
sync with nino and doc
2011-09-23 18:34:44 +02:00
Jocelyn Fiat eeaa47d4f1 Merge branch 'master' of github.com:jocelyn/Eiffel-Web-Framework 2011-09-23 18:23:35 +02:00
Jocelyn Fiat 0db4317a49 Added AutoTest simple cases for ewsgi using Nino web server 2011-09-23 18:22:42 +02:00
Jocelyn Fiat 668847f8e8 Fixing issue with experimental WGI_MULTIPLE_STRING_VALUE
Fixed issue with RAW_POST_DATA
2011-09-23 18:21:57 +02:00
Jocelyn Fiat e7fd7af2c5 Removed put_redirection' and replaced by put_location'
Removed useless code in some features
2011-09-23 18:20:23 +02:00
Jocelyn Fiat 24a5c7613d Use READABLE_STRING(_*) instead of just STRING(_*) 2011-09-23 18:20:16 +02:00
Jocelyn Fiat d9f6cbe80e Added feature to shutdown the Nino http server 2011-09-23 18:18:54 +02:00
Jocelyn Fiat 95ec2e77df Added error reporting in HTTP_CLIENT_RESPONSE
Added missing set_connect_timeout
2011-09-23 18:18:27 +02:00
jvelilla 19b5edd9b4 Added validations. 2011-09-23 09:06:23 -03:00
Jocelyn Fiat d25146dd27 Merge branch 'master' of https://github.com/jvelilla/Eiffel-Web-Framework 2011-09-22 16:19:48 +02:00
Jocelyn Fiat ab1c696837 Added code to create an HTTP_AUTHORIZATION from the client side as well.
So now we can either interpret an HTTP_AUTHORIZATION  or build one HTTP_AUTHORIZATION

So far , only Basic auth is supported.
2011-09-22 15:13:59 +02:00
Jocelyn Fiat dae8e1d67d Made all libraries compilable in any mode (voidsafe or not)
Fixed related examples
2011-09-22 15:12:33 +02:00
jvelilla 888bc61522 Initial import, work in progress restbuck example. Only support create
a resource
2011-09-22 09:29:59 -03:00
jvelilla 8291905da1 Merge remote-tracking branch 'jocelynEWF/master' 2011-09-22 07:53:23 -03:00
Jocelyn Fiat d9ba97d33b Fixed issue where Content-Type and Content-Length were translated into HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH instead of just
CONTENT_TYPE and CONTENT_LENGTH
2011-09-21 15:33:40 +02:00
Jocelyn Fiat 33eddd9197 better assertion to ensure `base' is a valid base url 2011-09-21 15:30:20 +02:00
Jocelyn Fiat 458cb56f75 synch with Nino 2011-09-21 15:29:25 +02:00
Jocelyn Fiat 88c015470e better return type for http client functions
added helper features
2011-09-21 15:29:12 +02:00
jvelilla f68a713c48 Merge remote-tracking branch 'jocelynEWF/master' 2011-09-21 07:49:40 -03:00
Jocelyn Fiat 0414cd4501 fixed case sensitive path 2011-09-20 18:19:23 +02:00
Jocelyn Fiat 284d7826c8 missing -safe.ecf config file for http_client 2011-09-20 16:59:54 +02:00
Jocelyn Fiat dff267cd58 Now using READABLE_STRING_... type 2011-09-20 16:57:28 +02:00
Jocelyn Fiat c2f7c198e0 Added simple HTTP client.
For now the implementation is using Eiffel cURL library.
It requires Eiffel cURL coming with next EiffelStudio 7.0 (or from eiffelstudio's repo from rev#87244 )
2011-09-20 16:55:44 +02:00
Jocelyn Fiat b3ef7c846b Fixed issues in WGI_REQUEST's invariant
Fixed issues with guessing the default format for REST handling
Fixed issue with .._ROUTING_.. component.
2011-09-16 20:59:06 +02:00
Jocelyn Fiat 111812c4e9 Fixed issue with uri template router ..
it was applying on request_uri instead of path_info
now it match on PATH_INFO
2011-09-16 18:56:02 +02:00
Jocelyn Fiat 92d8357d09 more flexible authenticated query .. on handler, and not anymore on context object 2011-09-16 18:55:26 +02:00
Jocelyn Fiat 64060cfa41 fixed wrong order in parameter for callers of set_meta_string_variable 2011-09-16 18:54:44 +02:00
Jocelyn Fiat d3239ec41b added debug_output to WGI_VALUE 2011-09-16 18:54:16 +02:00
Jocelyn Fiat 7b1557a52a first version of http authorization ..
for now, only basic digest
2011-09-16 18:53:57 +02:00
Jocelyn Fiat c9a4ebcb23 added request_handler_routes_recorder to provide an implementation for `REQUEST_HANDLER.on_handler_mapped' 2011-09-16 15:17:49 +02:00
Jocelyn Fiat 3f899f6aae Added "on_handler_mapped" callback
to allow any REQUEST_HANDLER to record the existing routes.
2011-09-16 15:11:37 +02:00
Jocelyn Fiat 18684d167b typo 2011-09-16 15:02:08 +02:00
jvelilla 32bb75b9dc Merge remote-tracking branch 'jocelynEWF/master' 2011-09-16 07:04:40 -03:00
Jocelyn Fiat d06bc76944 minor enhancement of error lib 2011-09-15 22:02:58 +02:00
Jocelyn Fiat 86825854ca Added WGI_MULTIPLE_STRING_VALUE
Renamed value as WGI_STRING_VALUE.string
Renamed a few classes .._CONTEXT_I  as .._CONTEXT
updated example.
2011-09-15 17:49:47 +02:00
Jocelyn Fiat 774cd004db cosmetic 2011-09-15 15:49:53 +02:00
Jocelyn Fiat c300cf5b6e Merge branch 'master' of git://github.com/Eiffel-World/Eiffel-Web-Framework 2011-09-15 11:17:07 +02:00
Jocelyn Fiat 68247a1849 updated README.md 2011-09-15 10:55:14 +02:00
Jocelyn Fiat 22fd7490fe Simplified interface of "router" library classes 2011-09-14 16:48:27 +02:00
Jocelyn Fiat 8b6e9273fa applied renaming for rest and router lib 2011-09-14 16:05:01 +02:00
Jocelyn Fiat 76fa3e9ff5 Reorganized library "server/request/rest" 2011-09-14 15:46:45 +02:00
Jocelyn Fiat 1e3770d724 some renaming to use _I for the generic classes, and removed the DEFAULT_ prefix for default implementation
this should makes things easier for new users
2011-09-14 15:39:37 +02:00
Jocelyn Fiat 840ae1e6e4 reorganized router library 2011-09-14 15:04:29 +02:00
Jocelyn Fiat 5626e03aa8 - Adopted deferred WGI_VALUE design for Result type of *_parameter and similar functions
- Adopted the ITERATION_CURSOR [WGI_VALUE] design for *_parameters and similar functions
- renamed parameter as item
- provided helper function to handle "string" value parameters

Experimental for now.
2011-09-14 14:54:06 +02:00
Jocelyn Fiat 4bcea900a6 better result type (using READABLE_..) 2011-09-14 14:48:08 +02:00
Jocelyn Fiat b1f5065e63 sync with nino 2011-09-14 14:47:29 +02:00
jvelilla c37fe9ad79 Merge remote-tracking branch 'jocelynEWF/master' 2011-09-14 07:58:40 -03:00
Jocelyn Fiat 2e53f7e0c4 updated changelogs 2011-09-13 17:12:12 +02:00
Jocelyn Fiat 512f2d2ce5 Added first draft for RESTful library
note: the interfaces are likely to change in the future
2011-09-13 17:08:40 +02:00
Jocelyn Fiat 92105ca7b3 updated config file and examples 2011-09-13 17:07:17 +02:00
Jocelyn Fiat f0c6eec23d adding routing handler
few renaming
2011-09-13 16:49:45 +02:00
Jocelyn Fiat 32197d0513 changing design to use generic instead of anchor types 2011-09-09 16:24:11 +02:00
Jocelyn Fiat 11286eeeef make router more easy to inherit from and specialized 2011-09-09 14:10:54 +02:00
Jocelyn Fiat fb8412fcae Merge branch 'master' of github.com:jocelyn/Eiffel-Web-Framework 2011-09-09 08:54:20 +02:00
Jocelyn Fiat 9ec87a4329 Added support during match for {/vars}
and also handle cases such as   /foo.{format}{/vars}  or /foo.{format}{?vars} where no literal exists between the uri template expressions
2011-09-09 08:51:45 +02:00
Jocelyn Fiat 0c7e6c08e7 better type for argument and result (using READABLE_...) 2011-09-09 08:50:29 +02:00
Jocelyn Fiat c1120a4226 change to standard default values 2011-09-09 08:50:05 +02:00
jvelilla 5c0cae35ef Sync to jocelyn EWF master 2011-09-08 07:45:10 -03:00
jvelilla 7bd5cdc232 Merge remote-tracking branch 'jocelynEWF/master' 2011-09-08 07:44:27 -03:00
jvelilla ef85c07603 Update 2011-09-08 07:43:36 -03:00
Jocelyn Fiat 10db3c28a5 sync doc/wiki 2011-09-07 14:31:52 +02:00
Jocelyn Fiat 54dc7de189 use `resource' as generic name for uri or uri_template 2011-09-07 12:46:09 +02:00
Jocelyn Fiat 2244d101ea added changelogs.txt 2011-09-07 12:22:11 +02:00
Jocelyn Fiat 244fdf1b02 Added request methods criteria for the router component.
Now one can decide

map_agent_with_request_methods ("/foo/bar/{bar_id}", agent handle_foo_bar, <<"GET">>)
(and similar for non agent way)
This might be useful in pure RESTful environment.
2011-09-07 12:14:03 +02:00
Jocelyn Fiat 3c9fce293f fixed example .. where we forgot to set the status, and send the header
(DbC helped here)
2011-09-07 12:10:48 +02:00
Jocelyn Fiat eee085dd5a renamed (un)set_meta_parameter as (un)set_meta_variable 2011-09-07 11:42:53 +02:00
Jocelyn Fiat 2d9e2d12a0 Missing HTTP_ prefix for header meta variable in REQUEST 2011-09-07 11:42:02 +02:00
Jocelyn Fiat 6a581f6d62 Changed prefix from EWSGI_ to WGI_
Changed meta variable type to READABLE_STRING_32
2011-08-30 19:20:42 +02:00
Jocelyn Fiat ed8f5d694f naming: meta_variable(s)
changed some string type to READABLE_STRING_32
or READABLE_STRING_8 for now regarding Meta variables (need decision here..)
2011-08-29 12:48:03 +02:00
Jocelyn Fiat c20600f281 changed prefix GW_ into EWF_ for EiffelWebFramework
use READABLE_STRING_GENERAL instead of just STRING
2011-08-25 16:00:18 +02:00
Jocelyn Fiat 53ccaa3fde sync wiki doc 2011-08-25 14:48:30 +02:00
Jocelyn Fiat 22afbd7ed0 Merge branch 'master' of github.com:jocelyn/Eiffel-Web-Framework
Conflicts:
	library/server/ewsgi/connectors/nino/src/gw_nino_connector.e
	library/server/ewsgi/ewsgi-safe.ecf
2011-08-25 14:48:02 +02:00
Jocelyn Fiat f6b362217c Merged REQUEST and ENVIRONMENT into REQUEST
renamed ENVIRONMENT_NAMES into META_NAMES
better usage of READABLE_STRING_GENERAL, and other strings
abstract RESPONSE_BUFFER in implementation of EWSGI
for the implementation, inheriting from deferred specification (more to come later)
2011-08-25 14:41:35 +02:00
Jocelyn Fiat e9ccf855b3 Merged REQUEST and ENVIRONMENT into REQUEST
renamed ENVIRONMENT_NAMES into META_NAMES
better usage of READABLE_STRING_GENERAL, and other strings
for the implementation, inheriting from deferred specification (more to come later)
2011-08-25 12:33:20 +02:00
Jocelyn Fiat 4d0148d562 fixing wrong feature usage 2011-08-24 15:54:01 +02:00
Jocelyn Fiat ec6cc5f2b8 code cleaning, and prepare for internal review 2011-08-18 12:25:40 +02:00
Jocelyn Fiat 40018d36eb enhanced the ERROR_HANDLER 2011-08-04 15:11:51 +02:00
Jocelyn Fiat 8e18329063 minor improvements on response_as_result code 2011-08-02 14:53:37 +02:00
Jocelyn Fiat c372494713 cosmetic in config file .ecf 2011-08-02 10:47:16 +02:00
Jocelyn Fiat 10f4a99ee1 add "write_headers_string" to RESPONSE_BUFFER 2011-08-02 10:46:53 +02:00
Jocelyn Fiat e9085c614c sync wiki 2011-08-01 17:02:33 +02:00
Jocelyn Fiat f7d3f519a7 moved ewsgi-full config file under tests (this is mainly for dev purpose, to be able to compile and edit all classes related to ewsgi) 2011-08-01 16:47:00 +02:00
Jocelyn Fiat 4eb22d0272 Tried to reduce gap between both EWSGI proposals
Re-adapt the Spec-compliant solution (instead of Lib-compliant solution).
  Thus no more 100% deferred interface.
Rename EWSGI_RESPONSE into EWSGI_RESPONSE_BUFFER
Added in extra/response-as-result/  an copy/paste from the implementation of Paul's proposal (not up to date with Paul's spec). But this is mainly for information and tests.
Removed part of the ewsgi/specification interfaces ... to be able to test EWSGI compliant library against the pure specification (experimental).
Renamed most of the GW_... into EWSGI_...
2011-08-01 16:41:16 +02:00
Jocelyn Fiat bbcc9ef44b added http_accept feature to represent "Accept:" HTTP header 2011-07-29 15:13:34 +02:00
Jocelyn Fiat 801caa4e69 added hello_routed_world example
few changes on new `router' library (still in-progress)
2011-07-29 15:13:08 +02:00
Jocelyn Fiat 1b49445077 Added first draft for a URI and/or URI-template base request router. 2011-07-29 10:51:22 +02:00
Jocelyn Fiat f005d8bb06 cosmetic 2011-07-29 10:50:31 +02:00
Jocelyn Fiat a278537f7b Added "flush" to the EWSGI_RESPONSE_STREAM 2011-07-29 10:50:24 +02:00
Jocelyn Fiat 78b5b6f5fe Merge branch 'master' of github.com:jocelyn/Eiffel-Web-Framework 2011-07-29 08:52:57 +02:00
Jocelyn Fiat a215c1e4d2 added missing non-void-safe .ecf 2011-07-29 08:52:36 +02:00
Jocelyn Fiat fe3726677b added missing non-void-safe .ecf 2011-07-29 08:45:26 +02:00
Jocelyn Fiat 94d4909644 Fixed various issue with URI template, added corresponding tests 2011-07-28 18:45:25 +02:00
Jocelyn Fiat 0da4b7d61b It seems good convention to also add the "Status:" header 2011-07-28 10:57:24 +02:00
Jocelyn Fiat 5c5ba9f038 fix hello world example 2011-07-28 10:41:57 +02:00
Jocelyn Fiat d65c8de1d2 ignore tests/temp 2011-07-28 08:28:54 +02:00
Jocelyn Fiat 3d93dbc66d added script to test compilations of .ecf in EWF 2011-07-27 18:35:17 +02:00
Jocelyn Fiat 436f2afd00 Added the possibility to set the "Status" header (different from the status line) in GW_HEADER
Renamed EWSGI_RESPONSE as EWSGI_RESPONSE_STREAM to avoid confusion with EWSGI_RESPONSE as stated in Paul's proposal
Added default "configuration" (for nino and cgi) to be independant of the connector (at compilation time)
Added example implementing Paul's proposal on top of EWSGI
2011-07-27 18:34:06 +02:00
Jocelyn Fiat 73284575d4 Added an implementation folder in ewsgi_spec, mainly to provide default implementation just to save the developer of connector some time.
changed structured
2011-07-27 17:34:53 +02:00
Jocelyn Fiat e9b05ffc0b added non void-safe configuration files 2011-07-27 16:07:00 +02:00
Jocelyn Fiat 012bb2f6c9 restructured specification folders 2011-07-27 15:58:31 +02:00
Jocelyn Fiat e883163fe9 Apply prefix renaming from the specification
Reduced the number of EWSGI classes
2011-07-27 15:56:44 +02:00
Jocelyn Fiat e5fb3f8328 now use prefix EWSGI_ instead of GW_ for ewsgi specification 2011-07-27 15:40:51 +02:00
Jocelyn Fiat 302ae8d030 First step to extract the interface of the EWSGI specification into its own library
Applied the changes
2011-07-27 15:34:22 +02:00
Jocelyn Fiat 694c0a193c removed implementation from APPLICATION , RESPONSE and REQUEST classes 2011-07-27 15:11:07 +02:00
Jocelyn Fiat 4075b08b7e removed the notion of status from GW_HEADER, since it should not be part of the HTTP header
added status setting in GW_RESPONSE
added a default implementation for write_status in OUTPUT_STREAM
  (it should be moved away in the future)
removed any implementation from GW_REQUEST, and put it in GW_REQUEST_IMP
2011-07-27 14:51:47 +02:00
Jocelyn Fiat 65800371cd replace write_string by write in RESPONSE 2011-07-26 16:01:23 +02:00
Jocelyn Fiat 2c6196017e various alternative implementation for response 2011-07-26 16:01:18 +02:00
Jocelyn Fiat 5a155e0cee Redesigned the RESPONSE to remove the output stream from the deferred interface
Redesigned the uploaded file part to be more object oriented
Move some implementation from REQUEST to REQUEST_IMP
2011-07-25 12:38:25 +02:00
Jocelyn Fiat 08bec49da4 added doc/spec for uri template 2011-07-25 12:38:16 +02:00
Jocelyn Fiat 4940ddb8f5 Fixed issue with matcher 2011-07-22 17:29:17 +02:00
Jocelyn Fiat 6599bf1a07 fixed typo 2011-07-22 17:06:08 +02:00
Jocelyn Fiat 0ef88eadf5 Improvement
and revert back to support draft 04
(but using custom variable, allow the user to follow draft 05 spec)
2011-07-22 16:58:31 +02:00
Jocelyn Fiat e1ef4c390e fixing issue with URI TEMPLATE matcher 2011-07-22 13:14:09 +02:00
Jocelyn Fiat 11baeefe1c Merge branch 'master' of github.com:jocelyn/Eiffel-Web-Framework 2011-07-22 08:30:49 +02:00
Jocelyn Fiat ac7f58722d added URI_TEMPLATE_MATCH_RESULT 2011-07-22 08:30:08 +02:00
Jocelyn Fiat acd395376a sync 2011-07-21 19:06:04 +02:00
Jocelyn Fiat a7a27bee0a updated README 2011-07-21 18:59:27 +02:00
Jocelyn Fiat fc0a25acc9 updated README 2011-07-21 18:48:54 +02:00
Jocelyn Fiat 0d363f065b added use of URL-encoder to unencode the URL values (to fill the parameters)
review design of GW_RESPONSE to hide the output, and remove the header attribute
added script_url in REQUEST to help the user build url relative to script_name

+ cosmetic
2011-07-20 18:27:02 +02:00
Jocelyn Fiat 51b70a2490 First version of URI Template library
as specified by http://tools.ietf.org/html/draft-gregorio-uritemplate-05
(it seems to contains some error in the spec .. or minor incoherences, to double check)
The matcher is basic, it does not handle all the details of the string builder, but that seems ok for now.
2011-07-20 12:11:05 +02:00
Jocelyn Fiat 917f80c0c8 added format and request method constants classes
+ license file
2011-07-18 16:36:56 +02:00
Jocelyn Fiat 73e5fd6cd6 added default rescue code on exception rescue 2011-07-18 16:33:10 +02:00
Jocelyn Fiat 0abab83566 nicer Eiffel code, let's not try to achieve everything-in-one-line style ... 2011-07-18 16:32:42 +02:00
Jocelyn Fiat f764e63b45 restrict creation only by GW_APPLICATION and descendant 2011-07-18 16:31:32 +02:00
Jocelyn Fiat 0a1c4676a4 add output helper feature to RESPONSE 2011-07-18 16:29:43 +02:00
Jocelyn Fiat 8a38519fb0 Fixed issue with nino handler and base url 2011-07-18 16:07:45 +02:00
Jocelyn Fiat 54c9addb30 sync nino and json 2011-07-18 16:06:21 +02:00
Jocelyn Fiat 30d4843a5b rename new_request_context by new_request 2011-07-14 14:56:34 +02:00
Jocelyn Fiat 3e73298806 cosmetic 2011-07-13 16:25:17 +02:00
Jocelyn Fiat 01b16d0a82 renamed GW_REQUEST_CONTEXT as GW_REQUEST 2011-07-13 16:22:20 +02:00
Jocelyn Fiat ac97d6019b Design change, now we have req' REQUEST and res' RESPONSE instead of just `ctx' 2011-07-13 16:13:25 +02:00
Jocelyn Fiat 4e2f0dbc72 enhanced comment for `execute' 2011-07-13 15:37:50 +02:00
Jocelyn Fiat 9d1fb56cc1 Make a simple hello world based on nino 2011-07-13 15:26:21 +02:00
Jocelyn Fiat bc98c5a317 Added GW_HEADER
Added pre_, post_ and rescue_execute for GW_APPLICATION
Fixed an unknown class in export clause
cosmetic + copyright
2011-07-12 17:47:17 +02:00
Jocelyn Fiat 681bb19ab7 fixed submodule path ... Windows path separator issue.. 2011-07-12 17:12:36 +02:00
Jocelyn Fiat 026b4f8682 added instruction to get the source code 2011-07-12 16:48:46 +02:00
Jocelyn Fiat f74ac66569 First integration of the new GW_ design more centralized on connector, and does not require specific feature on GW_APPLICATION depending on the connector.
So this is really more flexible this way, and much easier to write application supporting CGI, FCGI, Nino and so on .. as demonstrated in hello_world

This is a first version, more will come later, mainly migrating from Eiffel Web Reloaded to this Eiffel Web Framework project.
2011-07-12 11:53:00 +02:00
Jocelyn Fiat 4fb42df5fb focus on GW_APPLICATION 2011-07-08 11:27:06 +02:00
Jocelyn Fiat f1d8d18811 a few renaming
better GW_ENVIRONMENT interface
2011-07-07 17:24:21 +02:00
Jocelyn Fiat 545db51fc9 updated doc 2011-07-06 12:45:29 +02:00
Jocelyn Fiat 20bf9efaa0 cosmetic, license, copyright 2011-07-05 12:07:49 +02:00
Jocelyn Fiat a168cc62e7 added doc/wiki (wiki from github) 2011-07-05 10:52:05 +02:00
Jocelyn Fiat b9e89758ce First draft for the ewsgi spec 2011-07-05 10:45:16 +02:00
Jocelyn 19da9436ff Let's start the Eiffel Web Framework 2011-06-29 08:38:57 +02:00
393 changed files with 28535 additions and 6206 deletions
+3
View File
@@ -0,0 +1,3 @@
EIFGENs
tests/temp/
.svn/
+12
View File
@@ -0,0 +1,12 @@
[submodule "doc/wiki"]
path = doc/wiki
url = https://github.com/Eiffel-World/Eiffel-Web-Framework.wiki.git
[submodule "ext/server/nino"]
path = ext/server/nino
url = http://github.com/Eiffel-World/EiffelWebNino.git
[submodule "ext/text/json"]
path = ext/text/json
url = http://github.com/Eiffel-World/ejson-svn.git
[submodule "ext/ise_library/curl"]
path = ext/ise_library/curl
url = http://github.com/EiffelSoftware/mirror-Eiffel-cURL.git
+38
View File
@@ -0,0 +1,38 @@
History for Eiffel-Web-Framework
[2011-09-23] Jocelyn
* library "ewsgi":
- NEW simple autotest cases using Nino web server
-fixed issue with RAW_POST_DATA being added in form_data_parameters
instead of meta_variables ...
- Implemented WGI_VALUE for parameter's type (query_parameter,
form_data_parameter, item ...)
* Nino connector: added feature to shutdown the server from the WGI application
* NEW library "http_client": a new library to perform simple http requests
such as get, head, post, put, ... (currently implemented with Eiffel cURL)
* NEW library "http_authorization": added simple library to support
HTTP_AUTHORIZATION. For now only "Basic" auth type is supported ..
[2011-09-22] Javier
* NEW Example: added partial Restbuck example
[2011-09-21] Jocelyn
* Nino connector: fixed an issue with missing value for Content-Type and Content-Length
[2011-09-13] Jocelyn
* library "router": now using a generic design to allow customization of
request handler context class.
* NEW library "server/request/rest": first attempt to provide a library to
help building RESTful application (the interfaces are likely to change
soon) EXPERIMENTAL
[2011-09-09] Jocelyn
* library "uri-template": better support for {/vars} and {?vars}
[2011-09-07] Jocelyn
* library "router": now routing depends on uri (or uri template) and request methods
* Nino connector: Fixed issue where HTTP_ prefix were missing for header meta variable.
[2011-09-07] Jocelyn
* changelog: starting to write down changelogs file
-26
View File
@@ -1,26 +0,0 @@
History file for EJSON
======================
team: ""
date: "2011-07-06"
revision: "0.3.0"
+++++++++++++++++++++Important Changes since 0.2.0 version++++++++++++++++++++++++++++++++++++++++++++++
*Updated skip_white_spaces, now check %U and %T codes
*Undo changes to is_a_valid_number, because it's doesn't follow the
JSON spec. Tests : fail13.json, fail29.json and fail30.json are valid
with this implementation, so we go back to the previous
implementation.
*Added autotest test suite
*Added getest based test program
*Updated Eiffel configuration file, updated to the new clusters
*Added converters and factory classes
*Added new top level directories; library, test, build and example
+20
View File
@@ -0,0 +1,20 @@
Eiffel Forum License, version 2
1. Permission is hereby granted to use, copy, modify and/or distribute
this package, provided that:
* copyright notices are retained unchanged,
* any distribution of this package, whether modified or not,
includes this license text.
2. Permission is hereby also granted to distribute binary programs which
depend on this package. If the binary program depends on a modified
version of this package, you are encouraged to publicly release the
modified version of this package.
THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT WARRANTY. ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THIS PACKAGE.
-20
View File
@@ -1,20 +0,0 @@
Copyright (c) 2010 Javier Velilla and others, http://ejson.origo.ethz.ch
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Symlink
+1
View File
@@ -0,0 +1 @@
README.md
+37
View File
@@ -0,0 +1,37 @@
Official project site for Eiffel Web Framework:
* http://eiffel-world.github.com/Eiffel-Web-Framework/
For more information please have a look at the related wiki:
* https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki
How to get the source code?
---------------------------
* git clone https://github.com/Eiffel-World/Eiffel-Web-Framework.git
* cd Eiffel-Web-Framework
* git submodule update --init
* git submodule foreach git pull origin master
* git submodule foreach git checkout master
* And to build the required and related Clibs
** cd ext/ise_library/curl
** geant compile
Overview
--------
* library/server/ewsgi: Eiffel Web Server Gateway Interface
* library/server/ewsgi/connectors: various web server connectors for EWSGI
* library/server/libfcgi: Wrapper for libfcgi SDK
* library/server/request/router: URL dispatching/routing based on uri, uri_template, or custom.
* library/server/request/rest: experimental: RESTful library to help building RESTful services
* library/protocol/http: HTTP related classes, constants for status code, content types, ...
* library/protocol/uri_template: URI Template library (parsing and expander)
* library/error: very simple/basic library to handle error
* library/text/encoder: Various simpler encoder: base64, url-encoder, xml entities, html entities
For more information please have a look at the related wiki:
* https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki
-97
View File
@@ -1,97 +0,0 @@
Readme file for eJSON
=====================
team: "Javier Velilla,Jocelyn Fiat, Paul Cohen"
date: "$Date$"
revision: "$Revision$"
1. Introduction
---------------
eJSON stands for Eiffel JSON library and is a small Eiffel library for dealing
with the JSON format. The objective of the library is to provide two basic
features Eiffel2JSON and JSON2Eiffel.
2. Legal stuff
--------------
eJSON is copyrighted by the author Javier Velilla and others. It is licensed
under the MIT License. See the file license.txt in the same directory as this
readme file.
3. Versioning scheme
--------------------
eJSON version numbers has the form:
«major number».«minor number».«patch level»
eJSON will retain the major number 0 as long as it has beta status. A change in
major number indicates that a release is not backward compatible. A change in
minor number indicates that a release is backward compatible (within that major
number) but that new useful features may have been added. A change in patch
level simply indicates that the release contains bug fixes for the previous
release. Note that as long as eJSON is in beta status (0.Y.Z) backward
compatibility is not guranteed for changes in minor numbers!
4. Documentation
---------------
Currently the only documentation on eJSON is available at:
http://ejson.origo.ethz.ch/wiki/user_guide
5. Requirements and installation
--------------------------------
EJSON requires that you have:
1. Gobo 3.9 installed or later
2. One of the following compiler combinations installed:
* ISE Eiffel 6.5 or later.
* gec [try to test]
* tecomp [try to test]
eJSON probably works fine with other versions of the above compilers.
There are no known platform dependencies (Windows, Linux).
To install eJSON simply extract the ejson-X.Y.Z.zip file to some appropriate
place on your hard disk. There are no requirements on environment variables or
registry variables.
To verify that everything works you should compile the example programs and/or
the test program.
6. Contents of eJSON
--------------------
All directory names below are relative to the root directory of your ejson
installation.
Directory Description
--------- -----------
doc Contains the eJSON.pdf documentation file.
examples Contains the two example programs.
ejson Contains the actual eJSON library classes.
test Contains a test program for eJSON.
7. Contacting the Team
----------------------
Contact the team:
Javier Velilla «javier.hector@gmail.com»
Paul Cohen «paco@seibostudios.se»
Jocelyn Fiat «jfiat@eiffel.com»
8. Releases
-----------
For more information on what was changed in each release look in the file
history.txt.
Version Date Description
------- ---- -----------
0.3.0 2011-07-06 JSON Factory Converters
0.2.0 2010-02-07 Adapted to EiffelStudio 6.4 or later, supports void-safety
0.1.0 2010-02-07 First release, Adapted to SmartEiffel 1.2r7 and EiffelStudio 6.2 or previous
Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

View File
Submodule
+1
Submodule doc/wiki added at 2b112da43d
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="hello_routed_world" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433">
<target name="hello_routed_world">
<root class="HELLO_ROUTED_WORLD" feature="make"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
<assertions precondition="true" postcondition="true" invariant="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="connector_nino" location="..\..\library\server\ewsgi\connectors\nino\nino-safe.ecf" readonly="false"/>
<library name="default_nino" location="..\..\library\server\ewsgi\default\ewsgi_nino-safe.ecf" readonly="false"/>
<library name="encoder" location="..\..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
<library name="ewsgi" location="..\..\library\server\ewsgi\ewsgi-safe.ecf" readonly="false"/>
<library name="http" location="..\..\library\protocol\http\http-safe.ecf" readonly="false"/>
<library name="router" location="..\..\library\server\request\router\router-safe.ecf" readonly="false"/>
<library name="uri_template" location="..\..\library\protocol\uri_template\uri_template-safe.ecf" readonly="false"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
</system>
@@ -0,0 +1,9 @@
<html>
<head>
<title>Hello Eiffel::default</title>
<link rel="stylesheet" href="../style.css" type="text/css" media="all" />
</head>
<body>
<h1>Hello Eiffel Default World</h1>
</body>
</html>
@@ -0,0 +1,9 @@
<html>
<head>
<title>Hello Eiffel</title>
<link rel="stylesheet" href="style.css" type="text/css" media="all" />
</head>
<body>
<h1>Hello Eiffel World :D</h1>
</body>
</html>
Binary file not shown.
@@ -0,0 +1 @@
h1 { border: solid 1px #00f; margin: 5px; padding: 5px; }
+10
View File
@@ -0,0 +1,10 @@
${NOTE_KEYWORD}
copyright: "2011-${YEAR}, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,253 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
HELLO_ROUTED_WORLD
inherit
ANY
URI_TEMPLATE_ROUTED_APPLICATION
ROUTED_APPLICATION_HELPER
DEFAULT_WGI_APPLICATION
create
make
feature {NONE} -- Initialization
make
do
initialize_router
make_and_launch
end
create_router
do
create router.make (5)
end
setup_router
local
ra: REQUEST_AGENT_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
hello: REQUEST_URI_TEMPLATE_ROUTING_HANDLER
www: REQUEST_FILE_SYSTEM_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
do
router.map_agent ("/home", agent execute_home)
create www.make (document_root)
www.set_directory_index (<<"index.html">>)
router.map ("/www{/path}{?query}", www)
--| Map all "/hello*" using a ROUTING_HANDLER
create hello.make (3)
router.map ("/hello", hello)
create ra.make (agent handle_hello)
hello.map ("/hello/{name}.{format}", ra)
hello.map ("/hello.{format}/{name}", ra)
hello.map ("/hello/{name}", ra)
create ra.make (agent handle_anonymous_hello)
hello.map ("/hello", ra)
hello.map ("/hello.{format}", ra)
--| Various various route, directly on the "router"
router.map_agent_with_request_methods ("/method/any", agent handle_method_any, Void)
router.map_agent_with_request_methods ("/method/guess", agent handle_method_get_or_post, <<"GET", "POST">>)
router.map_agent_with_request_methods ("/method/custom", agent handle_method_get, <<"GET">>)
router.map_agent_with_request_methods ("/method/custom", agent handle_method_post, <<"POST">>)
end
document_root: READABLE_STRING_8
local
e: EXECUTION_ENVIRONMENT
dn: DIRECTORY_NAME
once
create e
create dn.make_from_string (e.current_working_directory)
dn.extend ("htdocs")
Result := dn.string
if Result[Result.count] = Operating_environment.directory_separator then
Result := Result.substring (1, Result.count - 1)
end
end
feature -- Execution
execute_default (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
local
h: EWF_HEADER
l_url: STRING
e: EXECUTION_ENVIRONMENT
n: INTEGER
i: INTEGER
s: STRING_8
do
l_url := req.script_url ("/home")
n := 3
create h.make
h.put_refresh (l_url, 5)
h.put_content_type_text_plain
h.put_transfer_encoding_chunked
-- h.put_content_length (0)
res.set_status_code ({HTTP_STATUS_CODE}.moved_permanently)
res.write_headers_string (h.string)
from
create e
create s.make (255)
until
n = 0
loop
if n > 1 then
s.append ("%NRedirected to " + l_url + " in " + n.out + " seconds :%N")
else
s.append ("%NRedirected to " + l_url + " in 1 second :%N")
end
write_chunk (s, res); s.wipe_out
from
i := 1
until
i = 1001
loop
s.append_character ('.')
if i \\ 100 = 0 then
s.append_character ('%N')
end
write_chunk (s, res); s.wipe_out
e.sleep (1_000_000)
i := i + 1
end
n := n - 1
end
s.append ("%NYou are now being redirected...%N")
write_chunk (s, res); s.wipe_out
write_chunk (Void, res)
end
write_chunk (s: detachable READABLE_STRING_8; res: WGI_RESPONSE_BUFFER)
do
if s /= Void then
res.write_string (s.count.to_hex_string + {HTTP_CONSTANTS}.crlf)
res.write_string (s)
else
res.write_string ("0" + {HTTP_CONSTANTS}.crlf)
end
res.flush
end
execute_home (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
local
l_body: STRING_8
do
create l_body.make (255)
l_body.append ("<html><body>Hello World ?!%N")
l_body.append ("<h3>Please try the following links</h3><ul>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/") + "%">default</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello") + "%">/hello</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello.html/Joce") + "%">/hello.html/Joce</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello.json/Joce") + "%">/hello.json/Joce</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce.html") + "%">/hello/Joce.html</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce.xml") + "%">/hello/Joce.xml</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce") + "%">/hello/Joce</a></li>%N")
l_body.append ("</ul>%N")
if attached req.item ("REQUEST_COUNT") as rqc then
l_body.append ("request #"+ rqc.as_string + "%N")
end
l_body.append ("</body></html>%N")
res.write_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_body.count.out]>>)
res.write_string (l_body)
end
execute_hello (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_name: detachable READABLE_STRING_32; ctx: REQUEST_HANDLER_CONTEXT)
local
l_response_content_type: detachable STRING
h: EWF_HEADER
content_type_supported: ARRAY [STRING]
l_body: STRING_8
do
if a_name /= Void then
l_body := "Hello %"" + a_name + "%" !%N"
else
l_body := "Hello anonymous visitor !%N"
end
content_type_supported := <<{HTTP_MIME_TYPES}.application_json, {HTTP_MIME_TYPES}.text_html, {HTTP_MIME_TYPES}.text_xml, {HTTP_MIME_TYPES}.text_plain>>
inspect ctx.request_format_id ("format", content_type_supported)
when {HTTP_FORMAT_CONSTANTS}.json then
l_response_content_type := {HTTP_MIME_TYPES}.application_json
l_body := "{%N%"application%": %"/hello%",%N %"message%": %"" + l_body + "%" %N}"
when {HTTP_FORMAT_CONSTANTS}.html then
l_response_content_type := {HTTP_MIME_TYPES}.text_html
when {HTTP_FORMAT_CONSTANTS}.xml then
l_response_content_type := {HTTP_MIME_TYPES}.text_xml
l_body := "<response><application>/hello</application><message>" + l_body + "</message></response>%N"
when {HTTP_FORMAT_CONSTANTS}.text then
l_response_content_type := {HTTP_MIME_TYPES}.text_plain
else
execute_content_type_not_allowed (req, res, content_type_supported,
<<{HTTP_FORMAT_CONSTANTS}.json_name, {HTTP_FORMAT_CONSTANTS}.html_name, {HTTP_FORMAT_CONSTANTS}.xml_name, {HTTP_FORMAT_CONSTANTS}.text_name>>
)
end
if l_response_content_type /= Void then
create h.make
h.put_content_type (l_response_content_type)
h.put_content_length (l_body.count)
res.set_status_code ({HTTP_STATUS_CODE}.ok)
res.write_headers_string (h.string)
res.write_string (l_body)
end
end
handle_hello (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
do
execute_hello (req, res, Void, ctx)
end
handle_anonymous_hello (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
do
execute_hello (req, res, ctx.string_parameter ("name"), ctx)
end
handle_method_any (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
do
execute_hello (req, res, req.request_method, ctx)
end
handle_method_get (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
do
execute_hello (req, res, "GET", ctx)
end
handle_method_post (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
do
execute_hello (req, res, "POST", ctx)
end
handle_method_get_or_post (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
do
execute_hello (req, res, "GET or POST", ctx)
end
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end
+1
View File
@@ -0,0 +1 @@
Examples ...
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-9-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-9-0 http://www.eiffel.com/developers/xml/configuration-1-9-0.xsd" name="client" uuid="D0059CEB-5F5C-4D21-8C71-842BD0F88468">
<target name="client">
<root class="RESTBUCK_CLIENT" feature="make"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="http_client" location="..\..\..\library\client\http_client\http_client-safe.ecf" readonly="false"/>
<library name="json" location="..\..\..\ext\text\json\library\json-safe.ecf" readonly="false"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="client" uuid="D0059CEB-5F5C-4D21-8C71-842BD0F88468">
<target name="client">
<root class="RESTBUCK_CLIENT" feature="make"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" void_safety="none" syntax="standard">
</option>
<setting name="concurrency" value="thread"/>
<library name="http_client" location="..\..\..\library\client\http_client\http_client.ecf"/>
<library name="json" location="..\..\..\ext\text\json\library\json.ecf" readonly="false"/>
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
<library name="thread" location="$ISE_LIBRARY/library/thread/thread.ecf"/>
<cluster name="src" location="./src" recursive="true"/>
</target>
</system>
@@ -0,0 +1,72 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
RESTBUCK_CLIENT
create
make
feature {NONE} -- Initialization
make
-- Initialize `Current'.
local
h: LIBCURL_HTTP_CLIENT
sess: HTTP_CLIENT_SESSION
s: READABLE_STRING_8
j: JSON_PARSER
id: detachable STRING
do
create h.make
sess := h.new_session ("http://127.0.0.1")
s := "[
{
"location":"takeAway",
"items":[
{
"name":"Late",
"option":"skim",
"size":"Small",
"quantity":1
}
]
}
]"
if attached sess.post ("/order", Void, s) as r then
if attached r.body as m then
create j.make_parser (m)
if j.is_parsed and attached j.parse_object as j_o then
if attached {JSON_STRING} j_o.item ("id") as l_id then
id := l_id.item
end
print (m)
io.put_new_line
end
end
end
if id /= Void and then attached sess.get ("/order/" + id, Void) as r then
print (r.body)
io.put_new_line
end
end
feature -- Status
feature -- Access
feature -- Change
feature {NONE} -- Implementation
invariant
-- invariant_clause: True
end
+4
View File
@@ -0,0 +1,4 @@
${NOTE_KEYWORD}
copyright: "2011-${YEAR}, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+51
View File
@@ -0,0 +1,51 @@
Restbuck Eiffel Implementation based on the book of REST in Practice
Verb URI or template Use
POST /order Create a new order, and upon success, receive a Locationheader specifying the new orders URI.
GET /order/{orderId} Request the current state of the order specified by the URI.
PUT /order/{orderId} Update an order at the given URI with new information, providing the full representation.
DELETE /order/{orderId} Logically remove the order identified by the given URI.
How to Create an order
* Uri: http://localhost:8080/order
* Method: POST
* Note: you will get in the response the "location" of the new your order.
* HEADERS:
Content-Type: application/json
* Example CONTENT
{
"location":"takeAway",
"items":[
{
"name":"Late",
"option":"skim",
"size":"Small",
"quantity":1
}
]
}
How to Read an order
* Uri: http://localhost:8080/order/{order_id}
* Method: GET
How to Update an order
* Uri: http://localhost:8080/order/{order_id}
* Method: PUT
How to Delete an order
* Uri: http://localhost:8080/order/{order_id}
* Method: DELETE
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="restbucks" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433">
<target name="restbucks">
<root class="RESTBUCKS_SERVER" feature="make"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
<assertions precondition="true" postcondition="true" invariant="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="connector_nino" location="..\..\library\server\ewsgi\connectors\nino\nino-safe.ecf" readonly="false"/>
<library name="default_nino" location="..\..\library\server\ewsgi\default\ewsgi_nino-safe.ecf" readonly="false"/>
<library name="encoder" location="..\..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
<library name="ewsgi" location="..\..\library\server\ewsgi\ewsgi-safe.ecf" readonly="false"/>
<library name="json" location="..\..\ext\text\json\library\json-safe.ecf" readonly="false"/>
<library name="http" location="..\..\library\protocol\http\http-safe.ecf" readonly="false"/>
<library name="router" location="..\..\library\server\request\router\router-safe.ecf" readonly="false"/>
<library name="uri_template" location="..\..\library\protocol\uri_template\uri_template-safe.ecf" readonly="false"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
</system>
@@ -1 +1 @@
@@ -0,0 +1,26 @@
note
description: "Summary description for {DATABASE_API}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
DATABASE_API
create
make
feature -- Initialization
make
do
create orders.make (10)
end
feature -- Access
orders: HASH_TABLE [ORDER, STRING]
;note
copyright: "2011-2011, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
@@ -0,0 +1,19 @@
note
description: "Summary description for {SHARED_DATABASE_API}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
SHARED_DATABASE_API
feature -- Access
db_access: DATABASE_API
once
create Result.make
end
note
copyright: "2011-2011, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+90
View File
@@ -0,0 +1,90 @@
note
description: "Summary description for {ITEM}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
ITEM
inherit
ITEM_CONSTANTS
create
make
feature -- Initialization
make ( a_name : STRING_32 ; a_size:STRING_32; a_option: STRING_32; a_quantity:INTEGER_8)
do
set_name (a_name)
set_size (a_size)
set_option (a_option)
set_quantity (a_quantity)
end
feature -- Access
name : STRING
-- product name type of Coffee(Late, Cappuccino, Expresso)
option : STRING
-- customization option Milk (skim, semi, whole)
size : STRING
-- small, mediumm large
quantity :INTEGER
feature -- Element Change
set_name (a_name: STRING)
require
valid_name: is_valid_coffee_type (a_name)
do
name := a_name
ensure
name_assigned : name.same_string(a_name)
end
set_size (a_size: STRING)
require
valid_size : is_valid_size_option (a_size)
do
size := a_size
ensure
size_assigned : size.same_string(a_size)
end
set_option (an_option: STRING)
require
valid_option : is_valid_milk_type (an_option)
do
option := an_option
ensure
option_assigned : option.same_string (an_option)
end
set_quantity (a_quantity: INTEGER)
require
valid_quantity : a_quantity > 0
do
quantity := a_quantity
ensure
quantity_assigned : quantity = a_quantity
end
feature -- Report
hash_code: INTEGER
--Hash code value
do
Result := option.hash_code + name.hash_code + size.hash_code + quantity.hash_code
end
invariant
valid_size : is_valid_size_option (size)
valid_coffe : is_valid_coffee_type (name)
valid_customization : is_valid_milk_type (option)
valid_quantity : quantity > 0
note
copyright: "2011-2011, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
@@ -0,0 +1,54 @@
note
description: "Summary description for {ITEM_CONSTANTS}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
ITEM_CONSTANTS
feature -- Access
is_valid_coffee_type (a_type: STRING) : BOOLEAN
--is `a_type' a valid coffee type
do
a_type.to_lower
coffe_types.compare_objects
Result := coffe_types.has (a_type)
end
Coffe_types : ARRAY[STRING]
-- List of valid Coffee types
once
Result := <<"late","cappuccino", "expresso">>
end
is_valid_milk_type (a_type: STRING) : BOOLEAN
--is `a_type' a valid milk type
do
a_type.to_lower
milk_types.compare_objects
Result := milk_types.has (a_type)
end
Milk_types : ARRAY[STRING]
-- List of valid Milk types
once
Result := <<"skim","semi", "whole">>
end
is_valid_size_option (an_option: STRING) : BOOLEAN
--is `an_option' a valid size option
do
an_option.to_lower
size_options.compare_objects
Result := size_options.has (an_option)
end
Size_options : ARRAY[STRING]
-- List of valid Size_options
once
Result := <<"small","mediumn", "large">>
end
note
copyright: "2011-2011, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
@@ -0,0 +1,170 @@
note
description: "Summary description for {JSON_ORDER_CONVERTER}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
JSON_ORDER_CONVERTER
inherit
JSON_CONVERTER
create
make
feature -- Initialization
make
do
create object.make ("","","")
end
feature -- Access
object : ORDER
value : detachable JSON_OBJECT
feature -- Conversion
from_json (j: attached like value): detachable like object
-- Convert from JSON value. Returns Void if unable to convert
local
s_id, s_location, s_status: detachable STRING_32
q: INTEGER_8
o: ORDER
i : ITEM
l_array : detachable ARRAYED_LIST [JSON_VALUE]
is_valid_from_json : BOOLEAN
do
is_valid_from_json := True
s_id ?= json.object (j.item (id_key), Void)
s_location ?= json.object (j.item (location_key), Void)
s_status ?= json.object (j.item (status_key), Void)
create o.make (s_id, s_location, s_status)
if attached {JSON_ARRAY} j.item (items_key) as l_val then
l_array := l_val.array_representation
from
l_array.start
until
l_array.after
loop
if attached {JSON_OBJECT} l_array.item_for_iteration as jv then
if attached {INTEGER_8} json.object (jv.item (quantity_key), Void) as l_integer then
q := l_integer
else
q := 0
end
if
attached {STRING_32} json.object (jv.item (name_key), Void) as s_name and then
attached {STRING_32} json.object (jv.item (size_key), Void) as s_key and then
attached {STRING_32} json.object (jv.item (option_key), Void) as s_option
then
if is_valid_item_customization (s_name, s_key, s_option,q) then
create i.make (s_name, s_key, s_option, q)
o.add_item (i)
else
is_valid_from_json := False
end
else
is_valid_from_json := False
end
end
l_array.forth
end
end
if not is_valid_from_json or o.items.is_empty then
Result := Void
else
Result := o
end
end
to_json (o: like object): like value
-- Convert to JSON value
local
ja : JSON_ARRAY
i : ITEM
jv: JSON_OBJECT
do
create Result.make
Result.put (json.value (o.id), id_key)
Result.put (json.value (o.location), location_key)
Result.put (json.value (o.status), status_key)
from
create ja.make_array
o.items.start
until
o.items.after
loop
i := o.items.item_for_iteration
create jv.make
jv.put (json.value (i.name), name_key)
jv.put (json.value (i.size),size_key)
jv.put (json.value (i.quantity), quantity_key)
jv.put (json.value (i.option), option_key)
ja.add (jv)
o.items.forth
end
Result.put (ja, items_key)
end
feature {NONE} -- Implementation
id_key: JSON_STRING
once
create Result.make_json ("id")
end
location_key: JSON_STRING
once
create Result.make_json ("location")
end
status_key: JSON_STRING
once
create Result.make_json ("status")
end
items_key : JSON_STRING
once
create Result.make_json ("items")
end
name_key : JSON_STRING
once
create Result.make_json ("name")
end
size_key : JSON_STRING
once
create Result.make_json ("size")
end
quantity_key : JSON_STRING
once
create Result.make_json ("quantity")
end
option_key : JSON_STRING
once
create Result.make_json ("option")
end
feature -- Validation
is_valid_item_customization ( name : STRING_32; size: STRING_32; option : STRING_32; quantity : INTEGER_8 ) : BOOLEAN
local
ic : ITEM_CONSTANTS
do
create ic
Result := ic.is_valid_coffee_type (name) and ic.is_valid_milk_type (option) and ic.is_valid_size_option (size) and quantity > 0
end
note
copyright: "2011-2011, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+111
View File
@@ -0,0 +1,111 @@
note
description: "Summary description for {ORDER}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
ORDER
create
make
feature -- Initialization
make ( an_id : detachable STRING_32; a_location: detachable STRING_32; a_status: detachable STRING_32)
do
create {ARRAYED_LIST [ITEM]} items.make (10)
if an_id /= Void then
set_id (an_id)
else
set_id ("")
end
if a_location /= Void then
set_location (a_location)
else
set_location ("")
end
if a_status /= Void then
set_status (a_status)
else
set_status ("")
end
revision := 0
end
feature -- Access
id : STRING_32
location : STRING_32
items: LIST[ITEM]
status : STRING_32
revision : INTEGER
feature -- element change
set_id (an_id : STRING_32)
do
id := an_id
ensure
id_assigned : id.same_string (an_id)
end
set_location (a_location : STRING_32)
do
location := a_location
ensure
location_assigned : location.same_string (a_location)
end
set_status (a_status : STRING_32)
do
status := a_status
ensure
status_asigned : status.same_string (a_status)
end
add_item (a_item : ITEM)
require
valid_item: a_item /= Void
do
items.force (a_item)
ensure
has_item : items.has (a_item)
end
add_revision
do
revision := revision + 1
ensure
revision_incremented : old revision + 1 = revision
end
feature -- Etag
etag : STRING_32
-- Etag generation for Order objects
do
Result := hash_code.out + revision.out
end
feature -- Report
hash_code: INTEGER_32
-- Hash code value
do
from
items.start
Result := items.item.hash_code
until
items.off
loop
Result:= ((Result \\ 8388593) |<< 8) + items.item.hash_code
items.forth
end
if items.count > 1 then
Result := Result \\ items.count
end
end
note
copyright: "2011-2011, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
@@ -0,0 +1,57 @@
note
description: "Summary description for {ORDER_TRANSITIONS}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
ORDER_VALIDATION
feature -- Access
is_valid_status_state (a_status: STRING) : BOOLEAN
--is `a_status' a valid coffee order state
do
a_status.to_lower
Order_states.compare_objects
Result := Order_states.has (a_status)
end
Order_states : ARRAY[STRING]
-- List of valid status states
once
Result := <<"submitted","pay","payed", "cancel","canceled","prepare","prepared","deliver","completed">>
end
is_valid_transition (order:ORDER a_status : STRING) :BOOLEAN
-- Given the current order state, determine if the transition is valid
do
a_status.to_lower
if order.status.same_string ("submitted") then
Result := a_status.same_string ("pay") or a_status.same_string ("cancel") or order.status.same_string (a_status)
elseif order.status.same_string ("pay") then
Result := a_status.same_string ("payed") or order.status.same_string (a_status)
elseif order.status.same_string ("cancel") then
Result := a_status.same_string ("canceled") or order.status.same_string (a_status)
elseif order.status.same_string ("payed") then
Result := a_status.same_string ("prepared") or order.status.same_string (a_status)
elseif order.status.same_string ("prepared") then
Result := a_status.same_string ("deliver") or order.status.same_string (a_status)
elseif order.status.same_string ("deliver") then
Result := a_status.same_string ("completed") or order.status.same_string (a_status)
end
end
is_state_valid_to_update ( a_status : STRING) : BOOLEAN
-- Given the current state `a_status' of an order, is possible to update the order?
do
if a_status.same_string ("submitted") or else a_status.same_string ("pay") or else a_status.same_string ("payed") then
Result := true
end
end
note
copyright: "2011-2011, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
@@ -0,0 +1,19 @@
note
description: "Summary description for {SHARED_ORDER_VALIDATION}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
SHARED_ORDER_VALIDATION
feature
order_validation : ORDER_VALIDATION
once
create Result
end
note
copyright: "2011-2011, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
@@ -0,0 +1,255 @@
note
description: "Summary description for {ORDER_HANDLER}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
ORDER_HANDLER [C -> REQUEST_HANDLER_CONTEXT]
inherit
REQUEST_HANDLER [C]
REQUEST_RESOURCE_HANDLER_HELPER [C]
redefine
do_get,
do_post,
do_put,
do_delete
end
SHARED_DATABASE_API
SHARED_EJSON
REFACTORING_HELPER
SHARED_ORDER_VALIDATION
feature -- execute
execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
-- Execute request handler
do
execute_methods (ctx, req, res)
end
feature -- API DOC
api_doc : STRING = "URI:/order METHOD: POST%N URI:/order/{orderid} METHOD: GET, PUT, DELETE%N"
feature -- HTTP Methods
do_get (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
-- Using GET to retrieve resource information.
-- If the GET request is SUCCESS, we response with
-- 200 OK, and a representation of the order
-- If the GET request is not SUCCESS, we response with
-- 404 Resource not found
local
id : STRING
do
if attached req.orig_path_info as orig_path then
id := get_order_id_from_path (orig_path)
if attached retrieve_order (id) as l_order then
compute_response_get (ctx, req, res, l_order)
else
handle_resource_not_found_response ("The following resource" + orig_path + " is not found ", ctx, req, res)
end
end
end
compute_response_get (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; l_order : ORDER)
local
h: EWF_HEADER
l_msg : STRING
do
create h.make
h.put_status ({HTTP_STATUS_CODE}.ok)
h.put_content_type_application_json
if attached {JSON_VALUE} json.value (l_order) as jv then
l_msg := jv.representation
h.put_content_length (l_msg.count)
if attached req.request_time as time then
h.add_header ("Date:" + time.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
end
res.set_status_code ({HTTP_STATUS_CODE}.ok)
res.write_headers_string (h.string)
res.write_string (l_msg)
end
end
do_put (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
local
l_post: STRING
l_location : STRING
l_order : detachable ORDER
h : EWF_HEADER
do
fixme ("TODO handle an Internal Server Error")
fixme ("Refactor the code, create new abstractions")
fixme ("Add Header Date to the response")
fixme ("Put implementation is wrong!!!!")
req.input.read_stream (req.content_length_value.as_integer_32)
l_post := req.input.last_string
l_order := extract_order_request(l_post)
fixme ("TODO move to a service method")
if l_order /= Void and then db_access.orders.has_key (l_order.id) then
update_order( l_order)
create h.make
h.put_status ({HTTP_STATUS_CODE}.ok)
h.put_content_type ("application/json")
if attached req.request_time as time then
h.add_header ("Date:" +time.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
end
if attached req.http_host as host then
l_location := "http://"+host +req.request_uri+"/" + l_order.id
h.add_header ("Location:"+ l_location)
end
if attached {JSON_VALUE} json.value (l_order) as jv then
h.put_content_length (jv.representation.count)
res.set_status_code ({HTTP_STATUS_CODE}.ok)
res.write_headers_string (h.string)
res.write_string (jv.representation)
end
else
handle_bad_request_response (l_post +"%N is not a valid ORDER, maybe the order does not exist in the system", ctx, req, res)
end
end
do_delete (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
local
id: STRING
h : EWF_HEADER
do
fixme ("TODO handle an Internal Server Error")
fixme ("Refactor the code, create new abstractions")
if attached req.orig_path_info as orig_path then
id := get_order_id_from_path (orig_path)
if db_access.orders.has_key (id) then
delete_order( id)
create h.make
h.put_status ({HTTP_STATUS_CODE}.no_content)
h.put_content_type ("application/json")
if attached req.request_time as time then
h.put_utc_date (time)
end
res.set_status_code ({HTTP_STATUS_CODE}.no_content)
res.write_headers_string (h.string)
else
handle_resource_not_found_response (orig_path + " not found in this server", ctx, req, res)
end
end
end
do_post (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
-- Here the convention is the following.
-- POST is used for creation and the server determines the URI
-- of the created resource.
-- If the request post is SUCCESS, the server will create the order and will response with
-- HTTP_RESPONSE 201 CREATED, the Location header will contains the newly created order's URI
-- if the request post is not SUCCESS, the server will response with
-- HTTP_RESPONSE 400 BAD REQUEST, the client send a bad request
-- HTTP_RESPONSE 500 INTERNAL_SERVER_ERROR, when the server can deliver the request
local
l_post: STRING
do
req.input.read_stream (req.content_length_value.as_integer_32)
l_post := req.input.last_string
if attached extract_order_request (l_post) as l_order then
save_order (l_order)
compute_response_post (ctx, req, res, l_order)
else
handle_bad_request_response (l_post +"%N is not a valid ORDER", ctx, req, res)
end
end
compute_response_post (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; l_order : ORDER)
local
h: EWF_HEADER
l_msg : STRING
l_location : STRING
joc : JSON_ORDER_CONVERTER
do
create h.make
create joc.make
json.add_converter(joc)
h.put_status ({HTTP_STATUS_CODE}.created)
h.put_content_type_application_json
if attached {JSON_VALUE} json.value (l_order) as jv then
l_msg := jv.representation
h.put_content_length (l_msg.count)
if attached req.http_host as host then
l_location := "http://" + host + req.request_uri + "/" + l_order.id
h.put_location (l_location)
end
if attached req.request_time as time then
h.put_utc_date (time)
end
res.set_status_code ({HTTP_STATUS_CODE}.created)
res.write_headers_string (h.string)
res.write_string (l_msg)
end
end
feature {NONE} -- URI helper methods
get_order_id_from_path (a_path: READABLE_STRING_32) : STRING
do
Result := a_path.split ('/').at (3)
end
feature {NONE} -- Implementation Repository Layer
retrieve_order ( id : STRING) : detachable ORDER
-- get the order by id if it exist, in other case, Void
do
Result := db_access.orders.item (id)
end
save_order (an_order: ORDER)
-- save the order to the repository
local
i : INTEGER
do
from
i := 1
until
not db_access.orders.has_key ((db_access.orders.count + i).out)
loop
i := i + 1
end
an_order.set_id ((db_access.orders.count + i).out)
an_order.set_status ("submitted")
an_order.add_revision
db_access.orders.force (an_order, an_order.id)
end
update_order (an_order: ORDER)
-- update the order to the repository
do
an_order.add_revision
db_access.orders.force (an_order, an_order.id)
end
delete_order (an_order: STRING)
-- update the order to the repository
do
db_access.orders.remove (an_order)
end
extract_order_request (l_post : STRING) : detachable ORDER
-- extract an object Order from the request, or Void
-- if the request is invalid
local
parser : JSON_PARSER
joc : JSON_ORDER_CONVERTER
do
create joc.make
json.add_converter(joc)
create parser.make_parser (l_post)
if attached parser.parse as jv and parser.is_parsed then
Result ?= json.object (jv, "ORDER")
end
end
note
copyright: "2011-2011, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+80
View File
@@ -0,0 +1,80 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
RESTBUCKS_SERVER
inherit
ANY
URI_TEMPLATE_ROUTED_APPLICATION
ROUTED_APPLICATION_HELPER
DEFAULT_WGI_APPLICATION
create
make
feature {NONE} -- Initialization
make
do
initialize_router
make_and_launch
end
create_router
do
create router.make (2)
end
setup_router
local
order_handler: ORDER_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
do
create order_handler
router.map_with_request_methods ("/order", order_handler, <<"POST">>)
router.map_with_request_methods ("/order/{orderid}", order_handler, <<"GET", "DELETE", "PUT">>)
end
feature -- Execution
execute_default (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
-- I'm using this method to handle the method not allowed response
-- in the case that the given uri does not have a corresponding http method
-- to handle it.
local
h : EWF_HEADER
l_description : STRING
l_api_doc : STRING
do
if req.content_length_value > 0 then
req.input.read_stream (req.content_length_value.as_integer_32)
end
create h.make
h.put_status ({HTTP_STATUS_CODE}.method_not_allowed)
h.put_content_type_text_plain
l_api_doc := "%NPlease check the API%NURI:/order METHOD: POST%NURI:/order/{orderid} METHOD: GET, PUT, DELETE%N"
l_description := req.request_method + req.request_uri + " is not allowed" + "%N" + l_api_doc
h.put_content_length (l_description.count)
h.put_current_date
res.set_status_code ({HTTP_STATUS_CODE}.method_not_allowed)
res.write_headers_string (h.string)
res.write_string (l_description)
end
note
copyright: "2011-2011, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end
+93
View File
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-5-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-5-0 http://www.eiffel.com/developers/xml/configuration-1-5-0.xsd" name="curl" uuid="D51EF190-6157-4B47-8E73-FA93DCBB7A71" library_target="curl">
<target name="curl">
<description>cURL: libcURL wrapper library for Eiffel.
Copyright (c) 1984-2006, Eiffel Software and others.
Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt).</description>
<root all_classes="true"/>
<file_rule>
<exclude>/\.svn$</exclude>
<exclude>/EIFGEN.{0,1}$</exclude>
<exclude>/temp$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" cat_call_detection="false" is_attached_by_default="true" void_safety="all" namespace="EiffelSoftware.Library">
</option>
<setting name="dotnet_naming_convention" value="true"/>
<external_include location="$(ECF_CONFIG_PATH)\curl\spec\include">
<condition>
<platform value="windows"/>
</condition>
</external_include>
<external_include location="$(ECF_CONFIG_PATH)/curl/spec/include">
<condition>
<platform excluded_value="windows"/>
</condition>
</external_include>
<external_object location="$(ECF_CONFIG_PATH)/curl/spec/$(ISE_PLATFORM)/lib/eiffel_curl.o">
<condition>
<platform excluded_value="windows"/>
<multithreaded value="false"/>
</condition>
</external_object>
<external_object location="$(ECF_CONFIG_PATH)/curl/spec/$(ISE_PLATFORM)/lib/MTeiffel_curl.o">
<condition>
<platform excluded_value="windows"/>
<multithreaded value="true"/>
</condition>
</external_object>
<external_object location="$(ECF_CONFIG_PATH)\curl\spec\$(ISE_C_COMPILER)\$(ISE_PLATFORM)\lib\eiffel_curl.lib">
<condition>
<platform value="windows"/>
<multithreaded value="false"/>
<dotnet value="false"/>
</condition>
</external_object>
<external_object location="$(ECF_CONFIG_PATH)\curl\spec\$(ISE_C_COMPILER)\$(ISE_PLATFORM)\lib\mteiffel_curl.lib">
<condition>
<platform value="windows"/>
<multithreaded value="true"/>
<dotnet value="false"/>
</condition>
</external_object>
<external_object location="$(ECF_CONFIG_PATH)\spec\$(ISE_C_COMPILER)\$(ISE_PLATFORM)\lib\ileiffel_curl.lib">
<condition>
<platform value="windows"/>
<dotnet value="true"/>
</condition>
</external_object>
<library name="api_wrapper" location="$ISE_LIBRARY\library\api_wrapper\api_wrapper-safe.ecf"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<cluster name="curl" location=".\" recursive="true">
<file_rule>
<exclude>/spec$</exclude>
<exclude>/Clib$</exclude>
</file_rule>
<file_rule>
<exclude>/gtk$</exclude>
<exclude>/mac$</exclude>
<condition>
<platform value="windows"/>
</condition>
</file_rule>
<file_rule>
<exclude>/mswin$</exclude>
<exclude>/gtk$</exclude>
<condition>
<platform value="macintosh"/>
<custom name="vision_implementation" value="cocoa"/>
</condition>
</file_rule>
<file_rule>
<exclude>/mswin$</exclude>
<exclude>/mac$</exclude>
<condition>
<platform excluded_value="windows"/>
<custom name="vision_implementation" excluded_value="cocoa"/>
</condition>
</file_rule>
</cluster>
</target>
<target name="curl_dotnet" extends="curl">
<setting name="msil_generation" value="true"/>
</target>
</system>
+93
View File
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-5-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-5-0 http://www.eiffel.com/developers/xml/configuration-1-5-0.xsd" name="curl" uuid="D51EF190-6157-4B47-8E73-FA93DCBB7A71" library_target="curl">
<target name="curl">
<description>cURL: libcURL wrapper library for Eiffel.
Copyright (c) 1984-2006, Eiffel Software and others.
Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt).</description>
<root all_classes="true"/>
<file_rule>
<exclude>/\.svn$</exclude>
<exclude>/EIFGEN.{0,1}$</exclude>
<exclude>/temp$</exclude>
</file_rule>
<option warning="true" namespace="EiffelSoftware.Library">
</option>
<setting name="dotnet_naming_convention" value="true"/>
<external_include location="$(ECF_CONFIG_PATH}\curl\spec\include">
<condition>
<platform value="windows"/>
</condition>
</external_include>
<external_include location="$(ECF_CONFIG_PATH}/curl/spec/include">
<condition>
<platform excluded_value="windows"/>
</condition>
</external_include>
<external_object location="$(ECF_CONFIG_PATH}/curl/spec/$(ISE_PLATFORM)/lib/eiffel_curl.o">
<condition>
<platform excluded_value="windows"/>
<multithreaded value="false"/>
</condition>
</external_object>
<external_object location="$(ECF_CONFIG_PATH}/curl/spec/$(ISE_PLATFORM)/lib/MTeiffel_curl.o">
<condition>
<platform excluded_value="windows"/>
<multithreaded value="true"/>
</condition>
</external_object>
<external_object location="$(ECF_CONFIG_PATH}\curl\spec\$(ISE_C_COMPILER)\$(ISE_PLATFORM)\lib\eiffel_curl.lib">
<condition>
<platform value="windows"/>
<multithreaded value="false"/>
<dotnet value="false"/>
</condition>
</external_object>
<external_object location="$(ECF_CONFIG_PATH}\curl\spec\$(ISE_C_COMPILER)\$(ISE_PLATFORM)\lib\mteiffel_curl.lib">
<condition>
<platform value="windows"/>
<multithreaded value="true"/>
<dotnet value="false"/>
</condition>
</external_object>
<external_object location="$(ECF_CONFIG_PATH}\curl\spec\$(ISE_C_COMPILER)\$(ISE_PLATFORM)\lib\ileiffel_curl.lib">
<condition>
<platform value="windows"/>
<dotnet value="true"/>
</condition>
</external_object>
<library name="api_wrapper" location="$ISE_LIBRARY\library\api_wrapper\api_wrapper.ecf"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<cluster name="curl" location=".\" recursive="true">
<file_rule>
<exclude>/spec$</exclude>
<exclude>/Clib$</exclude>
</file_rule>
<file_rule>
<exclude>/gtk$</exclude>
<exclude>/mac$</exclude>
<condition>
<platform value="windows"/>
</condition>
</file_rule>
<file_rule>
<exclude>/mswin$</exclude>
<exclude>/gtk$</exclude>
<condition>
<platform value="macintosh"/>
<custom name="vision_implementation" value="cocoa"/>
</condition>
</file_rule>
<file_rule>
<exclude>/mswin$</exclude>
<exclude>/mac$</exclude>
<condition>
<platform excluded_value="windows"/>
<custom name="vision_implementation" excluded_value="cocoa"/>
</condition>
</file_rule>
</cluster>
</target>
<target name="curl_dotnet" extends="curl">
<setting name="msil_generation" value="true"/>
</target>
</system>
+1
Submodule ext/server/nino added at 4cd1b67607
Submodule
+1
Submodule ext/text/json added at 5ec1bdd2ea
+1
View File
@@ -0,0 +1 @@
Simple HTTP client implemented using Eiffel cURL library
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-9-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-9-0 http://www.eiffel.com/developers/xml/configuration-1-9-0.xsd" name="http_client" uuid="628F5A96-021B-4191-926B-B3BF49272866" library_target="http_client">
<target name="http_client">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="curl" location="$ISE_LIBRARY\library\cURL\curl-safe.ecf">
<condition>
<version type="compiler" min="7.0.8.7340"/>
</condition>
</library>
<library name="curl_local" location="..\..\..\ext\ise_library\curl-safe.ecf">
<condition>
<version type="compiler" max="7.0.8.7339"/>
</condition>
</library>
<library name="encoder" location="..\..\text\encoder\encoder-safe.ecf"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="tests" extends="http_client">
<root class="ANY" feature="default_create"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
<assertions precondition="true"/>
</option>
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
<tests name="tests" location=".\tests\"/>
</target>
</system>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http_client" uuid="628F5A96-021B-4191-926B-B3BF49272866" library_target="http_client">
<target name="http_client">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" void_safety="none" syntax="provisional">
</option>
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
<library name="curl" location="$ISE_LIBRARY\library\cURL\curl.ecf">
<condition>
<version type="compiler" min="7.0.8.7340"/>
</condition>
</library>
<library name="curl_local" location="..\..\..\ext\ise_library\curl.ecf">
<condition>
<version type="compiler" max="7.0.8.7339"/>
</condition>
</library>
<library name="encoder" location="../../text/encoder/encoder.ecf"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>
@@ -0,0 +1,16 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
deferred class
HTTP_CLIENT
feature -- Status
new_session (a_base_url: READABLE_STRING_8): HTTP_CLIENT_SESSION
deferred
end
end
@@ -0,0 +1,37 @@
note
description: "Summary description for {HTTP_CLIENT_CONSTANTS}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
HTTP_CLIENT_CONSTANTS
feature -- Auth type
auth_type_id (a_auth_type_string: READABLE_STRING_8): INTEGER
local
s: STRING_8
do
create s.make_from_string (a_auth_type_string)
s.to_lower
if s.same_string_general ("basic") then
Result := Auth_type_basic
elseif s.same_string_general ("digest") then
Result := Auth_type_digest
elseif s.same_string_general ("any") then
Result := Auth_type_any
elseif s.same_string_general ("anysafe") then
Result := Auth_type_anysafe
elseif s.same_string_general ("none") then
Result := Auth_type_none
end
end
Auth_type_none: INTEGER = 0
Auth_type_basic: INTEGER = 1
Auth_type_digest: INTEGER = 2
Auth_type_any: INTEGER = 3
Auth_type_anysafe: INTEGER = 4
end
@@ -0,0 +1,183 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
deferred class
HTTP_CLIENT_REQUEST
inherit
REFACTORING_HELPER
feature {NONE} -- Initialization
make (a_url: READABLE_STRING_8; a_session: like session)
-- Initialize `Current'.
do
session := a_session
url := a_url
headers := session.headers.twin
end
session: HTTP_CLIENT_SESSION
feature -- Access
request_method: READABLE_STRING_8
deferred
end
url: READABLE_STRING_8
headers: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
feature -- Execution
import (ctx: HTTP_CLIENT_REQUEST_CONTEXT)
do
headers.fill (ctx.headers)
end
execute (ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
deferred
end
feature -- Authentication
auth_type: STRING
-- Set the authentication type for the request.
-- Types: "basic", "digest", "any"
do
Result := session.auth_type
end
auth_type_id: INTEGER
-- Set the authentication type for the request.
-- Types: "basic", "digest", "any"
do
Result := session.auth_type_id
end
username: detachable READABLE_STRING_32
do
Result := session.username
end
password: detachable READABLE_STRING_32
do
Result := session.password
end
credentials: detachable READABLE_STRING_32
do
Result := session.credentials
end
feature -- Settings
timeout: INTEGER
-- HTTP transaction timeout in seconds.
do
Result := session.timeout
end
connect_timeout: INTEGER
-- HTTP connection timeout in seconds.
do
Result := session.connect_timeout
end
max_redirects: INTEGER
-- Maximum number of times to follow redirects.
do
Result := session.max_redirects
end
ignore_content_length: BOOLEAN
-- Does this session ignore Content-Size headers?
do
Result := session.ignore_content_length
end
buffer_size: NATURAL
-- Set the buffer size for request. This option will
-- only be set if buffer_size is positive
do
Result := session.buffer_size
end
default_response_charset: detachable READABLE_STRING_8
-- Default encoding of responses. Used if no charset is provided by the host.
do
Result := session.default_response_charset
end
feature {NONE} -- Utilities
append_parameters_to_url (a_url: STRING; a_parameters: detachable ARRAY [detachable TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
-- Append parameters `a_parameters' to `a_url'
require
a_url_attached: a_url /= Void
local
i: INTEGER
l_first_param: BOOLEAN
do
if a_parameters /= Void and then a_parameters.count > 0 then
if a_url.index_of ('?', 1) > 0 then
l_first_param := False
elseif a_url.index_of ('&', 1) > 0 then
l_first_param := False
else
l_first_param := True
end
from
i := a_parameters.lower
until
i > a_parameters.upper
loop
if attached a_parameters[i] as a_param then
if l_first_param then
a_url.append_character ('?')
else
a_url.append_character ('&')
end
a_url.append_string (a_param.name)
a_url.append_character ('=')
a_url.append_string (a_param.value)
l_first_param := False
end
i := i + 1
end
end
end
feature {NONE} -- Utilities: encoding
url_encoder: URL_ENCODER
once
create Result
end
urlencode (s: READABLE_STRING_32): READABLE_STRING_8
-- URL encode `s'
do
Result := url_encoder.encoded_string (s)
end
urldecode (s: READABLE_STRING_8): READABLE_STRING_32
-- URL decode `s'
do
Result := url_encoder.decoded_string (s)
end
stripslashes (s: STRING): STRING
do
Result := s.string
Result.replace_substring_all ("\%"", "%"")
Result.replace_substring_all ("\'", "'")
Result.replace_substring_all ("\/", "/")
Result.replace_substring_all ("\\", "\")
end
end
@@ -0,0 +1,93 @@
note
description: "Summary description for {HTTP_CLIENT_REQUEST_CONTEXT}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
HTTP_CLIENT_REQUEST_CONTEXT
create
make,
make_with_credentials_required
feature {NONE} -- Initialization
make
do
create headers.make (2)
create query_parameters.make (5)
create form_data_parameters.make (10)
end
make_with_credentials_required
do
make
set_credentials_required (True)
end
feature -- Settings
credentials_required: BOOLEAN
feature -- Access
headers: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
query_parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_8]
form_data_parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_8]
upload_data: detachable READABLE_STRING_8
upload_filename: detachable READABLE_STRING_8
feature -- Status report
has_form_data: BOOLEAN
do
Result := not form_data_parameters.is_empty
end
has_upload_data: BOOLEAN
do
Result := attached upload_data as d and then not d.is_empty
end
has_upload_filename: BOOLEAN
do
Result := attached upload_filename as fn and then not fn.is_empty
end
feature -- Element change
add_query_parameter (k: READABLE_STRING_8; v: READABLE_STRING_32)
do
query_parameters.force (v, k)
end
add_form_data_parameter (k: READABLE_STRING_8; v: READABLE_STRING_32)
do
form_data_parameters.force (v, k)
end
set_credentials_required (b: BOOLEAN)
do
credentials_required := b
end
set_upload_data (a_data: like upload_data)
require
has_no_upload_data: not has_upload_data
do
upload_data := a_data
end
set_upload_filename (a_fn: like upload_filename)
require
has_no_upload_filename: not has_upload_filename
do
upload_filename := a_fn
end
end
@@ -0,0 +1,71 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
HTTP_CLIENT_RESPONSE
create
make
feature {NONE} -- Initialization
make
-- Initialize `Current'.
do
status := 200
raw_headers := ""
end
feature -- Status
error_occurred: BOOLEAN
-- Error occurred during request
feature {HTTP_CLIENT_REQUEST} -- Status setting
set_error_occurred (b: BOOLEAN)
-- Set `error_occurred' to `b'
do
error_occurred := b
end
feature -- Access
status: INTEGER assign set_status
raw_headers: READABLE_STRING_8
headers: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
local
tb: like internal_headers
do
tb := internal_headers
if tb = Void then
create tb.make (3)
internal_headers := tb
end
Result := tb
end
body: detachable READABLE_STRING_8 assign set_body
feature -- Change
set_status (s: INTEGER)
do
status := s
end
set_body (s: like body)
do
body := s
end
feature {NONE} -- Implementation
internal_headers: detachable like headers
end
@@ -0,0 +1,178 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
deferred class
HTTP_CLIENT_SESSION
feature {NONE} -- Initialization
make (a_base_url: READABLE_STRING_8)
-- Initialize `Current'.
do
set_defaults
create headers.make (3)
base_url := a_base_url
initialize
end
set_defaults
do
timeout := 5
connect_timeout := 1
max_redirects := 5
set_basic_auth_type
end
initialize
deferred
end
feature -- Basic operation
get (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
deferred
end
head (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
deferred
end
post (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; data: detachable READABLE_STRING_8): HTTP_CLIENT_RESPONSE
deferred
end
put (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; fn: detachable READABLE_STRING_8): HTTP_CLIENT_RESPONSE
deferred
end
delete (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
deferred
end
feature -- Settings
timeout: INTEGER
-- HTTP transaction timeout in seconds. Defaults to 5 seconds.
connect_timeout: INTEGER
-- HTTP connection timeout in seconds. Defaults to 1 second.
max_redirects: INTEGER
-- Maximum number of times to follow redirects.
-- Set to 0 to disable and -1 to follow all redirects. Defaults to 5.
ignore_content_length: BOOLEAN
-- Does this session ignore Content-Size headers?
buffer_size: NATURAL
-- Set the buffer size for request. This option will
-- only be set if buffer_size is positive
default_response_charset: detachable READABLE_STRING_8
-- Default encoding of responses. Used if no charset is provided by the host.
feature -- Access
base_url: READABLE_STRING_8
headers: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
feature -- Authentication
auth_type: STRING
-- Set the authentication type for the request.
-- Types: "basic", "digest", "any"
auth_type_id: INTEGER
-- See {HTTP_CLIENT_CONSTANTS}.Auth_type_*
username,
password: detachable READABLE_STRING_32
credentials: detachable READABLE_STRING_32
feature -- Change
set_base_url (u: like base_url)
do
base_url := u
end
set_timeout (n: like timeout)
do
timeout := n
end
set_connect_timeout (n: like connect_timeout)
do
connect_timeout := n
end
set_user_agent (v: READABLE_STRING_8)
do
add_header ("User-Agent", v)
end
add_header (k: READABLE_STRING_8; v: READABLE_STRING_8)
do
headers.force (v, k)
end
remove_header (k: READABLE_STRING_8)
do
headers.prune (k)
end
set_credentials (u: like username; p: like password)
do
username := u
password := p
if u /= Void and p /= Void then
credentials := u + ":" + p
else
credentials := Void
end
end
set_auth_type (s: READABLE_STRING_8)
do
auth_type := s
auth_type_id := http_client_constants.auth_type_id (s)
end
set_basic_auth_type
do
auth_type := "basic"
auth_type_id := {HTTP_CLIENT_CONSTANTS}.auth_type_basic
end
set_digest_auth_type
do
auth_type := "digest"
auth_type_id := {HTTP_CLIENT_CONSTANTS}.auth_type_digest
end
set_any_auth_type
do
auth_type := "any"
auth_type_id := {HTTP_CLIENT_CONSTANTS}.auth_type_any
end
set_anysafe_auth_type
do
auth_type := "anysafe"
auth_type_id := {HTTP_CLIENT_CONSTANTS}.auth_type_anysafe
end
feature {NONE} -- Implementation
http_client_constants: HTTP_CLIENT_CONSTANTS
once
create Result
end
end
@@ -0,0 +1,30 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
LIBCURL_HTTP_CLIENT
inherit
HTTP_CLIENT
create
make
feature {NONE} -- Initialization
make
-- Initialize `Current'.
do
end
feature -- Status
new_session (a_base_url: READABLE_STRING_8): LIBCURL_HTTP_CLIENT_SESSION
do
create Result.make (a_base_url)
end
end
@@ -0,0 +1,208 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
LIBCURL_HTTP_CLIENT_REQUEST
inherit
HTTP_CLIENT_REQUEST
rename
make as make_request
redefine
session
end
create
make
feature {NONE} -- Initialization
make (a_url: READABLE_STRING_8; a_request_method: like request_method; a_session: like session)
do
make_request (a_url, a_session)
request_method := a_request_method
end
session: LIBCURL_HTTP_CLIENT_SESSION
feature -- Access
request_method: READABLE_STRING_8
feature -- Execution
execute (ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
local
l_result: INTEGER
l_curl_string: CURL_STRING
l_url: READABLE_STRING_8
p: POINTER
a_data: CELL [detachable ANY]
l_form, l_last: CURL_FORM
curl: CURL_EXTERNALS
curl_easy: CURL_EASY_EXTERNALS
curl_handle: POINTER
do
curl := session.curl
curl_easy := session.curl_easy
l_url := url
if ctx /= Void then
if attached ctx.query_parameters as l_query_params then
from
l_query_params.start
until
l_query_params.after
loop
append_parameters_to_url (l_url, <<[l_query_params.key_for_iteration, urlencode (l_query_params.item_for_iteration)]>>)
l_query_params.forth
end
end
end
--| Configure cURL session
curl_handle := curl_easy.init
--| URL
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_url, l_url)
--| Timeout
if timeout > 0 then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_timeout, timeout)
end
--| Connect Timeout
if connect_timeout > 0 then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_connecttimeout, timeout)
end
--| Redirection
if max_redirects /= 0 then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_followlocation, 1)
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_maxredirs, max_redirects)
else
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_followlocation, 0)
end
if request_method.is_case_insensitive_equal ("GET") then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpget, 1)
elseif request_method.is_case_insensitive_equal ("POST") then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_post, 1)
elseif request_method.is_case_insensitive_equal ("PUT") then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_put, 1)
elseif request_method.is_case_insensitive_equal ("HEAD") then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_nobody, 1)
elseif request_method.is_case_insensitive_equal ("DELETE") then
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_customrequest, "DELETE")
else
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_customrequest, request_method)
--| ignored
end
--| Credential
if ctx /= Void and then ctx.credentials_required then
if attached credentials as l_credentials then
inspect auth_type_id
when {HTTP_CLIENT_CONSTANTS}.Auth_type_none then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpauth, {CURL_OPT_CONSTANTS}.curlauth_none)
when {HTTP_CLIENT_CONSTANTS}.Auth_type_basic then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpauth, {CURL_OPT_CONSTANTS}.curlauth_basic)
when {HTTP_CLIENT_CONSTANTS}.Auth_type_digest then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpauth, {CURL_OPT_CONSTANTS}.curlauth_digest)
when {HTTP_CLIENT_CONSTANTS}.Auth_type_any then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpauth, {CURL_OPT_CONSTANTS}.curlauth_any)
when {HTTP_CLIENT_CONSTANTS}.Auth_type_anysafe then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpauth, {CURL_OPT_CONSTANTS}.curlauth_anysafe)
else
end
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_userpwd, l_credentials)
else
--| Credentials not prov ided ...
end
end
if ctx /= Void and then ctx.has_form_data then
if attached ctx.form_data_parameters as l_posts and then not l_posts.is_empty then
-- curl_easy.set_debug_function (curl_handle)
-- curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_verbose, 1)
create l_form.make
create l_last.make
from
l_posts.start
until
l_posts.after
loop
curl.formadd_string_string (l_form, l_last, {CURL_FORM_CONSTANTS}.CURLFORM_COPYNAME, l_posts.key_for_iteration, {CURL_FORM_CONSTANTS}.CURLFORM_COPYCONTENTS, l_posts.item_for_iteration, {CURL_FORM_CONSTANTS}.CURLFORM_END)
l_posts.forth
end
l_last.release_item
curl_easy.setopt_form (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httppost, l_form)
end
end
if ctx /= Void then
if
request_method.is_case_insensitive_equal ("POST") and then
ctx.has_upload_data and then attached ctx.upload_data as l_upload_data
then
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_postfields, l_upload_data)
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_postfieldsize, l_upload_data.count)
elseif
request_method.is_case_insensitive_equal ("PUT") and then
ctx.has_upload_filename and then attached ctx.upload_filename as l_upload_filename
then
-- curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_postfields, l_upload_data)
-- curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_postfieldsize, l_upload_data.count)
--| Not Yet Implemented
end
end
curl.global_init
if attached headers as l_headers then
across
l_headers as curs
loop
p := curl.slist_append (p, curs.key + ": " + curs.item)
-- curl_easy.setopt_slist (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpheader, p)
end
end
p := curl.slist_append (p, "Expect:")
curl_easy.setopt_slist (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpheader, p)
curl.global_cleanup
curl_easy.set_read_function (curl_handle)
curl_easy.set_write_function (curl_handle)
create l_curl_string.make_empty
curl_easy.setopt_curl_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_writedata, l_curl_string)
debug ("service")
io.put_string ("SERVICE: " + l_url)
io.put_new_line
end
create Result.make
l_result := curl_easy.perform (curl_handle)
if l_result = {CURL_CODES}.curle_ok then
create a_data.put (Void)
l_result := curl_easy.getinfo (curl_handle, {CURL_INFO_CONSTANTS}.curlinfo_response_code, a_data)
if l_result = 0 and then attached {INTEGER} a_data.item as l_http_status then
Result.status := l_http_status
else
Result.status := 0
end
Result.body := l_curl_string.string
else
Result.set_error_occurred (True)
end
curl_easy.cleanup (curl_handle)
end
end
@@ -0,0 +1,101 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
LIBCURL_HTTP_CLIENT_SESSION
inherit
HTTP_CLIENT_SESSION
create
make
feature {NONE} -- Initialization
initialize
do
create curl -- cURL externals
create curl_easy -- cURL easy externals
end
feature -- Basic operation
get (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
local
req: HTTP_CLIENT_REQUEST
do
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "GET", Current)
Result := execute_request (req, ctx)
end
head (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
local
req: HTTP_CLIENT_REQUEST
do
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "HEAD", Current)
Result := execute_request (req, ctx)
end
post (a_path: READABLE_STRING_8; a_ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; a_data: detachable READABLE_STRING_8): HTTP_CLIENT_RESPONSE
local
req: HTTP_CLIENT_REQUEST
ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT
do
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "POST", Current)
ctx := a_ctx
if a_data /= Void then
if ctx = Void then
create ctx.make
end
ctx.set_upload_data (a_data)
end
Result := execute_request (req, ctx)
end
put (a_path: READABLE_STRING_8; a_ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; fn: detachable READABLE_STRING_8): HTTP_CLIENT_RESPONSE
local
req: HTTP_CLIENT_REQUEST
ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT
do
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "PUT", Current)
ctx := a_ctx
if fn /= Void then
if ctx = Void then
create ctx.make
end
ctx.set_upload_filename (fn)
end
Result := execute_request (req, ctx)
end
delete (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
local
req: HTTP_CLIENT_REQUEST
do
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "DELETE", Current)
Result := execute_request (req, ctx)
end
feature {NONE} -- Implementation
execute_request (req: HTTP_CLIENT_REQUEST; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
do
if ctx /= Void then
req.import (ctx)
end
Result := req.execute (ctx)
end
feature {LIBCURL_HTTP_CLIENT_REQUEST} -- Curl implementation
curl: CURL_EXTERNALS
-- cURL externals
curl_easy: CURL_EASY_EXTERNALS
-- cURL easy externals
end
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="error" uuid="C2DFF741-7091-43C7-B8B1-B075E7FF914F" library_target="error">
<target name="error">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
</system>
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="error" uuid="C2DFF741-7091-43C7-B8B1-B075E7FF914F" library_target="error">
<target name="error">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
</system>
+10
View File
@@ -0,0 +1,10 @@
${NOTE_KEYWORD}
copyright: "2011-${YEAR}, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
+80
View File
@@ -0,0 +1,80 @@
note
description : "Objects that represent an error"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
deferred class
ERROR
feature -- Access
code: INTEGER
deferred
ensure
result_not_zero: Result /= 0
end
name: STRING
deferred
ensure
result_attached: Result /= Void
end
message: detachable STRING_32
-- Potential error message
deferred
end
parent: detachable ERROR
-- Eventual error prior to Current
feature -- String representation
string_representation: STRING_32
-- String representation for Current
do
create Result.make_from_string (name.as_string_32)
Result.append_character (' ')
Result.append_character ('(')
Result.append_integer (code)
Result.append_character (')')
if attached message as m then
Result.append_character (':')
Result.append_character (' ')
Result.append_string (m)
end
end
feature -- Change
set_parent (a_parent: like parent)
-- Set `parent' to `a_parent'
do
parent := a_parent
end
feature -- Visitor
process (a_visitor: ERROR_VISITOR)
-- Process Current using `a_visitor'.
require
a_visitor_not_void: a_visitor /= Void
deferred
end
invariant
name_attached: name /= Void
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end
+57
View File
@@ -0,0 +1,57 @@
note
description : "Objects that represent a custom error"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
ERROR_CUSTOM
inherit
ERROR
create
make
feature {NONE} -- Initialization
make (a_code: INTEGER; a_name: STRING; a_message: detachable like message)
-- Initialize `Current'.
do
code := a_code
name := a_name
if attached a_message then
message := a_message
else
message := "Error: " + a_name + " (code=" + a_code.out + ")"
end
end
feature -- Access
code: INTEGER
name: STRING
message: STRING_32
feature -- Visitor
process (a_visitor: ERROR_VISITOR)
-- Process Current using `a_visitor'.
do
a_visitor.process_custom (Current)
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end
+75
View File
@@ -0,0 +1,75 @@
note
description : "Objects that represent a group of errors"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
ERROR_GROUP
inherit
ERROR
create
make
feature {NONE} -- Initialization
make (a_errors: LIST [ERROR])
-- Initialize `Current'.
do
name := a_errors.count.out + " errors"
create {ARRAYED_LIST [ERROR]} sub_errors.make (a_errors.count)
sub_errors.fill (a_errors)
end
feature -- Access
code: INTEGER = -1
name: STRING
message: detachable STRING_32
do
create Result.make_from_string (name)
from
sub_errors.start
until
sub_errors.after
loop
if
attached sub_errors.item as e and then
attached e.message as m
then
Result.append_character ('%N')
Result.append_string (m)
end
sub_errors.forth
end
end
sub_errors: LIST [ERROR]
-- Error contained by Current
feature -- Visitor
process (a_visitor: ERROR_VISITOR)
-- Process Current using `a_visitor'.
do
a_visitor.process_group (Current)
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end
+161
View File
@@ -0,0 +1,161 @@
note
description : "Objects that handle error..."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
ERROR_HANDLER
inherit
ANY
DEBUG_OUTPUT
create
make
feature {NONE} -- Initialization
make
-- Initialize `Current'.
do
create {ARRAYED_LIST [ERROR]} errors.make (3)
create error_added_actions
end
feature -- Status
has_error: BOOLEAN
-- Has error?
do
Result := count > 0
end
count: INTEGER
do
Result := errors.count
end
feature {ERROR_HANDLER, ERROR_VISITOR} -- Restricted access
errors: LIST [ERROR]
-- Errors container
feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
if has_error then
Result := count.out + " errors"
else
Result := "no error"
end
end
feature -- Events
error_added_actions: ACTION_SEQUENCE [TUPLE [ERROR]]
-- Actions triggered when a new error is added
feature {NONE} -- Event: implementation
on_error_added (e: ERROR)
-- Error `e' was just added
do
error_added_actions.call ([e])
end
feature -- Basic operation
add_error (a_error: ERROR)
-- Add `a_error' to the stack of error
do
errors.force (a_error)
on_error_added (a_error)
end
add_error_details, add_custom_error (a_code: INTEGER; a_name: STRING; a_message: detachable STRING_32)
-- Add custom error to the stack of error
local
e: ERROR_CUSTOM
do
create e.make (a_code, a_name, a_message)
add_error (e)
end
append (other: ERROR_HANDLER)
-- Append errors from `a_err_handler'
local
other_errs: LIST [ERROR]
do
other_errs := other.errors
if other_errs.count > 0 then
from
other_errs.start
until
other_errs.after
loop
add_error (other_errs.item)
other_errs.forth
end
end
ensure
other_error_appended: other.has_error implies has_error
new_count: count = old count + other.count
end
feature -- Access
as_single_error: detachable ERROR
do
if count > 1 then
create {ERROR_GROUP} Result.make (errors)
elseif count > 0 then
Result := errors.first
end
ensure
has_error_implies_result_attached: has_error implies Result /= Void
end
as_string_representation: STRING
require
has_error
do
if attached as_single_error as e then
Result := e.string_representation
else
check has_error: False end
Result := "Error occured"
end
end
feature -- Element changes
concatenate
-- Concatenate into a single error if any
do
if count > 1 and then attached as_single_error as e then
wipe_out
errors.force (e)
end
end
reset, wipe_out
do
errors.wipe_out
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end
@@ -0,0 +1,11 @@
note
description: "Summary description for {ERROR_HANDLER_WITH_EVENT}."
author: ""
date: "$Date$"
revision: "$Revision$"
@@ -0,0 +1,49 @@
note
description : "Error list iterator"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
ERROR_ITERATOR
inherit
ERROR_VISITOR
feature -- Access
process_error (e: ERROR)
do
end
process_custom (e: ERROR_CUSTOM)
do
process_error (e)
end
process_group (g: ERROR_GROUP)
do
if attached g.sub_errors as err then
from
err.start
until
err.after
loop
process_error (err.item)
err.forth
end
end
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end
@@ -0,0 +1,38 @@
note
description : "Null error visitor"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
ERROR_NULL_VISITOR
inherit
ERROR_VISITOR
feature -- Access
process_error (e: ERROR)
do
end
process_custom (e: ERROR_CUSTOM)
do
end
process_group (g: ERROR_GROUP)
do
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end
+35
View File
@@ -0,0 +1,35 @@
note
description : "Objects to visit an ERROR"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
deferred class
ERROR_VISITOR
feature -- Access
process_error (e: ERROR)
deferred
end
process_custom (e: ERROR_CUSTOM)
deferred
end
process_group (g: ERROR_GROUP)
deferred
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end
@@ -0,0 +1,53 @@
note
description: "File error output visitor"
date: "$Date$"
revision: "$Revision$"
class
FILE_OUTPUT_ERROR_VISITOR
inherit
OUTPUT_ERROR_VISITOR
redefine
output_integer,
output_new_line
end
create
make
feature -- Initialization
make (f: like file)
require
f_open_write: f /= Void and then f.is_open_write
do
file := f
end
feature -- Access
file: FILE
feature -- Output
output_string (a_str: detachable STRING_GENERAL)
-- Output Unicode string
do
if a_str /= Void then
to_implement ("Convert into UTF-8 or console encoding before output")
file.put_string (a_str.as_string_8)
end
end
output_integer (i: INTEGER)
do
file.put_integer (i)
end
output_new_line
do
file.put_new_line
end
end
@@ -0,0 +1,93 @@
note
description: "General error output visitor"
date: "$Date$"
revision: "$Revision$"
deferred class
OUTPUT_ERROR_VISITOR
inherit
ERROR_VISITOR
REFACTORING_HELPER
feature -- Output
output_string (a_str: detachable STRING_GENERAL)
-- Output Unicode string
deferred
end
output_any (obj: detachable ANY)
-- Output Unicode string
do
if attached {STRING_GENERAL} obj as l_str then
to_implement ("Convert into UTF-8 or console encoding before output")
output_string (l_str)
elseif obj /= Void then
output_string (obj.out)
end
end
output_integer (i: INTEGER)
do
output_string (i.out)
end
output_new_line
do
output_string ("%N")
end
feature -- Process
process_error (e: ERROR)
do
output_string ({STRING_32}"Error Name: ")
output_string (e.name)
output_string ({STRING_32}"Code: ")
output_integer (e.code)
output_new_line
output_string ({STRING_32}"%TMessage: ")
output_string (e.message)
output_new_line
end
process_custom (e: ERROR_CUSTOM)
do
output_string ({STRING_32}"Error Name: ")
output_string (e.name)
output_string ({STRING_32}"Code: ")
output_integer (e.code)
output_new_line
output_string ({STRING_32}"%TMessage: ")
output_string (e.message)
output_new_line
end
process_group (g: ERROR_GROUP)
local
l_errors: LIST [ERROR]
do
from
l_errors := g.sub_errors
l_errors.start
until
l_errors.after
loop
l_errors.item.process (Current)
l_errors.forth
end
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end
@@ -0,0 +1,53 @@
note
description: "Text error output visitor"
date: "$Date$"
revision: "$Revision$"
class
TEXT_OUTPUT_ERROR_VISITOR
inherit
OUTPUT_ERROR_VISITOR
redefine
output_integer,
output_new_line
end
create
make
feature -- Initialization
make (buf: like buffer)
require
buf_attached: buf /= Void
do
buffer := buf
end
feature -- Access
buffer: STRING
feature -- Output
output_string (a_str: detachable STRING_GENERAL)
-- Output Unicode string
do
if a_str /= Void then
to_implement ("Convert into UTF-8 or console encoding before output")
buffer.append_string_general (a_str)
end
end
output_integer (i: INTEGER)
do
buffer.append_integer (i)
end
output_new_line
do
buffer.append_character ('%N')
end
end
-38
View File
@@ -1,38 +0,0 @@
note
description: "Objects that ..."
author: ""
date: "$Date$"
revision: "$Revision$"
class
JSON_FILE_READER
feature -- Access
read_json_from (a_path: STRING): detachable STRING
local
l_file: PLAIN_TEXT_FILE
template_content: STRING
l_last_string: detachable STRING
do
create l_file.make (a_path)
-- We perform several checks until we make a real attempt to open the file.
if not l_file.exists then
print ("error: '" + a_path + "' does not exist%N")
else
if not l_file.is_readable then
print ("error: '" + a_path + "' is not readable.%N")
else
l_file.open_read
create template_content.make_empty
l_file.read_stream (l_file.count)
l_last_string := l_file.last_string
check l_last_string /= Void end -- implied by postcondition of `l_file.read_stream'
template_content.append (l_last_string.string)
Result := template_content
l_file.close
end
end
end
end
@@ -1,175 +0,0 @@
note
description: "JSON_PRETTY_STRING_VISITOR Generates the JSON-String for a JSON_VALUE"
revision: "0.1"
class
JSON_PRETTY_STRING_VISITOR
inherit
JSON_VISITOR
create
make,
make_custom
feature -- Initialization
make (a_output: like output)
-- Create a new instance
do
make_custom (a_output, 1, 1)
end
make_custom (a_output: like output; a_object_count_inlining, a_array_count_inlining: INTEGER)
-- Create a new instance
do
output := a_output
create indentation.make_empty
indentation_step := "%T"
object_count_inlining := a_object_count_inlining
array_count_inlining := a_array_count_inlining
end
feature -- Access
output: STRING_32
-- JSON representation
indentation: like output
indentation_step: like indentation
line_number: INTEGER
indent
do
indentation.append (indentation_step)
end
exdent
do
indentation.remove_tail (indentation_step.count)
end
new_line
do
output.append ("%N")
output.append (indentation)
line_number := line_number + 1
end
object_count_inlining: INTEGER
array_count_inlining: INTEGER
feature -- Visitor Pattern
visit_json_array (a_json_array: JSON_ARRAY)
-- Visit `a_json_array'.
local
value: JSON_VALUE
l_json_array: ARRAYED_LIST [JSON_VALUE]
l_line: like line_number
l_multiple_lines: BOOLEAN
do
l_json_array := a_json_array.array_representation
l_multiple_lines := l_json_array.count >= array_count_inlining or across l_json_array as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end
output.append ("[")
l_line := line_number
indent
from
l_json_array.start
until
l_json_array.off
loop
if
line_number > l_line or
l_multiple_lines
then
new_line
end
value := l_json_array.item
value.accept (Current)
l_json_array.forth
if not l_json_array.after then
output.append (", ")
end
end
exdent
if
line_number > l_line or
l_json_array.count >= array_count_inlining
then
new_line
end
output.append ("]")
end
visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
-- Visit `a_json_boolean'.
do
output.append (a_json_boolean.item.out)
end
visit_json_null (a_json_null: JSON_NULL)
-- Visit `a_json_null'.
do
output.append ("null")
end
visit_json_number (a_json_number: JSON_NUMBER)
-- Visit `a_json_number'.
do
output.append (a_json_number.item)
end
visit_json_object (a_json_object: JSON_OBJECT)
-- Visit `a_json_object'.
local
l_pairs: HASH_TABLE [JSON_VALUE, JSON_STRING]
l_line: like line_number
l_multiple_lines: BOOLEAN
do
l_pairs := a_json_object.map_representation
l_multiple_lines := l_pairs.count >= object_count_inlining or across l_pairs as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end
output.append ("{")
l_line := line_number
indent
from
l_pairs.start
until
l_pairs.off
loop
if
line_number > l_line or
l_multiple_lines
then
new_line
end
l_pairs.key_for_iteration.accept (Current)
output.append (": ")
l_pairs.item_for_iteration.accept (Current)
l_pairs.forth
if not l_pairs.after then
output.append (", ")
end
end
exdent
if
line_number > l_line or
l_pairs.count >= object_count_inlining
then
new_line
end
output.append ("}")
end
visit_json_string (a_json_string: JSON_STRING)
-- Visit `a_json_string'.
do
output.append ("%"")
output.append (a_json_string.item)
output.append ("%"")
end
end
-59
View File
@@ -1,59 +0,0 @@
note
description:
"JSON Visitor"
pattern: "Visitor"
author: "Javier Velilla"
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
date: "2008/08/24"
revision: "Revision 0.1"
deferred class
JSON_VISITOR
feature -- Visitor Pattern
visit_json_array (a_json_array: JSON_ARRAY)
-- Visit `a_json_array'.
require
a_json_array_not_void: a_json_array /= Void
deferred
end
visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
-- Visit `a_json_boolean'.
require
a_json_boolean_not_void: a_json_boolean /= Void
deferred
end
visit_json_null (a_json_null: JSON_NULL)
-- Visit `a_json_null'.
require
a_json_null_not_void: a_json_null /= Void
deferred
end
visit_json_number (a_json_number: JSON_NUMBER)
-- Visit `a_json_number'.
require
a_json_number_not_void: a_json_number /= Void
deferred
end
visit_json_object (a_json_object: JSON_OBJECT)
-- Visit `a_json_object'.
require
a_json_object_not_void: a_json_object /= Void
deferred
end
visit_json_string (a_json_string: JSON_STRING)
-- Visit `a_json_string'.
require
a_json_string_not_void: a_json_string /= Void
deferred
end
end
-102
View File
@@ -1,102 +0,0 @@
note
description: "PRINT_JSON_VISITOR Generates the JSON-String for a JSON_VALUE"
author: "jvelilla"
date: "2008/08/24"
revision: "0.1"
class
PRINT_JSON_VISITOR
inherit
JSON_VISITOR
create make
feature -- Initialization
make
-- Create a new instance
do
create to_json.make_empty
end
feature -- Access
to_json: STRING
-- JSON representation
feature -- Visitor Pattern
visit_json_array (a_json_array: JSON_ARRAY)
-- Visit `a_json_array'.
local
value: JSON_VALUE
l_json_array: ARRAYED_LIST [JSON_VALUE]
do
l_json_array:=a_json_array.array_representation
to_json.append ("[")
from
l_json_array.start
until
l_json_array.off
loop
value := l_json_array.item
value.accept (Current)
l_json_array.forth
if not l_json_array.after then
to_json.append(",")
end
end
to_json.append ("]")
end
visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
-- Visit `a_json_boolean'.
do
to_json.append (a_json_boolean.item.out)
end
visit_json_null (a_json_null: JSON_NULL)
-- Visit `a_json_null'.
do
to_json.append ("null")
end
visit_json_number (a_json_number: JSON_NUMBER)
-- Visit `a_json_number'.
do
to_json.append (a_json_number.item)
end
visit_json_object (a_json_object: JSON_OBJECT)
-- Visit `a_json_object'.
local
l_pairs: HASH_TABLE[JSON_VALUE,JSON_STRING]
do
l_pairs := a_json_object.map_representation
to_json.append ("{")
from
l_pairs.start
until
l_pairs.off
loop
l_pairs.key_for_iteration.accept (Current)
to_json.append (":")
l_pairs.item_for_iteration.accept (Current)
l_pairs.forth
if not l_pairs.after then
to_json.append (",")
end
end
to_json.append ("}")
end
visit_json_string (a_json_string: JSON_STRING)
-- Visit `a_json_string'.
do
to_json.append ("%"")
to_json.append (a_json_string.item)
to_json.append ("%"")
end
end
@@ -1,81 +0,0 @@
note
description: "A JSON converter for DS_HASH_TABLE [ANY, HASHABLE]"
author: "Paul Cohen"
date: "$Date: $"
revision: "$Revision: $"
file: "$HeadURL: $"
class JSON_DS_HASH_TABLE_CONVERTER
inherit
JSON_CONVERTER
create
make
feature {NONE} -- Initialization
make
do
create object.make (0)
end
feature -- Access
value: JSON_OBJECT
object: DS_HASH_TABLE [ANY, HASHABLE]
feature -- Conversion
from_json (j: like value): detachable like object
local
keys: ARRAY [JSON_STRING]
i: INTEGER
h: HASHABLE
a: ANY
do
keys := j.current_keys
create Result.make (keys.count)
from
i := 1
until
i > keys.count
loop
h ?= json.object (keys [i], void)
check h /= Void end
a := json.object (j.item (keys [i]), Void)
Result.put (a, h)
i := i + 1
end
end
to_json (o: like object): like value
local
c: DS_HASH_TABLE_CURSOR [ANY, HASHABLE]
js: JSON_STRING
jv: JSON_VALUE
failed: BOOLEAN
do
create Result.make
from
c := o.new_cursor
c.start
until
c.after
loop
create js.make_json (c.key.out)
jv := json.value (c.item)
if jv /= Void then
Result.put (jv, js)
else
failed := True
end
c.forth
end
if failed then
Result := Void
end
end
end -- class JSON_DS_HASH_TABLE_CONVERTER
@@ -1,62 +0,0 @@
note
description: "A JSON converter for DS_LINKED_LIST [ANY]"
author: "Paul Cohen"
date: "$Date: $"
revision: "$Revision: $"
file: "$HeadURL: $"
class JSON_DS_LINKED_LIST_CONVERTER
inherit
JSON_CONVERTER
create
make
feature {NONE} -- Initialization
make
do
create object.make
end
feature -- Access
value: JSON_ARRAY
object: DS_LINKED_LIST [ANY]
feature -- Conversion
from_json (j: like value): detachable like object
local
i: INTEGER
do
create Result.make
from
i := 1
until
i > j.count
loop
Result.put_last (json.object (j [i], Void))
i := i + 1
end
end
to_json (o: like object): like value
local
c: DS_LIST_CURSOR [ANY]
do
create Result.make_array
from
c := o.new_cursor
c.start
until
c.after
loop
Result.add (json.value (c.item))
c.forth
end
end
end -- class JSON_DS_LINKED_LIST_CONVERTER
-32
View File
@@ -1,32 +0,0 @@
note
description: "[
Shared factory class for creating JSON objects. Maps JSON
objects to Gobo DS_HASH_TABLEs and JSON arrays to Gobo
DS_LINKED_LISTs. Use non-conforming inheritance from this
class to ensure that your classes share the same
JSON_FACTORY instance.
]"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
class SHARED_GOBO_EJSON
feature
json: EJSON
-- A shared EJSON instance with default converters for
-- DS_LINKED_LIST [ANY] and DS_HASH_TABLE [ANY, HASHABLE]
local
jllc: JSON_DS_LINKED_LIST_CONVERTER
jhtc: JSON_DS_HASH_TABLE_CONVERTER
once
create Result
create jllc.make
Result.add_converter (jllc)
create jhtc.make
Result.add_converter (jhtc)
end
end -- class SHARED_GOBO_EJSON
-28
View File
@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="json" uuid="4E21C3BD-7951-4C6E-A673-431E762D7414" library_target="json">
<target name="json">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard" namespace="EJSON.Library">
<assertions/>
<warning name="export_class_missing" enabled="false"/>
<warning name="old_verbatim_strings" enabled="false"/>
<warning name="syntax" enabled="false"/>
<warning name="vjrv" enabled="false"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf" readonly="true"/>
<cluster name="json" location=".\" recursive="true">
<file_rule>
<exclude>^/gobo$</exclude>
<exclude>^/kernel$</exclude>
<exclude>^/extras$</exclude>
</file_rule>
<cluster name="kernel" location=".\kernel\" recursive="true"/>
<cluster name="extras" location=".\extras\" recursive="true"/>
</cluster>
</target>
</system>
-28
View File
@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="json" uuid="4E21C3BD-7951-4C6E-A673-431E762D7414" library_target="json">
<target name="json">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" void_safety="none" syntax="standard" namespace="EJSON.Library">
<assertions/>
<warning name="export_class_missing" enabled="false"/>
<warning name="old_verbatim_strings" enabled="false"/>
<warning name="syntax" enabled="false"/>
<warning name="vjrv" enabled="false"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
<cluster name="json" location=".\" recursive="true">
<file_rule>
<exclude>^/gobo$</exclude>
<exclude>^/kernel$</exclude>
<exclude>^/extras$</exclude>
</file_rule>
<cluster name="kernel" location=".\kernel\" recursive="true"/>
<cluster name="extras" location=".\extras\" recursive="true"/>
</cluster>
</target>
</system>
-17
View File
@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="json_gobo" uuid="437195AB-8B3C-4238-8998-A932A1423449" library_target="json_gobo">
<target name="json_gobo">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" void_safety="none" syntax="standard" namespace="EJSON.Library">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
<library name="json" location="json.ecf" readonly="true"/>
<library name="gobo_structure" location="$ISE_LIBRARY\library\gobo\gobo_structure.ecf"/>
<cluster name="json_gobo" location=".\gobo" recursive="true" />
</target>
</system>
@@ -1,30 +0,0 @@
note
description: "A JSON converter for ARRAYED_LIST [ANY]"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
class JSON_ARRAYED_LIST_CONVERTER
inherit
JSON_LIST_CONVERTER
redefine
object
end
create
make
feature -- Access
object: ARRAYED_LIST [detachable ANY]
feature {NONE} -- Factory
new_object (nb: INTEGER): like object
do
create Result.make (nb)
end
end -- class JSON_ARRAYED_LIST_CONVERTER
@@ -1,36 +0,0 @@
note
description: "A JSON converter"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
deferred class JSON_CONVERTER
inherit
SHARED_EJSON
feature -- Access
object: ANY
-- Eiffel object
deferred
end
feature -- Conversion
from_json (j: attached like to_json): detachable like object
-- Convert from JSON value.
-- Returns Void if unable to convert
deferred
end
to_json (o: like object): detachable JSON_VALUE
-- Convert to JSON value
deferred
end
invariant
has_eiffel_object: object /= Void -- An empty object must be created at creation time!
end
@@ -1,88 +0,0 @@
note
description: "A JSON converter for HASH_TABLE [ANY, HASHABLE]"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
class JSON_HASH_TABLE_CONVERTER
inherit
JSON_CONVERTER
create
make
feature {NONE} -- Initialization
make
do
create object.make (0)
end
feature -- Access
object: HASH_TABLE [ANY, HASHABLE]
feature -- Conversion
from_json (j: attached like to_json): like object
local
keys: ARRAY [JSON_STRING]
i: INTEGER
h: detachable HASHABLE
jv: detachable JSON_VALUE
a: detachable ANY
do
keys := j.current_keys
create Result.make (keys.count)
from
i := 1
until
i > keys.count
loop
h ?= json.object (keys [i], Void)
check h /= Void end
jv := j.item (keys [i])
if jv /= Void then
a := json.object (jv, Void)
if a /= Void then
Result.put (a, h)
else
check a_attached: a /= Void end
end
else
check j_has_item: False end
end
i := i + 1
end
end
to_json (o: like object): detachable JSON_OBJECT
local
c: HASH_TABLE_ITERATION_CURSOR [ANY, HASHABLE]
js: JSON_STRING
jv: detachable JSON_VALUE
failed: BOOLEAN
do
create Result.make
from
c := o.new_cursor
until
c.after
loop
create js.make_json (c.key.out)
jv := json.value (c.item)
if jv /= Void then
Result.put (jv, js)
else
failed := True
end
c.forth
end
if failed then
Result := Void
end
end
end -- class JSON_HASH_TABLE_CONVERTER
@@ -1,30 +0,0 @@
note
description: "A JSON converter for LINKED_LIST [ANY]"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
class JSON_LINKED_LIST_CONVERTER
inherit
JSON_LIST_CONVERTER
redefine
object
end
create
make
feature -- Access
object: LINKED_LIST [detachable ANY]
feature {NONE} -- Factory
new_object (nb: INTEGER): like object
do
create Result.make
end
end -- class JSON_LINKED_LIST_CONVERTER
@@ -1,74 +0,0 @@
note
description: "A JSON converter for LIST [ANY]"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
deferred class JSON_LIST_CONVERTER
inherit
JSON_CONVERTER
feature {NONE} -- Initialization
make
do
object := new_object (0)
end
feature -- Access
object: LIST [detachable ANY]
feature {NONE} -- Factory
new_object (nb: INTEGER): like object
deferred
ensure
Result /= Void
end
feature -- Conversion
from_json (j: attached like to_json): detachable like object
local
i: INTEGER
do
Result := new_object (j.count)
from
i := 1
until
i > j.count
loop
Result.extend (json.object (j [i], Void))
i := i + 1
end
end
to_json (o: like object): detachable JSON_ARRAY
local
c: ITERATION_CURSOR [detachable ANY]
jv: detachable JSON_VALUE
failed: BOOLEAN
do
create Result.make_array
from
c := o.new_cursor
until
c.after
loop
jv := json.value (c.item)
if jv /= Void then
Result.add (jv)
else
failed := True
end
c.forth
end
if failed then
Result := Void
end
end
end -- class JSON_ARRAYED_LIST_CONVERTER
-268
View File
@@ -1,268 +0,0 @@
note
description: "Core factory class for creating JSON objects and corresponding Eiffel objects."
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
class EJSON
inherit
EXCEPTIONS
feature -- Access
value (an_object: detachable ANY): detachable JSON_VALUE
-- JSON value from Eiffel object. Raises an "eJSON exception" if
-- unable to convert value.
local
i: INTEGER
ja: JSON_ARRAY
do
-- Try to convert from basic Eiffel types. Note that we check with
-- `conforms_to' since the client may have subclassed the base class
-- that these basic types are derived from.
if an_object = Void then
create {JSON_NULL} Result
elseif attached {BOOLEAN} an_object as b then
create {JSON_BOOLEAN} Result.make_boolean (b)
elseif attached {INTEGER_8} an_object as i8 then
create {JSON_NUMBER} Result.make_integer (i8)
elseif attached {INTEGER_16} an_object as i16 then
create {JSON_NUMBER} Result.make_integer (i16)
elseif attached {INTEGER_32} an_object as i32 then
create {JSON_NUMBER} Result.make_integer (i32)
elseif attached {INTEGER_64} an_object as i64 then
create {JSON_NUMBER} Result.make_integer (i64)
elseif attached {NATURAL_8} an_object as n8 then
create {JSON_NUMBER} Result.make_natural (n8)
elseif attached {NATURAL_16} an_object as n16 then
create {JSON_NUMBER} Result.make_natural (n16)
elseif attached {NATURAL_32} an_object as n32 then
create {JSON_NUMBER} Result.make_natural (n32)
elseif attached {NATURAL_64} an_object as n64 then
create {JSON_NUMBER} Result.make_natural (n64)
elseif attached {REAL_32} an_object as r32 then
create {JSON_NUMBER} Result.make_real (r32)
elseif attached {REAL_64} an_object as r64 then
create {JSON_NUMBER} Result.make_real (r64)
elseif attached {ARRAY [detachable ANY]} an_object as a then
create ja.make_array
from
i := a.lower
until
i > a.upper
loop
if attached value (a @ i) as v then
ja.add (v)
else
check value_attached: False end
end
i := i + 1
end
Result := ja
elseif attached {CHARACTER_8} an_object as c8 then
create {JSON_STRING} Result.make_json (c8.out)
elseif attached {CHARACTER_32} an_object as c32 then
create {JSON_STRING} Result.make_json (c32.out)
elseif attached {STRING_8} an_object as s8 then
create {JSON_STRING} Result.make_json (s8)
elseif attached {STRING_32} an_object as s32 then
create {JSON_STRING} Result.make_json_from_string_32 (s32)
end
if Result = Void then
-- Now check the converters
if an_object /= Void and then attached converter_for (an_object) as jc then
Result := jc.to_json (an_object)
else
raise (exception_failed_to_convert_to_json (an_object))
end
end
end
object (a_value: detachable JSON_VALUE; base_class: detachable STRING): detachable ANY
-- Eiffel object from JSON value. If `base_class' /= Void an eiffel
-- object based on `base_class' will be returned. Raises an "eJSON
-- exception" if unable to convert value.
local
i: INTEGER
ll: LINKED_LIST [detachable ANY]
t: HASH_TABLE [detachable ANY, STRING_GENERAL]
keys: ARRAY [JSON_STRING]
do
if a_value = Void then
Result := Void
else
if base_class = Void then
if a_value = Void then
Result := Void
elseif attached {JSON_NULL} a_value then
Result := Void
elseif attached {JSON_BOOLEAN} a_value as jb then
Result := jb.item
elseif attached {JSON_NUMBER} a_value as jn then
if jn.item.is_integer_8 then
Result := jn.item.to_integer_8
elseif jn.item.is_integer_16 then
Result := jn.item.to_integer_16
elseif jn.item.is_integer_32 then
Result := jn.item.to_integer_32
elseif jn.item.is_integer_64 then
Result := jn.item.to_integer_64
elseif jn.item.is_natural_64 then
Result := jn.item.to_natural_64
elseif jn.item.is_double then
Result := jn.item.to_double
end
elseif attached {JSON_STRING} a_value as js then
create {STRING_32} Result.make_from_string (js.unescaped_string_32)
elseif attached {JSON_ARRAY} a_value as ja then
from
create ll.make
i := 1
until
i > ja.count
loop
ll.extend (object (ja [i], Void))
i := i + 1
end
Result := ll
elseif attached {JSON_OBJECT} a_value as jo then
keys := jo.current_keys
create t.make (keys.count)
from
i := keys.lower
until
i > keys.upper
loop
if attached {STRING_GENERAL} object (keys [i], Void) as s then
t.put (object (jo.item (keys [i]), Void), s)
end
i := i + 1
end
Result := t
end
else
if converters.has_key (base_class) and then attached converters.found_item as jc then
Result := jc.from_json (a_value)
else
raise (exception_failed_to_convert_to_eiffel (a_value, base_class))
end
end
end
end
object_from_json (json: STRING; base_class: detachable STRING): detachable ANY
-- Eiffel object from JSON representation. If `base_class' /= Void an
-- Eiffel object based on `base_class' will be returned. Raises an
-- "eJSON exception" if unable to convert value.
require
json_not_void: json /= Void
local
jv: detachable JSON_VALUE
do
json_parser.set_representation (json)
jv := json_parser.parse
if jv /= Void then
Result := object (jv, base_class)
end
end
converter_for (an_object: ANY): detachable JSON_CONVERTER
-- Converter for objects. Returns Void if none found.
require
an_object_not_void: an_object /= Void
do
if converters.has_key (an_object.generator) then
Result := converters.found_item
end
end
json_reference (s: STRING): JSON_OBJECT
-- A JSON (Dojo style) reference object using `s' as the
-- reference value. The caller is responsable for ensuring
-- the validity of `s' as a json reference.
require
s_not_void: s /= Void
local
js_key, js_value: JSON_STRING
do
create Result.make
create js_key.make_json ("$ref")
create js_value.make_json (s)
Result.put (js_value, js_key)
end
json_references (l: LIST [STRING]): JSON_ARRAY
-- A JSON array of JSON (Dojo style) reference objects using the
-- strings in `l' as reference values. The caller is responsable
-- for ensuring the validity of all strings in `l' as json
-- references.
require
l_not_void: l /= Void
local
c: ITERATION_CURSOR [STRING]
do
create Result.make_array
from
c := l.new_cursor
until
c.after
loop
Result.add (json_reference (c.item))
c.forth
end
end
feature -- Change
add_converter (jc: JSON_CONVERTER)
-- Add the converter `jc'.
require
jc_not_void: jc /= Void
do
converters.force (jc, jc.object.generator)
ensure
has_converter: converter_for (jc.object) /= Void
end
feature {NONE} -- Implementation
converters: HASH_TABLE [JSON_CONVERTER, STRING]
-- Converters hashed by generator (base class)
once
create Result.make (10)
end
feature {NONE} -- Implementation (Exceptions)
exception_prefix: STRING = "eJSON exception: "
exception_failed_to_convert_to_eiffel (a_value: JSON_VALUE; base_class: detachable STRING): STRING
-- Exception message for failing to convert a JSON_VALUE to an instance of `a'.
do
Result := exception_prefix + "Failed to convert JSON_VALUE to an Eiffel object: " + a_value.generator
if base_class /= Void then
Result.append (" -> " + base_class)
end
end
exception_failed_to_convert_to_json (an_object: detachable ANY): STRING
-- Exception message for failing to convert `a' to a JSON_VALUE.
do
Result := exception_prefix + "Failed to convert Eiffel object to a JSON_VALUE"
if an_object /= Void then
Result := ": " + an_object.generator
end
end
feature {NONE} -- Implementation (JSON parser)
json_parser: JSON_PARSER
once
create Result.make_parser ("")
end
end -- class EJSON
-141
View File
@@ -1,141 +0,0 @@
note
description: "[
JSON_ARRAY represent an array in JSON.
An array in JSON is an ordered set of names.
Examples
array
[]
[elements]
]"
author: "Javier Velilla"
date: "2008/08/24"
revision: "Revision 0.1"
class
JSON_ARRAY
inherit
JSON_VALUE
DEBUG_OUTPUT
create
make_array
feature {NONE} -- Initialization
make_array
-- Initialize JSON Array
do
create values.make (10)
end
feature -- Access
i_th alias "[]" (i: INTEGER): JSON_VALUE
-- Item at `i'-th position
require
is_valid_index: valid_index (i)
do
Result := values.i_th (i)
end
representation: STRING
local
i: INTEGER
do
Result := "["
from
i := 1
until
i > count
loop
Result.append (i_th (i).representation)
i := i + 1
if i <= count then
Result.append_character (',')
end
end
Result.append_character (']')
end
feature -- Visitor pattern
accept (a_visitor: JSON_VISITOR)
-- Accept `a_visitor'.
-- (Call `visit_json_array' procedure on `a_visitor'.)
do
a_visitor.visit_json_array (Current)
end
feature -- Mesurement
count: INTEGER
-- Number of items.
do
Result := values.count
end
feature -- Status report
valid_index (i: INTEGER): BOOLEAN
-- Is `i' a valid index?
do
Result := (1 <= i) and (i <= count)
end
feature -- Change Element
add (value: JSON_VALUE)
require
value_not_null: value /= void
do
values.extend (value)
ensure
has_new_value: old values.count + 1 = values.count and
values.has (value)
end
feature -- Report
hash_code: INTEGER
-- Hash code value
do
from
values.start
Result := values.item.hash_code
until
values.off
loop
Result:= ((Result \\ 8388593) |<< 8) + values.item.hash_code
values.forth
end
Result := Result \\ values.count
end
feature -- Conversion
array_representation: ARRAYED_LIST [JSON_VALUE]
-- Representation as a sequences of values
do
Result := values
end
feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
Result := count.out
end
feature {NONE} -- Implementation
values: ARRAYED_LIST [JSON_VALUE]
-- Value container
invariant
value_not_void: values /= Void
end
-61
View File
@@ -1,61 +0,0 @@
note
description: "JSON Truth values"
author: "Javier Velilla"
date: "2008/08/24"
revision: "Revision 0.1"
class
JSON_BOOLEAN
inherit
JSON_VALUE
create
make_boolean
feature {NONE} -- Initialization
make_boolean (an_item: BOOLEAN)
--Initialize.
do
item := an_item
end
feature -- Access
item: BOOLEAN
-- Content
hash_code: INTEGER
-- Hash code value
do
Result := item.hash_code
end
representation: STRING
do
if item then
Result := "true"
else
Result := "false"
end
end
feature -- Visitor pattern
accept (a_visitor: JSON_VISITOR)
-- Accept `a_visitor'.
-- (Call `visit_json_boolean' procedure on `a_visitor'.)
do
a_visitor.visit_json_boolean (Current)
end
feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
Result := item.out
end
end
-47
View File
@@ -1,47 +0,0 @@
note
description: "JSON Null Values"
author: "Javier Velilla"
date: "2008/08/24"
revision: "Revision 0.1"
class
JSON_NULL
inherit
JSON_VALUE
feature --Access
hash_code: INTEGER
-- Hash code value
do
Result := null_value.hash_code
end
representation: STRING
do
Result := "null"
end
feature -- Visitor pattern
accept (a_visitor: JSON_VISITOR)
-- Accept `a_visitor'.
-- (Call `visit_element_a' procedure on `a_visitor'.)
do
a_visitor.visit_json_null (Current)
end
feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
Result := null_value
end
feature {NONE}-- Implementation
null_value: STRING = "null"
end
-99
View File
@@ -1,99 +0,0 @@
note
description: "JSON Numbers, octal and hexadecimal formats are not used."
author: "Javier Velilla"
date: "2008/08/24"
revision: "Revision 0.1"
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
class
JSON_NUMBER
inherit
JSON_VALUE
redefine
is_equal
end
create
make_integer,
make_natural,
make_real
feature {NONE} -- initialization
make_integer (an_argument: INTEGER_64)
-- Initialize an instance of JSON_NUMBER from the integer value of `an_argument'.
do
item := an_argument.out
numeric_type := INTEGER_TYPE
end
make_natural (an_argument: NATURAL_64)
-- Initialize an instance of JSON_NUMBER from the unsigned integer value of `an_argument'.
do
item := an_argument.out
numeric_type := NATURAL_TYPE
end
make_real (an_argument: DOUBLE)
-- Initialize an instance of JSON_NUMBER from the floating point value of `an_argument'.
do
item := an_argument.out
numeric_type := DOUBLE_TYPE
end
feature -- Access
item: STRING
-- Content
hash_code: INTEGER
--Hash code value
do
Result := item.hash_code
end
representation: STRING
do
Result := item
end
feature -- Visitor pattern
accept (a_visitor: JSON_VISITOR)
-- Accept `a_visitor'.
-- (Call `visit_json_number' procedure on `a_visitor'.)
do
a_visitor.visit_json_number (Current)
end
feature -- Status
is_equal (other: like Current): BOOLEAN
-- Is `other' attached to an object of the same type
-- as current object and identical to it?
do
Result := item.is_equal (other.item)
end
feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
Result := item
end
feature -- Implementation
INTEGER_TYPE: INTEGER = 1
DOUBLE_TYPE: INTEGER = 2
NATURAL_TYPE: INTEGER = 3
numeric_type: INTEGER
invariant
item_not_void: item /= Void
end
-191
View File
@@ -1,191 +0,0 @@
note
description: "[
An JSON_OBJECT represent an object in JSON.
An object is an unordered set of name/value pairs
Examples:
object
{}
{"key","value"}
]"
author: "Javier Velilla"
date: "2008/08/24"
revision: "Revision 0.1"
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
class
JSON_OBJECT
inherit
JSON_VALUE
TABLE_ITERABLE [JSON_VALUE, JSON_STRING]
create
make
feature {NONE} -- Initialization
make
-- Initialize
do
create object.make (10)
end
feature -- Change Element
put (value: detachable JSON_VALUE; key: JSON_STRING)
-- Assuming there is no item of key `key',
-- insert `value' with `key'.
require
key_not_present: not has_key (key)
local
l_value: like value
do
l_value := value
if l_value = Void then
create {JSON_NULL} l_value
end
object.extend (l_value, key)
end
replace (value: detachable JSON_VALUE; key: JSON_STRING)
-- Assuming there is no item of key `key',
-- insert `value' with `key'.
local
l_value: like value
do
l_value := value
if l_value = Void then
create {JSON_NULL} l_value
end
object.force (l_value, key)
end
feature -- Access
has_key (key: JSON_STRING): BOOLEAN
-- has the JSON_OBJECT contains a specific key 'key'.
do
Result := object.has (key)
end
has_item (value: JSON_VALUE): BOOLEAN
-- has the JSON_OBJECT contain a specfic item 'value'
do
Result := object.has_item (value)
end
item (key: JSON_STRING): detachable JSON_VALUE
-- the json_value associated with a key.
do
Result := object.item (key)
end
current_keys: ARRAY [JSON_STRING]
-- array containing actually used keys
do
Result := object.current_keys
end
representation: STRING
local
t: HASH_TABLE [JSON_VALUE, JSON_STRING]
do
Result := "{"
from
t := map_representation
t.start
until
t.after
loop
Result.append (t.key_for_iteration.representation)
Result.append (":")
Result.append (t.item_for_iteration.representation)
t.forth
if not t.after then
Result.append_character (',')
end
end
Result.append_character ('}')
end
feature -- Mesurement
count: INTEGER
-- Number of field
do
Result := object.count
end
feature -- Access
new_cursor: TABLE_ITERATION_CURSOR [JSON_VALUE, JSON_STRING]
-- Fresh cursor associated with current structure
do
Result := object.new_cursor
end
feature -- Status report
is_empty: BOOLEAN
-- Is empty object?
do
Result := object.is_empty
end
feature -- Visitor pattern
accept (a_visitor: JSON_VISITOR)
-- Accept `a_visitor'.
-- (Call `visit_json_object' procedure on `a_visitor'.)
do
a_visitor.visit_json_object (Current)
end
feature -- Conversion
map_representation: HASH_TABLE [JSON_VALUE, JSON_STRING]
--A representation that maps keys to values
do
Result := object
end
feature -- Report
hash_code: INTEGER
-- Hash code value
do
from
object.start
Result := object.item_for_iteration.hash_code
until
object.off
loop
Result := ((Result \\ 8388593) |<< 8) + object.item_for_iteration.hash_code
object.forth
end
-- Ensure it is a positive value.
Result := Result.hash_code
end
feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
Result := object.count.out
end
feature {NONE} -- Implementation
object: HASH_TABLE [JSON_VALUE, JSON_STRING]
-- Value container
invariant
object_not_null: object /= Void
end
-329
View File
@@ -1,329 +0,0 @@
note
description: "[
A JSON_STRING represent a string in JSON.
A string is a collection of zero or more Unicodes characters, wrapped in double
quotes, using blackslash espaces.
]"
author: "Javier Velilla"
date: "2008/08/24"
revision: "Revision 0.1"
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
class
JSON_STRING
inherit
JSON_VALUE
redefine
is_equal
end
create
make_json,
make_json_from_string_32,
make_with_escaped_json
convert
make_json ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}),
make_json_from_string_32 ({READABLE_STRING_32, STRING_32, IMMUTABLE_STRING_32})
feature {NONE} -- Initialization
make_json (s: READABLE_STRING_8)
-- Initialize.
require
item_not_void: s /= Void
do
make_with_escaped_json (escaped_json_string (s))
end
make_json_from_string_32 (s: READABLE_STRING_32)
-- Initialize from STRING_32 `s'.
require
item_not_void: s /= Void
do
make_with_escaped_json (escaped_json_string_32 (s))
end
make_with_escaped_json (s: READABLE_STRING_8)
-- Initialize with an_item already escaped
require
item_not_void: s /= Void
do
item := s
end
feature -- Access
item: STRING
-- Contents with escaped entities if any
unescaped_string_8: STRING_8
-- Unescaped string from `item'
local
s: like item
i, n: INTEGER
c: CHARACTER
do
s := item
n := s.count
create Result.make (n)
from i := 1 until i > n loop
c := s[i]
if c = '\' then
if i < n then
inspect s[i+1]
when '\' then
Result.append_character ('\')
i := i + 2
when '%"' then
Result.append_character ('%"')
i := i + 2
when 'n' then
Result.append_character ('%N')
i := i + 2
when 'r' then
Result.append_character ('%R')
i := i + 2
when 'u' then
--| Leave unicode \uXXXX unescaped
Result.append_character ('\')
i := i + 1
else
Result.append_character ('\')
i := i + 1
end
else
Result.append_character ('\')
i := i + 1
end
else
Result.append_character (c)
i := i + 1
end
end
end
unescaped_string_32: STRING_32
-- Unescaped string 32 from `item'
local
s: like item
i, n: INTEGER
c: CHARACTER
hex: STRING
do
s := item
n := s.count
create Result.make (n)
from i := 1 until i > n loop
c := s[i]
if c = '\' then
if i < n then
inspect s[i+1]
when '\' then
Result.append_character ('\')
i := i + 2
when '%"' then
Result.append_character ('%"')
i := i + 2
when 'n' then
Result.append_character ('%N')
i := i + 2
when 'r' then
Result.append_character ('%R')
i := i + 2
when 'u' then
hex := s.substring (i+2, i+2+4 - 1)
if hex.count = 4 then
Result.append_code (hexadecimal_to_natural_32 (hex))
end
i := i + 2 + 4
else
Result.append_character ('\')
i := i + 1
end
else
Result.append_character ('\')
i := i + 1
end
else
Result.append_character (c.to_character_32)
i := i + 1
end
end
end
representation: STRING
-- String representation of `item' with escaped entities if any
do
create Result.make (item.count + 2)
Result.append_character ('%"')
Result.append (item)
Result.append_character ('%"')
end
feature -- Visitor pattern
accept (a_visitor: JSON_VISITOR)
-- Accept `a_visitor'.
-- (Call `visit_json_string' procedure on `a_visitor'.)
do
a_visitor.visit_json_string (Current)
end
feature -- Comparison
is_equal (other: like Current): BOOLEAN
-- Is JSON_STRING made of same character sequence as `other'
-- (possibly with a different capacity)?
do
Result := item.same_string (other.item)
end
feature -- Change Element
append (a_string: STRING)
-- Add a_string
require
a_string_not_void: a_string /= Void
do
item.append_string (a_string)
end
feature -- Status report
hash_code: INTEGER
-- Hash code value
do
Result := item.hash_code
end
feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
Result := item
end
feature {NONE} -- Implementation
is_hexadecimal (s: READABLE_STRING_8): BOOLEAN
-- Is `s' an hexadecimal value?
do
Result := across s as scur all scur.item.is_hexa_digit end
end
hexadecimal_to_natural_32 (s: READABLE_STRING_8): NATURAL_32
-- Hexadecimal string `s' converted to NATURAL_32 value
require
s_not_void: s /= Void
is_hexadecimal: is_hexadecimal (s)
local
i, nb: INTEGER
char: CHARACTER
do
nb := s.count
if nb >= 2 and then s.item (2) = 'x' then
i := 3
else
i := 1
end
from
until
i > nb
loop
Result := Result * 16
char := s.item (i)
if char >= '0' and then char <= '9' then
Result := Result + (char |-| '0').to_natural_32
else
Result := Result + (char.lower |-| 'a' + 10).to_natural_32
end
i := i + 1
end
end
escaped_json_string (s: READABLE_STRING_8): STRING_8
-- JSON string with '"' and '\' characters escaped
require
s_not_void: s /= Void
local
i, n: INTEGER
c: CHARACTER_8
do
n := s.count
create Result.make (n + n // 10)
from i := 1 until i > n loop
c := s.item (i)
inspect c
when '%"' then Result.append_string ("\%"")
when '\' then Result.append_string ("\\")
when '%R' then Result.append_string ("\r")
when '%N' then Result.append_string ("\n")
else
Result.extend (c)
end
i := i + 1
end
end
escaped_json_string_32 (s: READABLE_STRING_32): STRING_8
-- JSON string with '"' and '\' characters and unicode escaped
require
s_not_void: s /= Void
local
i, j, n: INTEGER
uc: CHARACTER_32
c: CHARACTER_8
h: STRING_8
do
n := s.count
create Result.make (n + n // 10)
from i := 1 until i > n loop
uc := s.item (i)
if uc.is_character_8 then
c := uc.to_character_8
inspect c
when '%"' then Result.append_string ("\%"")
when '\' then Result.append_string ("\\")
when '%R' then Result.append_string ("\r")
when '%N' then Result.append_string ("\n")
else
Result.extend (c)
end
else
Result.append ("\u")
h := uc.code.to_hex_string
-- Remove first 0 and keep 4 hexa digit
from
j := 1
until
h.count = 4 or (j <= h.count and then h.item (j) /= '0')
loop
j := j + 1
end
h := h.substring (j, h.count)
from
until
h.count >= 4
loop
h.prepend_integer (0)
end
check h.count = 4 end
Result.append (h)
end
i := i + 1
end
end
invariant
item_not_void: item /= Void
end
-43
View File
@@ -1,43 +0,0 @@
note
description:"[
JSON_VALUE represent a value in JSON.
A value can be
* a string in double quotes
* a number
* boolean value(true, false )
* null
* an object
* an array
]"
author: "Javier Velilla"
date: "2008/05/19"
revision: "Revision 0.1"
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
deferred class
JSON_VALUE
inherit
HASHABLE
DEBUG_OUTPUT
feature -- Access
representation: STRING
-- UTF-8 encoded Unicode string representation of Current
deferred
end
feature -- Visitor pattern
accept (a_visitor: JSON_VISITOR)
-- Accept `a_visitor'.
-- (Call `visit_*' procedure on `a_visitor'.)
require
a_visitor_not_void: a_visitor /= Void
deferred
end
end
-513
View File
@@ -1,513 +0,0 @@
note
description: "Parse serialized JSON data"
author: "jvelilla"
date: "2008/08/24"
revision: "Revision 0.1"
class
JSON_PARSER
inherit
JSON_READER
JSON_TOKENS
create
make_parser
feature {NONE} -- Initialize
make_parser (a_json: STRING)
-- Initialize.
require
json_not_empty: a_json /= Void and then not a_json.is_empty
do
make (a_json)
is_parsed := True
create errors.make
end
feature -- Status report
is_parsed: BOOLEAN
-- Is parsed?
errors: LINKED_LIST [STRING]
-- Current errors
current_errors: STRING
-- Current errors as string
do
create Result.make_empty
from
errors.start
until
errors.after
loop
Result.append_string (errors.item + "%N")
errors.forth
end
end
feature -- Element change
report_error (e: STRING)
-- Report error `e'
require
e_not_void: e /= Void
do
errors.force (e)
end
feature -- Commands
parse_json: detachable JSON_VALUE
-- Parse JSON data `representation'
-- start ::= object | array
do
if is_valid_start_symbol then
Result := parse
if extra_elements then
is_parsed := False
end
else
is_parsed := False
report_error ("Syntax error unexpected token, expecting `{' or `['")
end
end
parse: detachable JSON_VALUE
-- Parse JSON data `representation'
local
c: CHARACTER
do
if is_parsed then
skip_white_spaces
c := actual
inspect c
when j_OBJECT_OPEN then
Result := parse_object
when j_STRING then
Result := parse_string
when j_ARRAY_OPEN then
Result := parse_array
else
if c.is_digit or c = j_MINUS then
Result := parse_number
elseif is_null then
Result := create {JSON_NULL}
next
next
next
elseif is_true then
Result := create {JSON_BOOLEAN}.make_boolean (True)
next
next
next
elseif is_false then
Result := create {JSON_BOOLEAN}.make_boolean (False)
next
next
next
next
else
is_parsed := False
report_error ("JSON is not well formed in parse")
Result := Void
end
end
end
ensure
is_parsed_implies_result_not_void: is_parsed implies Result /= Void
end
parse_object: JSON_OBJECT
-- object
-- {}
-- {"key" : "value" [,]}
local
has_more: BOOLEAN
l_json_string: detachable JSON_STRING
l_value: detachable JSON_VALUE
do
create Result.make
-- check if is an empty object {}
next
skip_white_spaces
if actual = j_OBJECT_CLOSE then
--is an empty object
else
-- a complex object {"key" : "value"}
previous
from has_more := True until not has_more loop
next
skip_white_spaces
l_json_string := parse_string
next
skip_white_spaces
if actual = ':' then
next
skip_white_spaces
else
is_parsed := False
report_error ("%N Input string is a not well formed JSON, expected: : found: " + actual.out)
has_more := False
end
l_value := parse
if is_parsed and then (l_value /= Void and l_json_string /= Void) then
Result.put (l_value, l_json_string)
next
skip_white_spaces
if actual = j_OBJECT_CLOSE then
has_more := False
elseif actual /= ',' then
has_more := False
is_parsed := False
report_error ("JSON Object syntactically malformed expected , found: [" + actual.out + "]")
end
else
has_more := False
-- explain the error
end
end
end
end
parse_string: detachable JSON_STRING
-- Parsed string
local
has_more: BOOLEAN
l_json_string: STRING
l_unicode: STRING
c: like actual
do
create l_json_string.make_empty
if actual = j_STRING then
from
has_more := True
until
not has_more
loop
next
c := actual
if c = j_STRING then
has_more := False
elseif c = '%H' then
next
c := actual
if c = 'u' then
create l_unicode.make_from_string ("\u")
l_unicode.append (read_unicode)
c := actual
if is_valid_unicode (l_unicode) then
l_json_string.append (l_unicode)
else
has_more := False
is_parsed := False
report_error ("Input String is not well formed JSON, expected a Unicode value, found [" + c.out + " ]")
end
elseif (not is_special_character (c) and not is_special_control (c)) or c = '%N' then
has_more := False
is_parsed := False
report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
else
l_json_string.append_character ('\')
l_json_string.append_character (c)
end
else
if is_special_character (c) and c /= '/' then
has_more := False
is_parsed := False
report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
else
l_json_string.append_character (c)
end
end
end
create Result.make_with_escaped_json (l_json_string)
else
Result := Void
end
end
parse_array: JSON_ARRAY
-- array
-- []
-- [elements [,]]
local
flag: BOOLEAN
l_value: detachable JSON_VALUE
c: like actual
do
create Result.make_array
--check if is an empty array []
next
skip_white_spaces
if actual = j_array_close then
--is an empty array
else
previous
from
flag := True
until
not flag
loop
next
skip_white_spaces
l_value := parse
if is_parsed and then l_value /= Void then
Result.add (l_value)
next
skip_white_spaces
c := actual
if c = j_ARRAY_CLOSE then
flag := False
elseif c /= ',' then
flag := False
is_parsed := False
report_error ("Array is not well formed JSON, found [" + c.out + " ]")
end
else
flag := False
report_error ("Array is not well formed JSON, found [" + actual.out + " ]")
end
end
end
end
parse_number: detachable JSON_NUMBER
-- Parsed number
local
sb: STRING
flag: BOOLEAN
is_integer: BOOLEAN
c: like actual
do
create sb.make_empty
sb.append_character (actual)
from
flag := True
until
not flag
loop
next
c := actual
if not has_next or is_close_token (c)
or c = ',' or c = '%N' or c = '%R'
then
flag := False
previous
else
sb.append_character (c)
end
end
if is_valid_number (sb) then
if sb.is_integer then
create Result.make_integer (sb.to_integer)
is_integer := True
elseif sb.is_double and not is_integer then
create Result.make_real (sb.to_double)
end
else
is_parsed := False
report_error ("Expected a number, found: [ " + sb + " ]")
end
end
is_null: BOOLEAN
-- Word at index represents null?
local
l_null: STRING
l_string: STRING
do
l_null := null_id
l_string := json_substring (index,index + l_null.count - 1)
if l_string.is_equal (l_null) then
Result := True
end
end
is_false: BOOLEAN
-- Word at index represents false?
local
l_false: STRING
l_string: STRING
do
l_false := false_id
l_string := json_substring (index, index + l_false.count - 1)
if l_string.is_equal (l_false) then
Result := True
end
end
is_true: BOOLEAN
-- Word at index represents true?
local
l_true: STRING
l_string: STRING
do
l_true := true_id
l_string := json_substring (index,index + l_true.count - 1)
if l_string.is_equal (l_true) then
Result := True
end
end
read_unicode: STRING
-- Read unicode and return value
local
i: INTEGER
do
create Result.make_empty
from
i := 1
until
i > 4 or not has_next
loop
next
Result.append_character (actual)
i := i + 1
end
end
feature {NONE} -- Implementation
is_valid_number (a_number: STRING): BOOLEAN
-- is 'a_number' a valid number based on this regular expression
-- "-?(?: 0|[1-9]\d+)(?: \.\d+)?(?: [eE][+-]?\d+)?\b"?
local
s: detachable STRING
c: CHARACTER
i,n: INTEGER
do
create s.make_empty
n := a_number.count
if n = 0 then
Result := False
else
Result := True
i := 1
--| "-?"
c := a_number[i]
if c = '-' then
s.extend (c); i := i + 1; c := a_number[i]
end
--| "0|[1-9]\d*
if c.is_digit then
if c = '0' then
--| "0"
s.extend (c); i := i + 1; c := a_number[i]
else
--| "[1-9]"
s.extend (c); i := i + 1; c := a_number[i]
--| "\d*"
from until i > n or not c.is_digit loop
s.extend (c); i := i + 1; c := a_number[i]
end
end
end
end
if Result then
--| "(\.\d+)?"
if c = '.' then
--| "\.\d+" = "\.\d\d*"
s.extend (c); i := i + 1; c := a_number[i]
if c.is_digit then
from until i > n or not c.is_digit loop
s.extend (c); i := i + 1; c := a_number[i]
end
else
Result := False --| expecting digit
end
end
end
if Result then --| "(?:[eE][+-]?\d+)?\b"
if c = 'e' or c = 'E' then
--| "[eE][+-]?\d+"
s.extend (c); i := i + 1; c := a_number[i]
if c = '+' or c = '-' then
s.extend (c); i := i + 1; c := a_number[i]
end
if c.is_digit then
from until i > n or not c.is_digit loop
s.extend (c); i := i + 1; c := a_number[i]
end
else
Result := False --| expecting digit
end
end
end
if Result then --| "\b"
from until i > n or not c.is_space loop
s.extend (c); i := i + 1; c := a_number[i]
end
Result := i > n and then s.same_string (a_number)
end
end
is_valid_unicode (a_unicode: STRING): BOOLEAN
-- is 'a_unicode' a valid unicode based on this regular expression
-- "\\u[0-9a-fA-F]{4}"
local
i: INTEGER
do
if
a_unicode.count = 6 and then
a_unicode[1] = '\' and then
a_unicode[2] = 'u'
then
from
Result := True
i := 3
until
i > 6 or Result = False
loop
inspect a_unicode[i]
when '0'..'9', 'a'..'f', 'A'..'F' then
else
Result := False
end
i := i + 1
end
end
end
extra_elements: BOOLEAN
-- has more elements?
local
c: like actual
do
if has_next then
next
end
from
c := actual
until
c /= ' ' or c /= '%R' or c /= '%U' or c /= '%T' or c /= '%N' or not has_next
loop
next
end
Result := has_next
end
is_valid_start_symbol : BOOLEAN
-- expecting `{' or `[' as start symbol
do
if attached representation as s and then s.count > 0 then
Result := s[1] = '{' or s[1] = '['
end
end
feature {NONE} -- Constants
false_id: STRING = "false"
true_id: STRING = "true"
null_id: STRING = "null"
end
-118
View File
@@ -1,118 +0,0 @@
note
description: "Objects that ..."
author: "jvelilla"
date: "2008/08/24"
revision: "0.1"
class
JSON_READER
create
make
feature {NONE} -- Initialization
make (a_json: STRING)
-- Initialize Reader
do
set_representation (a_json)
end
feature -- Commands
set_representation (a_json: STRING)
-- Set `representation'.
do
a_json.left_adjust
a_json.right_adjust
representation := a_json
index := 1
end
read: CHARACTER
-- Read character
do
if not representation.is_empty then
Result := representation.item (index)
end
end
next
-- Move to next index
require
has_more_elements: has_next
do
index := index + 1
ensure
incremented: old index + 1 = index
end
previous
-- Move to previous index
require
not_is_first: has_previous
do
index := index - 1
ensure
incremented: old index - 1 = index
end
skip_white_spaces
-- Remove white spaces
local
c: like actual
do
from
c := actual
until
(c /= ' ' and c /= '%N' and c /= '%R' and c /= '%U' and c /= '%T' ) or not has_next
loop
next
c := actual
end
end
json_substring (start_index, end_index: INTEGER_32): STRING
-- JSON representation between `start_index' and `end_index'
do
Result := representation.substring (start_index, end_index)
end
feature -- Status report
has_next: BOOLEAN
-- Has a next character?
do
Result := index <= representation.count
end
has_previous: BOOLEAN
-- Has a previous character?
do
Result := index >= 1
end
feature -- Access
representation: STRING
-- Serialized representation of the original JSON string
feature {NONE} -- Implementation
actual: CHARACTER
-- Current character or '%U' if none
do
if index > representation.count then
Result := '%U'
else
Result := representation.item (index)
end
end
index: INTEGER
-- Actual index
invariant
representation_not_void: representation /= Void
end
-77
View File
@@ -1,77 +0,0 @@
note
description: ""
author: "jvelilla"
date: "2008/08/24"
revision: "0.1"
class
JSON_TOKENS
feature -- Access
j_OBJECT_OPEN: CHARACTER = '{'
j_ARRAY_OPEN: CHARACTER = '['
j_OBJECT_CLOSE: CHARACTER = '}'
j_ARRAY_CLOSE: CHARACTER = ']'
j_STRING: CHARACTER = '"'
j_PLUS: CHARACTER = '+'
j_MINUS: CHARACTER = '-'
j_DOT: CHARACTER = '.'
feature -- Status report
is_open_token (c: CHARACTER): BOOLEAN
-- Characters which open a type
do
inspect c
when j_OBJECT_OPEN, j_ARRAY_OPEN, j_STRING, j_PLUS, j_MINUS, j_DOT then
Result := True
else
end
end
is_close_token (c: CHARACTER): BOOLEAN
-- Characters which close a type
do
inspect c
when j_OBJECT_CLOSE, j_ARRAY_CLOSE, j_STRING then
Result := True
else
end
end
is_special_character (c: CHARACTER): BOOLEAN
-- Control Characters
-- %F Form feed
-- %H backslasH
-- %N Newline
-- %R carriage Return
-- %T horizontal Tab
-- %B Backspace
-- / Solidus
-- " Quotation
do
inspect c
when '%F', '%H', '%N', '%R', '%T', '%B', '/', '"' then
Result := True
else
end
end
is_special_control (c: CHARACTER): BOOLEAN
--Control Characters
-- \b\f\n\r\t
do
inspect c
when 'b', 'f', 'n', 'r', 't' then
Result := True
else
end
end
end
-38
View File
@@ -1,38 +0,0 @@
note
description: "[
Shared factory class for creating JSON objects. Maps JSON
objects to ELKS HASH_TABLEs and JSON arrays to ELKS
LINKED_LISTs. Use non-conforming inheritance from this
class to ensure that your classes share the same
JSON_FACTORY instance.
]"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision: 89185 $"
file: "$HeadURL: $"
class SHARED_EJSON
feature
json: EJSON
-- A shared EJSON instance with default converters for
--LINKED_LIST [ANY] and HASH_TABLE [ANY, HASHABLE]
local
jalc: JSON_ARRAYED_LIST_CONVERTER
jllc: JSON_LINKED_LIST_CONVERTER
jhtc: JSON_HASH_TABLE_CONVERTER
once
create Result
create jalc.make
Result.add_converter (jalc)
create jllc.make
Result.add_converter (jllc)
create jhtc.make
Result.add_converter (jhtc)
end
end -- class SHARED_EJSON
+38
View File
@@ -0,0 +1,38 @@
# Available libraries.
http_client-safe : c:\_dev\Dev-Process\web-framework\library\client\http_client\http_client-safe.ecf
http_client : c:\_dev\Dev-Process\web-framework\library\client\http_client\http_client.ecf
error-safe : c:\_dev\Dev-Process\web-framework\library\error\error-safe.ecf
error : c:\_dev\Dev-Process\web-framework\library\error\error.ecf
http-safe : c:\_dev\Dev-Process\web-framework\library\protocol\http\http-safe.ecf
http : c:\_dev\Dev-Process\web-framework\library\protocol\http\http.ecf
uri_template-safe : c:\_dev\Dev-Process\web-framework\library\protocol\uri_template\uri_template-safe.ecf
uri_template : c:\_dev\Dev-Process\web-framework\library\protocol\uri_template\uri_template.ecf
http_authorization-safe : c:\_dev\Dev-Process\web-framework\library\server\authentication\http_authorization\http_authorization-safe.ecf
http_authorization : c:\_dev\Dev-Process\web-framework\library\server\authentication\http_authorization\http_authorization.ecf
ewsgi-safe : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\ewsgi-safe.ecf
ewsgi : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\ewsgi.ecf
ewsgi_spec-safe : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\ewsgi_spec-safe.ecf
ewsgi_spec : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\ewsgi_spec.ecf
cgi-safe : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\connectors\cgi\cgi-safe.ecf
cgi : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\connectors\cgi\cgi.ecf
libfcgi-safe : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\connectors\libfcgi\libfcgi-safe.ecf
libfcgi : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\connectors\libfcgi\libfcgi.ecf
nino-safe : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\connectors\nino\nino-safe.ecf
nino : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\connectors\nino\nino.ecf
ewsgi_cgi-safe : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\default\ewsgi_cgi-safe.ecf
ewsgi_cgi : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\default\ewsgi_cgi.ecf
ewsgi_nino-safe : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\default\ewsgi_nino-safe.ecf
ewsgi_nino : c:\_dev\Dev-Process\web-framework\library\server\ewsgi\default\ewsgi_nino.ecf
fcgi-safe : c:\_dev\Dev-Process\web-framework\library\server\libfcgi\fcgi-safe.ecf
fcgi : c:\_dev\Dev-Process\web-framework\library\server\libfcgi\fcgi.ecf
libfcgi-safe : c:\_dev\Dev-Process\web-framework\library\server\libfcgi\libfcgi-safe.ecf
libfcgi : c:\_dev\Dev-Process\web-framework\library\server\libfcgi\libfcgi.ecf
rest-safe : c:\_dev\Dev-Process\web-framework\library\server\request\rest\rest-safe.ecf
rest : c:\_dev\Dev-Process\web-framework\library\server\request\rest\rest.ecf
router-safe : c:\_dev\Dev-Process\web-framework\library\server\request\router\router-safe.ecf
router : c:\_dev\Dev-Process\web-framework\library\server\request\router\router.ecf
encoder-safe : c:\_dev\Dev-Process\web-framework\library\text\encoder\encoder-safe.ecf
encoder : c:\_dev\Dev-Process\web-framework\library\text\encoder\encoder.ecf
+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http" uuid="F8BE3C55-88E8-4103-A936-B1E5CB1D330E" library_target="http">
<target name="http">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http" uuid="F8BE3C55-88E8-4103-A936-B1E5CB1D330E" library_target="http">
<target name="http">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" syntax="provisional">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

Some files were not shown because too many files have changed in this diff Show More