3 See the NOTICE file distributed with
this work
for additional information
4 regarding copyright ownership.
6 Licensed under the Apache License, Version 2.0 (the
"License");
7 you may not use
this file except in compliance with the License.
8 You may obtain a copy of the License at
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an
"AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License
for the specific language governing permissions and
16 limitations under the License.
23 Please email comments or questions to the
public Ensembl
24 developers list at <http:
26 Questions may also be sent to the Ensembl help desk at
38 # or use Bio::EnsEMBL::Utils::URI qw/:all/; # to bring everything in
40 my $db_uri = parse_uri(
'mysql://user@host:3157/db');
41 my $http_uri = parse_uri(
'http://www.google.co.uk:80/search?q=t');
43 is_uri(
'mysql://user@host'); # returns 1
44 is_uri(
'file:///my/path'); # returns 1
45 is_uri(
'/my/path'); # returns 0
49 This
object is a
generic URI parser which is primarily used in the
50 parsing of database URIs into a more managable data structure. We also provide
51 the resulting
URI object
55 L<URI::Escape> is an optional dependency but
if available the code will attempt
56 to perform
URI encoding/decoding on parameters. If you
do not want
this
57 functionality then modify the global C<$Bio::EnsEMBL::Utils::URI::URI_ESCAPE>
64 package Bio::EnsEMBL::Utils::URI;
69 use Scalar::Util qw/looks_like_number/;
77 URI::Escape->import();
81 use base qw/Exporter/;
84 @EXPORT_OK = qw/parse_uri is_uri/;
85 %EXPORT_TAGS = ( all => [@EXPORT_OK] );
92 Example : is_uri(
'mysql://user:pass@host:415/db');
93 Description : Looks
for the existence of a
URI scheme to decide
if this
94 is a classical
URI. Whilst non-scheme based URIs can still be
95 interprited it is useful to use when you need to know
if
96 you are going to work with a
URI or not
106 my $SCHEME = qr{ ([^:]*) :
107 return ($uri =~ $SCHEME) ? 1 : 0;
112 Arg[1] : Scalar; URI to parse
113 Example : my $uri = parse_uri(
'mysql://user:pass@host:415/db');
114 Description : A URL parser which attempts to convert many different types
115 of URL into a common data structure.
125 my $SCHEME = qr{ ([^:]*) :
126 my $USER = qr{ ([^/:\@]+)? :? ([^/\@]+)? \@ }xms;
127 my $HOST = qr{ ([^/:]+)? :? ([^/]+)? }xms;
128 my $DB = qr{ / ([^/?]+)? /? ([^/?]+)? }xms;
129 my $PARAMS = qr{ \? (.+)}xms;
133 if($url =~ qr{ $SCHEME ([^?]+) (?:$PARAMS)? }xms) {
135 $scheme = ($URI_ESCAPE) ? uri_unescape($scheme) : $scheme;
137 my ($locator, $params) = ($2, $3);
139 if($scheme eq
'file') {
142 elsif($scheme eq
'sqlite') {
146 if($locator =~ s/^$USER
150 if($locator =~ s/^$HOST
151 $p->host(($URI_ESCAPE) ? uri_unescape($1) : $1);
152 $p->port(($URI_ESCAPE) ? uri_unescape($2) : $2);
155 if($p->is_db_scheme() || $scheme eq q{}) {
156 if($locator =~ $DB) {
157 $p->db_params()->{dbname} = ($URI_ESCAPE) ? uri_unescape($1) : $1;
158 $p->db_params()->{table} = ($URI_ESCAPE) ? uri_unescape($2) : $2;
166 if(defined $params) {
167 my @kv_pairs = split(/;|&/, $params);
168 foreach my $kv_string (@kv_pairs) {
169 my ($key, $value) =
map { ($URI_ESCAPE) ? uri_unescape($_) : $_ } split(/=/, $kv_string);
170 $p->add_param($key, $value);
184 Arg[1] : String; scheme the URI will confrom to
185 Description : New
object call
186 Returntype : Bio::EnsEMBL::Utils::URIParser::URI
187 Exceptions : Thrown
if scheme is undefined.
193 my ($class, $scheme) = @_;
194 $class = ref($class) || $class;
195 throw "Scheme cannot be undefined. Empty string is allowed" if ! defined $scheme;
209 Description: Returns a hash of scheme names known to be databases
218 return {
map { $_ => 1 } qw/mysql ODBC sqlite Oracle Sybase/};
222 =head2 is_db_scheme()
224 Description: Returns true if the code believes the scheme to be a Database
233 return ( exists $self->db_schemes()->{$self->scheme()} ) ? 1 : 0;
238 Description : Getter for the scheme attribute
247 return $self->{scheme};
252 Arg[1] : Setter argument
253 Description : Getter/setter for the path attribute
261 my ($self, $path) = @_;
262 $self->{path} = $path
if defined $path;
263 return $self->{path};
268 Arg[1] : Setter argument
269 Description : Getter/setter for the user attribute
277 my ($self, $user) = @_;
278 $self->{user} = $user
if defined $user;
279 return $self->{user};
284 Arg[1] : Setter argument
285 Description : Getter/setter for the password attribute
293 my ($self, $pass) = @_;
294 $self->{pass} = $pass
if defined $pass;
295 return $self->{pass};
300 Arg[1] : Setter argument
301 Description : Getter/setter for the host attribute
309 my ($self, $host) = @_;
310 $self->{host} = $host
if defined $host;
311 return $self->{host};
316 Arg[1] : Setter argument
317 Description : Getter/setter for the port attribute
319 Exceptions : If port is not a number, less than 1 or not a whole integer
325 my ($self, $port) = @_;
327 if(! looks_like_number($port) || $port < 1 ||
int($port) != $port) {
328 throw "Port $port is not a number, less than 1 or not a whole integer";
330 $self->{port} = $port
if defined $port;
332 return $self->{port};
337 Description : Getter for the paramater
map keys in the order they were first
338 seen. Keys should only appear once in this array
339 Returntype : ArrayRef
347 return [@{$self->{param_keys}}];
350 =head2 param_exists_ci()
353 Description : Performs a case-insensitive search for the given key
354 Returntype : Boolean; returns true if your given key was seen
360 sub param_exists_ci {
361 my ($self, $key) = @_;
362 my %keys =
map { uc($_) => 1 } @{$self->param_keys()};
363 return ($keys{uc($key)}) ? 1 : 0;
369 Arg[1] : Scalar; value
370 Description : Add a key/value to the params
map. Multiple inserts of the same
379 my ($self, $key, $value) = @_;
380 if(!exists $self->{params}->{$key}) {
381 $self->{params}->{$key} = [];
382 push(@{$self->{param_keys}}, $key);
384 push(@{$self->{params}->{$key}}, $value);
391 Description : Returns the values which were found to be linked to the given
392 key. Arrays are returned because one key can have many
394 Returntype : ArrayRef[Scalar]
401 my ($self, $key) = @_;
402 return []
if ! exists $self->{params}->{$key};
403 return [@{$self->{params}->{$key}}];
408 Description : Storage of parameters used only for database URIs since
410 Returntype : HashRef; Database name is keyed under C<dbname> and the
411 table is keyed under C<table>
419 return $self->{db_params};
422 =head2 generate_dbsql_params()
424 Arg[1] :
boolean $no_table alows you to avoid pushing -TABLE as an
426 Description : Generates a Hash of Ensembl compatible parameters to be used
427 to construct a DB
object. We combine those parameters
428 which are deemed to be part of the C<db_params()> method
429 under C<-DBNAME> and C<-TABLE>. We also search for a number
430 of optional parameters which are lowercased equivalents
431 of the construction parameters available from a
433 L<
Bio::
EnsEMBL::DBSQL::DBConnection> as well as C<verbose>
436 We also convert the scheme type into the driver attribute
438 Returntype : Hash (not a reference). Output can be put into a C<DBConnection>
445 sub generate_dbsql_params {
446 my ($self, $no_table) = @_;
449 $db_params{-DRIVER} = $self->scheme();
450 $db_params{-HOST} = $self->host()
if $self->host();
451 $db_params{-PORT} = $self->port()
if $self->port();
452 $db_params{-USER} = $self->user()
if $self->user();
453 $db_params{-PASS} = $self->pass()
if $self->pass();
457 if($self->scheme() eq
'sqlite') {
458 ($dbname, $table) = $self->_decode_sqlite();
461 $dbname = $self->db_params()->{dbname};
462 $table = $self->db_params()->{table};
465 $db_params{-DBNAME} = $dbname
if $dbname;
466 $db_params{-TABLE} = $table
if ! $no_table && $table;
468 foreach my $boolean_param (qw/disconnect_when_inactive reconnect_when_connection_lost is_multispecies no_cache verbose/) {
469 if($self->param_exists_ci($boolean_param)) {
470 $db_params{q{-}.uc($boolean_param)} = 1;
473 foreach my $value_param (qw/species group species_id wait_timeout/) {
474 if($self->param_exists_ci($value_param)) {
475 $db_params{q{-}.uc($value_param)} = $self->get_params($value_param)->[0];
482 =head2 _decode_sqlite
484 Description : Performs path gymnastics to decode into a number of possible
485 options. The issue with SQLite is that the normal URI scheme
487 that the DB name is C</my/path.sqlite> and the table is
490 The code takes a path, looks
for the full path &
if it cannot
491 be found looks
for the file a directory back. In the above
492 example it would have looked
for C</my/path.sqlite/table>,
493 found it to be non-existant, looked
for C</my/path.sqlite>
496 If the path splitting procdure resulted in just 1 file after
497 the first existence check e.g. C<sqlite:
498 that should be the name. If no file can be found we
default to
499 the full length path.
508 my $path = $self->path();
513 my ($volume, $directories, $file) = File::Spec->splitpath($path);
514 my @splitdirs = File::Spec->splitdir($directories);
515 if(@splitdirs == 1) {
519 my $new_file = pop(@splitdirs);
521 my $new_path = File::Spec->catpath($volume, File::Spec->catdir(@splitdirs), $new_file);
522 if($new_path ne File::Spec->rootdir() && -f $new_path) {
532 $self->db_params()->{dbname} = $dbname
if $dbname;
533 $self->db_params()->{table} = $table
if $table;
535 return ($dbname, $table);
538 =head2 generate_uri()
540 Description : Generates a URI
string from the paramaters in this
object
549 my $scheme = sprintf(
'%s://', ($URI_ESCAPE) ? uri_escape($self->scheme()) : $self->scheme());
550 my $user_credentials = q{};
551 my $host_credentials = q{};
554 if($self->user() || $self->pass()) {
555 my $user = $self->user();
556 my $pass = $self->pass();
558 $user = uri_escape($user)
if $user;
559 $pass = uri_escape($pass)
if $pass;
561 $user_credentials = sprintf(
'%s%s@',
562 ( $user ? $user : q{} ),
563 ( $pass ? q{:}.$pass : q{} )
567 if($self->host() || $self->port()) {
568 my $host = $self->host();
569 my $port = $self->port();
571 $host = uri_escape($host)
if $host;
572 $port = uri_escape($port)
if $port;
574 $host_credentials = sprintf(
'%s%s',
575 ( $host ? $host : q{} ),
576 ( $port ? q{:}.$port : q{} )
580 if($self->is_db_scheme() || $self->scheme() eq
'') {
581 if($self->scheme() eq
'sqlite') {
582 if(! $self->path()) {
583 my $tmp_loc = $self->db_params()->{dbname};
584 throw "There is no dbname available" unless $tmp_loc;
585 $tmp_loc .= q{/}.$self->db_params()->{table}
if $self->db_params()->{table};
586 $self->path($tmp_loc);
588 $location = $self->path();
591 my $dbname = $self->db_params()->{dbname};
592 my $table = $self->db_params()->{table};
593 if($dbname || $table) {
595 $dbname = uri_escape($dbname)
if $dbname;
596 $table = uri_escape($table)
if $table;
598 $location = sprintf(
'/%s%s',
599 ($dbname ? $dbname : q{}),
600 ($table ? q{/}.$table : q{})
606 $location = $self->path()
if $self->path();
609 my $param_string = q{};
610 if(@{$self->param_keys()}) {
611 $param_string = q{?};
613 foreach my $key (@{$self->param_keys}) {
614 my $values_array = $self->get_params($key);
615 foreach my $value (@{$values_array}) {
616 my $encoded_key = ($URI_ESCAPE) ? uri_escape($key) : $key;
617 my $encoded_value = ($URI_ESCAPE) ? uri_escape($value) : $value;
618 push(@params, ($encoded_value) ?
"$encoded_key=$encoded_value" : $encoded_key);
621 $param_string .= join(q{;}, @params);
624 return join(q{}, $scheme, $user_credentials, $host_credentials, $location, $param_string);