This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.discovery.api-1.0.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-discovery-api.git
commit 4a29199d6c185ac15fab162b0ee72b8308296fae Author: Carsten Ziegeler <[email protected]> AuthorDate: Wed Apr 17 12:59:51 2013 +0000 Add standard properties and provide an implementation delivering these properties git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/discovery/api@1468881 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 2 - .../sling/discovery/InstanceDescription.java | 23 ++- .../apache/sling/discovery/PropertyProvider.java | 5 +- .../discovery/impl/StandardPropertyProvider.java | 219 +++++++++++++++++++++ 4 files changed, 245 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index a836cdb..f30d328 100644 --- a/pom.xml +++ b/pom.xml @@ -63,8 +63,6 @@ <dependency> <groupId>biz.aQute</groupId> <artifactId>bndlib</artifactId> - <version>1.50.0</version> - <scope>provided</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> diff --git a/src/main/java/org/apache/sling/discovery/InstanceDescription.java b/src/main/java/org/apache/sling/discovery/InstanceDescription.java index 55e941f..f3ce846 100644 --- a/src/main/java/org/apache/sling/discovery/InstanceDescription.java +++ b/src/main/java/org/apache/sling/discovery/InstanceDescription.java @@ -26,11 +26,32 @@ import java.util.Map; * <p> * Note that all methods are idempotent - they always return the same values * on subsequent calls. Rather, on any change new InstanceDescriptions are created. + * + * * @see TopologyView */ public interface InstanceDescription { - /** + /** + * Property containing a name for the instance. + * The instance should provide this property. + */ + String PROPERTY_NAME = "org.apache.sling.instance.name"; + + /** + * Property containing a description for the instance. + * The instance should provide this property. + */ + String PROPERTY_DESCRIPTION = "org.apache.sling.instance.name"; + + /** + * Property containing endpoints to connect to the instance. The + * value is a comma separated list. + * The instance should provide this property. + */ + String PROPERTY_ENDPOINTS = "org.apache.sling.instance.endpoints"; + + /** * Returns the ClusterView of which this instance is part of. * <p> * Every instance is part of a ClusterView even if it is standalone. diff --git a/src/main/java/org/apache/sling/discovery/PropertyProvider.java b/src/main/java/org/apache/sling/discovery/PropertyProvider.java index 31b4ed3..6e7aa8e 100644 --- a/src/main/java/org/apache/sling/discovery/PropertyProvider.java +++ b/src/main/java/org/apache/sling/discovery/PropertyProvider.java @@ -46,7 +46,10 @@ public interface PropertyProvider { * and broadcast to the <code>TopologyView</code> instances. * <p> * These properties are non-persistent and disappear after my own instance goes down. - * @return The value of the property or <code>null</code> + * + * @return The value of the property or <code>null</code>. If the property + * value can't be provided or if the provider does not support this + * property, it must return <code>null</code>. */ String getProperty(final String name); } diff --git a/src/main/java/org/apache/sling/discovery/impl/StandardPropertyProvider.java b/src/main/java/org/apache/sling/discovery/impl/StandardPropertyProvider.java new file mode 100644 index 0000000..798ff0a --- /dev/null +++ b/src/main/java/org/apache/sling/discovery/impl/StandardPropertyProvider.java @@ -0,0 +1,219 @@ +/* + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.sling.discovery.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Modified; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.ReferencePolicy; +import org.apache.sling.discovery.InstanceDescription; +import org.apache.sling.discovery.PropertyProvider; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.http.HttpService; + +/** + * This service provides the standard instance properties (if available) + */ +@Component(immediate=true) +@Reference(referenceInterface=HttpService.class, + cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE, + policy=ReferencePolicy.DYNAMIC) +public class StandardPropertyProvider { + + /** Endpoint service registration property from RFC 189 */ + private static final String REG_PROPERTY_ENDPOINTS = "osgi.http.service.endpoints"; + + private volatile long changeCount; + + private String instanceName; + + private String instanceDescription; + + private ServiceRegistration propagationService; + + private final Map<Long, String[]> endpoints = new HashMap<Long, String[]>(); + + private String endpointString; + + private Dictionary<String, Object> getRegistrationProperties() { + final List<String> names = new ArrayList<String>(); + if ( this.instanceName != null ) { + names.add(InstanceDescription.PROPERTY_NAME); + } + if ( this.instanceDescription != null ) { + names.add(InstanceDescription.PROPERTY_DESCRIPTION); + } + names.add(InstanceDescription.PROPERTY_ENDPOINTS); + + final StringBuilder sb = new StringBuilder(); + boolean first = true; + synchronized ( this.endpoints ) { + for(final String[] points : endpoints.values()) { + for(final String point : points) { + if ( first ) { + first = false; + } else { + sb.append(","); + } + sb.append(point); + } + } + } + this.endpointString = sb.toString(); + + final Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(); + serviceProps.put(PropertyProvider.PROPERTY_PROPERTIES, names.toArray(new String[names.size()])); + // we add a changing property to the service registration + // to make sure a modification event is really sent + synchronized ( this ) { + serviceProps.put("changeCount", this.changeCount++); + } + return serviceProps; + } + + private String getPropertyValue(final ComponentContext bc, final String key) { + Object value = bc.getProperties().get(key); + if ( value == null ) { + value = bc.getBundleContext().getProperty(key); + } + if ( value != null ) { + return value.toString(); + } + return null; + } + + @Activate + protected void activate(final ComponentContext cc) { + this.modified(cc); + } + + @Modified + protected void modified(final ComponentContext cc) { + this.instanceName = this.getPropertyValue(cc, "sling.name"); + this.instanceDescription = this.getPropertyValue(cc, "sling.description"); + + this.propagationService = cc.getBundleContext().registerService(PropertyProvider.class.getName(), + new PropertyProvider() { + + public String getProperty(final String name) { + if ( InstanceDescription.PROPERTY_DESCRIPTION.equals(name) ) { + return instanceDescription; + } + if ( InstanceDescription.PROPERTY_NAME.equals(name) ) { + return instanceName; + } + if ( InstanceDescription.PROPERTY_ENDPOINTS.equals(name) ) { + return endpointString; + } + return null; + } + }, this.getRegistrationProperties()); + } + + @Deactivate + protected void deactivate() { + if ( this.propagationService != null ) { + this.propagationService.unregister(); + this.propagationService = null; + } + } + + /** + * Bind a http service + */ + protected void bindHttpService(final ServiceReference reference) { + final String[] endpointUrls = toStringArray(reference.getProperty(REG_PROPERTY_ENDPOINTS)); + if ( endpointUrls != null ) { + synchronized ( this.endpoints ) { + this.endpoints.put((Long)reference.getProperty(Constants.SERVICE_ID), endpointUrls); + } + if ( this.propagationService != null ) { + this.propagationService.setProperties(this.getRegistrationProperties()); + } + } + } + + /** + * Unbind a http service + */ + protected void unbindHttpService(final ServiceReference reference) { + boolean changed = false; + synchronized ( this.endpoints ) { + if ( this.endpoints.remove(reference.getProperty(Constants.SERVICE_ID)) != null ) { + changed = true; + } + } + if ( changed && this.propagationService != null ) { + this.propagationService.setProperties(this.getRegistrationProperties()); + } + } + + private String[] toStringArray(final Object propValue) { + if (propValue == null) { + // no value at all + return null; + + } else if (propValue instanceof String) { + // single string + return new String[] { (String) propValue }; + + } else if (propValue instanceof String[]) { + // String[] + return (String[]) propValue; + + } else if (propValue.getClass().isArray()) { + // other array + Object[] valueArray = (Object[]) propValue; + List<String> values = new ArrayList<String>(valueArray.length); + for (Object value : valueArray) { + if (value != null) { + values.add(value.toString()); + } + } + return values.toArray(new String[values.size()]); + + } else if (propValue instanceof Collection<?>) { + // collection + Collection<?> valueCollection = (Collection<?>) propValue; + List<String> valueList = new ArrayList<String>(valueCollection.size()); + for (Object value : valueCollection) { + if (value != null) { + valueList.add(value.toString()); + } + } + return valueList.toArray(new String[valueList.size()]); + } + + return null; + } +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
