Permalink
Browse files

-fixed action header for soap12 requests to contain action rather tha…

…n operation;

-added namespace registry to allow for wsdl inline schemas in different namespaces
  • Loading branch information...
kdcircle committed Jul 6, 2012
1 parent 38df2eb commit 32d4de14439ed937ee128e7e9532903919e1e2de
Showing with 66 additions and 16 deletions.
  1. +66 −16 src/yaws_soap12_lib.erl
View
@@ -46,8 +46,11 @@
-record(yaws_soap_config, {atts, xsd_path, user_module, wsdl_file, add_files}).
-record(xsd_file, {atts, name, prefix, import_specs}).
-record(import_specs, {atts, namespace, prefix, location}).
+-record(namespace_spec, {namespace, prefix}).
+-record(namespace_registry, {specs = [], counter = 0}).
-define(DefaultPrefix, "p").
+-define(CustomPrefix, "cp").
%%%
@@ -235,7 +238,7 @@ call_attach(#wsdl{operations = Operations, model = Model},
{ok, XmlMessage} ->
{ContentType, Request} =
- make_request_body(XmlMessage, Attachments, Operation),
+ make_request_body(XmlMessage, Attachments, Action),
HttpClientOptions = [],
?dbg("+++ Request = ~p~n", [Request]),
HttpRes = http_request(URL, Action, Request,
@@ -369,66 +372,113 @@ initModel2(WsdlFile, ErlsomOptions, Path, Import, AddFiles) ->
%%% Parse a list of WSDLs and import (recursively)
%%% Returns {Model, Operations}
%%% --------------------------------------------------------------------
-parseWsdls([], _WsdlModel, _Options, Acc) ->
+parseWsdls(WsdlFiles, WsdlModel, Options, Acc) ->
+ parseWsdls(WsdlFiles, WsdlModel, Options, Acc, #namespace_registry{}).
+
+parseWsdls([], _WsdlModel, _Options, Acc, _NSRegistry) ->
Acc;
-parseWsdls([WsdlFile | Tail], WsdlModel, Options, {AccModel, AccOperations}) ->
+parseWsdls([WsdlFile | Tail], WsdlModel, Options, {AccModel, AccOperations}, NSRegistry) ->
WsdlFileNoSpaces = rmsp(WsdlFile),
{ok, WsdlFileContent} = get_url_file(WsdlFileNoSpaces),
{ok, ParsedWsdl, _} = erlsom:scan(WsdlFileContent, WsdlModel),
+ WsdlTargetNameSpace = getTargetNamespaceFromWsdl(ParsedWsdl),
+ {Prefix, PrefixlessOptions} = remove_prefix_option(Options),
+ TNSEnrichedNSRegistry = extend_namespace_registry(WsdlTargetNameSpace, Prefix, NSRegistry),
%% get the xsd elements from this model, and hand it over to erlsom_compile.
Xsds = getXsdsFromWsdl(ParsedWsdl),
%% Now we need to build a list: [{Namespace, Xsd, Prefix}, ...] for
%% all the Xsds in the WSDL.
%% This list is used when a schema includes one of the other schemas.
%% The AXIS java2wsdl tool generates wsdls that depend on this feature.
- ImportList = makeImportList(Xsds, []),
- Model2 = addSchemas(Xsds, AccModel, Options, ImportList),
+ {ImportsEnrichedNSRegistry, ImportList} = makeImportList(Xsds, TNSEnrichedNSRegistry, []),
+ Model2 = addSchemas(Xsds, AccModel, PrefixlessOptions, ImportList),
Ports = getPorts(ParsedWsdl),
Operations = getOperations(ParsedWsdl, Ports),
Imports = getImports(filename:dirname(WsdlFileNoSpaces), ParsedWsdl),
+ %% use Options rather than PrefixlessOptions because imports come in the wsdl targetNamespace
Model3 = addSchemaFiles(Imports, Model2, Options, []),
Acc2 = {Model3, Operations ++ AccOperations},
%% process imports (recursively, so that imports in the imported files are
%% processed as well).
%% For the moment, the namespace is ignored on operations etc.
%% this makes it a bit easier to deal with imported wsdl's.
%% TODO uncomment if imports can be WSDL
- %%Acc3 = parseWsdls(Imports, WsdlModel, Options, Acc2),
- parseWsdls(Tail, WsdlModel, Options, Acc2).
+ %%Acc3 = parseWsdls(Imports, WsdlModel, Options, Acc2, ImportsEnrichedNSRegistry),
+ parseWsdls(Tail, WsdlModel, PrefixlessOptions, Acc2, ImportsEnrichedNSRegistry).
+
+remove_prefix_option(Options) ->
+ case lists:keytake(prefix, 1, Options) of
+ {value, {prefix, Prefix}, NewOptions} ->
+ {Prefix, NewOptions};
+ false ->
+ {undefined, Options}
+ end.
+
+%empty registry, initializing
+extend_namespace_registry(WsdlTargetNameSpace, undefined, #namespace_registry{specs = []} = NSRegistry) ->
+ {NewCounter, NewPrefix} = create_unique_prefix(NSRegistry),
+ NSRegistry#namespace_registry{specs = [#namespace_spec{namespace = WsdlTargetNameSpace, prefix = NewPrefix}], counter = NewCounter};
+extend_namespace_registry(WsdlTargetNameSpace, Prefix, #namespace_registry{specs = []} = NSRegistry) ->
+ NSRegistry#namespace_registry{specs = [#namespace_spec{namespace = WsdlTargetNameSpace, prefix = Prefix}]};
+extend_namespace_registry(WsdlTargetNameSpace, _Prefix, #namespace_registry{specs = Specs} = NSRegistry) ->
+ case lists:keyfind(WsdlTargetNameSpace, #namespace_spec.namespace, Specs) of
+ #namespace_spec{} ->
+ NSRegistry;
+ false ->
+ {NewCounter, NewPrefix} = create_unique_prefix(NSRegistry),
+ NSRegistry#namespace_registry{specs = [#namespace_spec{namespace = WsdlTargetNameSpace, prefix = NewPrefix}|Specs], counter = NewCounter}
+ end.
+
+create_unique_prefix(#namespace_registry{specs = Specs, counter = Counter} = NSRegistry) ->
+ NewCounter = Counter+1,
+ NewPrefix = ?CustomPrefix ++ integer_to_list(NewCounter),
+ case lists:keyfind(NewPrefix, #namespace_spec.prefix, Specs) of
+ #namespace_spec{} ->
+ create_unique_prefix(NSRegistry#namespace_registry{counter = Counter+1});
+ false ->
+ {NewCounter, NewPrefix}
+ end.
%%% --------------------------------------------------------------------
%%% build a list: [{Namespace, Xsd}, ...] for all the Xsds in the WSDL.
%%% This list is used when a schema inlcudes one of the other schemas.
%%% The AXIS java2wsdl tool generates wsdls that depend on this feature.
-makeImportList([], Acc) ->
- Acc;
-makeImportList([ Xsd | Tail], Acc) ->
- makeImportList(Tail, [{erlsom_lib:getTargetNamespaceFromXsd(Xsd),
- undefined, Xsd} | Acc]).
+makeImportList([], NSRegistry, Acc) ->
+ {NSRegistry, Acc};
+makeImportList([ Xsd | Tail], NSRegistry, Acc) ->
+ XsdNS = erlsom_lib:getTargetNamespaceFromXsd(Xsd),
+ NewNSRegistry = extend_namespace_registry(XsdNS, undefined, NSRegistry),
+ #namespace_spec{prefix = Prefix} =
+ lists:keyfind(XsdNS, #namespace_spec.namespace, NewNSRegistry#namespace_registry.specs),
+ makeImportList(Tail, NewNSRegistry, [{XsdNS, Prefix, Xsd} | Acc]).
+getTargetNamespaceFromWsdl(#'wsdl:tDefinitions'{targetNamespace = TNS}) ->
+ TNS.
%%% --------------------------------------------------------------------
%%% compile each of the schemas, and add it to the model.
%%% Returns Model
%%% (TODO: using the same prefix for all XSDS makes no sense)
%%% --------------------------------------------------------------------
-addSchemas([], AccModel, _Options, _ImportList) ->
+addSchemas([], AccModel, _PrefixlessOptions, _ImportList) ->
AccModel;
-addSchemas([Xsd| Tail], AccModel, Options, ImportList) ->
+addSchemas([Xsd| Tail], AccModel, PrefixlessOptions, ImportList) ->
Model2 = case Xsd of
undefined ->
AccModel;
_ ->
+ {_, Prefix, _} = lists:keyfind(erlsom_lib:getTargetNamespaceFromXsd(Xsd), 1, ImportList),
+ NewOptions = [{prefix, Prefix}|PrefixlessOptions],
{ok, Model} =
erlsom_compile:compile_parsed_xsd(
Xsd,
- [{include_files, ImportList} |Options]),
+ [{include_files, ImportList} |NewOptions]),
case AccModel of
undefined -> Model;
_ -> erlsom:add_model(AccModel, Model)
end
end,
- addSchemas(Tail, Model2, Options, ImportList).
+ addSchemas(Tail, Model2, PrefixlessOptions, ImportList).
%%% --------------------------------------------------------------------
%%% compile each of the schema files, and add it to the model.

0 comments on commit 32d4de1

Please sign in to comment.