Refactor directory structrue

This commit is contained in:
jvelilla
2014-11-13 11:57:36 -03:00
parent 8ab4343d5b
commit d963fd218b
154 changed files with 12 additions and 11 deletions

13
library/layout/Readme.md Normal file
View File

@@ -0,0 +1,13 @@
Layout Library
==============
Define a generic layout to be re-used by different applications.
site/
doc/
logs/
www/
assets
template
theme
config/

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="layout" uuid="7AE9E48B-5A15-43F8-B99A-04F4185DED6B" library_target="layout">
<target name="layout">
<root all_classes="true"/>
<option warning="true">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="console_application" value="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<library name="logging" location="$ISE_LIBRARY\library\runtime\logging\logging-safe.ecf"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
<cluster name="src" location=".\src\" recursive="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
</cluster>
</target>
</system>

View File

@@ -0,0 +1,3 @@
${NOTE_KEYWORD}
copyright: "2011-${YEAR}, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"

View File

@@ -0,0 +1,168 @@
note
description: "[
Application layout
Related to file system locations such as
- configuration locations
- application
- log
- documentation
- www
- assets
- templates (html, Collection+JSON, ...)
- ...
]"
date: "$Date$"
revision: "$Revision$"
class
APPLICATION_LAYOUT
create
make_default,
make_with_path
feature {NONE} -- Initialization
make_default
-- Create a default layout based on current working directory.
local
p: PATH
do
create p.make_current
p := p.extended ("site")
make_with_path (p)
end
make_with_path (p: PATH)
-- Create a layour based on a path `p'.
do
path := p.absolute_path.canonical_path
end
feature -- Access
path: PATH
-- Root location.
feature -- Access: internal
config_path: PATH
-- Configuration file path.
local
p: detachable PATH
do
p := internal_config_path
if p = Void then
p := path.extended ("config")
internal_config_path := p
end
Result := p
end
application_config_path: PATH
-- Database Configuration file path.
local
p: detachable PATH
do
p := internal_application_config_path
if p = Void then
p := config_path.extended ("application_configuration.json")
internal_application_config_path := p
end
Result := p
end
logs_path: PATH
-- Directory for logs.
local
p: detachable PATH
do
p := internal_logs_path
if p = Void then
p := path.extended ("logs")
internal_logs_path := p
end
Result := p
end
documentation_path: PATH
-- Directory for API documentation.
local
p: detachable PATH
do
p := internal_documentation_path
if p = Void then
p := path.extended ("doc")
internal_documentation_path := p
end
Result := p
end
www_path: PATH
-- Directory for www.
local
p: detachable PATH
do
p := internal_www_path
if p = Void then
p := path.extended ("www")
internal_www_path := p
end
Result := p
end
assets_path: PATH
-- Directory for public assets.
-- css, images, js.
local
p: detachable PATH
do
p := internal_assets_path
if p = Void then
p := www_path.extended ("assets")
internal_assets_path := p
end
Result := p
end
template_path: PATH
-- Directory for templates (HTML, etc).
local
p: detachable PATH
do
p := internal_template_path
if p = Void then
p := www_path.extended ("template")
internal_template_path := p
end
Result := p
end
feature {NONE} -- Implementation
internal_config_path: detachable like config_path
-- Configuration file path.
internal_application_config_path: detachable like application_config_path
-- Database Configuration file path.
internal_logs_path: detachable like logs_path
-- Directory for logs.
internal_documentation_path: detachable like documentation_path
-- Directory for API documentation.
internal_www_path: detachable like www_path
-- Directory for www.
internal_assets_path: detachable like assets_path
-- Directory for public assets.
-- css, images, js.
internal_template_path: detachable like template_path
-- Directory for templates (HTML, etc).
;note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,42 @@
note
description: "Object that represent Database configuration settings"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
DATABASE_CONFIGURATION
create
make
feature {NONE} -- Initialization
make (a_driver: READABLE_STRING_32; a_connection: READABLE_STRING_32)
-- Create a database configuration setting: `driver' with `a_driver',
-- `database_string' with `a_connection'.
do
driver := a_driver
database_string := a_connection
ensure
driver_set: driver = a_driver
server_set: database_string = a_connection
end
feature -- Access
driver: READABLE_STRING_32
--Database driver.
database_string: READABLE_STRING_32
-- Database connection.
connection_string: READABLE_STRING_32
-- Connection string
do
Result := "Driver={"+driver+"};" + database_string;
end
note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,103 @@
note
description: "Provide access to json configuration"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
JSON_CONFIGURATION
feature -- Application Configuration
new_smtp_configuration (a_path: PATH): READABLE_STRING_32
-- Build a new database configuration.
local
l_parser: JSON_PARSER
do
Result := ""
if attached json_file_from (a_path) as json_file then
l_parser := new_json_parser (json_file)
if attached {JSON_OBJECT} l_parser.parse as jv and then l_parser.is_parsed and then
attached {JSON_OBJECT} jv.item ("smtp") as l_smtp and then
attached {JSON_STRING} l_smtp.item ("server") as l_server then
Result := l_server.item
end
end
end
new_database_configuration (a_path: PATH): detachable DATABASE_CONFIGURATION
-- Build a new database configuration.
local
l_parser: JSON_PARSER
do
if attached json_file_from (a_path) as json_file then
l_parser := new_json_parser (json_file)
if attached {JSON_OBJECT} l_parser.parse as jv and then l_parser.is_parsed and then
attached {JSON_OBJECT} jv.item ("database") as l_database and then
attached {JSON_OBJECT} l_database.item ("datasource") as l_datasource and then
attached {JSON_STRING} l_datasource.item ("driver") as l_driver and then
attached {JSON_STRING} l_datasource.item ("environment") as l_envrionment and then
attached {JSON_OBJECT} l_database.item ("environments") as l_environments and then
attached {JSON_OBJECT} l_environments.item (l_envrionment.item) as l_environment_selected and then
attached {JSON_STRING} l_environment_selected.item ("connection_string") as l_connection_string then
create Result.make (l_driver.item, l_connection_string.unescaped_string_8)
end
end
end
new_logger_level_configuration (a_path: PATH): READABLE_STRING_32
-- Retrieve a new logger level configuration.
-- By default, level is set to `DEBUG'.
local
l_parser: JSON_PARSER
do
Result := "DEBUG"
if attached json_file_from (a_path) as json_file then
l_parser := new_json_parser (json_file)
if attached {JSON_OBJECT} l_parser.parse as jv and then l_parser.is_parsed and then
attached {JSON_OBJECT} jv.item ("logger") as l_logger and then
attached {JSON_STRING} l_logger.item ("level") as l_level then
Result := l_level.item
end
end
end
new_database_configuration_test (a_path: PATH): detachable DATABASE_CONFIGURATION
-- Build a new database configuration for testing purposes.
local
l_parser: JSON_PARSER
do
if attached json_file_from (a_path) as json_file then
l_parser := new_json_parser (json_file)
if attached {JSON_OBJECT} l_parser.parse as jv and then l_parser.is_parsed and then
attached {JSON_OBJECT} jv.item ("database") as l_database and then
attached {JSON_OBJECT} l_database.item ("datasource") as l_datasource and then
attached {JSON_STRING} l_datasource.item ("driver") as l_driver and then
attached {JSON_STRING} l_datasource.item ("environment") as l_envrionment and then
attached {JSON_STRING} l_datasource.item ("trusted") as l_trusted and then
attached {JSON_OBJECT} l_database.item ("environments") as l_environments and then
attached {JSON_OBJECT} l_environments.item ("test") as l_environment_selected and then
attached {JSON_STRING} l_environment_selected.item ("connection_string") as l_connection_string and then
attached {JSON_STRING} l_environment_selected.item ("name") as l_name then
create Result.make (l_driver.item, l_connection_string.unescaped_string_8)
end
end
end
feature {NONE} -- JSON
json_file_from (a_fn: PATH): detachable STRING
do
Result := (create {JSON_FILE_READER}).read_json_from (a_fn.name.out)
end
new_json_parser (a_string: STRING): JSON_PARSER
do
create Result.make_parser (a_string)
end
note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,83 @@
note
description: "Object that represents Logger configuration settings"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
LOGGER_CONFIGURATION
inherit
LOG_PRIORITY_CONSTANTS
rename
default_create as log_default_create
end
ANY
redefine
default_create
select
default_create
end
create
default_create
feature -- Initialization
default_create
-- Initialize a Logger Instance configuration with default values
-- backups = `4' and level = `DEBUG'.
do
backup_count := 4
level := Log_debug
ensure then
backup_count_set: backup_count = 4
level_set: level = Log_debug
end
feature -- Access
backup_count: NATURAL
-- Max number of backup files.
-- When 0, no backup files are created, and the log file is simply truncated when it becomes larger than `max_file_size'.
-- When non-zero, the value specifies the maximum number of backup files.
level: INTEGER
-- Logger level.
feature -- Element Change
set_backup_count (a_backup: NATURAL)
-- Set backup_count to `a_backup'.
do
backup_count := a_backup
ensure
backup_count_set: backup_count = a_backup
end
set_level (a_level: READABLE_STRING_GENERAL)
-- Set a level based on `a_level'.
do
if a_level.is_case_insensitive_equal (emerg_str) then
level := log_emergency
elseif a_level.is_case_insensitive_equal (alert_str) then
level := log_alert
elseif a_level.is_case_insensitive_equal (crit_str) then
level := log_critical
elseif a_level.is_case_insensitive_equal (error_str) then
level := log_error
elseif a_level.is_case_insensitive_equal (warn_str) then
level := log_warning
elseif a_level.is_case_insensitive_equal (notic_str) then
level := log_notice
elseif a_level.is_case_insensitive_equal (info_str) then
level := log_information
elseif a_level.is_case_insensitive_equal (debug_str) then
level := log_debug
else
level := 0
end
end
note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,54 @@
note
description: "Object handling error information"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
BASIC_ERROR_HANDLER
create
make
feature -- Initialization
make (a_error_message: READABLE_STRING_32; a_error_location: READABLE_STRING_32)
-- Create an object error, set `error_message' to `a_error_message'
-- set `error_location' to `a_error_location'.
do
set_error_message (a_error_message)
set_error_location (a_error_location)
ensure
error_message_set: error_message = a_error_message
error_location_set: error_location = a_error_location
end
feature -- Access
error_message: READABLE_STRING_32
-- Message.
error_location: READABLE_STRING_32
-- Code to represent an error.
feature -- Change Element
set_error_message (a_message: like error_message)
-- Set error_message with `a_message'.
do
error_message := a_message
ensure
message_set: error_message = a_message
end
set_error_location (a_location: READABLE_STRING_32)
-- Set error_location with `a_location'.
do
error_location := a_location
ensure
error_location_set: error_location = a_location
end
note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,108 @@
note
description: "Provides error information"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
SHARED_ERROR
inherit
SHARED_LOGGER
feature -- Access
last_error: detachable BASIC_ERROR_HANDLER
-- Object represent last error.
last_error_message: READABLE_STRING_32
-- Last error string representation.
do
if attached last_error as ll_error then
Result := ll_error.error_message
else
Result := ""
end
end
feature -- Status Report
successful: BOOLEAN
-- Was last operation successful?
-- If not, `last_error' must be set.
feature -- Element Settings
set_last_error_from_exception (a_location: STRING)
-- Initialize instance from last exception.
-- Don't show too much internal details (e.g. stack trace).
-- We really don't want this to fail since it is called from rescue clauses.
require
attached_location: a_location /= Void
local
l_exceptions: EXCEPTIONS
l_message: STRING
l_tag: detachable STRING
l_retried: BOOLEAN
do
if not l_retried then
create l_exceptions
create l_message.make (256)
l_tag := l_exceptions.tag_name
if l_tag /= Void then
l_message.append ("The following exception was raised: ")
l_message.append (l_tag)
else
l_message.append ("An unknown exception was raised.")
end
set_last_error (l_message, a_location)
log.write_critical (generator + ".set_last_error_from_exception " + l_message)
else
set_last_error ("Generic error", "")
log.write_critical (generator + ".set_last_error_from_exception Generic Error")
end
rescue
l_retried := True
retry
end
set_last_error (a_message, a_location: STRING)
-- Set `last_error_message' with `a_message',
-- `last_error_location' with `a_location' and
-- `successful' to `False'.
require
attached_message: a_message /= Void
attached_location: a_location /= Void
do
create last_error.make (a_message, a_location)
log.write_critical (generator + ".set_last_error " + a_message)
successful := False
ensure
last_error_set: attached last_error
failed: not successful
end
set_last_error_from_handler (a_error: detachable BASIC_ERROR_HANDLER)
-- Set `last_error' with `a_error'.
do
last_error := a_error
successful := False
ensure
last_error_set: attached last_error
failed: not successful
end
set_successful
-- Reset `last_error_message' and `last_error_location' and
-- set `successful' to `True'.
do
last_error := Void
successful := True
ensure
last_error__reset: last_error = Void
successful: successful
end
note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,140 @@
note
description: "Wrapper class providing synchronize logging access."
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
LOGGING_FACILITY
create
make
feature -- Initialization
make
do
create logging.make
end
feature -- Access
logging: LOG_LOGGING_FACILITY
register_log_writer (a_log_writer: LOG_WRITER)
-- -- Register the non-default log writer `a_log_writer'.
do
logging.register_log_writer (a_log_writer)
end
feature -- Output
write_alert (msg: STRING)
-- Write `msg' to the log writers as an alert.
local
l_retry: BOOLEAN
do
if not l_retry then
logging.write_alert (msg)
end
rescue
l_retry := True
retry
end
write_critical (msg: STRING)
-- Write `msg' to the log writers as an critical
local
l_retry: BOOLEAN
do
if not l_retry then
logging.write_critical (msg)
end
rescue
l_retry := True
retry
end
write_debug (msg: STRING)
-- Write `msg' to the log writers as an debug.
local
l_retry: BOOLEAN
do
if not l_retry then
logging.write_debug (msg)
end
rescue
l_retry := True
retry
end
write_emergency (msg: STRING)
-- Write `msg' to the log writers as an emergency.
local
l_retry: BOOLEAN
do
if not l_retry then
logging.write_emergency (msg)
end
rescue
l_retry := True
retry
end
write_error (msg: STRING)
-- Write `msg' to the log writers as an error.
local
l_retry: BOOLEAN
do
if not l_retry then
logging.write_error (msg)
end
rescue
l_retry := True
retry
end
write_information (msg: STRING)
-- Write `msg' to the log writers as an information.
local
l_retry: BOOLEAN
do
if not l_retry then
logging.write_information (msg)
end
rescue
l_retry := True
retry
end
write_notice (msg: STRING)
-- Write `msg' to the log writers as an notice.
local
l_retry: BOOLEAN
do
if not l_retry then
logging.write_notice (msg)
end
rescue
l_retry := True
retry
end
write_warning (msg: STRING)
-- Write `msg' to the log writers as an warning.
local
l_retry: BOOLEAN
do
if not l_retry then
logging.write_warning (msg)
end
rescue
l_retry := True
retry
end
note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,112 @@
note
description: "Provides logger information"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
SHARED_LOGGER
inherit
LOG_PRIORITY_CONSTANTS
ARGUMENTS
feature -- Logger
log: LOGGING_FACILITY
-- New `log' (once per process)
-- that could be shared between threads
-- without reinitializing it.
local
l_log_writer: LOG_ROLLING_WRITER_FILE
l_environment: EXECUTION_ENVIRONMENT
l_path: PATH
l_logger_config: LOGGER_CONFIGURATION
once ("PROCESS")
--| Initialize the logging facility
create Result.make
create l_environment
if attached separate_character_option_value ('d') as l_dir then
l_path := create {PATH}.make_from_string (l_dir)
create l_log_writer.make_at_location (l_path.extended ("..").appended ("\api.log"))
else
l_path := create {PATH}.make_current
create l_log_writer.make_at_location (l_path.extended("api.log"))
end
l_log_writer.set_max_file_size ({NATURAL_64}1024*1204)
if attached separate_character_option_value ('d') as l_dir then
l_logger_config := new_logger_level_configuration (l_path.extended("config").extended ("application_configuration.json"))
else
l_logger_config := new_logger_level_configuration (l_path.extended ("site").extended("config").extended ("application_configuration.json"))
end
l_log_writer.set_max_backup_count (l_logger_config.backup_count)
set_logger_level (l_log_writer, l_logger_config.level)
log.register_log_writer (l_log_writer)
--| Write an informational message
Result.write_information ("The application is starting up...")
end
feature {NONE} -- JSON
set_logger_level (a_log_writer: LOG_ROLLING_WRITER_FILE; a_priority: INTEGER)
-- Setup the logger level based on `a_priority'
do
if a_priority = log_debug then
a_log_writer.enable_debug_log_level
elseif a_priority = Log_emergency then
a_log_writer.enable_emergency_log_level
elseif a_priority = Log_alert then
a_log_writer.enable_alert_log_level
elseif a_priority = Log_critical then
a_log_writer.enable_critical_log_level
elseif a_priority = Log_error then
a_log_writer.enable_error_log_level
elseif a_priority = Log_warning then
a_log_writer.enable_warning_log_level
elseif a_priority = Log_notice then
a_log_writer.enable_notice_log_level
elseif a_priority = Log_information then
a_log_writer.enable_information_log_level
else
a_log_writer.enable_unkno_log_level
end
end
new_logger_level_configuration (a_path: PATH): LOGGER_CONFIGURATION
-- Retrieve a new logger level configuration.
-- By default, level is set to `DEBUG'.
local
l_parser: JSON_PARSER
do
create Result
if attached json_file_from (a_path) as json_file then
l_parser := new_json_parser (json_file)
if attached {JSON_OBJECT} l_parser.parse as jv and then l_parser.is_parsed and then
attached {JSON_OBJECT} jv.item ("logger") as l_logger and then
attached {JSON_STRING} l_logger.item ("backup_count") as l_count and then
attached {JSON_STRING} l_logger.item ("level") as l_level then
Result.set_level (l_level.item)
if l_count.item.is_natural then
Result.set_backup_count (l_count.item.to_natural)
end
end
end
end
json_file_from (a_fn: PATH): detachable STRING
do
Result := (create {JSON_FILE_READER}).read_json_from (a_fn.name.out)
end
new_json_parser (a_string: STRING): JSON_PARSER
do
create Result.make_parser (a_string)
end
note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end