blob: 29c85b68efa92c86b21fc16b9c3cc88b128c0908 [file] [log] [blame]
/*
* 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.camel.blueprint;
import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.aries.blueprint.ext.PropertyPlaceholderExt;
import org.apache.camel.spi.PropertiesSource;
import org.apache.camel.support.ObjectHelper;
import org.apache.camel.support.service.ServiceSupport;
import org.apache.camel.util.ReflectionHelper;
import org.osgi.service.blueprint.container.BlueprintContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Blueprint {@link PropertiesSource} which supports looking up
* property placeholders from the Blueprint Property Placeholder Service.
*/
public class BlueprintPropertiesSource extends ServiceSupport implements PropertiesSource {
private static final Logger LOG = LoggerFactory.getLogger(BlueprintPropertiesSource.class);
private final BlueprintContainer container;
private final List<String> ids;
private final Set<PropertyPlaceholderWrapper> placeholders = new LinkedHashSet<>();
public BlueprintPropertiesSource(BlueprintContainer container, List<String> ids) {
this.container = container;
this.ids = ids;
}
@Override
public String getName() {
return "BlueprintPropertiesSource" + ids;
}
@Override
public String getProperty(String name) {
String answer = null;
for (PropertyPlaceholderWrapper placeholder : placeholders) {
boolean isDefault = false;
if (placeholders.size() > 1) {
// okay we have multiple placeholders and we want to return the answer that
// is not the default placeholder if there is multiple keys
Map map = placeholder.getDefaultProperties();
isDefault = map != null && map.containsKey(name);
LOG.trace("Blueprint property key: {} is part of default properties: {}", name, isDefault);
}
try {
String candidate = placeholder.retrieveValue(name);
if (candidate != null) {
if (answer == null || !isDefault) {
LOG.trace("Blueprint candidate property key: {} as value: {}", name, answer);
answer = candidate;
}
}
} catch (Exception ex) {
// Here we just catch the exception and try to use other candidate
}
}
LOG.debug("Blueprint getProperty: {}={}", name, answer);
return answer;
}
/**
* Adds the given Blueprint property placeholder service with the given id
*
* @param id id of the Blueprint property placeholder service to add.
*/
private void addPropertyPlaceholder(String id) {
Object component = container.getComponentInstance(id);
if (component instanceof PropertyPlaceholderExt) {
Class<?> clazz = component.getClass();
if (clazz != null) {
LOG.debug("Adding Blueprint PropertyPlaceholder: {}", id);
Method method = ReflectionHelper.findMethod(clazz, "retrieveValue", String.class);
Method defaultMethod = ReflectionHelper.findMethod(clazz, "getDefaultProperties");
if (method != null) {
method.setAccessible(true);
if (defaultMethod != null) {
defaultMethod.setAccessible(true);
}
placeholders.add(new PropertyPlaceholderWrapper(component, method, defaultMethod));
} else {
throw new IllegalStateException("Cannot add blueprint property placeholder: " + id
+ " as the method retrieveValue is not found");
}
}
}
}
@Override
protected void doInit() throws Exception {
for (String id : ids) {
addPropertyPlaceholder(id);
}
}
@Override
protected void doStart() throws Exception {
// noop
}
@Override
protected void doStop() throws Exception {
// noop
}
private class PropertyPlaceholderWrapper {
private final Object delegate;
private final Method method;
private final Method defaultMethod;
PropertyPlaceholderWrapper(Object delegate, Method method, Method defaultMethod) {
this.delegate = delegate;
this.method = method;
this.defaultMethod = defaultMethod;
}
String retrieveValue(String key) {
Object v = ObjectHelper.invokeMethod(method, delegate, key);
return v == null ? null : v.toString();
}
Map getDefaultProperties() {
if (defaultMethod != null) {
return (Map) ObjectHelper.invokeMethod(defaultMethod, delegate);
}
return null;
}
}
}