blob: 57b17e6a57cc2c1e51b76e34ea0c2a66a13af748 [file] [log] [blame]
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Carsten Ziegelerefdde672007-08-20 07:33:20 +000019package org.apache.felix.scrplugin.xml;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +000020
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +000021import java.awt.Component;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +000022import java.io.File;
23import java.io.IOException;
24import java.io.InputStream;
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +000025import java.security.Provider.Service;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +000026import java.util.ArrayList;
27import java.util.List;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +000028import java.util.StringTokenizer;
29
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +000030import javax.xml.transform.TransformerException;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +000031
Felix Meschberger1fd58292009-10-02 12:59:27 +000032import org.apache.felix.scrplugin.SCRDescriptorException;
Carsten Ziegeler44ee8942012-06-14 15:03:37 +000033import org.apache.felix.scrplugin.SpecVersion;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +000034import org.apache.felix.scrplugin.description.ClassDescription;
35import org.apache.felix.scrplugin.description.ComponentConfigurationPolicy;
36import org.apache.felix.scrplugin.description.ComponentDescription;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +000037import org.apache.felix.scrplugin.description.PropertyDescription;
38import org.apache.felix.scrplugin.description.PropertyType;
Carsten Ziegeler61a12e22012-07-03 09:33:50 +000039import org.apache.felix.scrplugin.description.PropertyUnbounded;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +000040import org.apache.felix.scrplugin.description.ReferenceCardinality;
41import org.apache.felix.scrplugin.description.ReferenceDescription;
42import org.apache.felix.scrplugin.description.ReferencePolicy;
Carsten Ziegelerd156e362012-06-14 15:34:11 +000043import org.apache.felix.scrplugin.description.ReferencePolicyOption;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +000044import org.apache.felix.scrplugin.description.ReferenceStrategy;
45import org.apache.felix.scrplugin.description.ServiceDescription;
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +000046import org.apache.felix.scrplugin.helper.ComponentContainer;
47import org.apache.felix.scrplugin.helper.DescriptionContainer;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +000048import org.apache.felix.scrplugin.helper.IssueLog;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +000049import org.xml.sax.Attributes;
50import org.xml.sax.ContentHandler;
51import org.xml.sax.SAXException;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +000052import org.xml.sax.helpers.AttributesImpl;
53import org.xml.sax.helpers.DefaultHandler;
54
55/**
56 * <code>ComponentDescriptorIO</code>
57 *
58 * is a helper class to read and write component descriptor files.
59 *
60 */
61public class ComponentDescriptorIO {
62
Carsten Ziegeler482c3302012-07-03 09:58:43 +000063 private static final String PROPERTY_ATTR_TYPE = "type";
64
Carsten Ziegeler61a12e22012-07-03 09:33:50 +000065 /** General attribute for the name (component, reference, property) */
66 private static final String ATTR_NAME = "name";
67
68 private static final String ATTR_CARDINALITY = "cardinality";
69
70 private static final String ATTR_DESCRIPTION = "description";
71
72 private static final String ATTR_LABEL = "label";
73
Carsten Ziegelerc9325f72009-06-12 14:06:07 +000074 /** The inner namespace - used for all inner elements. */
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +000075 public static final String INNER_NAMESPACE_URI = "";
76
Carsten Ziegelerc9325f72009-06-12 14:06:07 +000077 /** The prefix used for the namespace. */
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +000078 private static final String PREFIX = "scr";
79
Carsten Ziegelerc9325f72009-06-12 14:06:07 +000080 /** The root element. */
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +000081 private static final String COMPONENTS = "components";
82
Carsten Ziegelerc9325f72009-06-12 14:06:07 +000083 /** The component element. */
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +000084 private static final String COMPONENT = "component";
85
Carsten Ziegelerc9325f72009-06-12 14:06:07 +000086 /** The qualified component element. */
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +000087 private static final String COMPONENT_QNAME = PREFIX + ':' + COMPONENT;
88
Carsten Ziegeler84fc4352009-06-12 14:11:02 +000089 /** The enabled attribute. */
90 private static final String COMPONENT_ATTR_ENABLED = "enabled";
91
Carsten Ziegeler35a53ef2009-06-12 14:48:14 +000092 /** Component: The policy attribute. */
Carsten Ziegelerc9325f72009-06-12 14:06:07 +000093 private static final String COMPONENT_ATTR_POLICY = "configuration-policy";
94
Carsten Ziegeler35a53ef2009-06-12 14:48:14 +000095 /** Component: The factory attribute. */
Carsten Ziegeler84fc4352009-06-12 14:11:02 +000096 private static final String COMPONENT_ATTR_FACTORY = "factory";
97
Carsten Ziegeler35a53ef2009-06-12 14:48:14 +000098 /** Component: The immediate attribute. */
Carsten Ziegeler84fc4352009-06-12 14:11:02 +000099 private static final String COMPONENT_ATTR_IMMEDIATE = "immediate";
100
Carsten Ziegeler51c4e862009-07-13 07:18:41 +0000101 /** Component: The activate attribute. */
Carsten Ziegeler35a53ef2009-06-12 14:48:14 +0000102 private static final String COMPONENT_ATTR_ACTIVATE = "activate";
103
Carsten Ziegeler51c4e862009-07-13 07:18:41 +0000104 /** Component: The deactivate attribute. */
Carsten Ziegeler35a53ef2009-06-12 14:48:14 +0000105 private static final String COMPONENT_ATTR_DEACTIVATE = "deactivate";
106
Carsten Ziegeler51c4e862009-07-13 07:18:41 +0000107 /** Component: The modified attribute. */
108 private static final String COMPONENT_ATTR_MODIFIED = "modified";
109
Carsten Ziegeler66005132012-06-14 15:48:32 +0000110 /** Component: The configuration pid attribute. */
111 private static final String COMPONENT_ATTR_CONFIGURATION_PID = "configuration-pid";
112
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000113 private static final String IMPLEMENTATION = "implementation";
114
Carsten Ziegelerd2df1a32008-08-22 12:19:56 +0000115 private static final String IMPLEMENTATION_QNAME = IMPLEMENTATION;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000116
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000117 private static final String IMPLEMENTATION_ATTR_CLASS = "class";
118
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000119 private static final String SERVICE = "service";
120
Carsten Ziegelerd2df1a32008-08-22 12:19:56 +0000121 private static final String SERVICE_QNAME = SERVICE;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000122
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000123 private static final String SERVICE_ATTR_FACTORY = "servicefactory";
124
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000125 private static final String PROPERTY = "property";
126
Carsten Ziegelerd2df1a32008-08-22 12:19:56 +0000127 private static final String PROPERTY_QNAME = PROPERTY;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000128
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000129 private static final String PROPERTY_ATTR_VALUE = "value";
130
Carsten Ziegeler482c3302012-07-03 09:58:43 +0000131 private static final String PROPERTY_ATTR_PRIVATE = "private";
132
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000133 private static final String REFERENCE = "reference";
134
Carsten Ziegelerd2df1a32008-08-22 12:19:56 +0000135 private static final String REFERENCE_QNAME = REFERENCE;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000136
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000137 private static final String REFERENCE_ATTR_POLICY = "policy";
138
139 private static final String REFERENCE_ATTR_POLICY_OPTION = "policy-option";
140
141 private static final String REFERENCE_ATTR_UPDATED = "updated";
142
143 private static final String REFERENCE_ATTR_UNBIND = "unbind";
144
145 private static final String REFERENCE_ATTR_BIND = "bind";
146
147 private static final String REFERENCE_ATTR_TARGET = "target";
148
Carsten Ziegeler482c3302012-07-03 09:58:43 +0000149 private static final String REFERENCE_ATTR_STRATEGY = "strategy";
150
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000151 private static final String INTERFACE = "provide";
152
Carsten Ziegelerd2df1a32008-08-22 12:19:56 +0000153 private static final String INTERFACE_QNAME = INTERFACE;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000154
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000155 private static final String INTERFACE_ATTR_NAME = "interface";
156
Carsten Ziegeler482c3302012-07-03 09:58:43 +0000157 private static final String PROPERTIES = "properties";
158
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000159 public static List<ClassDescription> read(final InputStream file,
160 final ClassLoader classLoader,
161 final IssueLog iLog, final String location) throws SCRDescriptorException {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000162 try {
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000163 final XmlHandler xmlHandler = new XmlHandler(classLoader, iLog, location);
Carsten Ziegeler1da03592007-08-24 07:27:04 +0000164 IOUtils.parse(file, xmlHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000165 return xmlHandler.components;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000166 } catch (final TransformerException e) {
Carsten Ziegeler9a8d32e2012-06-27 14:07:35 +0000167 throw new SCRDescriptorException("Unable to read xml", location, e);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000168 }
169 }
170
171 /**
172 * Write the component descriptors to the file.
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000173 *
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000174 * @param module
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000175 * @param file
Felix Meschberger1fd58292009-10-02 12:59:27 +0000176 * @throws SCRDescriptorException
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000177 */
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000178 public static void write(final DescriptionContainer module, final File file) throws SCRDescriptorException {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000179 try {
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000180 generateXML(module, IOUtils.getSerializer(file));
181 } catch (final TransformerException e) {
182 throw new SCRDescriptorException("Unable to write xml", file.toString(), e);
183 } catch (final SAXException e) {
184 throw new SCRDescriptorException("Unable to generate xml", file.toString(), e);
185 } catch (final IOException e) {
186 throw new SCRDescriptorException("Unable to write xml", file.toString(), e);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000187 }
188 }
189
190 /**
191 * Generate the xml top level element and start streaming
192 * the components.
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000193 *
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000194 * @param components
195 * @param contentHandler
196 * @throws SAXException
197 */
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000198 protected static void generateXML(final DescriptionContainer module,
Carsten Ziegeler66005132012-06-14 15:48:32 +0000199 final ContentHandler contentHandler) throws SAXException {
Carsten Ziegelerc9325f72009-06-12 14:06:07 +0000200 // detect namespace to use
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000201 final String namespace = module.getOptions().getSpecVersion().getNamespaceUrl();
Carsten Ziegeler98e992a2012-06-13 15:50:00 +0000202
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000203 contentHandler.startDocument();
Carsten Ziegelerc9325f72009-06-12 14:06:07 +0000204 contentHandler.startPrefixMapping(PREFIX, namespace);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000205
206 // wrapper element to generate well formed xml
207 contentHandler.startElement("", ComponentDescriptorIO.COMPONENTS, ComponentDescriptorIO.COMPONENTS, new AttributesImpl());
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000208 IOUtils.newline(contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000209
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000210 for (final ComponentContainer component : module.getComponents()) {
Carsten Ziegeler561e4e22012-06-27 06:38:28 +0000211 generateXML(namespace, module, component, contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000212 }
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000213
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000214 // end wrapper element
215 contentHandler.endElement("", ComponentDescriptorIO.COMPONENTS, ComponentDescriptorIO.COMPONENTS);
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000216 IOUtils.newline(contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000217 contentHandler.endPrefixMapping(PREFIX);
218 contentHandler.endDocument();
219 }
220
221 /**
222 * Write the xml for a {@link Component}.
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000223 *
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000224 * @param component
225 * @param contentHandler
226 * @throws SAXException
227 */
Carsten Ziegeler561e4e22012-06-27 06:38:28 +0000228 protected static void generateXML(final String namespace,
229 final DescriptionContainer module,
230 final ComponentContainer container,
231 final ContentHandler contentHandler)
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000232 throws SAXException {
233 final ComponentDescription component = container.getComponentDescription();
234
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000235 final AttributesImpl ai = new AttributesImpl();
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000236 IOUtils.addAttribute(ai, COMPONENT_ATTR_ENABLED, component.getEnabled());
237 IOUtils.addAttribute(ai, COMPONENT_ATTR_IMMEDIATE, component.getImmediate());
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000238 IOUtils.addAttribute(ai, ATTR_NAME, component.getName());
Carsten Ziegeler84fc4352009-06-12 14:11:02 +0000239 IOUtils.addAttribute(ai, COMPONENT_ATTR_FACTORY, component.getFactory());
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000240
Carsten Ziegelerc9325f72009-06-12 14:06:07 +0000241 // attributes new in 1.1
Carsten Ziegeler561e4e22012-06-27 06:38:28 +0000242 if (module.getOptions().getSpecVersion().ordinal() >= SpecVersion.VERSION_1_1.ordinal() ) {
Carsten Ziegeler133a6a42012-07-23 08:42:54 +0000243 if ( component.getConfigurationPolicy() != null
244 && component.getConfigurationPolicy() != ComponentConfigurationPolicy.OPTIONAL ) {
Carsten Ziegelerd156e362012-06-14 15:34:11 +0000245 IOUtils.addAttribute(ai, COMPONENT_ATTR_POLICY, component.getConfigurationPolicy().name().toLowerCase());
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000246 }
Carsten Ziegeler35a53ef2009-06-12 14:48:14 +0000247 IOUtils.addAttribute(ai, COMPONENT_ATTR_ACTIVATE, component.getActivate());
248 IOUtils.addAttribute(ai, COMPONENT_ATTR_DEACTIVATE, component.getDeactivate());
Carsten Ziegeler51c4e862009-07-13 07:18:41 +0000249 IOUtils.addAttribute(ai, COMPONENT_ATTR_MODIFIED, component.getModified());
Carsten Ziegelerc9325f72009-06-12 14:06:07 +0000250 }
Carsten Ziegeler66005132012-06-14 15:48:32 +0000251 // attributes new in 1.2
Carsten Ziegeler561e4e22012-06-27 06:38:28 +0000252 if ( module.getOptions().getSpecVersion().ordinal() >= SpecVersion.VERSION_1_2.ordinal() ) {
Carsten Ziegeler66005132012-06-14 15:48:32 +0000253 if ( component.getConfigurationPid() != null && !component.getConfigurationPid().equals(component.getName())) {
254 IOUtils.addAttribute(ai, COMPONENT_ATTR_CONFIGURATION_PID, component.getConfigurationPid());
255 }
256 }
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000257 IOUtils.indent(contentHandler, 1);
Carsten Ziegelerc9325f72009-06-12 14:06:07 +0000258 contentHandler.startElement(namespace, ComponentDescriptorIO.COMPONENT, ComponentDescriptorIO.COMPONENT_QNAME, ai);
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000259 IOUtils.newline(contentHandler);
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000260 generateImplementationXML(container, contentHandler);
261 if (container.getServiceDescription() != null) {
262 generateServiceXML(container.getServiceDescription(), contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000263 }
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000264 for (final PropertyDescription property : container.getProperties().values()) {
265 generatePropertyXML(property, contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000266 }
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000267
268 for (final ReferenceDescription reference : container.getReferences().values()) {
Carsten Ziegeler561e4e22012-06-27 06:38:28 +0000269 generateReferenceXML(component, module, reference, contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000270 }
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000271
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000272 IOUtils.indent(contentHandler, 1);
Carsten Ziegelerc9325f72009-06-12 14:06:07 +0000273 contentHandler.endElement(namespace, ComponentDescriptorIO.COMPONENT, ComponentDescriptorIO.COMPONENT_QNAME);
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000274 IOUtils.newline(contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000275 }
276
277 /**
278 * Write the xml for a {@link Implementation}.
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000279 *
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000280 * @param implementation
281 * @param contentHandler
282 * @throws SAXException
283 */
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000284 protected static void generateImplementationXML(ComponentContainer component, ContentHandler contentHandler) throws SAXException {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000285 final AttributesImpl ai = new AttributesImpl();
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000286 IOUtils.addAttribute(ai, IMPLEMENTATION_ATTR_CLASS, component.getClassDescription().getDescribedClass().getName());
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000287 IOUtils.indent(contentHandler, 2);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000288 contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.IMPLEMENTATION,
289 ComponentDescriptorIO.IMPLEMENTATION_QNAME, ai);
290 contentHandler.endElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.IMPLEMENTATION,
291 ComponentDescriptorIO.IMPLEMENTATION_QNAME);
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000292 IOUtils.newline(contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000293 }
294
295 /**
296 * Write the xml for a {@link Service}.
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000297 *
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000298 * @param service
299 * @param contentHandler
300 * @throws SAXException
301 */
Carsten Ziegeler44ee8942012-06-14 15:03:37 +0000302 protected static void generateServiceXML(
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000303 final ServiceDescription service,
Carsten Ziegeler44ee8942012-06-14 15:03:37 +0000304 final ContentHandler contentHandler)
305 throws SAXException {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000306 final AttributesImpl ai = new AttributesImpl();
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000307 IOUtils.addAttribute(ai, SERVICE_ATTR_FACTORY, String.valueOf(service.isServiceFactory()));
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000308 IOUtils.indent(contentHandler, 2);
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000309 contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.SERVICE, ComponentDescriptorIO.SERVICE_QNAME, ai);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000310 if (service.getInterfaces() != null && service.getInterfaces().size() > 0) {
Carsten Ziegelerfe62b032008-06-03 11:45:32 +0000311 IOUtils.newline(contentHandler);
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000312 for (final String interf : service.getInterfaces()) {
313 generateServiceXML(interf, contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000314 }
Carsten Ziegelerfe62b032008-06-03 11:45:32 +0000315 IOUtils.indent(contentHandler, 2);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000316 }
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000317 contentHandler.endElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.SERVICE, ComponentDescriptorIO.SERVICE_QNAME);
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000318 IOUtils.newline(contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000319 }
320
321 /**
322 * Write the xml for a {@link Interface}.
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000323 *
Carsten Ziegeler9e6bee02007-12-06 12:40:08 +0000324 * @param interf
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000325 * @param contentHandler
326 * @throws SAXException
327 */
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000328 private static void generateServiceXML(final String interfaceName, final ContentHandler contentHandler)
329 throws SAXException {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000330 final AttributesImpl ai = new AttributesImpl();
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000331 IOUtils.addAttribute(ai, INTERFACE_ATTR_NAME, interfaceName);
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000332 IOUtils.indent(contentHandler, 3);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000333 contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.INTERFACE, ComponentDescriptorIO.INTERFACE_QNAME,
334 ai);
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000335 contentHandler.endElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.INTERFACE, ComponentDescriptorIO.INTERFACE_QNAME);
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000336 IOUtils.newline(contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000337 }
338
339 /**
340 * Write the xml for a {@link Property}.
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000341 *
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000342 * @param property
343 * @param contentHandler
344 * @throws SAXException
345 */
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000346 protected static void generatePropertyXML(PropertyDescription property, ContentHandler contentHandler) throws SAXException {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000347 final AttributesImpl ai = new AttributesImpl();
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000348 IOUtils.addAttribute(ai, ATTR_NAME, property.getName());
Carsten Ziegeler0f368082012-07-02 10:57:16 +0000349 if ( property.getType() != PropertyType.String ) {
Carsten Ziegeler482c3302012-07-03 09:58:43 +0000350 IOUtils.addAttribute(ai, PROPERTY_ATTR_TYPE, property.getType());
Carsten Ziegeler0f368082012-07-02 10:57:16 +0000351 }
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000352 IOUtils.addAttribute(ai, PROPERTY_ATTR_VALUE, property.getValue());
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000353
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000354 IOUtils.indent(contentHandler, 2);
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000355 contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.PROPERTY, ComponentDescriptorIO.PROPERTY_QNAME, ai);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000356 if (property.getMultiValue() != null && property.getMultiValue().length > 0) {
Carsten Ziegeler57a58632007-08-28 16:03:34 +0000357 // generate a new line first
358 IOUtils.text(contentHandler, "\n");
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000359 for (int i = 0; i < property.getMultiValue().length; i++) {
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000360 IOUtils.indent(contentHandler, 3);
Carsten Ziegeler28ff2702007-08-28 15:40:03 +0000361 IOUtils.text(contentHandler, property.getMultiValue()[i]);
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000362 IOUtils.newline(contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000363 }
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000364 IOUtils.indent(contentHandler, 2);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000365 }
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000366 contentHandler.endElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.PROPERTY, ComponentDescriptorIO.PROPERTY_QNAME);
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000367 IOUtils.newline(contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000368 }
369
370 /**
371 * Write the xml for a {@link Reference}.
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000372 *
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000373 * @param reference
374 * @param contentHandler
375 * @throws SAXException
376 */
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000377 protected static void generateReferenceXML(final ComponentDescription component,
Carsten Ziegeler561e4e22012-06-27 06:38:28 +0000378 final DescriptionContainer module,
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000379 final ReferenceDescription reference,
Carsten Ziegeler44ee8942012-06-14 15:03:37 +0000380 final ContentHandler contentHandler)
381 throws SAXException {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000382 final AttributesImpl ai = new AttributesImpl();
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000383 IOUtils.addAttribute(ai, ATTR_NAME, reference.getName());
384 IOUtils.addAttribute(ai, INTERFACE_ATTR_NAME, reference.getInterfaceName());
385 IOUtils.addAttribute(ai, ATTR_CARDINALITY, reference.getCardinality().getCardinalityString());
386 IOUtils.addAttribute(ai, REFERENCE_ATTR_POLICY, reference.getPolicy().name().toLowerCase());
387 IOUtils.addAttribute(ai, REFERENCE_ATTR_TARGET, reference.getTarget());
388 IOUtils.addAttribute(ai, REFERENCE_ATTR_BIND, reference.getBind());
389 IOUtils.addAttribute(ai, REFERENCE_ATTR_UNBIND, reference.getUnbind());
Carsten Ziegelereff7ff72009-12-07 15:33:57 +0000390
391 // attributes new in 1.1-felix (FELIX-1893)
Carsten Ziegeler561e4e22012-06-27 06:38:28 +0000392 if (module.getOptions().getSpecVersion().ordinal() >= SpecVersion.VERSION_1_1_FELIX.ordinal() ) {
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000393 IOUtils.addAttribute(ai, REFERENCE_ATTR_UPDATED, reference.getUpdated());
Carsten Ziegelereff7ff72009-12-07 15:33:57 +0000394 }
395
Carsten Ziegelerd156e362012-06-14 15:34:11 +0000396 // attributes new in 1.2
Carsten Ziegeler561e4e22012-06-27 06:38:28 +0000397 if (module.getOptions().getSpecVersion().ordinal() >= SpecVersion.VERSION_1_2.ordinal() ) {
Carsten Ziegelerd156e362012-06-14 15:34:11 +0000398 if ( reference.getPolicyOption() != ReferencePolicyOption.RELUCTANT ) {
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000399 IOUtils.addAttribute(ai, REFERENCE_ATTR_POLICY_OPTION, reference.getPolicyOption().name().toLowerCase());
Carsten Ziegelerd156e362012-06-14 15:34:11 +0000400 }
401 }
402
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000403 IOUtils.indent(contentHandler, 2);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000404 contentHandler.startElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.REFERENCE, ComponentDescriptorIO.REFERENCE_QNAME,
405 ai);
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000406 contentHandler.endElement(INNER_NAMESPACE_URI, ComponentDescriptorIO.REFERENCE, ComponentDescriptorIO.REFERENCE_QNAME);
Carsten Ziegeler1d4f1e52008-06-03 07:47:40 +0000407 IOUtils.newline(contentHandler);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000408 }
409
410 /**
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000411 * A content handler for parsing the component descriptions.
412 *
413 */
414 protected static final class XmlHandler extends DefaultHandler {
415
416 /** The components container. */
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000417 private final List<ClassDescription> components = new ArrayList<ClassDescription>();
418
419 /** Spec version. */
420 private SpecVersion specVersion;
421
422 /** A reference to the current class. */
423 private ClassDescription currentClass;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000424
425 /** A reference to the current component. */
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000426 private ComponentDescription currentComponent;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000427
428 /** The current service. */
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000429 private ServiceDescription currentService;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000430
431 /** Pending property. */
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000432 private PropertyDescription pendingProperty;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000433
434 /** Flag for detecting the first element. */
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000435 private boolean firstElement = true;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000436
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000437 /** Flag for elements inside a component element */
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000438 private boolean isComponent = false;
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000439
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000440 /** Override namespace. */
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000441 private String overrideNamespace;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000442
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000443 /** The issue log. */
444 private final IssueLog iLog;
445
446 /** XML file location. */
447 private final String location;
448
449 /** Classloader. */
450 private final ClassLoader classLoader;
451
452 public XmlHandler(final ClassLoader classLoader, final IssueLog iLog, final String loc) {
453 this.iLog = iLog;
454 this.location = loc;
455 this.classLoader = classLoader;
456 }
457
458 /**
459 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
460 */
461 public void startElement(String uri, final String localName, final String name, final Attributes attributes)
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000462 throws SAXException {
463 // according to the spec, the elements should have the namespace,
464 // except when the root element is the "component" element
465 // So we check this for the first element, we receive.
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000466 if (this.firstElement) {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000467 this.firstElement = false;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000468 if (localName.equals(COMPONENT) && "".equals(uri)) {
Carsten Ziegeler98e992a2012-06-13 15:50:00 +0000469 this.overrideNamespace = SpecVersion.VERSION_1_0.getNamespaceUrl();
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000470 }
471 }
472
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000473 if (this.overrideNamespace != null && "".equals(uri)) {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000474 uri = this.overrideNamespace;
475 }
476
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000477 // however the spec also states that the inner elements
478 // of a component are unqualified, so they don't have
479 // the namespace - we allow both: with or without namespace!
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000480 if (this.isComponent && "".equals(uri)) {
Carsten Ziegeler98e992a2012-06-13 15:50:00 +0000481 uri = SpecVersion.VERSION_1_0.getNamespaceUrl();
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000482 }
483
484 // from here on, uri has the namespace regardless of the used xml format
Carsten Ziegeler98e992a2012-06-13 15:50:00 +0000485 specVersion = SpecVersion.fromNamespaceUrl(uri);
486 if (specVersion != null) {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000487
488 if (localName.equals(COMPONENT)) {
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000489 this.isComponent = true;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000490
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000491 final ComponentDescription desc = new ComponentDescription(null);
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000492 desc.setName(attributes.getValue(ATTR_NAME));
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000493
494 // enabled attribute is optional
Carsten Ziegeler84fc4352009-06-12 14:11:02 +0000495 if (attributes.getValue(COMPONENT_ATTR_ENABLED) != null) {
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000496 desc.setEnabled(Boolean.valueOf(attributes.getValue(COMPONENT_ATTR_ENABLED)));
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000497 }
498
499 // immediate attribute is optional
Carsten Ziegeler84fc4352009-06-12 14:11:02 +0000500 if (attributes.getValue(COMPONENT_ATTR_IMMEDIATE) != null) {
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000501 desc.setImmediate(Boolean.valueOf(attributes.getValue(COMPONENT_ATTR_IMMEDIATE)));
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000502 }
503
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000504 desc.setFactory(attributes.getValue(COMPONENT_ATTR_FACTORY));
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000505
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000506 desc.setConfigurationPolicy(ComponentConfigurationPolicy.OPTIONAL);
Carsten Ziegeler84fc4352009-06-12 14:11:02 +0000507 // check for version 1.1 attributes
Carsten Ziegeler44ee8942012-06-14 15:03:37 +0000508 if (specVersion.ordinal() >= SpecVersion.VERSION_1_1.ordinal()) {
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000509 final String policy = attributes.getValue(COMPONENT_ATTR_POLICY);
510 if ( policy != null ) {
511 try {
Carsten Ziegelerfaba0eb2012-06-27 16:22:55 +0000512 desc.setConfigurationPolicy(ComponentConfigurationPolicy.valueOf(policy.toUpperCase()));
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000513 } catch (final IllegalArgumentException iae) {
514 iLog.addWarning("Invalid value for attribute " + COMPONENT_ATTR_POLICY + " : " + policy, this.location);
515 }
516 }
517 if ( attributes.getValue(COMPONENT_ATTR_ACTIVATE) != null ) {
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000518 desc.setActivate(attributes.getValue(COMPONENT_ATTR_ACTIVATE));
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000519 }
520 if ( attributes.getValue(COMPONENT_ATTR_DEACTIVATE) != null ) {
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000521 desc.setDeactivate(attributes.getValue(COMPONENT_ATTR_DEACTIVATE));
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000522 }
523 if ( attributes.getValue(COMPONENT_ATTR_MODIFIED) != null ) {
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000524 desc.setModified(attributes.getValue(COMPONENT_ATTR_MODIFIED));
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000525 }
Carsten Ziegeler84fc4352009-06-12 14:11:02 +0000526 }
Carsten Ziegeler9a8d32e2012-06-27 14:07:35 +0000527
528 this.currentComponent = desc;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000529 } else if (localName.equals(IMPLEMENTATION)) {
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000530 // now we can create the class description and attach the component description
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000531 // Set the implementation class name (mandatory)
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000532 final String className = attributes.getValue(IMPLEMENTATION_ATTR_CLASS);
Carsten Ziegeleraa66ac02012-06-27 15:49:34 +0000533 Class<?> cl = null;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000534 try {
Carsten Ziegeleraa66ac02012-06-27 15:49:34 +0000535 cl = this.classLoader.loadClass(className);
536 } catch (final Throwable e) {
Carsten Ziegeler834d5272012-07-02 05:51:56 +0000537 // this doesn't have an effect as the classes we processed are loaded
538 // anyway.
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000539 }
Carsten Ziegeleraa66ac02012-06-27 15:49:34 +0000540 this.currentClass = new ClassDescription(cl, "classpath:" + className);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000541 this.currentClass.add(this.currentComponent);
Carsten Ziegeler4ca92cc2012-06-28 18:26:31 +0000542 this.components.add(this.currentClass);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000543
544 } else if (localName.equals(PROPERTY)) {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000545
Felix Meschberger1fd58292009-10-02 12:59:27 +0000546 // read the property, unless it is the service.pid
547 // property which must not be inherited
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000548 final String propName = attributes.getValue(ATTR_NAME);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000549 if (!org.osgi.framework.Constants.SERVICE_PID.equals(propName)) {
550 final PropertyDescription prop = new PropertyDescription(null);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000551
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000552 prop.setName(propName);
Carsten Ziegeler482c3302012-07-03 09:58:43 +0000553 final String type = attributes.getValue(PROPERTY_ATTR_TYPE);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000554 if ( type != null ) {
555 try {
556 prop.setType(PropertyType.valueOf(type));
557 } catch (final IllegalArgumentException iae) {
558 iLog.addWarning("Invalid value for attribute type : " + type, this.location);
559 }
Felix Meschberger1fd58292009-10-02 12:59:27 +0000560 }
Carsten Ziegeler0338cc62012-07-02 18:02:41 +0000561 if ( prop.getType() == null ) {
562 prop.setType(PropertyType.String);
563 }
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000564
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000565 if (attributes.getValue(PROPERTY_ATTR_VALUE) != null) {
566 prop.setValue(attributes.getValue(PROPERTY_ATTR_VALUE));
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000567 this.currentClass.add(prop);
568 } else {
Felix Meschberger1fd58292009-10-02 12:59:27 +0000569 // hold the property pending as we have a multi value
570 this.pendingProperty = prop;
571 }
572 // check for abstract properties
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000573 prop.setLabel(attributes.getValue(ATTR_LABEL));
574 prop.setDescription(attributes.getValue(ATTR_DESCRIPTION));
575 final String cardinality = attributes.getValue(ATTR_CARDINALITY);
576 prop.setUnbounded(PropertyUnbounded.DEFAULT);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000577 if ( cardinality != null ) {
578 prop.setCardinality(Integer.valueOf(cardinality));
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000579 if ( prop.getCardinality() == Integer.MAX_VALUE ) {
580 prop.setCardinality(0);
581 prop.setUnbounded(PropertyUnbounded.ARRAY);
582 } else if ( prop.getCardinality() == Integer.MIN_VALUE ) {
583 prop.setCardinality(0);
584 prop.setUnbounded(PropertyUnbounded.VECTOR);
585 }
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000586 }
Carsten Ziegeler482c3302012-07-03 09:58:43 +0000587 final String pValue = attributes.getValue(PROPERTY_ATTR_PRIVATE);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000588 if (pValue != null) {
589 prop.setPrivate(Boolean.valueOf(pValue));
Felix Meschberger1fd58292009-10-02 12:59:27 +0000590 }
Carsten Ziegelerd2c1b092008-03-04 13:02:15 +0000591 }
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000592
Carsten Ziegeler482c3302012-07-03 09:58:43 +0000593 } else if (localName.equals(PROPERTIES)) {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000594
595 // TODO: implement the properties tag
596
597 } else if (localName.equals(SERVICE)) {
598
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000599 this.currentService = new ServiceDescription(null);
600 this.currentClass.add(this.currentService);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000601
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000602 if (attributes.getValue(SERVICE_ATTR_FACTORY) != null) {
603 this.currentService.setServiceFactory(Boolean.valueOf(attributes.getValue(SERVICE_ATTR_FACTORY)));
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000604 }
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000605
606 } else if (localName.equals(INTERFACE)) {
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000607 this.currentService.addInterface(attributes.getValue(INTERFACE_ATTR_NAME));
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000608
609 } else if (localName.equals(REFERENCE)) {
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000610 final ReferenceDescription ref = new ReferenceDescription(null);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000611
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000612 ref.setName(attributes.getValue(ATTR_NAME));
613 ref.setInterfaceName(attributes.getValue(INTERFACE_ATTR_NAME));
614 final String cardinality = attributes.getValue(ATTR_CARDINALITY);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000615 if ( cardinality != null ) {
616 ref.setCardinality(ReferenceCardinality.fromValue(cardinality));
617 if ( ref.getCardinality() == null ) {
618 iLog.addWarning("Invalid value for attribute cardinality : " + cardinality, this.location);
619 }
620 }
Carsten Ziegelerd156e362012-06-14 15:34:11 +0000621 ref.setPolicy(ReferencePolicy.STATIC);
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000622 final String policy = attributes.getValue(REFERENCE_ATTR_POLICY);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000623 if ( policy != null ) {
624 try {
Carsten Ziegelerd156e362012-06-14 15:34:11 +0000625 ref.setPolicy(ReferencePolicy.valueOf(policy.toUpperCase()));
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000626 } catch (final IllegalArgumentException iae) {
627 iLog.addWarning("Invalid value for attribute policy : " + policy, this.location);
628 }
629 }
Carsten Ziegelerd156e362012-06-14 15:34:11 +0000630 ref.setPolicyOption(ReferencePolicyOption.RELUCTANT);
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000631 final String policyOption = attributes.getValue(REFERENCE_ATTR_POLICY_OPTION);
Carsten Ziegelerd156e362012-06-14 15:34:11 +0000632 if ( policyOption != null ) {
633 try {
634 ref.setPolicyOption(ReferencePolicyOption.valueOf(policyOption.toUpperCase()));
635 } catch (final IllegalArgumentException iae) {
636 iLog.addWarning("Invalid value for attribute policy-option : " + policyOption, this.location);
637 }
638 }
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000639 ref.setTarget(attributes.getValue(REFERENCE_ATTR_TARGET));
640 if ( attributes.getValue(REFERENCE_ATTR_BIND) != null ) {
641 ref.setBind(attributes.getValue(REFERENCE_ATTR_BIND));
Carsten Ziegeler46d03502008-07-25 10:07:56 +0000642 }
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000643 if ( attributes.getValue(REFERENCE_ATTR_UNBIND) != null ) {
644 ref.setUnbind(attributes.getValue(REFERENCE_ATTR_UNBIND));
Carsten Ziegeler9a496fe2012-06-27 06:20:28 +0000645 }
Carsten Ziegeler61a12e22012-07-03 09:33:50 +0000646 if ( attributes.getValue(REFERENCE_ATTR_UPDATED) != null ) {
647 ref.setUnbind(attributes.getValue(REFERENCE_ATTR_UPDATED));
Carsten Ziegeler4723a302011-06-06 14:20:01 +0000648 }
Carsten Ziegeler46d03502008-07-25 10:07:56 +0000649
Carsten Ziegeler482c3302012-07-03 09:58:43 +0000650 final String strategy = attributes.getValue(REFERENCE_ATTR_STRATEGY);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000651 if ( strategy != null ) {
652 try {
Carsten Ziegelerd156e362012-06-14 15:34:11 +0000653 ref.setStrategy(ReferenceStrategy.valueOf(strategy.toUpperCase()));
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000654 } catch (final IllegalArgumentException iae) {
655 throw new SAXException("Invalid value for attribute strategy : " + strategy);
656 }
657 }
658
659 this.currentClass.add(ref);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000660 }
661 }
662 }
663
664 /**
665 * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
666 */
667 public void endElement(String uri, String localName, String name) throws SAXException {
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000668 if (this.overrideNamespace != null && "".equals(uri)) {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000669 uri = this.overrideNamespace;
670 }
671
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000672 if (this.isComponent && "".equals(uri)) {
Carsten Ziegeler98e992a2012-06-13 15:50:00 +0000673 uri = SpecVersion.VERSION_1_0.getNamespaceUrl();
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000674 }
675
Carsten Ziegeler98e992a2012-06-13 15:50:00 +0000676 if (SpecVersion.fromNamespaceUrl(uri) != null) {
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000677 if (localName.equals(COMPONENT)) {
678 this.currentClass = null;
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000679 this.currentComponent = null;
Carsten Ziegeler0ad4f782008-08-22 07:27:00 +0000680 this.isComponent = false;
681 } else if (localName.equals(PROPERTY) && this.pendingProperty != null) {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000682 // now split the value
683 final String text = this.pendingProperty.getValue();
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000684 if (text != null) {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000685 final StringTokenizer st = new StringTokenizer(text);
686 final String[] values = new String[st.countTokens()];
687 int index = 0;
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000688 while (st.hasMoreTokens()) {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000689 values[index] = st.nextToken();
690 index++;
691 }
692 this.pendingProperty.setMultiValue(values);
693 }
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000694 this.currentClass.add(this.pendingProperty);
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000695 this.pendingProperty = null;
696 }
697 }
698 }
699
700 /**
701 * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
702 */
703 public void characters(char[] ch, int start, int length) throws SAXException {
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000704 if (this.pendingProperty != null) {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000705 final String text = new String(ch, start, length);
Carsten Ziegeler55c96d32012-06-13 12:03:35 +0000706 if (this.pendingProperty.getValue() == null) {
Carsten Ziegeler4ccaaeb2007-08-20 07:20:03 +0000707 this.pendingProperty.setValue(text);
708 } else {
709 this.pendingProperty.setValue(this.pendingProperty.getValue() + text);
710 }
711 }
712 }
713 }
714}