singleton-ruby 0.0.2 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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
+