blob: 187c7232351264c54b6ffddf593c992be046e603 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _DECAF_NET_URI_H_
#define _DECAF_NET_URI_H_
#include <decaf/util/Config.h>
#include <decaf/lang/Comparable.h>
#include <decaf/lang/exceptions/IllegalArgumentException.h>
#include <decaf/net/URISyntaxException.h>
#include <decaf/net/MalformedURLException.h>
#include <decaf/internal/net/URIType.h>
#include <string>
namespace decaf {
namespace net {
class URL;
/**
* This class represents an instance of a URI as defined by RFC 2396.
*/
class DECAF_API URI: public lang::Comparable<URI> {
private:
// The structure that holds the parsed URI data.
decaf::internal::net::URIType uri;
// The original string entered from URI( string ), empty if not set.
mutable std::string uriString;
static const std::string unreserved;
static const std::string punct;
static const std::string reserved;
static const std::string someLegal;
static const std::string allLegal;
public:
/**
* Default Constructor, same as calling a Constructor with all fields empty.
*/
URI();
/**
* Constructs a URI as a copy of another URI
*
* @param uri - uri to copy
*
* @throws URISyntaxException if the URI passed is malformed.
*/
URI(const URI& uri);
/**
* Constructs a URI from the given string.
*
* @param uri - string uri to parse.
*
* @throws URISyntaxException if the URI passed is malformed.
*/
URI(const std::string& uri);
/**
* Constructs a URI from the given components.
*
* @param scheme - the uri scheme
* @param ssp - Scheme specific part
* @param fragment - Fragment
*
* @throws URISyntaxException if the URI passed is malformed.
*/
URI(const std::string& scheme, const std::string& ssp, const std::string& fragment);
/**
* Constructs a URI from the given components.
*
* @param scheme - Scheme name
* @param userInfo - User name and authorization information
* @param host - Host name
* @param port - Port number
* @param path - Path
* @param query - Query
* @param fragment - Fragment
*
* @throws URISyntaxException if the URI passed is malformed.
*/
URI(const std::string& scheme, const std::string& userInfo, const std::string& host, int port,
const std::string& path, const std::string& query, const std::string& fragment);
/**
* Constructs a URI from the given components.
* @param scheme - Scheme name
* @param host - Host name
* @param path - Path
* @param fragment - Fragment
*
* @throws URISyntaxException if the URI passed is malformed.
*/
URI(const std::string& scheme, const std::string& host,
const std::string& path, const std::string& fragment);
/**
* Constructs a URI from the given components.
* @param scheme - Scheme name
* @param authority - Authority
* @param path - Path
* @param query - Query
* @param fragment - Fragment
*
* @throws URISyntaxException if the URI passed is malformed.
*/
URI(const std::string& scheme, const std::string& authority,
const std::string& path, const std::string& query,
const std::string& fragment);
virtual ~URI() {}
/**
* Compares this object with the specified object for order. Returns a
* negative integer, zero, or a positive integer as this object is less
* than, equal to, or greater than the specified object.
* @param value - the value to compare to this one.
* @return zero if equal minus one if less than and one if greater than.
*/
virtual int compareTo(const URI& value) const;
/**
* @return true if this value is considered equal to the passed value.
*/
virtual bool equals(const URI& value) const;
/**
* Compares equality between this object and the one passed.
* @param value - the value to be compared to this one.
* @return true if this object is equal to the one passed.
*/
virtual bool operator==(const URI& value) const;
/**
* Compares this object to another and returns true if this object
* is considered to be less than the one passed. This
* @param value - the value to be compared to this one.
* @return true if this object is equal to the one passed.
*/
virtual bool operator<(const URI& value) const;
/**
* @return the decoded authority component of this URI.
*/
std::string getAuthority() const;
/**
* @return the decoded fragment component of this URI.
*/
std::string getFragment() const;
/**
* @return the host component of this URI.
*/
std::string getHost() const;
/**
* @return the path component of this URI.
*/
std::string getPath() const;
/**
* @return the port component of this URI.
*/
int getPort() const;
/**
* @return the query component of this URI.
*/
std::string getQuery() const;
/**
* @return the scheme component of this URI
*/
std::string getScheme() const;
/**
* @return the user info component of this URI
*/
std::string getUserInfo() const;
/**
* Returns the raw authority component of this URI.
*
* The authority component of a URI, if defined, only contains the
* commercial-at character ('@') and characters in the unreserved, punct,
* escaped, and other categories. If the authority is server-based then
* it is further constrained to have valid user-information, host, and
* port components.
*
* @return the raw authority component of the URI
*/
std::string getRawAuthority() const;
/**
* Returns the raw fragment component of this URI.
*
* The fragment component of a URI, if defined, only contains legal URI
* characters.
*
* @return the raw fragment component of this URI
*/
std::string getRawFragment() const;
/**
* Returns the raw path component of this URI.
*
* The path component of a URI, if defined, only contains the slash
* character ('/'), the commercial-at character ('@'), and characters
* in the unreserved, punct, escaped, and other categories.
*
* @return the raw path component of this URI
*/
std::string getRawPath() const;
/**
* Returns the raw query component of this URI.
*
* The query component of a URI, if defined, only contains legal URI characters.
*
* @return the raw query component of the URI.
*/
std::string getRawQuery() const;
/**
* Returns the raw scheme-specific part of this URI. The scheme-specific
* part is never undefined, though it may be empty.
*
* The scheme-specific part of a URI only contains legal URI characters.
*
* @return the raw scheme special part of the uri
*/
std::string getRawSchemeSpecificPart() const;
/**
* Returns the decoded scheme-specific part of this URI.
* The string returned by this method is equal to that returned by the
* getRawSchemeSpecificPart method except that all sequences of escaped
* octets are decoded.
*
* @return the raw scheme specific part of the uri.
*/
std::string getSchemeSpecificPart() const;
/**
* Returns the raw user-information component of this URI.
* The user-information component of a URI, if defined, only contains
* characters in the unreserved, punct, escaped, and other categories.
*
* @return the raw user-information component of the URI
*/
std::string getRawUserInfo() const;
/**
* Tells whether or not this URI is absolute. A URI is absolute if,
* and only if, it has a scheme component.
*
* @return true if, and only if, this URI is absolute
*/
bool isAbsolute() const;
/**
* Tells whether or not this URI is opaque. A URI is opaque if, and only
* if, it is absolute and its scheme-specific part does not begin with a
* slash character ('/'). An opaque URI has a scheme, a scheme-specific
* part, and possibly a fragment; all other components are undefined.
*
* @return true if, and only if, this URI is opaque
*/
bool isOpaque() const;
/**
* Normalizes this URI's path. If this URI is opaque, or if its path is
* already in normal form, then this URI is returned. Otherwise a new URI
* is constructed that is identical to this URI except that its path is
* computed by normalizing this URI's path in a manner consistent with
* RFC 2396, section 5.2, step 6, sub-steps c through f; that is:
*
* 1. All "." segments are removed.
* 2. If a ".." segment is preceded by a non-".." segment then both of
* these segments are removed. This step is repeated until it is no
* longer applicable.
* 3. If the path is relative, and if its first segment contains a colon
* character (':'), then a "." segment is prepended. This prevents a
* relative URI with a path such as "a:b/c/d" from later being re-parsed
* as an opaque URI with a scheme of "a" and a scheme-specific part of
* "b/c/d". (Deviation from RFC 2396)
*
* A normalized path will begin with one or more ".." segments if there were
* insufficient non-".." segments preceding them to allow their removal. A
* normalized path will begin with a "." segment if one was inserted by step
* 3 above. Otherwise, a normalized path will not contain any "." or ".."
* segments.
*
* @return A URI equivalent to this URI, but whose path is in normal form
*/
URI normalize() const;
/**
* Attempts to parse this URI's authority component, if defined, into
* user-information, host, and port components.
*
* If this URI's authority component has already been recognized as being
* server-based then it will already have been parsed into user-information,
* host, and port components. In this case, or if this URI has no authority
* component, this method simply returns this URI.
*
* Otherwise this method attempts once more to parse the authority component
* into user-information, host, and port components, and throws an exception
* describing why the authority component could not be parsed in that way.
*
* @return A URI whose authority field has been parsed as a server-based
* authority
*
* @throws URISyntaxException If the authority component of this URI is
* defined but cannot be parsed as a server-based authority.
*/
URI parseServerAuthority() const;
/**
* Relativizes the given URI against this URI. The relativization of the
* given URI against this URI is computed as follows:
*
* 1. If either this URI or the given URI are opaque, or if the scheme and
* authority components of the two URIs are not identical, or if the path
* of this URI is not a prefix of the path of the given URI, then the
* given URI is returned.
* 2. Otherwise a new relative hierarchical URI is constructed with query
* and fragment components taken from the given URI and with a path
* component computed by removing this URI's path from the beginning of
* the given URI's path.
*
* @param uri
* The URI to be relativized against this URI
*
* @return The resulting URI
*/
URI relativize(const URI& uri) const;
/**
* Constructs a new URI by parsing the given string and then resolving it
* against this URI.
*
* This convenience method works as if invoking it were equivalent to
* evaluating the expression resolve( URI::create( str ) ).
*
* @param str
* The string to be parsed into a URI
*
* @return The resulting URI
*
* @throws IllegalArgumentException - If the given string violates RFC 2396
*/
URI resolve(const std::string& str) const;
/**
* Resolves the given URI against this URI.
*
* If the given URI is already absolute, or if this URI is opaque, then a
* copy of the given URI is returned.
*
* If the given URI's fragment component is defined, its path component is
* empty, and its scheme, authority, and query components are undefined, then
* a URI with the given fragment but with all other components equal to those
* of this URI is returned. This allows a URI representing a standalone
* fragment reference, such as "#foo", to be usefully resolved against a base
* URI.
*
* Otherwise this method constructs a new hierarchical URI in a manner
* consistent with RFC 2396, section 5.2; that is:
*
* 1. A new URI is constructed with this URI's scheme and the given URI's
* query and fragment components.
* 2. If the given URI has an authority component then the new URI's authority
* and path are taken from the given URI.
* 3. Otherwise the new URI's authority component is copied from this URI,
* and its path is computed as follows:
*
* 1. If the given URI's path is absolute then the new URI's path is
* taken from the given URI.
* 2. Otherwise the given URI's path is relative, and so the new URI's
* path is computed by resolving the path of the given URI against the
* path of this URI. This is done by concatenating all but the last
* segment of this URI's path, if any, with the given URI's path and
* then normalizing the result as if by invoking the normalize method.
*
* The result of this method is absolute if, and only if, either this URI is
* absolute or the given URI is absolute.
*
* @param uri
* The URI to be resolved against this URI
*
* @return The resulting URI
*/
URI resolve(const URI& uri) const;
/**
* Returns the content of this URI as a string.
*
* If this URI was created by invoking one of the constructors in this class
* then a string equivalent to the original input string, or to the string
* computed from the originally-given components, as appropriate, is returned.
* Otherwise this URI was created by normalization, resolution, or
* relativization, and so a string is constructed from this URI's components
* according to the rules specified in RFC 2396, section 5.2, step 7.
*
* @return the string form of this URI
*/
std::string toString() const;
/**
* Constructs a URL from this URI.
*
* This convenience method works as if invoking it were equivalent to
* evaluating the expression new URL(this.toString()) after first checking
* that this URI is absolute.
*
* @return A URL constructed from this URI
*
* @throws IllegalArgumentException - If this URL is not absolute
* @throws MalformedURLException - If a protocol handler for the URL could not
* be found, or if some other error occurred while constructing the URL
*/
URL toURL() const;
public: // Static Methods
/**
* Creates a URI by parsing the given string.
* This convenience factory method works as if by invoking the URI(string)
* constructor; any URISyntaxException thrown by the constructor is caught
* and wrapped in a new IllegalArgumentException object, which is then thrown.
*
* @param uri - URI string to parse
*
* @throws IllegalArgumentException
*/
static URI create(const std::string uri);
private:
/**
* Parses a URI string and fills in the member data, throws a
* URISyntaxException if things fail.
*
* @param uri - the URI to parse
* @param forceServer - should a server authority be enforced.
* @throws URISyntaxException if an error occurs.
*/
void parseURI(const std::string& uri, bool forceServer);
/*
* Quote illegal chars for each component, but not the others
*
* @param component the component to be converted
* @param legalset the legal character set allowed in the component strng
* @return the converted string
*/
std::string quoteComponent(const std::string& component, const std::string& legalset);
/*
* Encode Unicode chars that are not part of US-ASCII char set into the
* escaped form
*
* i.e. The Euro currency symbol is encoded as "%E2%82%AC".
*
* @param src the string to be encoded
* @return the converted string
*/
std::string encodeOthers(const std::string& src) const;
/**
* Decode an encoded URI String.
*
* @param src - the encoded string
* @return the unencoded string version of src.
*/
std::string decode(const std::string& src) const;
/**
* Compare the Two Hexadecimal encoded strings and return if they are equal.
*
* @param first - First String to compare.
* @param second - The second string to compare.
*/
bool equalsHexCaseInsensitive(const std::string& first, const std::string& second) const;
/*
* Takes a string that may contain hex sequences like %F1 or %2b and
* converts the hex values following the '%' to lowercase.
*
* @param s - String to convert the hex in.
*/
std::string convertHexToLowerCase(const std::string& s) const;
/*
* Normalize path, and return the resulting string.
*
* @param path - the path value to normalize.
*/
std::string normalize(const std::string& path) const;
/**
* Helper method used to re-calculate the scheme specific part of the
* resolved or normalized URIs
*/
void setSchemeSpecificPart();
};
}}
#endif /*_DECAF_NET_URI_H_*/