libzypp 17.37.1
MediaHandlerFactory.cc
Go to the documentation of this file.
2
3#include <zypp-core/APIConfig.h>
4#include <zypp/base/Logger.h>
5#include <zypp/base/Env.h>
6
7#include <zypp-media/MediaException>
9
10#include <zypp/media/MediaNFS.h>
11#include <zypp/media/MediaCD.h>
12#include <zypp/media/MediaDIR.h>
17#include <zypp/media/MediaISO.h>
20
21namespace zypp::media {
22
27
28 std::optional<MediaHandlerFactory::MediaHandlerType> MediaHandlerFactory::handlerType(const Url &url)
29 {
30 std::string scheme = url.getScheme();
31 if (scheme == "cd" || scheme == "dvd")
32 return MediaCDType;
33 else if (scheme == "nfs" || scheme == "nfs4")
34 return MediaNFSType;
35 else if (scheme == "iso")
36 return MediaISOType;
37 else if (scheme == "file" || scheme == "dir")
38 return MediaFileType;
39 else if (scheme == "hd" )
40 return MediaDISKType;
41 else if (scheme == "cifs" || scheme == "smb")
42 return MediaCIFSType;
43 else if (scheme == "ftp" || scheme == "tftp" || scheme == "http" || scheme == "https")
44 return MediaCURLType;
45 else if (scheme == "plugin" )
46 return MediaPluginType;
47 return {};
48 }
49
50 std::unique_ptr<MediaHandler> MediaHandlerFactory::createHandler(const std::vector<MediaUrl> &o_url, const Pathname &preferred_attach_point )
51 {
52 if ( o_url.empty() ) {
53 MIL << "Url list is empty" << std::endl;
54 ZYPP_THROW(MediaException("Can not create a MediaHandler without a Url."));
55 }
56
57 std::optional<MediaUrl> primary; // primary URL, this one dictates the initial schmeme and so the handler to be used
58 std::vector<MediaUrl> resolved; // all Mirrors
59 std::optional<MediaHandlerFactory::MediaHandlerType> hdlType; // Handler type as detected from primary
60 std::for_each( o_url.begin (), o_url.end(), [&]( const MediaUrl &u ){
61
62 if( !u.url().isValid() ) {
63 MIL << "Url is not valid" << std::endl;
64 ZYPP_THROW(MediaBadUrlException(u.url()));
65 }
66
67 UrlResolverPlugin::HeaderList custom_headers;
68 if ( u.hasConfig("http-headers") )
69 custom_headers = u.getConfig<UrlResolverPlugin::HeaderList>( "http-headers" );
70
71 Url url = UrlResolverPlugin::resolveUrl(u.url(), custom_headers);
72 MIL << "Trying scheme '" << url.getScheme() << "'" << std::endl;
73
74 auto myHdlType = handlerType( url );
75 if ( !myHdlType ) {
77 }
78 if ( !hdlType )
79 hdlType = myHdlType;
80 else if ( myHdlType != hdlType ) {
81 // we ignore if we have a Url handler different than the primary one
82 // Urls should be grouped by type already from the calling code
83 MIL << "Different handler type than primary URL, ignoring" << std::endl;
84 return;
85 }
86
87 MediaUrl newUrl( url, u.config()) ; // keep settings that were passed in
88 if ( !custom_headers.empty () ) {
89 newUrl.setConfig ( "http-headers", std::move(custom_headers) );
90 }
91
92 if ( !primary )
93 primary = newUrl;
94
95 resolved.push_back (std::move(newUrl));
96 });
97
98 // should not happen, we will at least always have the primary Url here.
99 // But for completeness we check
100 if ( !primary ) {
101 ZYPP_THROW(MediaException("No valid Url left after resolving."));
102 }
103
104 if ( resolved.size() > 1 && *hdlType != MediaCURLType )
105 ERR << "Got mirrors for handler type: " << *hdlType << " they will be ignored!" << std::endl;
106
107 std::unique_ptr<MediaHandler> _handler;
108 switch(*hdlType) {
109 case MediaCDType: {
110 _handler = std::make_unique<MediaCD> (*primary,preferred_attach_point);
111 break;
112 }
113 case MediaNFSType: {
114 _handler = std::make_unique<MediaNFS> (*primary,preferred_attach_point);
115 break;
116 }
117 case MediaISOType: {
118 _handler = std::make_unique<MediaISO> (*primary,preferred_attach_point);
119 break;
120 }
121 case MediaFileType: {
122 _handler = std::make_unique<MediaDIR> (*primary,preferred_attach_point);
123 break;
124 }
125 case MediaDISKType: {
126 _handler = std::make_unique<MediaDISK> (*primary,preferred_attach_point);
127 break;
128 }
129 case MediaCIFSType: {
130 _handler = std::make_unique<MediaCIFS> (*primary,preferred_attach_point);
131 break;
132 }
133 case MediaCURLType: {
134 enum WhichHandler { choose, curl, curl2 };
135 WhichHandler which = choose;
136 // Leagcy: choose handler in Url query
137 if ( const std::string & queryparam = primary->url().getQueryParam("mediahandler"); ! queryparam.empty() ) {
138 if ( queryparam == "curl" )
139 which = curl;
140 else if ( queryparam == "curl2" )
141 which = curl2;
142 else if ( queryparam == "network" || queryparam == "multicurl" )
143 which = choose; // old backends, choose default
144 else
145 WAR << "Unknown mediahandler='" << queryparam << "' in URL; Choosing the default" << std::endl;
146 }
147 // Otherwise choose handler through ENV
148 if ( which == choose ) {
149 TriBool envstate = env::getenvBool( "ZYPP_CURL2" );
150 if ( indeterminate(envstate) ) {
151#if APIConfig(LIBZYPP_CONFIG_USE_LEGACY_CURL_BACKEND_BY_DEFAULT)
152 which = curl;
153#else
154 which = curl2;
155#endif
156 } else {
157 which = bool(envstate) ? curl2 : curl;
158 }
159 }
160 // Finally use the default
161 std::unique_ptr<MediaNetworkCommonHandler> handler;
162 switch ( which ) {
163 default:
164 case curl2:
165 handler = std::make_unique<MediaCurl2>( *primary, resolved, preferred_attach_point );
166 break;
167 case curl:
168 handler = std::make_unique<MediaCurl>( *primary, resolved, preferred_attach_point );
169 break;
170 }
171 _handler = std::move(handler);
172 break;
173 }
174 case MediaPluginType: {
175 // bsc#1228208: MediaPluginType must be resolved to a valid schema by the
176 // above UrlResolverPlugin::resolveUrl call. MediaPlugin exists as a stub,
177 // but is not a usable handler type.
179 break;
180 }
181 }
182
183 if ( !_handler ) {
185 }
186
187 // check created handler
188 if ( !_handler ){
189 ERR << "Failed to create media handler" << std::endl;
190 ZYPP_THROW(MediaSystemException(primary->url(), "Failed to create media handler"));
191 }
192
193 MIL << "Opened: " << *_handler << std::endl;
194 return _handler;
195 }
196
197}
Url manipulation class.
Definition Url.h:93
Just inherits Exception to separate media exceptions.
static std::unique_ptr< MediaHandler > createHandler(const std::vector< MediaUrl > &o_url, const Pathname &preferred_attach_point)
static std::optional< MediaHandlerType > handlerType(const Url &url)
std::multimap< std::string, std::string > HeaderList
static Url resolveUrl(const Url &url, HeaderList &headers)
Resolves an url using the installed plugins If no plugin is found the url is resolved as its current ...
TriBool getenvBool(const C_Str &var_r)
If the environment variable var_r is set to a legal true or false string return bool,...
Definition Env.h:32
Url details namespace.
Definition UrlBase.cc:58
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition String.h:31
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
#define MIL
Definition Logger.h:100
#define ERR
Definition Logger.h:102
#define WAR
Definition Logger.h:101