wurfl_cloud_client_light 1.0.0

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