1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.Windsor
.Configuration
.Interpreters
19 using System
.Configuration
;
20 using Castle
.Core
.Configuration
.Xml
;
21 using Castle
.Core
.Resource
;
22 using Castle
.Core
.Configuration
;
24 using Castle
.MicroKernel
;
25 using Castle
.MicroKernel
.SubSystems
.Resource
;
27 using Castle
.Windsor
.Configuration
.Interpreters
.XmlProcessor
;
30 /// Reads the configuration from a XmlFile. Sample structure:
32 /// <configuration>
33 /// <facilities>
34 /// <facility id="myfacility">
37 /// </facilities>
39 /// <components>
40 /// <component id="component1">
42 /// </component>
43 /// </components>
44 /// </configuration>
47 public class XmlInterpreter
: AbstractInterpreter
49 private IKernel kernel
;
54 /// Initializes a new instance of the <see cref="XmlInterpreter"/> class.
56 public XmlInterpreter()
61 /// Initializes a new instance of the <see cref="XmlInterpreter"/> class.
63 /// <param name="filename">The filename.</param>
64 public XmlInterpreter(String filename
) : base(filename
)
69 /// Initializes a new instance of the <see cref="XmlInterpreter"/> class.
71 /// <param name="source">The source.</param>
72 public XmlInterpreter(Castle
.Core
.Resource
.IResource source
) : base(source
)
79 /// Gets or sets the kernel.
81 /// <value>The kernel.</value>
84 get { return kernel ; }
85 set { kernel = value; }
88 public override void ProcessResource(IResource source
, IConfigurationStore store
)
90 XmlProcessor
.XmlProcessor processor
= (kernel
== null) ?
91 new XmlProcessor
.XmlProcessor(EnvironmentName
) :
92 new XmlProcessor
.XmlProcessor(EnvironmentName
,
93 kernel
.GetSubSystem(SubSystemConstants
.ResourceKey
) as IResourceSubSystem
);
97 XmlNode element
= processor
.Process(source
);
99 Deserialize(element
, store
);
101 catch(XmlProcessorException
)
103 string message
= "Unable to process xml resource ";
105 throw new ConfigurationErrorsException(message
);
109 protected void Deserialize(XmlNode section
, IConfigurationStore store
)
111 foreach(XmlNode node
in section
)
113 if (XmlConfigurationDeserializer
.IsTextNode(node
))
115 string message
= String
.Format("{0} cannot contain text nodes", node
.Name
);
117 throw new ConfigurationErrorsException(message
);
119 else if (node
.NodeType
== XmlNodeType
.Element
)
121 DeserializeElement(node
, store
);
126 private void DeserializeElement(XmlNode node
, IConfigurationStore store
)
128 if (ContainersNodeName
.Equals(node
.Name
))
130 DeserializeContainers(node
.ChildNodes
, store
);
132 else if (FacilitiesNodeName
.Equals(node
.Name
))
134 DeserializeFacilities(node
.ChildNodes
, store
);
136 else if (ComponentsNodeName
.Equals(node
.Name
))
138 DeserializeComponents(node
.ChildNodes
, store
);
140 else if (BootstrapNodeName
.Equals(node
.Name
))
142 DeserializeBootstrapComponents(node
.ChildNodes
, store
);
146 string message
= string.Format(
147 "Configuration parser encountered <{0}>, but it was expecting to find " +
148 "<{1}>, <{2}>, <{3}> or <{4}>. There might be either a typo on <{0}> or " +
149 "you might have forgotten to nest it properly.",
150 node
.Name
, ContainersNodeName
, FacilitiesNodeName
, ComponentsNodeName
, BootstrapNodeName
);
151 throw new ConfigurationErrorsException(message
);
155 private void DeserializeContainers(XmlNodeList nodes
, IConfigurationStore store
)
157 foreach(XmlNode node
in nodes
)
159 if (node
.NodeType
== XmlNodeType
.Element
)
161 AssertNodeName(node
, ContainerNodeName
);
163 DeserializeContainer(node
, store
);
168 private void DeserializeContainer(XmlNode node
, IConfigurationStore store
)
170 String name
= GetRequiredAttributeValue(node
, "name");
172 IConfiguration config
= XmlConfigurationDeserializer
.GetDeserializedNode(node
);
173 IConfiguration newConfig
= new MutableConfiguration(config
.Name
, node
.InnerXml
);
175 // Copy all attributes
176 string[] allKeys
= config
.Attributes
.AllKeys
;
178 foreach(string key
in allKeys
)
180 newConfig
.Attributes
.Add(key
, config
.Attributes
[key
]);
184 newConfig
.Children
.AddRange(config
.Children
);
186 AddChildContainerConfig(name
, newConfig
, store
);
189 private void DeserializeFacilities(XmlNodeList nodes
, IConfigurationStore store
)
191 foreach(XmlNode node
in nodes
)
193 if (node
.NodeType
== XmlNodeType
.Element
)
195 AssertNodeName(node
, FacilityNodeName
);
197 DeserializeFacility(node
, store
);
202 private void DeserializeFacility(XmlNode node
, IConfigurationStore store
)
204 String id
= GetRequiredAttributeValue(node
, "id");
206 IConfiguration config
= XmlConfigurationDeserializer
.GetDeserializedNode(node
);
208 AddFacilityConfig(id
, config
, store
);
211 private void DeserializeComponents(XmlNodeList nodes
, IConfigurationStore store
)
213 foreach(XmlNode node
in nodes
)
215 if (node
.NodeType
== XmlNodeType
.Element
)
217 AssertNodeName(node
, ComponentNodeName
);
219 DeserializeComponent(node
, store
);
224 private void DeserializeBootstrapComponents(XmlNodeList nodes
, IConfigurationStore store
)
226 foreach(XmlNode node
in nodes
)
228 if (node
.NodeType
== XmlNodeType
.Element
)
230 AssertNodeName(node
, ComponentNodeName
);
232 DeserializeBootstrapComponent(node
, store
);
237 private void DeserializeComponent(XmlNode node
, IConfigurationStore store
)
239 String id
= GetRequiredAttributeValue(node
, "id");
241 IConfiguration config
= XmlConfigurationDeserializer
.GetDeserializedNode(node
);
243 AddComponentConfig(id
, config
, store
);
246 private void DeserializeBootstrapComponent(XmlNode node
, IConfigurationStore store
)
248 String id
= GetRequiredAttributeValue(node
, "id");
250 IConfiguration config
= XmlConfigurationDeserializer
.GetDeserializedNode(node
);
252 AddBootstrapComponentConfig(id
, config
, store
);
255 private String
GetRequiredAttributeValue(XmlNode node
, String attName
)
257 String
value = GetAttributeValue(node
, attName
);
259 if (value.Length
== 0)
261 String message
= String
.Format("{0} elements expects required non blank attribute {1}",
264 throw new ConfigurationErrorsException(message
);
270 private String
GetAttributeValue(XmlNode node
, String attName
)
272 XmlAttribute att
= node
.Attributes
[attName
];
274 return (att
== null) ? String
.Empty
: att
.Value
.Trim();
277 private void AssertNodeName(XmlNode node
, string expectedName
)
279 if (!expectedName
.Equals(node
.Name
))
281 String message
= String
.Format("Unexpected node under '{0}': Expected '{1}' but found '{2}'",
282 expectedName
, expectedName
, node
.Name
);
284 throw new ConfigurationErrorsException(message
);