ch.sourcepond.commons.smartswitch.impl.SmartSwitchBuilderImpl Maven / Gradle / Ivy
/*Copyright (C) 2017 Roland Hauser,
Licensed 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 ch.sourcepond.commons.smartswitch.impl;
import ch.sourcepond.commons.smartswitch.api.SmartSwitchBuilder;
import ch.sourcepond.commons.smartswitch.api.ToDefaultSwitchObserver;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.wiring.BundleWiring;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Supplier;
import static java.lang.String.format;
import static java.lang.reflect.Proxy.newProxyInstance;
import static java.util.Objects.requireNonNull;
import static org.osgi.framework.Constants.OBJECTCLASS;
/**
*
*/
final class SmartSwitchBuilderImpl implements SmartSwitchBuilder {
private final SmartSwitchFactory smartSwitchFactory;
private final Executor executor;
private final Class serviceInterface;
private final BundleContext context;
private volatile String filterOrNull;
private volatile ToDefaultSwitchObserver observerOrNull;
private volatile Consumer shutdownHookOrNull;
SmartSwitchBuilderImpl(final SmartSwitchFactory pSmartSwitchFactory,
final Executor pExecutor,
final BundleContext pContext,
final Class pServiceInterface) {
smartSwitchFactory = pSmartSwitchFactory;
executor = pExecutor;
context = pContext;
serviceInterface = pServiceInterface;
}
private T createProxy(final SmartSwitch pSmartSwitch) {
return (T) newProxyInstance(
context.getBundle().adapt(BundleWiring.class).getClassLoader(),
new Class>[]{serviceInterface},
pSmartSwitch);
}
@Override
public SmartSwitchBuilder setObserver(final ToDefaultSwitchObserver pObserver) {
observerOrNull = pObserver;
return this;
}
@Override
public SmartSwitchBuilder setFilter(final String pFilter) {
// Check that the filter specified is valid
try {
context.createFilter(pFilter);
} catch (final InvalidSyntaxException e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
filterOrNull = pFilter;
return this;
}
@Override
public SmartSwitchBuilder setShutdownHook(final Consumer pShutdownHook) {
if (pShutdownHook == null) {
throw new NullPointerException("ShutdownHook is null");
}
shutdownHookOrNull = pShutdownHook;
return this;
}
private String createServiceFilter() {
if (filterOrNull == null) {
return format("(%s=%s)", OBJECTCLASS, serviceInterface.getName());
}
return format("(&(%s=%s)%s)", OBJECTCLASS, serviceInterface.getName(), filterOrNull);
}
@Override
public T build(final Supplier pSupplier) {
// The supplier cannot be null otherwise fail here
requireNonNull(pSupplier, "Supplier is null");
final SmartSwitch smartSwitch = smartSwitchFactory.create(executor, pSupplier, shutdownHookOrNull, observerOrNull);
try {
context.addServiceListener(smartSwitch, createServiceFilter());
} catch (final InvalidSyntaxException e) {
// This should never happen because it has been validated
// that the filter specified by the user is valid.
throw new IllegalStateException(e.getMessage(), e);
}
return createProxy(smartSwitch);
}
}