singleton-ruby 0.0.2 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +17 -0
  3. data/README.md +3 -0
  4. data/Rakefile +140 -0
  5. data/lib/generators/sgtnclient/USAGE +3 -0
  6. data/lib/generators/sgtnclient/install_generator.rb +15 -0
  7. data/lib/generators/sgtnclient/templates/sgtnclient.rb +2 -0
  8. data/lib/generators/sgtnclient/templates/sgtnclient.yml +33 -0
  9. data/lib/sgtn-client/api/source.rb +64 -0
  10. data/lib/sgtn-client/api/translation.rb +83 -0
  11. data/lib/sgtn-client/cldr/core_ext.rb +3 -0
  12. data/lib/sgtn-client/cldr/localized_date.rb +27 -0
  13. data/lib/sgtn-client/cldr/localized_datetime.rb +33 -0
  14. data/lib/sgtn-client/cldr/localized_time.rb +27 -0
  15. data/lib/sgtn-client/core/cache.rb +83 -0
  16. data/lib/sgtn-client/core/config.rb +173 -0
  17. data/lib/sgtn-client/core/exceptions.rb +112 -0
  18. data/lib/sgtn-client/core/logging.rb +50 -0
  19. data/lib/sgtn-client/core/request.rb +17 -0
  20. data/lib/{sgtn-client.rb → sgtn-client/sgtn-client.rb} +29 -1
  21. data/lib/sgtn-client/util/cache-util.rb +35 -0
  22. data/lib/sgtn-client/util/validate-util.rb +44 -0
  23. data/lib/singleton-ruby.rb +2 -0
  24. data/lib/version.rb +3 -0
  25. data/spec/config/locales/default/JAVA/en.yml +2 -0
  26. data/spec/config/locales/l10n/bundles/logInsight/4.8.1/JAVA/messages_en.json +1 -0
  27. data/spec/config/locales/l10n/bundles/logInsight/4.8.1/JAVA/messages_zh_CN.json +11 -0
  28. data/spec/config/sgtnclient-invalidate.yml +48 -0
  29. data/spec/config/sgtnclient.yml +11 -2
  30. data/spec/spec_helper.rb +2 -1
  31. data/spec/unit/cache_spec.rb +35 -0
  32. data/spec/unit/config_spec.rb +1 -1
  33. data/spec/unit/datetime_spec.rb +43 -0
  34. data/spec/unit/inconfig_spec.rb +17 -0
  35. data/spec/unit/logging_spec.rb +2 -3
  36. data/spec/unit/offclient_spec.rb +15 -0
  37. data/spec/unit/restclient_spec.rb +10 -1
  38. metadata +50 -3
@@ -0,0 +1,27 @@
1
+ require 'date'
2
+ require 'time'
3
+
4
+ Time.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
5
+ def to_full_s(locale = TwitterCldr.locale)
6
+ self.localize(locale).to_full_s
7
+ end
8
+ LOCALIZE
9
+
10
+ Time.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
11
+ def to_long_s(locale = TwitterCldr.locale)
12
+ self.localize(locale).to_long_s
13
+ end
14
+ LOCALIZE
15
+
16
+ Time.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
17
+ def to_medium_s(locale = TwitterCldr.locale)
18
+ self.localize(locale).to_medium_s
19
+ end
20
+ LOCALIZE
21
+
22
+
23
+ Time.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
24
+ def to_short_s(locale = TwitterCldr.locale)
25
+ self.localize(locale).to_short_s
26
+ end
27
+ LOCALIZE
@@ -0,0 +1,83 @@
1
+ require 'date'
2
+
3
+ module SgtnClient::Core
4
+ class Cache
5
+ Entry = Struct.new(:expiry, :value)
6
+
7
+ def self.initialize(disabled=false, opts={})
8
+ $opts = opts
9
+ SgtnClient.logger.debug "Initialize cache......"
10
+ if disabled == false
11
+ $data = Hash.new
12
+ SgtnClient.logger.debug "Cache is enabled!"
13
+ else
14
+ SgtnClient.logger.debug "Cache is disabled!"
15
+ end
16
+ end
17
+
18
+ def self.keys
19
+ if $data == nil
20
+ return nil
21
+ end
22
+ SgtnClient.logger.debug "Get cache keys"
23
+ $data.keys
24
+ end
25
+
26
+ def self.get(key)
27
+ if $data == nil
28
+ return nil
29
+ end
30
+ SgtnClient.logger.debug "Get cache for key: " + key
31
+ invalidate
32
+ $data[key][:value] if has(key)
33
+ end
34
+
35
+ def self.has(key)
36
+ if $data == nil
37
+ return nil
38
+ end
39
+ SgtnClient.logger.debug "Has cache for key: " + key
40
+ $data.has_key? key
41
+ end
42
+
43
+ def self.put(key, value, ttl=nil)
44
+ if $data == nil
45
+ return nil
46
+ end
47
+ ttl ||= @opts[:ttl]
48
+ # hours from new
49
+ SgtnClient.logger.debug "Put cache for key '" + key + "' with expired time at'" + (Time.now + ttl*60).to_s
50
+ $data[key] = Entry.new(Time.now + ttl*60, value)
51
+ end
52
+
53
+ def self.delete(key)
54
+ if $data == nil
55
+ return nil
56
+ end
57
+ SgtnClient.logger.debug "Delete cache for key: " + key
58
+ $data.delete key
59
+ end
60
+
61
+ def self.clear
62
+ if $data == nil
63
+ return nil
64
+ end
65
+ SgtnClient.logger.debug "Clear cache!"
66
+ $data = Hash.new
67
+ end
68
+
69
+ def self.invalidate
70
+ if $data == nil
71
+ return nil
72
+ end
73
+ SgtnClient.logger.debug "Invalidating expired cache......"
74
+ now = Time.now
75
+ $data.each {
76
+ |k, v|
77
+ SgtnClient.logger.debug "Checking cache: key=#{k}, expiredtime=#{v[:expiry]}, now=#{now}, expired=#{(v[:expiry] < now)}"
78
+ }
79
+ $data.delete_if {|k, v| v[:expiry] < now}
80
+ end
81
+ end
82
+
83
+ end
@@ -0,0 +1,173 @@
1
+ require 'erb'
2
+ require 'yaml'
3
+
4
+ module SgtnClient
5
+ #include Exceptions
6
+ module Configuration
7
+
8
+ def config
9
+ @config ||= Config.config
10
+ end
11
+
12
+ def set_config(env, override_configurations = {})
13
+ @config =
14
+ case env
15
+ when Config
16
+ env
17
+ when Hash
18
+ begin
19
+ config.dup.merge!(env)
20
+ rescue Errno::ENOENT => error
21
+ Config.new(env)
22
+ end
23
+ else
24
+ Config.config(env, override_configurations)
25
+ end
26
+ end
27
+
28
+ alias_method :config=, :set_config
29
+
30
+ end
31
+
32
+
33
+ class Config
34
+
35
+ attr_accessor :username, :password, :signature, :app_id, :cert_path,
36
+ :token, :token_secret, :subject,
37
+ :http_timeout, :http_proxy,
38
+ :device_ipaddress, :sandbox_email_address,
39
+ :mode, :endpoint, :merchant_endpoint, :platform_endpoint, :ipn_endpoint,
40
+ :rest_endpoint, :rest_token_endpoint, :client_id, :client_secret,
41
+ :openid_endpoint, :openid_redirect_uri, :openid_client_id, :openid_client_secret,
42
+ :verbose_logging, :product_name, :version, :vip_server, :bundle_mode,
43
+ :translation_bundle, :source_bundle, :cache_expiry_period, :disable_cache
44
+
45
+
46
+ # Create Config object
47
+ # === Options(Hash)
48
+ # * <tt>username</tt> -- Username
49
+ # * <tt>password</tt> -- Password
50
+ # * <tt>signature</tt> (Optional if certificate present) -- Signature
51
+ # * <tt>app_id</tt> -- Application ID
52
+ # * <tt>cert_path</tt> (Optional if signature present) -- Certificate file path
53
+ def initialize(options)
54
+ merge!(options)
55
+ end
56
+
57
+ # Override configurations
58
+ def merge!(options)
59
+ options.each do |key, value|
60
+ send("#{key}=", value)
61
+ end
62
+ self
63
+ end
64
+
65
+ class << self
66
+
67
+ @@config_cache = {}
68
+
69
+ # Load configurations from file
70
+ # === Arguments
71
+ # * <tt>file_name</tt> -- Configuration file path
72
+ # * <tt>default_environment</tt> (Optional) -- default environment configuration to load
73
+ # === Example
74
+ # Config.load('config/paypal.yml', 'development')
75
+ def load(file_name, default_env = default_environment)
76
+ @@config_cache = {}
77
+ @@configurations = read_configurations(file_name)
78
+ @@default_environment = default_env
79
+ config
80
+ end
81
+
82
+
83
+ # Get default environment name
84
+ def default_environment
85
+ @@default_environment ||= ENV['SGTN_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || "development"
86
+ end
87
+
88
+
89
+ # Set default environment
90
+ def default_environment=(env)
91
+ @@default_environment = env.to_s
92
+ end
93
+
94
+ def configure(options = {}, &block)
95
+ begin
96
+ self.config.merge!(options)
97
+ rescue Errno::ENOENT
98
+ self.configurations = { default_environment => options }
99
+ end
100
+ block.call(self.config) if block
101
+ self.config
102
+ end
103
+ alias_method :set_config, :configure
104
+
105
+ # Create or Load Config object based on given environment and configurations.
106
+ # === Attributes
107
+ # * <tt>env</tt> (Optional) -- Environment name
108
+ # * <tt>override_configuration</tt> (Optional) -- Override the configuration given in file.
109
+ # === Example
110
+ # Config.config
111
+ # Config.config(:development)
112
+ # Config.config(:development, { :app_id => "XYZ" })
113
+ def config(env = default_environment, override_configuration = {})
114
+ if env.is_a? Hash
115
+ override_configuration = env
116
+ env = default_environment
117
+ end
118
+ if override_configuration.nil? or override_configuration.empty?
119
+ default_config(env)
120
+ else
121
+ default_config(env).dup.merge!(override_configuration)
122
+ end
123
+ end
124
+
125
+ def default_config(env = nil)
126
+ env = (env || default_environment).to_s
127
+ if configurations[env]
128
+ @@config_cache[env] ||= new(configurations[env])
129
+ else
130
+ raise SgtnClient::Exceptions::MissingConfig.new("Configuration[#{env}] NotFound")
131
+ end
132
+ end
133
+
134
+ # Get raw configurations in Hash format.
135
+ def configurations
136
+ @@configurations ||= read_configurations
137
+ end
138
+
139
+ # Set configuration
140
+ def configurations=(configs)
141
+ @@config_cache = {}
142
+ @@configurations = configs && Hash[configs.map{|k,v| [k.to_s, v] }]
143
+ end
144
+
145
+ # Set logger
146
+ def logger=(logger)
147
+ Logging.logger = logger
148
+ end
149
+
150
+ # Get logger
151
+ def logger
152
+ if @@configurations[:mode] == 'live' and Logging.logger.level == Logger::DEBUG
153
+ Logging.logger.warn "DEBUG log level not allowed in live mode for security of confidential information. Changing log level to INFO..."
154
+ Logging.logger.level = Logger::INFO
155
+ end
156
+ Logging.logger
157
+ end
158
+
159
+ private
160
+ # Read configurations from the given file name
161
+ # === Arguments
162
+ # * <tt>file_name</tt> (Optional) -- Configuration file path
163
+ def read_configurations(file_name = "config/sgtnclient.yml")
164
+ erb = ERB.new(File.read(file_name))
165
+ erb.filename = file_name
166
+ YAML.load(erb.result)
167
+ end
168
+
169
+
170
+ end
171
+ end
172
+
173
+ end
@@ -0,0 +1,112 @@
1
+ require 'json'
2
+ require 'pp'
3
+
4
+ module SgtnClient
5
+ module Exceptions
6
+ class ConnectionError < StandardError # :nodoc:
7
+ attr_reader :response
8
+
9
+ def initialize(response, message = nil)
10
+ @response = response
11
+ @message = message
12
+ end
13
+
14
+ def to_s
15
+ begin
16
+ response_body = JSON.parse(response.body)
17
+ debug_id = response["paypal-debug-id"]
18
+ debug_id = response["correlation-id"] if debug_id.to_s == ''
19
+ debug_id = response_body["debug_id"] if debug_id.to_s == ''
20
+ rescue
21
+ end
22
+ message = "Failed."
23
+ message << " Response code = #{response.code}." if response.respond_to?(:code)
24
+ message << " Response message = #{response.message}." if response.respond_to?(:message)
25
+ message << " Response debug ID = #{debug_id}." if debug_id
26
+ message
27
+ end
28
+ end
29
+
30
+ # Raised when a Timeout::Error occurs.
31
+ class TimeoutError < ConnectionError
32
+ def initialize(message)
33
+ @message = message
34
+ end
35
+ def to_s; @message ;end
36
+ end
37
+
38
+ # Raised when a OpenSSL::SSL::SSLError occurs.
39
+ class SSLError < ConnectionError
40
+ def initialize(message)
41
+ @message = message
42
+ end
43
+ def to_s; @message ;end
44
+ end
45
+
46
+ # 3xx Redirection
47
+ class Redirection < ConnectionError # :nodoc:
48
+ def to_s
49
+ response['Location'] ? "#{super} => #{response['Location']}" : super
50
+ end
51
+ end
52
+
53
+ class MissingParam < ArgumentError # :nodoc:
54
+ end
55
+
56
+ class MissingConfig < StandardError # :nodoc:
57
+ end
58
+
59
+ # 4xx Client Error
60
+ class ClientError < ConnectionError # :nodoc:
61
+ end
62
+
63
+ # 400 Bad Request
64
+ class BadRequest < ClientError # :nodoc:
65
+ end
66
+
67
+ # 401 Unauthorized
68
+ class UnauthorizedAccess < ClientError # :nodoc:
69
+ end
70
+
71
+ # 403 Forbidden
72
+ class ForbiddenAccess < ClientError # :nodoc:
73
+ end
74
+
75
+ # 404 Not Found
76
+ class ResourceNotFound < ClientError # :nodoc:
77
+ end
78
+
79
+ # 409 Conflict
80
+ class ResourceConflict < ClientError # :nodoc:
81
+ end
82
+
83
+ # 410 Gone
84
+ class ResourceGone < ClientError # :nodoc:
85
+ end
86
+
87
+ # 422 Unprocessable Entity
88
+ class ResourceInvalid < ClientError # :nodoc:
89
+ end
90
+
91
+ # 5xx Server Error
92
+ class ServerError < ConnectionError # :nodoc:
93
+ end
94
+
95
+ # 405 Method Not Allowed
96
+ class MethodNotAllowed < ClientError # :nodoc:
97
+ def allowed_methods
98
+ @response['Allow'].split(',').map { |verb| verb.strip.downcase.to_sym }
99
+ end
100
+ end
101
+
102
+ # API error: returned as 200 + "error" key in response.
103
+ class UnsuccessfulApiCall < RuntimeError
104
+ attr_reader :api_error
105
+
106
+ def initialize(api_error)
107
+ super(api_error['message'])
108
+ @api_error = api_error
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,50 @@
1
+ require 'logger'
2
+
3
+ module SgtnClient
4
+
5
+ # Include Logging module to provide logger functionality.
6
+ # == Configure logger
7
+ # Logging.logger = Logger.new(STDERR)
8
+ #
9
+ # == Example
10
+ # include Logger
11
+ # logger.info "Debug message"
12
+ module Logging
13
+
14
+ # Get logger object
15
+ def logger
16
+ @logger ||= Logging.logger
17
+ end
18
+
19
+ def log_event(message, &block)
20
+ start_time = Time.now
21
+ block.call
22
+ ensure
23
+ logger.info sprintf("[%.3fs] %s", Time.now - start_time, message)
24
+ end
25
+
26
+ class << self
27
+
28
+ # Get or Create configured logger based on the default environment configuration
29
+ def logger
30
+ @logger ||= Logger.new(STDERR)
31
+ end
32
+
33
+ # Set logger directly and clear the loggers cache.
34
+ # === Attributes
35
+ # * <tt>logger</tt> -- Logger object
36
+ # === Example
37
+ # Logging.logger = Logger.new(STDERR)
38
+ def logger=(logger)
39
+ @logger = logger
40
+ if Config.config.mode.eql? 'live' and @logger.level == Logger::DEBUG
41
+ @logger.warn "DEBUG log level not allowed in live mode for security of confidential information. Changing log level to INFO..."
42
+ @logger.level = Logger::INFO
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+
49
+ end
50
+