wurfl_cloud_client_light 1.0.0

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. data/.gitignore +5 -0
  2. data/FOSS_THIRD_PARTY_LICENSES.txt +23 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +40 -0
  5. data/LICENSE.txt +75 -0
  6. data/Rakefile +14 -0
  7. data/lib/wurfl_cloud/cache/cookie.rb +36 -0
  8. data/lib/wurfl_cloud/cache/local_memory.rb +36 -0
  9. data/lib/wurfl_cloud/cache/null.rb +34 -0
  10. data/lib/wurfl_cloud/client.rb +98 -0
  11. data/lib/wurfl_cloud/configuration.rb +81 -0
  12. data/lib/wurfl_cloud/device_capabilities.rb +71 -0
  13. data/lib/wurfl_cloud/environment.rb +41 -0
  14. data/lib/wurfl_cloud/errors.rb +16 -0
  15. data/lib/wurfl_cloud/helper.rb +14 -0
  16. data/lib/wurfl_cloud/rack/cache_manager.rb +47 -0
  17. data/lib/wurfl_cloud/rails.rb +27 -0
  18. data/lib/wurfl_cloud/version.rb +7 -0
  19. data/lib/wurfl_cloud.rb +42 -0
  20. data/spec/files/generic.json +1 -0
  21. data/spec/files/generic_filtered.json +1 -0
  22. data/spec/files/lumia.json +1 -0
  23. data/spec/files/lumia_filtered.json +1 -0
  24. data/spec/files/strange_values.json +1 -0
  25. data/spec/spec_helper.rb +20 -0
  26. data/spec/support/rack_helpers.rb +79 -0
  27. data/spec/support/string_extensions.rb +26 -0
  28. data/spec/wurfl_cloud/client_spec.rb +200 -0
  29. data/spec/wurfl_cloud/configuration_spec.rb +111 -0
  30. data/spec/wurfl_cloud/cookie_cache_spec.rb +44 -0
  31. data/spec/wurfl_cloud/device_capabilities_spec.rb +136 -0
  32. data/spec/wurfl_cloud/environment_spec.rb +86 -0
  33. data/spec/wurfl_cloud/helper_spec.rb +28 -0
  34. data/spec/wurfl_cloud/null_cache_spec.rb +30 -0
  35. data/spec/wurfl_cloud/rack_cache_manager_spec.rb +69 -0
  36. data/spec/wurfl_cloud/server_request_spec.rb +38 -0
  37. data/wurfl_cloud_client_light.gemspec +31 -0
  38. metadata +161 -0
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ coverage
5
+ test_api_key.rb
@@ -0,0 +1,23 @@
1
+ License of ./spec/support/rack_helpers.rb:
2
+
3
+ # Copyright (c) 2009 Daniel Neighman
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in wurfl_cloud_client.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,40 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ wurfl_cloud_client (0.0.2)
5
+ json
6
+ rack
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ addressable (2.2.7)
12
+ crack (0.3.1)
13
+ diff-lcs (1.1.3)
14
+ json (1.6.5)
15
+ multi_json (1.1.0)
16
+ rack (1.4.1)
17
+ rspec (2.8.0)
18
+ rspec-core (~> 2.8.0)
19
+ rspec-expectations (~> 2.8.0)
20
+ rspec-mocks (~> 2.8.0)
21
+ rspec-core (2.8.0)
22
+ rspec-expectations (2.8.0)
23
+ diff-lcs (~> 1.1.2)
24
+ rspec-mocks (2.8.0)
25
+ simplecov (0.6.1)
26
+ multi_json (~> 1.0)
27
+ simplecov-html (~> 0.5.3)
28
+ simplecov-html (0.5.3)
29
+ webmock (1.8.0)
30
+ addressable (>= 2.2.7)
31
+ crack (>= 0.1.7)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ rspec
38
+ simplecov
39
+ webmock
40
+ wurfl_cloud_client!
data/LICENSE.txt ADDED
@@ -0,0 +1,75 @@
1
+
2
+
3
+
4
+
5
+
6
+ License for WURFL Cloud Client
7
+
8
+ This software is © ScientiaMobile and all rights are reserved.
9
+ Software is licensed for your personal use, only in compliance
10
+ with the conditions set out in this license and solely for
11
+ connecting with certain services rendered by ScientiaMobile
12
+ under the name of WURFL Cloud, and with the several ones if any that
13
+ from time to time will be listed at http://www.scientiamobile.com/cloud.
14
+
15
+ License is subject the execution of the WURFL Cloud License Agreement and
16
+ the conditions therein are incorporated herewith. No other use is allowed
17
+ unless explicitly authorized in writing by ScientiaMobile.
18
+
19
+ License is personal, conditioned, non-transferable, limited to the version
20
+ received and does not allow making derivative works even when
21
+ the source code is provided or the language is an interpreted one and regardless
22
+ whether the code is not obfuscated. By way of clarification “derivatives”
23
+ within the working of this license does not extend to linking an unmodified
24
+ instance of software lawfully obtained from ScientiaMobile with any other
25
+ software however licensed, no further permission is required for
26
+ this limited scope (linking exception).
27
+
28
+ The software could contain, rely upon, depend on, interact with, link to
29
+ Free and Open Source Software (“FOSS”), Insofar as said FOSS is concerned
30
+ and where locally specified, the terms of the FOSS license prevail.
31
+ If You or any third party find any inconsistency, lack of clarity, or any
32
+ contradiction to the applicable FOSS license, and/or if You or any third party
33
+ want to exercise your or its rights under it, you or said party is invited to
34
+ write to FOSS-compliance@scientiamobile.com
35
+
36
+ License will be terminated at the sole option of ScientiaMobile if You or
37
+ anybody on your behalf or under your control or solicitation will start or
38
+ threaten to start litigation against ScientiaMobile or any of its affiliates
39
+ and distributors for causes of action involving any ScientiaMobile software
40
+ or services, or if the WURFL Cloud License Agreement is terminated for
41
+ whichever reason or cause.
42
+
43
+ SOFTWARE IS PROVIDED "AS IS" AND “AS AVAILABLE.” ALL EXPRESS OR IMPLIED
44
+ CONDITIONS, REPRESENTATIONS, AND WARRANTIES INCLUDING, WITHOUT LIMITATION,
45
+ ANY IMPLIED WARRANTY OR CONDITION OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
46
+ PURPOSE, NON-INFRINGEMENT, SATISFACTORY QUALITY, NON-INTERFERENCE, ACCURACY
47
+ OF INFORMATIONAL CONTENT, OR ARISING FROM A COURSE OF DEALING, LAW, USAGE,
48
+ OR TRADE PRACTICE, ARE HEREBY EXCLUDED. IN PARTICULAR, WE DO NOT REPRESENT
49
+ OR WARRANT TO YOU THAT YOUR USE OF THE SERVICES WILL MEET YOUR REQUIREMENTS,
50
+ YOUR USE OF THE SERVICES WILL BE UNINTERRUPTED, TIMELY, SECURE OR FREE FROM
51
+ ERROR, OR THAT DEFECTS IN THE OPERATION OR FUNCTIONALITY OF THE SERVICES OR
52
+ ANY SOFTWARE PROVIDED TO YOU AS PART OF THE SERVICES WILL BE CORRECTED.
53
+ LIMITATION OF LIABILITY. YOU EXPRESSLY UNDERSTAND AND AGREE THAT WE SHALL
54
+ NOT BE LIABLE TO YOU FOR: (A) ANY INDIRECT, INCIDENTAL, SPECIAL CONSEQUENTIAL
55
+ OR EXEMPLARY DAMAGES WHICH MAY BE INCURRED BY YOU, HOWEVER CAUSED AND UNDER
56
+ ANY THEORY OF LIABILITY, INCLUDING, BUT NOT BE LIMITED TO, ANY LOSS OF PROFIT
57
+ (WHETHER INCURRED DIRECTLY OR INDIRECTLY), ANY LOSS OF GOODWILL OR BUSINESS
58
+ REPUTATION, ANY LOSS OF DATA SUFFERED, COST OF PROCUREMENT OF SUBSTITUTE
59
+ GOODS OR SERVICES, OR OTHER INTANGIBLE LOSS; (B) ANY DIRECT LOSS OR DAMAGE
60
+ WHICH MAY BE INCURRED BY YOU IN EXCESS OF THE AMOUNT YOU PAID FOR THE SERVICE
61
+ IN THE CONTRACT MONTH IN WHICH THE LOSS OR DAMAGE WAS INCURRED (OR IN THE
62
+ CASE OF A FREE ACCOUNT TEN DOLLARS). THE LIMITATIONS ON OUR LIABILITY TO
63
+ YOU IN THIS AGREEMENT SHALL APPLY WHETHER OR NOT WE HAVE BEEN ADVISED OF
64
+ OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
65
+ Should you need to verify the working of the software for ensuring that
66
+ the same is adequate to your use, does not contain dangerous or malicious
67
+ code or is sufficiently hardened, as well in order to submit patches
68
+ and/or bug fixes, and in order to perform said activities you need a
69
+ copy of the corresponding source code that is not already readily available,
70
+ you are invited to contact ScientiaMobile and ask for a copy under a separate
71
+ agreement, which will be negotiated in good faith.
72
+
73
+ The laws of the Commonwealth of Virginia apply to this license.
74
+
75
+
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ #
2
+ # This software is the Copyright of ScientiaMobile, Inc.
3
+ # Please refer to the LICENSE.txt file distributed with the software for licensing information
4
+ #
5
+ require 'bundler'
6
+
7
+ task 'build' do
8
+ Bundler::GemHelper.new(Dir.pwd, 'wurfl_cloud_client').build_gem
9
+ Bundler::GemHelper.new(Dir.pwd, 'wurfl_cloud_client_light').build_gem
10
+
11
+ end
12
+
13
+ # Bundler::GemHelper.install_tasks
14
+
@@ -0,0 +1,36 @@
1
+ #
2
+ # This software is the Copyright of ScientiaMobile, Inc.
3
+ # Please refer to the LICENSE.txt file distributed with the software for licensing information
4
+ #
5
+ module WurflCloud
6
+ module Cache
7
+ class Cookie
8
+
9
+ def initialize(options, environment)
10
+ @env = environment
11
+ end
12
+
13
+ attr_accessor :mtime
14
+
15
+ def mtime
16
+ nil
17
+ end
18
+
19
+ # Validates the cache
20
+ # it's a no-op in the cookie cache
21
+ def validate(current_mtime)
22
+ end
23
+
24
+ # Should return the value stored for the key, nil if the key is not in cache
25
+ # The Cookie cache always returns the value of the env (no matter what the key)
26
+ def [](key)
27
+ @env['wurfl.cookie.device_cache']
28
+ end
29
+
30
+ # Sets the value in the cache, for the Cookie cache it sets the env
31
+ def []=(key, value)
32
+ @env['wurfl.cookie.device_cache'] = value
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ #
2
+ # This software is the Copyright of ScientiaMobile, Inc.
3
+ # Please refer to the LICENSE.txt file distributed with the software for licensing information
4
+ #
5
+ module WurflCloud
6
+ module Cache
7
+ class LocalMemory
8
+
9
+ def initialize(options=nil, environment=nil)
10
+ @cache = {}
11
+ end
12
+
13
+ attr_accessor :mtime
14
+
15
+ def mtime
16
+ nil
17
+ end
18
+
19
+ # Validates the cache
20
+ # it's a no-op in the local memory cache
21
+ def validate(current_mtime)
22
+ end
23
+
24
+ # Should return the value stored for the key, nil if the key is not in cache
25
+ # The LocalMemory cache stores the values in the local hash
26
+ def [](key)
27
+ @cache[key]
28
+ end
29
+
30
+ # reads the value from the local hash
31
+ def []=(key, value)
32
+ @cache[key] = value
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,34 @@
1
+ #
2
+ # This software is the Copyright of ScientiaMobile, Inc.
3
+ # Please refer to the LICENSE.txt file distributed with the software for licensing information
4
+ #
5
+ module WurflCloud
6
+ module Cache
7
+ class Null
8
+
9
+ def initialize(options, environment)
10
+ end
11
+
12
+ attr_accessor :mtime
13
+
14
+ def mtime
15
+ nil
16
+ end
17
+
18
+ # Validates the cache
19
+ # it's a no-op in the null cache
20
+ def validate(current_mtime)
21
+ end
22
+
23
+ # Should return the value stored for the key, nil if the key is not in cache
24
+ # The Null cache always returns nil (nothing is cacheed)
25
+ def [](key)
26
+ nil
27
+ end
28
+
29
+ # It's a no-op for the Null cache
30
+ def []=(key, value)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,98 @@
1
+ #
2
+ # This software is the Copyright of ScientiaMobile, Inc.
3
+ # Please refer to the LICENSE.txt file distributed with the software for licensing information
4
+ #
5
+ require 'wurfl_cloud/device_capabilities'
6
+ require 'net/http'
7
+
8
+ module WurflCloud
9
+ class Client
10
+
11
+ attr_reader :device_capabilities, :read_from_cache
12
+
13
+ def initialize(e, c)
14
+ @environment = e
15
+ @cache = c
16
+ @device_capabilities = WurflCloud::DeviceCapabilities.new(@environment.user_agent)
17
+ @read_from_cache = false
18
+ end
19
+
20
+ def [](capability_key)
21
+ if !@device_capabilities.has_key?(capability_key) && @read_from_cache
22
+ load_from_server!
23
+ store_in_cache
24
+ end
25
+ @device_capabilities[capability_key]
26
+ end
27
+
28
+ def detect
29
+ unless load_from_cache
30
+ load_from_server!
31
+ store_in_cache
32
+ end
33
+ end
34
+
35
+ def load_from_server!
36
+ begin
37
+ # make the request
38
+ Net::HTTP.start(WurflCloud.configuration.host,WurflCloud.configuration.port) do |http|
39
+ req = Net::HTTP::Get.new(WurflCloud.configuration.path, http_headers)
40
+ req.basic_auth WurflCloud.configuration.api_user, WurflCloud.configuration.api_password
41
+ res = http.request(req)
42
+
43
+ # emit the result
44
+ if res.code=="200"
45
+ # read the response
46
+ @device_capabilities = WurflCloud::DeviceCapabilities.parse(res.body)
47
+ @cache.validate(@device_capabilities.mtime.to_i)
48
+ @read_from_cache = false
49
+ else
50
+ raise WurflCloud::Errors::ConnectionError.new("#{res.code} #{res.message}")
51
+ end
52
+ end
53
+ rescue WurflCloud::Errors::GenericError => exc
54
+ raise exc
55
+ rescue Exception => exc
56
+ raise WurflCloud::Errors::ConnectionError.new(exc.message)
57
+ end
58
+ end
59
+
60
+ class << self
61
+
62
+ def detect_device(environment, cache)
63
+ new(environment, cache).tap do |client|
64
+ client.detect
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ private
71
+
72
+ def http_headers
73
+ {
74
+ 'X-Cloud-Client' => "WurflCloudClient/Ruby_#{WurflCloud::VERSION}",
75
+ "Content-Type"=>"application/json; charset=UTF-8"
76
+ }.tap do |h|
77
+ h['User-Agent'] = @environment.user_agent unless @environment.user_agent.nil?
78
+ h['X-Forwarded-For'] = @environment.x_forwarded_for unless @environment.x_forwarded_for.nil?
79
+ h['X-Accept'] = @environment.x_accept unless @environment.x_accept.nil?
80
+ h['X-Wap-Profile'] = @environment.x_wap_profile unless @environment.x_wap_profile.nil?
81
+ end
82
+ end
83
+
84
+ def store_in_cache
85
+ @cache[@environment.user_agent] = @device_capabilities.to_hash
86
+ end
87
+
88
+ def load_from_cache
89
+ if cached_capabilities = @cache[@environment.user_agent]
90
+ @device_capabilities = WurflCloud::DeviceCapabilities.new(@environment.user_agent)
91
+ @device_capabilities.merge(cached_capabilities)
92
+ @read_from_cache = true
93
+ return true
94
+ end
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,81 @@
1
+ #
2
+ # This software is the Copyright of ScientiaMobile, Inc.
3
+ # Please refer to the LICENSE.txt file distributed with the software for licensing information
4
+ #
5
+ require 'wurfl_cloud/errors'
6
+
7
+ module WurflCloud
8
+ class Configuration
9
+ # The API key to access the WurflCloud api (defaults to "100000:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").
10
+ attr_accessor :api_key
11
+
12
+ # The API user id decoded from the api_key
13
+ attr_reader :api_user
14
+
15
+ # The API password decoded from the api_key
16
+ attr_reader :api_password
17
+
18
+ # The schema of the URI for the api server (defaults to http).
19
+ attr_accessor :schema
20
+
21
+ # The host to connect to (defaults to api.wurflcloud.com).
22
+ attr_accessor :host
23
+
24
+ # The port on which your WurflCloud server runs (defaults to 80).
25
+ attr_accessor :port
26
+
27
+ # The path (URL) for the API endpoint at the host (defaults to /v1/json).
28
+ attr_accessor :path
29
+
30
+ # The API Type, defaults to http (*not used*)
31
+ attr_accessor :api_type
32
+
33
+ # The search parameter format (defaults to "search:(%{capabilities})")
34
+ attr_accessor :search_parameter
35
+
36
+ # The search parameter capabilities separator (defaults to ",")
37
+ attr_accessor :search_parameter_separator
38
+
39
+ # The cache class to be used (defaults to a WurflCloud::Cache::Null )
40
+ attr_accessor :cache_class
41
+
42
+ # The cache_options to be used (defaults to {})
43
+ attr_accessor :cache_options
44
+
45
+ def initialize
46
+ @api_key = "100000:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
47
+ @api_user = 100000
48
+ @api_password = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
49
+ @host = 'api.wurflcloud.com'
50
+ @schema = 'http'
51
+ @port = 80
52
+ @path = '/v1/json'
53
+ @api_type = 'http'
54
+ @search_parameter = "search:(%{capabilities})"
55
+ @search_parameter_separator = ','
56
+ @cache_class = WurflCloud::Cache::Null
57
+ @cache_options = {}
58
+ end
59
+
60
+ def api_key=(new_key)
61
+ @api_key = new_key
62
+ if new_key=~/^(\d{6}):(\w{32})$/
63
+ @api_user = $1.to_i
64
+ @api_password = $2
65
+ else
66
+ raise WurflCloud::Errors::ConfigurationError.new
67
+ end
68
+ end
69
+
70
+ def api_uri
71
+ "#{@schema}://#{@host}:#{@port}#{@path}"
72
+ end
73
+
74
+ # creates a cache instance using the class and the options
75
+ # given in the confinguration and passing whatever environment
76
+ # is passed in the parameters
77
+ def cache(environment)
78
+ @cache_class.new(@cache_options, environment)
79
+ end
80
+ end
81
+ end