rgeoserver 0.5.6 → 0.5.7

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  == RGeoServer
4
4
 
5
- RGeoServer is a Ruby client for the GeoServer RESTful administrative interface.
5
+ RGeoServer is a Ruby client for the GeoServer RESTful Configuration interface.
6
6
 
7
7
  It provides primitive Ruby model abstraction.
8
8
 
@@ -63,13 +63,28 @@ A full sample script creating coverage stores in a small cluster:
63
63
 
64
64
  (1..7).each do |cat_id|
65
65
  cat = RGeoServer::Catalog.new :user=>'admin', :url => "http://geoserver-app#{cat_id}/rest", :password => "osgeo!"
66
- ws = cat.get_workspace('cite')
66
+ ws = cat.get_default_workspace
67
67
  cat.list(RGeoServer::CoverageStore, layers.keys, :workspace => ws) do |cs|
68
- cs.description = layers[cs.name]['description']
69
68
  cs.url = layers[cs.name]['url']
70
69
  cs.data_type = layers[cs.name]['type']
71
70
  cs.enabled = 'true'
72
71
  cs.save
72
+ # Create the corresponding layer
73
+ c = RGeoServer::Coverage.new cat, :workspace => ws, :coverage_store => cs, :name => cs.name
74
+ c.title = cs_name.gsub('_',' ').titleize
75
+ c.abstract = layers[cs.name]['description']
76
+ c.save
77
+ # Seed the tile cache
78
+ l = RGeoServer::Layer.new cat, :name => cs.name
79
+ l.seed :issue, {
80
+ :srs => {
81
+ :number => 4326
82
+ },
83
+ :zoomStart => 1,
84
+ :zoomStop => 10,
85
+ :format => 'image/png',
86
+ :threadCount => 1
87
+ }
73
88
  end
74
89
  end
75
90
 
@@ -89,7 +104,7 @@ To enter into an irb console with all classess loaded:
89
104
  $ rake console
90
105
 
91
106
  == Logging
92
- For now we use {RestClient's}[https://github.com/adamwiggins/rest-client] base logger. It can be enabled by setting:
107
+ For now we use {RestClient's}[https://github.com/archiloque/rest-client] base logger. It can be enabled by setting:
93
108
 
94
109
  RestClient.log = '/tmp/restclient.log'
95
110
 
@@ -117,18 +132,22 @@ or set an environment variable, for example:
117
132
  - <b>v0.5</b> - Initial alpha release
118
133
 
119
134
  == TODO
120
- - Handle default resources transparently.
121
135
  - Complete data stores and coverages functionality and data upload.
136
+ - Complete updating data in objects. On failure, objects should roll back.
122
137
  - Complete documentation.
123
138
  - Complete test coverage:
124
- - Add functional tests
139
+ - Add functional tests and hook to CI service (most likely travis-ci).
140
+ - Break down testing into separate specs per class.
125
141
  - Add more flexibility for integration tests with embedded Jetty and other containers.
126
- - Hook to CI service.
142
+ - Add ability to perform integration tests in a CI server.
143
+ - Add GeoWebCache REST API operations for seeding and truncating layers.
127
144
  - Provide more examples:
128
145
  - Customize configuration.
129
146
  - Connect under SSL.
130
147
  - Batch processing.
131
148
  - Migrate base HTTP client to {Weary}[https://github.com/mwunsch/weary]?
149
+ - Curlify operations: To provide optional log/output of the curl command that would produce the same
150
+ result as the ResourceInfo#save method.
132
151
 
133
152
  == Contributing with Patches and Pull requests checklist
134
153
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
@@ -150,4 +169,4 @@ Inspired on the {Rubydora}[https://github.com/cbeer/rubydora] and RSolr gems. Fo
150
169
 
151
170
  Copyright (c) 2011 Renzo Sanchez-Silva <renzo@stanford.edu>.
152
171
 
153
- Licensed under the [MIT License](http://www.opensource.org/licenses/MIT).
172
+ Licensed under the {MIT License}[http://www.opensource.org/licenses/MIT].
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.6
1
+ 0.5.7
@@ -1,5 +1,6 @@
1
1
  geoserver:
2
2
  url: "http://localhost:8080/geoserver/rest"
3
+ geowebcache_url: "http://localhost:8080/geoserver/gwc/rest"
3
4
  user: admin
4
5
  password: geoserver
5
6
  ssl:
@@ -0,0 +1,105 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ # RGeoServer Batch demo (batch_demo.rb)
4
+
5
+ #require 'rubygems'
6
+ require 'yaml'
7
+ require 'rgeoserver'
8
+
9
+ #= Input data.
10
+ # Assume we have a YAML file (layers.yaml) with records of the form:
11
+
12
+ # record_19:
13
+ # filename: g3881015alpha.tif
14
+ # title: Antietam 1867
15
+ # layername: antietam_1867
16
+ # size: 208 MB
17
+ # projection: GCS_WGS_1984
18
+ # format: GeoTIFF
19
+ # description: Map shows the U.S. Civil War battle of Antietam. It indicates fortifications,
20
+ # roads, railroads, houses, names of residents, fences, drainage, vegetation, and
21
+ # relief by hachures.
22
+ # metadata: http://example.com/geonetwork/srv/en/fgdc.xml?id=1090
23
+
24
+
25
+ # After parsing we save it in the $layers variable.
26
+ $layers = YAML::load(File.open(File.join(File.dirname(__FILE__), 'layers.yaml')))
27
+
28
+ # The records will look like this
29
+
30
+ # ["record_19", {"format"=>"GeoTIFF", "size"=>"208 MB", "title"=> "Antietam 1867", "metadata"=>"http://example.com/geonetwork/srv/en/fgdc.xml?id=1090", "projection"=>"GCS_WGS_1984", "filename"=>"g3881015alpha.tif", "description"=>"Map shows the U.S. Civil War battle of Antietam. It indicates fortifications, roads, railroads, houses, names of residents, fences, drainage, vegetation, and relief by hachures.", "layername"=>"Antietam 1867"}]
31
+
32
+ # Connect to the GS catalog
33
+ $c = RGeoServer::Catalog.new :url=>"http://geoserver.example.com/geoserver/rest", :geowebcache_url => "http://geoserver.example.com/geoserver/gwc/rest", :password=>"admin", :user=>"admin"
34
+
35
+ # Obtain a handle to the workspace.
36
+ ws = RGeoServer::Workspace.new $c, :name => 'orbis'
37
+ ws.delete :recurse => true unless ws.new? # comment or uncomment to start from scratch
38
+ ws.save if ws.new?
39
+
40
+ # GWC configuration
41
+ SEED = false
42
+ SEED_OPTIONS = {
43
+ :srs => {
44
+ :number => 4326
45
+ },
46
+ :zoomStart => 1,
47
+ :zoomStop => 10,
48
+ :format => 'image/png',
49
+ :threadCount => 1
50
+ }
51
+
52
+ # Iterate over all records in YAML file and create stores in the catalog
53
+
54
+ $layers.each{ |id, val|
55
+ title = val['title']
56
+ layername = val['layername']
57
+ format = val['format']
58
+ metadata = val['metadata']
59
+ filename = val['filename']
60
+ description = val['description'
61
+ name = layername
62
+
63
+ if format == 'GeoTIFF'
64
+ begin
65
+ # Create of a coverage store
66
+ cs = RGeoServer::CoverageStore.new $c, :workspace => ws, :name => name
67
+ cs.url = "file:///geo_data/staging/#{filename}"
68
+ cs.description = description
69
+ cs.enabled = 'true'
70
+ cs.data_type = format
71
+ cs.save
72
+ # Now create the actual coverage
73
+ cv = RGeoServer::Coverage.new $c, :workspace => ws, :coverage_store => cs, :name => name
74
+ cv.title = title
75
+ cv.save
76
+ #cv.metadata_links = [{"type"=>"text/plain", "metadataType"=>"FGDC", "content"=> metadata}]
77
+ #cv.save
78
+ # Check if a layer has been created, extract some metadata
79
+ lyr = RGeoServer::Layer.new $c, :name => name
80
+ if !lyr.new? && SEED
81
+ lyr.seed :issue, SEED_OPTIONS
82
+ end
83
+ rescue Exception => e
84
+ puts e.inspect
85
+ end
86
+
87
+ elsif format == 'Shapefile'
88
+ begin
89
+ # Create data stores for shapefiles
90
+ cs = RGeoServer::DataStore.new $c, :workspace => ws, :name => name
91
+ cs.connection_parameters = {
92
+ "url" => "file:///geo_data/staging/#{filename}",
93
+ "namespace" => "http://example.com"
94
+ }
95
+ cs.enabled = 'true'
96
+ cs.save
97
+ ft = RGeoServer::FeatureType.new $c, :workspace => ws, :data_store => cs, :name => name
98
+ ft.title = title
99
+ ft.abstract = description
100
+ ft.save
101
+ rescue Exception => e
102
+ puts e.inspect
103
+ end
104
+ end
105
+ }
@@ -0,0 +1,30 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ #require 'rubygems'
4
+ require 'rgeoserver'
5
+
6
+ layers = {
7
+ 'south_america_1787' => {
8
+ 'url' => 'file:///geo_data/rumsey/g0411047.tif',
9
+ 'description' => "Map of South America by D'Anville",
10
+ 'type' => 'GeoTIFF'
11
+ },
12
+ 'city_of_san_francisco_1859' => {
13
+ 'url' => 'file:///geo_data/rumsey/g1030000alpha.tif',
14
+ 'description' => 'Map of San Francisco by the U.S. Coast Survey, with detail of the unsettled lands',
15
+ 'type' => 'GeoTIFF'
16
+ }
17
+ }
18
+
19
+ (1..7).each do |cat_id|
20
+ cat = RGeoServer::Catalog.new :user=>'admin', :url => "http://geoserver-app#{cat_id}/rest", :password => "osgeo!"
21
+ ws = cat.get_workspace('cite')
22
+ RGeoServer::ResourceInfo.list(RGeoServer::CoverageStore, cat, layers.keys, :workspace => ws) do |cs|
23
+ cs.description = layers[cs.name]['description']
24
+ cs.url = layers[cs.name]['url']
25
+ cs.data_type = layers[cs.name]['type']
26
+ cs.enabled = 'true'
27
+ cs.save
28
+ end
29
+
30
+ end
data/lib/rgeoserver.rb CHANGED
@@ -8,6 +8,7 @@ module RGeoServer
8
8
  autoload :RestApiClient, "rgeoserver/rest_api_client"
9
9
  autoload :GeoServerUrlHelpers, "rgeoserver/geoserver_url_helpers"
10
10
  autoload :ResourceInfo, "rgeoserver/resource"
11
+ autoload :Namespace, "rgeoserver/namespace"
11
12
  autoload :Workspace, "rgeoserver/workspace"
12
13
  autoload :FeatureType, "rgeoserver/featuretype"
13
14
  autoload :Coverage, "rgeoserver/coverage"
@@ -6,7 +6,6 @@ module RGeoServer
6
6
 
7
7
  class Catalog
8
8
  include RGeoServer::RestApiClient
9
- include ActiveSupport::Benchmarkable
10
9
 
11
10
  attr_reader :config
12
11
 
@@ -22,11 +21,6 @@ module RGeoServer
22
21
  "Catalog: #{@config[:url]}"
23
22
  end
24
23
 
25
- def client config = {}
26
- c = self.config.merge(config)
27
- @client ||= RestClient::Resource.new(c[:url], :user => c[:user], :password => c[:password], :headers => c[:headers])
28
- end
29
-
30
24
  def headers format
31
25
  sym = :xml || format.to_sym
32
26
  {:accept => sym, :content_type=> sym}
@@ -67,14 +61,20 @@ module RGeoServer
67
61
 
68
62
  # @return [RGeoServer::Workspace]
69
63
  def get_default_workspace
70
- dw = Workspace.new self, :name => 'default'
71
- w = Workspace.new self, :name => w.name
72
- raise "No default workspace is available in the catalog" unless w.new?
73
- w
64
+ response = self.search :workspaces => 'default'
65
+ doc = Nokogiri::XML(response)
66
+ name = doc.at_xpath("#{Workspace.member_xpath}/name/text()").to_s
67
+ return Workspace.new self, :name => name
74
68
  end
75
69
 
76
- def set_default_workspace
77
- raise NotImplementedError
70
+ # Assign default workspace
71
+ # @param [String] workspace name
72
+ def set_default_workspace workspace
73
+ raise TypeError, "Workspace name must be a string" unless workspace.instance_of? String
74
+ dws = Workspace.new self, :name => 'default'
75
+ dws.name = workspace # This creates a new workspace if name is new
76
+ dws.save
77
+ dws
78
78
  end
79
79
 
80
80
  # @param [String] store
@@ -99,8 +99,8 @@ module RGeoServer
99
99
  def get_layer layer
100
100
  response = self.search :layers => layer
101
101
  doc = Nokogiri::XML(response)
102
- name = doc.at_xpath(Layer.member_xpath)
103
- return Layer.new self, :name => name.text if name
102
+ name = doc.at_xpath("#{Layer.member_xpath}/name/text()").to_s
103
+ return Layer.new self, :name => name
104
104
  end
105
105
 
106
106
  #= Styles (SLD Style Layer Descriptor)
@@ -119,8 +119,8 @@ module RGeoServer
119
119
  def get_style style
120
120
  response = self.search :styles => style
121
121
  doc = Nokogiri::XML(response)
122
- name = doc.at_xpath(Style.member_xpath)
123
- return Style.new self, :name => name.text if name
122
+ name = doc.at_xpath("#{Style.member_xpath}/name/text()").to_s
123
+ return Style.new self, :name => name
124
124
  end
125
125
 
126
126
 
@@ -132,8 +132,13 @@ module RGeoServer
132
132
  raise NotImplementedError
133
133
  end
134
134
 
135
+ # @return [RGeoServer::Namespace]
135
136
  def get_default_namespace
136
- raise NotImplementedError
137
+ response = self.search :namespaces => 'default'
138
+ doc = Nokogiri::XML(response)
139
+ name = doc.at_xpath("#{Namespace.member_xpath}/prefix/text()").to_s
140
+ uri = doc.at_xpath("#{Namespace.member_xpath}/uri/text()").to_s
141
+ return Namespace.new self, :name => name, :uri => uri
137
142
  end
138
143
 
139
144
  def set_default_namespace id, prefix, uri
@@ -229,13 +234,13 @@ module RGeoServer
229
234
  #= Configuration reloading
230
235
  # Reloads the catalog and configuration from disk. This operation is used to reload GeoServer in cases where an external tool has modified the on disk configuration. This operation will also force GeoServer to drop any internal caches and reconnect to all data stores.
231
236
  def reload
232
- do_url 'reload', method = :put
237
+ do_url 'reload', :put
233
238
  end
234
239
 
235
240
  #= Resource reset
236
241
  # Resets all store/raster/schema caches and starts fresh. This operation is used to force GeoServer to drop all caches and stores and reconnect fresh to each of them first time they are needed by a request. This is useful in case the stores themselves cache some information about the data structures they manage that changed in the meantime.
237
242
  def reset
238
- do_url 'reset', method = :put
243
+ do_url 'reset', :put
239
244
  end
240
245
 
241
246
  end
@@ -3,8 +3,8 @@ module RGeoServer
3
3
  # A coverage is a raster based data set which originates from a coverage store.
4
4
  class Coverage < ResourceInfo
5
5
 
6
- OBJ_ATTRIBUTES = {:catalog => "catalog", :workspace => "workspace", :coverage_store => "coverage_store", :name => "name", :title => "title" }
7
- OBJ_DEFAULT_ATTRIBUTES = {:catalog => nil, :workspace => nil, :coverage_store => nil, :name => nil, :title => nil }
6
+ OBJ_ATTRIBUTES = {:catalog => "catalog", :workspace => "workspace", :coverage_store => "coverage_store", :name => "name", :title => "title", :abstract => "abstract", :metadata_links => "metadataLinks" }
7
+ OBJ_DEFAULT_ATTRIBUTES = {:catalog => nil, :workspace => nil, :coverage_store => nil, :name => nil, :title => nil, :abstract => nil, :metadata_links => [] }
8
8
 
9
9
  define_attribute_methods OBJ_ATTRIBUTES.keys
10
10
  update_attribute_accessors OBJ_ATTRIBUTES
@@ -33,7 +33,20 @@ module RGeoServer
33
33
  builder = Nokogiri::XML::Builder.new do |xml|
34
34
  xml.coverage {
35
35
  xml.name @name
36
- xml.title @title
36
+ xml.title @title
37
+ unless new?
38
+ xml.nativeName @name
39
+ xml.abstract @abtract if abstract_changed?
40
+ xml.metadataLinks {
41
+ @metadata_links.each{ |m|
42
+ xml.metadataLink {
43
+ xml.type_ m['type']
44
+ xml.metadataType m['metadataType']
45
+ xml.content m['content']
46
+ }
47
+ }
48
+ } if metadata_links_changed?
49
+ end
37
50
  }
38
51
  end
39
52
  @message = builder.doc.to_xml
@@ -75,9 +88,33 @@ module RGeoServer
75
88
  "coverage_store" => @coverage_store.name,
76
89
  "workspace" => @workspace.name,
77
90
  "name" => doc.at_xpath('//name').text.strip,
78
- "nativeName" => doc.at_xpath('//nativeName').to_s,
79
- "title" => doc.at_xpath('//title').to_s,
80
- "supportedFormats" => doc.xpath('//supportedFormats/string').collect{ |t| t.to_s }
91
+ "nativeName" => doc.at_xpath('//nativeName/text()').to_s,
92
+ "nativeCRS" => doc.at_xpath('//nativeCRS/text()').to_s,
93
+ "title" => doc.at_xpath('//title/text()').to_s,
94
+ "srs" => doc.at_xpath('//srs/text()').to_s,
95
+ "nativeBoundingBox" => {
96
+ 'minx' => doc.at_xpath('//nativeBoundingBox/minx/text()').to_s,
97
+ 'miny' => doc.at_xpath('//nativeBoundingBox/miny/text()').to_s,
98
+ 'maxx' => doc.at_xpath('//nativeBoundingBox/maxx/text()').to_s,
99
+ 'maxy' => doc.at_xpath('//nativeBoundingBox/maxy/text()').to_s,
100
+ 'crs' => doc.at_xpath('//nativeBoundingBox/crs/text()').to_s
101
+ },
102
+ "latLonBoundingBox" => {
103
+ 'minx' => doc.at_xpath('//latLonBoundingBox/minx/text()').to_s,
104
+ 'miny' => doc.at_xpath('//latLonBoundingBox/miny/text()').to_s,
105
+ 'maxx' => doc.at_xpath('//latLonBoundingBox/maxx/text()').to_s,
106
+ 'maxy' => doc.at_xpath('//latLonBoundingBox/maxy/text()').to_s,
107
+ 'crs' => doc.at_xpath('//latLonBoundingBox/crs/text()').to_s
108
+ },
109
+ "abstract" => doc.at_xpath('//abstract/text()').to_s,
110
+ "supportedFormats" => doc.xpath('//supportedFormats/string').collect{ |t| t.to_s },
111
+ "metadataLinks" => doc.xpath('//metadataLinks/metadataLink').collect{ |m|
112
+ {
113
+ 'type' => m.at_xpath('//type/text()').to_s,
114
+ 'metadataType' => m.at_xpath('//metadataType/text()').to_s,
115
+ 'content' => m.at_xpath('//content').text.strip
116
+ }
117
+ }
81
118
  }.freeze
82
119
  h
83
120
  end
@@ -32,10 +32,14 @@ module RGeoServer
32
32
  @@route % @workspace.name
33
33
  end
34
34
 
35
+ def update_params name_route = @name
36
+ { :name => name_route, :workspace => @workspace.name }
37
+ end
38
+
35
39
  def message
36
40
  builder = Nokogiri::XML::Builder.new do |xml|
37
41
  xml.coverageStore {
38
- xml.name @name if new?
42
+ xml.name @name
39
43
  xml.workspace {
40
44
  xml.name @workspace.name
41
45
  }
@@ -4,7 +4,7 @@ module RGeoServer
4
4
  class DataStore < ResourceInfo
5
5
 
6
6
  OBJ_ATTRIBUTES = {:enabled => "enabled", :catalog => "catalog", :workspace => "workspace", :name => "name", :connection_parameters => "connectionParameters"}
7
- OBJ_DEFAULT_ATTRIBUTES = {:enabled => true, :catalog => nil, :workspace => nil, :name => nil, :connection_parameters => {}}
7
+ OBJ_DEFAULT_ATTRIBUTES = {:enabled => 'true', :catalog => nil, :workspace => nil, :name => nil, :connection_parameters => {}}
8
8
  define_attribute_methods OBJ_ATTRIBUTES.keys
9
9
  update_attribute_accessors OBJ_ATTRIBUTES
10
10
 
@@ -41,12 +41,12 @@ module RGeoServer
41
41
  def message
42
42
  builder = Nokogiri::XML::Builder.new do |xml|
43
43
  xml.dataStore {
44
- xml.enabled true
45
44
  xml.name @name
45
+ xml.enabled @enabled
46
46
  xml.connectionParameters { # this could be empty
47
47
  @connection_parameters.each_pair { |k,v|
48
48
  xml.entry(:key => k) {
49
- xml.text v
49
+ xml.text v
50
50
  }
51
51
  } unless @connection_parameters.empty?
52
52
  }