Author: alien11689 Date: Sat Feb 4 11:02:53 2017 New Revision: 1781654 URL: http://svn.apache.org/viewvc?rev=1781654&view=rev Log: [ARIES-1677] Create typed service properties via annotations
Added: aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/ServiceProperty.java aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/test/java/org/apache/aries/blueprint/plugin/test/ServiceWithTypedParameters.java Modified: aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/OsgiServiceHandler.java aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/OsgiServiceProviderHandler.java aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/model/Bean.java aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/model/Blueprint.java aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/test/java/org/apache/aries/blueprint/plugin/BlueprintFileWriterTest.java Modified: aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/OsgiServiceHandler.java URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/OsgiServiceHandler.java?rev=1781654&r1=1781653&r2=1781654&view=diff ============================================================================== --- aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/OsgiServiceHandler.java (original) +++ aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/OsgiServiceHandler.java Sat Feb 4 11:02:53 2017 @@ -42,20 +42,7 @@ public class OsgiServiceHandler implemen final Class<?> clazz = getClass(annotatedElement); contextEnricher.addBean(id, getClass(annotatedElement)); - contextEnricher.addBlueprintContentWriter("osgiService/" + clazz.getName() + "/" + id, new XmlWriter() { - @Override - public void write(XMLStreamWriter writer) throws XMLStreamException { - writer.writeEmptyElement("reference"); - writer.writeAttribute("id", id); - writer.writeAttribute("interface", clazz.getName()); - if (serviceFilter.filter != null && !"".equals(serviceFilter.filter)) { - writer.writeAttribute("filter", serviceFilter.filter); - } - if (serviceFilter.compName != null && !"".equals(serviceFilter.compName)) { - writer.writeAttribute("component-name", serviceFilter.compName); - } - } - }); + contextEnricher.addBlueprintContentWriter(getWriterId(id, clazz), getXmlWriter(id, clazz, serviceFilter)); return id; } @@ -65,7 +52,12 @@ public class OsgiServiceHandler implemen final String id = name != null ? name : generateReferenceId(clazz, serviceFilter); contextEnricher.addBean(id, clazz); - contextEnricher.addBlueprintContentWriter("osgiService/" + clazz.getName() + "/" + id, new XmlWriter() { + contextEnricher.addBlueprintContentWriter(getWriterId(id, clazz), getXmlWriter(id, clazz, serviceFilter)); + return id; + } + + private XmlWriter getXmlWriter(final String id, final Class<?> clazz, final ServiceFilter serviceFilter) { + return new XmlWriter() { @Override public void write(XMLStreamWriter writer) throws XMLStreamException { writer.writeEmptyElement("reference"); @@ -78,8 +70,11 @@ public class OsgiServiceHandler implemen writer.writeAttribute("component-name", serviceFilter.compName); } } - }); - return id; + }; + } + + private String getWriterId(String id, Class<?> clazz) { + return "osgiService/" + clazz.getName() + "/" + id; } private Class<?> getClass(AnnotatedElement annotatedElement) { @@ -111,7 +106,7 @@ public class OsgiServiceHandler implemen return prefix + suffix; } - protected static String getBeanNameFromSimpleName(String name) { + private static String getBeanNameFromSimpleName(String name) { return name.substring(0, 1).toLowerCase() + name.substring(1, name.length()); } @@ -137,10 +132,10 @@ public class OsgiServiceHandler implemen } private static class ServiceFilter { - final public String filter; - final public String compName; + final String filter; + final String compName; - public ServiceFilter(String filterValue) { + ServiceFilter(String filterValue) { if (filterValue == null || filterValue.isEmpty()) { filter = null; compName = null; Modified: aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/OsgiServiceProviderHandler.java URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/OsgiServiceProviderHandler.java?rev=1781654&r1=1781653&r2=1781654&view=diff ============================================================================== --- aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/OsgiServiceProviderHandler.java (original) +++ aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/OsgiServiceProviderHandler.java Sat Feb 4 11:02:53 2017 @@ -31,10 +31,9 @@ import org.ops4j.pax.cdi.api.Property; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import java.lang.reflect.AnnotatedElement; +import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class OsgiServiceProviderHandler implements BeanAnnotationHandler<OsgiServiceProvider> { @@ -56,21 +55,18 @@ public class OsgiServiceProviderHandler final List<String> interfaceNames = extractServiceInterfaces(serviceProvider); - final Map<String, String> propertiesAsMap = extractProperties(properties); + final List<ServiceProperty> serviceProperties = extractProperties(properties); contextEnricher.addBlueprintContentWriter("OsgiServiceProvider/" + annotatedElement + "/" + id, new XmlWriter() { @Override public void write(XMLStreamWriter writer) throws XMLStreamException { - writeService(writer, propertiesAsMap, interfaceNames, id); + writeService(writer, serviceProperties, interfaceNames, id); } }); } - private void writeService(XMLStreamWriter writer, Map<String, String> propertiesAsMap, List<String> interfaceNames, String id) throws XMLStreamException { - // If there are no properties to write and only one service attribute (either - // interface="MyServiceInterface" or auto-export="interfaces") then create an - // empty element - boolean writeEmptyElement = propertiesAsMap.isEmpty() && interfaceNames.size() < 2; + private void writeService(XMLStreamWriter writer, List<ServiceProperty> serviceProperties, List<String> interfaceNames, String id) throws XMLStreamException { + boolean writeEmptyElement = serviceProperties.isEmpty() && interfaceNames.size() < 2; if (writeEmptyElement) { writer.writeEmptyElement("service"); } else { @@ -86,9 +82,9 @@ public class OsgiServiceProviderHandler writeInterfacesElement(writer, interfaceNames); } - if (!propertiesAsMap.isEmpty()) { - writeRanking(writer, propertiesAsMap); - writeProperties(writer, propertiesAsMap); + if (!serviceProperties.isEmpty()) { + writeRanking(writer, serviceProperties); + writeProperties(writer, serviceProperties); } if (!writeEmptyElement) { @@ -96,14 +92,14 @@ public class OsgiServiceProviderHandler } } - private static Map<String, String> extractProperties(Properties properties) { - Map<String, String> propertiesAsMap = new HashMap<>(); + private static List<ServiceProperty> extractProperties(Properties properties) { + List<ServiceProperty> serviceProperties = new ArrayList<>(); if (properties != null) { for (Property property : properties.value()) { - propertiesAsMap.put(property.name(), property.value()); + serviceProperties.add(new ServiceProperty(property.name(), property.value())); } } - return propertiesAsMap; + return serviceProperties; } private static List<String> extractServiceInterfaces(OsgiServiceProvider serviceProvider) { @@ -124,24 +120,24 @@ public class OsgiServiceProviderHandler writer.writeEndElement(); } - private void writeRanking(XMLStreamWriter writer, Map<String, String> propertiesAsMap) throws XMLStreamException { - if (propertiesAsMap.containsKey("service.ranking")) { - try { - Integer ranking = Integer.parseInt(propertiesAsMap.get("service.ranking")); - writer.writeAttribute("ranking", ranking.toString()); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("service.ranking property must be an integer!"); + private void writeRanking(XMLStreamWriter writer, List<ServiceProperty> serviceProperties) throws XMLStreamException { + for (ServiceProperty serviceProperty : serviceProperties) { + if ("service.ranking".equals(serviceProperty.name)) { + try { + Integer ranking = Integer.parseInt(serviceProperty.getSingleValue()); + writer.writeAttribute("ranking", ranking.toString()); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("service.ranking property must be an integer!"); + } } } } - private void writeProperties(XMLStreamWriter writer, Map<String, String> properties) throws XMLStreamException { + private void writeProperties(XMLStreamWriter writer, List<ServiceProperty> serviceProperties) throws XMLStreamException { writer.writeStartElement("service-properties"); - for (Map.Entry<String, String> property : properties.entrySet()) { - if (!SPECIAL_PROPERTIES.contains(property.getKey())) { - writer.writeEmptyElement("entry"); - writer.writeAttribute("key", property.getKey()); - writer.writeAttribute("value", property.getValue()); + for (ServiceProperty serviceProperty : serviceProperties) { + if (!SPECIAL_PROPERTIES.contains(serviceProperty.name)) { + serviceProperty.write(writer); } } writer.writeEndElement(); Added: aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/ServiceProperty.java URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/ServiceProperty.java?rev=1781654&view=auto ============================================================================== --- aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/ServiceProperty.java (added) +++ aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/handlers/pax/ServiceProperty.java Sat Feb 4 11:02:53 2017 @@ -0,0 +1,104 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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. + */ +package org.apache.aries.blueprint.plugin.handlers.pax; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import java.util.Arrays; +import java.util.List; + +class ServiceProperty { + final String name; + private final String type; + private final boolean isArray; + private final List<String> values; + + ServiceProperty(String name, String value) { + if (hasTypeSignature(name)) { + String[] splitName = name.split(":"); + this.name = splitName[0]; + this.type = getType(splitName[1]); + this.isArray = splitName[1].endsWith("[]"); + this.values = isArray ? Arrays.asList(value.split("\\|")) : Arrays.asList(value); + } else { + this.name = name; + this.type = null; + this.isArray = false; + this.values = Arrays.asList(value); + } + } + + private static boolean hasTypeSignature(String name) { + return name.contains(":"); + } + + private static String getType(String typeSignature) { + String rawType; + if (typeSignature.endsWith("[]")) { + rawType = typeSignature.substring(0, typeSignature.length() - 2); + } else { + rawType = typeSignature; + } + + if ("".equals(rawType)) { + return null; + } + if (rawType.contains(".")) { + return rawType; + } else { + return "java.lang." + rawType; + } + } + + void write(XMLStreamWriter writer) throws XMLStreamException { + if (type == null && !isArray) { + writer.writeEmptyElement("entry"); + writer.writeAttribute("key", name); + writer.writeAttribute("value", values.get(0)); + } else { + writer.writeStartElement("entry"); + writer.writeAttribute("key", name); + if (isArray) { + writer.writeStartElement("array"); + if (type != null) { + writer.writeAttribute("value-type", type); + } + for (String value : values) { + writer.writeStartElement("value"); + writer.writeCharacters(value); + writer.writeEndElement(); + } + writer.writeEndElement(); + } else { + writer.writeStartElement("value"); + writer.writeAttribute("type", type); + writer.writeCharacters(values.get(0)); + writer.writeEndElement(); + } + writer.writeEndElement(); + } + } + + String getSingleValue() { + if (values.size() > 1) { + throw new IllegalArgumentException("Property has more than one value"); + } + return values.get(0); + } +} Modified: aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/model/Bean.java URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/model/Bean.java?rev=1781654&r1=1781653&r2=1781654&view=diff ============================================================================== --- aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/model/Bean.java (original) +++ aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/model/Bean.java Sat Feb 4 11:02:53 2017 @@ -47,10 +47,10 @@ import static org.apache.aries.blueprint class Bean extends BeanRef implements BeanEnricher { public SortedSet<Property> properties = new TreeSet<>(); - public List<Argument> constructorArguments = new ArrayList<>(); + List<Argument> constructorArguments = new ArrayList<>(); public boolean isPrototype; public final Map<String, String> attributes = new HashMap<>(); - public final Map<String, XmlWriter> beanContentWriters = new HashMap<>(); + final Map<String, XmlWriter> beanContentWriters = new HashMap<>(); protected final ContextEnricher contextEnricher; Bean(Class<?> clazz, ContextEnricher contextEnricher) { @@ -195,19 +195,19 @@ class Bean extends BeanRef implements Be return clazz.getName(); } - public void writeProperties(XMLStreamWriter writer) throws XMLStreamException { + void writeProperties(XMLStreamWriter writer) throws XMLStreamException { for (Property property : properties) { property.write(writer); } } - public void writeArguments(XMLStreamWriter writer) throws XMLStreamException { + void writeArguments(XMLStreamWriter writer) throws XMLStreamException { for (Argument argument : constructorArguments) { argument.write(writer); } } - public boolean needFieldInjection() { + boolean needFieldInjection() { for (Property property : properties) { if (property.isField) { return true; @@ -225,4 +225,10 @@ class Bean extends BeanRef implements Be public void addBeanContentWriter(String id, XmlWriter blueprintWriter) { beanContentWriters.put(id, blueprintWriter); } + + void writeCustomContent(XMLStreamWriter writer) throws XMLStreamException { + for (XmlWriter xmlWriter : beanContentWriters.values()) { + xmlWriter.write(writer); + } + } } Modified: aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/model/Blueprint.java URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/model/Blueprint.java?rev=1781654&r1=1781653&r2=1781654&view=diff ============================================================================== --- aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/model/Blueprint.java (original) +++ aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/main/java/org/apache/aries/blueprint/plugin/model/Blueprint.java Sat Feb 4 11:02:53 2017 @@ -154,6 +154,7 @@ public class Blueprint implements Bluepr for (Bean bean : getBeans()) { writeBeanStart(writer, bean); + bean.writeCustomContent(writer); bean.writeArguments(writer); bean.writeProperties(writer); writer.writeEndElement(); @@ -193,9 +194,6 @@ public class Blueprint implements Bluepr if (bean instanceof BeanFromFactory) { writeFactory(writer, (BeanFromFactory) bean); } - for (XmlWriter xmlWriter : bean.beanContentWriters.values()) { - xmlWriter.write(writer); - } } private void writeFactory(XMLStreamWriter writer, BeanFromFactory bean) throws XMLStreamException { Modified: aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/test/java/org/apache/aries/blueprint/plugin/BlueprintFileWriterTest.java URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/test/java/org/apache/aries/blueprint/plugin/BlueprintFileWriterTest.java?rev=1781654&r1=1781653&r2=1781654&view=diff ============================================================================== --- aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/test/java/org/apache/aries/blueprint/plugin/BlueprintFileWriterTest.java (original) +++ aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/test/java/org/apache/aries/blueprint/plugin/BlueprintFileWriterTest.java Sat Feb 4 11:02:53 2017 @@ -719,6 +719,39 @@ public class BlueprintFileWriterTest { assertXpathEquals(bean, "@factory-method", "getBean3"); } + @Test + public void typedProperties() throws Exception { + Node service = getServiceByRef("serviceWithTypedParameters"); + assertXpathEquals(service, "count(service-properties/entry)", "6"); + assertXpathEquals(service, "service-properties/entry[@key='test1']/@value", "test"); + + assertXpathDoesNotExist(service, "service-properties/entry[@key='test2']/@value"); + assertXpathEquals(service, "service-properties/entry[@key='test2']/value", "15"); + assertXpathEquals(service, "service-properties/entry[@key='test2']/value/@type", "java.lang.Integer"); + + assertXpathDoesNotExist(service, "service-properties/entry[@key='test3']/@value"); + assertXpathEquals(service, "service-properties/entry[@key='test3']/value", "true"); + assertXpathEquals(service, "service-properties/entry[@key='test3']/value/@type", "java.lang.Boolean"); + + assertXpathDoesNotExist(service, "service-properties/entry[@key='test4']/@value"); + assertXpathEquals(service, "service-properties/entry[@key='test4']/array/value[1]", "val1"); + assertXpathEquals(service, "service-properties/entry[@key='test4']/array/value[2]", "val2"); + assertXpathDoesNotExist(service, "service-properties/entry[@key='test4']/array/@value-type"); + + assertXpathDoesNotExist(service, "service-properties/entry[@key='test5']/@value"); + assertXpathEquals(service, "service-properties/entry[@key='test5']/array/value[1]", "1"); + assertXpathEquals(service, "service-properties/entry[@key='test5']/array/value[2]", "2"); + assertXpathEquals(service, "service-properties/entry[@key='test5']/array/value[3]", "3"); + assertXpathEquals(service, "service-properties/entry[@key='test5']/array/@value-type", "java.lang.Short"); + + assertXpathDoesNotExist(service, "service-properties/entry[@key='test6']/@value"); + assertXpathEquals(service, "service-properties/entry[@key='test6']/array/value[1]", "1.5"); + assertXpathEquals(service, "service-properties/entry[@key='test6']/array/value[2]", "0.8"); + assertXpathEquals(service, "service-properties/entry[@key='test6']/array/value[3]", "-7.1"); + assertXpathEquals(service, "service-properties/entry[@key='test6']/array/@value-type", "java.lang.Double"); + + } + private void assertXpathDoesNotExist(Node node, String xpathExpression) throws XPathExpressionException { assertXpathEquals(node, "count(" + xpathExpression + ")", "0"); } Added: aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/test/java/org/apache/aries/blueprint/plugin/test/ServiceWithTypedParameters.java URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/test/java/org/apache/aries/blueprint/plugin/test/ServiceWithTypedParameters.java?rev=1781654&view=auto ============================================================================== --- aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/test/java/org/apache/aries/blueprint/plugin/test/ServiceWithTypedParameters.java (added) +++ aries/trunk/blueprint/plugin/blueprint-maven-plugin/src/test/java/org/apache/aries/blueprint/plugin/test/ServiceWithTypedParameters.java Sat Feb 4 11:02:53 2017 @@ -0,0 +1,20 @@ +package org.apache.aries.blueprint.plugin.test; + +import org.ops4j.pax.cdi.api.OsgiServiceProvider; +import org.ops4j.pax.cdi.api.Properties; +import org.ops4j.pax.cdi.api.Property; + +import javax.inject.Singleton; + +@OsgiServiceProvider +@Properties({ + @Property(name = "test1", value = "test"), + @Property(name = "test2:Integer", value = "15"), + @Property(name = "test3:java.lang.Boolean", value = "true"), + @Property(name = "test4:[]", value = "val1|val2"), + @Property(name = "test5:Short[]", value = "1|2|3"), + @Property(name = "test6:java.lang.Double[]", value = "1.5|0.8|-7.1") +}) +@Singleton +public class ServiceWithTypedParameters { +}