/*
* Copyright 2016 Guillaume Nodet
*
* 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 org.ops4j.pax.cdi.extension.impl.component2;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.felix.scr.impl.helper.ComponentMethod;
import org.apache.felix.scr.impl.helper.ComponentMethods;
import org.apache.felix.scr.impl.helper.ConfigAdminTracker;
import org.apache.felix.scr.impl.helper.InitReferenceMethod;
import org.apache.felix.scr.impl.helper.MethodResult;
import org.apache.felix.scr.impl.helper.ReferenceMethod;
import org.apache.felix.scr.impl.helper.ReferenceMethods;
import org.apache.felix.scr.impl.helper.SimpleLogger;
import org.apache.felix.scr.impl.manager.AbstractComponentManager;
import org.apache.felix.scr.impl.manager.ComponentActivator;
import org.apache.felix.scr.impl.manager.ComponentContainer;
import org.apache.felix.scr.impl.manager.ComponentContextImpl;
import org.apache.felix.scr.impl.manager.ComponentHolder;
import org.apache.felix.scr.impl.manager.ConfigurableComponentHolder;
import org.apache.felix.scr.impl.manager.DependencyManager;
import org.apache.felix.scr.impl.manager.ExtendedServiceEvent;
import org.apache.felix.scr.impl.manager.ExtendedServiceListener;
import org.apache.felix.scr.impl.manager.PrototypeServiceFactoryComponentManager;
import org.apache.felix.scr.impl.manager.RefPair;
import org.apache.felix.scr.impl.manager.RegionConfigurationSupport;
import org.apache.felix.scr.impl.manager.ScrConfiguration;
import org.apache.felix.scr.impl.manager.ServiceFactoryComponentManager;
import org.apache.felix.scr.impl.manager.SingleComponentManager;
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
import org.apache.felix.scr.impl.metadata.TargetedPID;
import org.ops4j.pax.cdi.extension.impl.support.Consumer;
import org.ops4j.pax.cdi.extension.impl.support.PrivateRegistryWrapper;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentException;
import org.osgi.service.log.LogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ComponentRegistry implements ComponentActivator, SimpleLogger {
private static final Logger log = LoggerFactory.getLogger(ComponentRegistry.class);
private final BeanManager beanManager;
private final BundleContext bundleContext;
private final Map<Bean<?>, AbstractDescriptor> descriptors = new HashMap<>();
private final List<ComponentHolder<?>> holders = new ArrayList<>();
private final Map<String, ComponentHolder<?>> holdersByName = new HashMap<>();
private final Map<String, Set<ComponentHolder<?>>> holdersByPid = new HashMap<>();
ConfigAdminTracker configAdminTracker;
private final ScrConfiguration m_configuration = new ScrConfigurationImpl();
private final Map<String, ListenerInfo> listenerMap = new HashMap<>();
private final Map<ExtendedServiceListener, ServiceListener> privateListeners = new HashMap<>();
private final AtomicInteger componentId = new AtomicInteger();
private final Map<ServiceReference<?>, List<Entry>> m_missingDependencies = new HashMap<>();
private final ConcurrentMap<Long, RegionConfigurationSupport> bundleToRcsMap = new ConcurrentHashMap<>();
private final Executor m_componentActor = Executors.newSingleThreadExecutor();
private final AtomicBoolean started = new AtomicBoolean();
public ComponentRegistry(BeanManager beanManager, BundleContext bundleContext) {
this.beanManager = beanManager;
this.bundleContext = new PrivateRegistryWrapper(bundleContext);
}
public BeanManager getBeanManager() {
return beanManager;
}
public void preStart(AfterBeanDiscovery event, GlobalDescriptor global) {
for (AbstractDescriptor descriptor : descriptors.values()) {
for (Bean<?> bean : descriptor.getProducers()) {
event.addBean(bean);
}
}
global.validate(this);
global.pauseIfNeeded();
ComponentHolder<?> h = new CdiComponentHolder<>(this, global);
h.enableComponents(false);
for (Bean<?> bean : global.getProducers()) {
event.addBean(bean);
}
}
private final ThreadLocal<List<ServiceReference<?>>> circularInfos = new ThreadLocal<> ();
public <T> boolean enterCreate(final ServiceReference<T> serviceReference) {
List<ServiceReference<?>> info = circularInfos.get();
if (info == null) {
circularInfos.set(info = new ArrayList<>());
}
if (info.contains(serviceReference)) {
log(LogService.LOG_ERROR,
"Circular reference detected trying to get service {0}: stack of references: {1}",
new Object[] {serviceReference, info},
null);
return true;
}
log(LogService.LOG_DEBUG,
"getService {0}: stack of references: {1}",
new Object[] {serviceReference, info},
null);
info.add(serviceReference);
return false;
}
public <T> void leaveCreate(final ServiceReference<T> serviceReference) {
List<ServiceReference<?>> info = circularInfos.get();
if (info != null) {
if (!info.isEmpty() && info.iterator().next().equals(serviceReference)) {
circularInfos.remove();
} else {
info.remove(serviceReference);
}
}
}
public void start() {
if (!started.compareAndSet(false, true)) {
return;
}
for (AbstractDescriptor d : descriptors.values()) {
d.validate(this);
ComponentHolder<?> h = new CdiComponentHolder<>(this, d);
holders.add(h);
}
for (ComponentHolder<?> h : holders) {
if (holdersByName.put(h.getComponentMetadata().getName(), h) != null) {
throw new ComponentException("The component name '{0}" + h.getComponentMetadata().getName() + "' has already been registered.");
}
}
for (ComponentHolder<?> h : holders) {
for (String pid : h.getComponentMetadata().getConfigurationPid()) {
Set<ComponentHolder<?>> set = holdersByPid.get(pid);
if (set == null) {
set = new HashSet<>();
holdersByPid.put(pid, set);
}
set.add(h);
}
}
ConfigAdminTracker tracker = null;
for (ComponentHolder<?> holder : holders) {
if (!holder.getComponentMetadata().isConfigurationIgnored()) {
tracker = new ConfigAdminTracker(this);
break;
}
}
configAdminTracker = tracker;
for (ComponentHolder<?> h : holders) {
try {
h.enableComponents(false);
} catch (RuntimeException e) {
h.disableComponents(false);
throw e;
}
}
}
public void stop() {
int reason = bundleContext.getBundle().getState() == Bundle.STOPPING
? ComponentConstants.DEACTIVATION_REASON_BUNDLE_STOPPED
: ComponentConstants.DEACTIVATION_REASON_DISPOSED;
for (ComponentHolder<?> h : holders) {
h.disposeComponents(reason);
}
}
public ComponentDescriptor addComponent(Bean<Object> component) {
ComponentDescriptor descriptor = new ComponentDescriptor(component, this);
descriptors.put(component, descriptor);
return descriptor;
}
public BundleContext getBundleContext() {
return bundleContext;
}
public Set<Bean<?>> getComponents() {
return descriptors.keySet();
}
public ComponentDescriptor getDescriptor(Bean<?> component) {
return (ComponentDescriptor) descriptors.get(component);
}
@Override
public boolean isActive() {
return true;
}
@Override
public ScrConfiguration getConfiguration() {
return m_configuration;
}
@Override
public void schedule(Runnable runnable) {
if (isActive()) {
m_componentActor.execute(runnable);
}
}
@Override
public long registerComponentId(AbstractComponentManager<?> sAbstractComponentManager) {
return componentId.incrementAndGet();
}
@Override
public void unregisterComponentId(AbstractComponentManager<?> sAbstractComponentManager) {
}
@Override
public <S, T> void registerMissingDependency(org.apache.felix.scr.impl.manager.DependencyManager<S, T> dependencyManager, ServiceReference<T> serviceReference, int trackingCount) {
//check that the service reference is from scr
if (serviceReference.getProperty(ComponentConstants.COMPONENT_NAME) == null || serviceReference.getProperty(ComponentConstants.COMPONENT_ID) == null) {
return;
}
List<Entry> dependencyManagers = m_missingDependencies.get(serviceReference);
if (dependencyManagers == null) {
dependencyManagers = new ArrayList<>();
m_missingDependencies.put(serviceReference, dependencyManagers);
}
dependencyManagers.add(new Entry(dependencyManager, trackingCount));
}
@Override
public <T> void missingServicePresent(final ServiceReference<T> serviceReference) {
final List<Entry> dependencyManagers = m_missingDependencies.remove(serviceReference);
if (dependencyManagers != null) {
m_componentActor.execute(new Runnable() {
public void run() {
for (Entry entry : dependencyManagers) {
DependencyManager<?, T> dm = entry.getDm();
dm.invokeBindMethodLate(serviceReference, entry.getTrackingCount());
}
}
@Override
public String toString() {
return "Late binding task of reference " + serviceReference + " for dependencyManagers " + dependencyManagers;
}
});
}
}
@Override
public void enableComponent(String name) {
final Collection<ComponentHolder<?>> holders = getComponentHoldersByName(name);
for (ComponentHolder<?> holder : holders) {
try {
log(LogService.LOG_DEBUG, "Enabling Component", holder.getComponentMetadata(), null, null);
holder.enableComponents(true);
} catch (Throwable t) {
log(LogService.LOG_ERROR, "Cannot enable component", holder.getComponentMetadata(), null, t);
}
}
}
@Override
public void disableComponent(String name) {
throw new UnsupportedOperationException();
}
@Override
public RegionConfigurationSupport setRegionConfigurationSupport(ServiceReference<ConfigurationAdmin> reference) {
RegionConfigurationSupport trialRcs = new RegionConfigurationSupport(this, reference) {
protected Collection<ComponentHolder<?>> getComponentHolders(TargetedPID pid) {
return getComponentHoldersByPid(pid);
}
};
RegionConfigurationSupport rcs = registerRegionConfigurationSupport(trialRcs);
for (ComponentHolder<?> holder : holders) {
rcs.configureComponentHolder(holder);
}
return rcs;
}
public RegionConfigurationSupport registerRegionConfigurationSupport(RegionConfigurationSupport trialRcs) {
Long bundleId = trialRcs.getBundleId();
RegionConfigurationSupport existing;
RegionConfigurationSupport previous = null;
while (true) {
existing = bundleToRcsMap.putIfAbsent(bundleId, trialRcs);
if (existing == null) {
trialRcs.start();
return trialRcs;
}
if (existing == previous) {
//the rcs we referenced is still current
return existing;
}
if (existing.reference()) {
//existing can still be used
previous = existing;
} else {
//existing was discarded in another thread, start over
previous = null;
}
}
}
@Override
public void unsetRegionConfigurationSupport(RegionConfigurationSupport rcs) {
if (rcs.dereference()) {
bundleToRcsMap.remove(rcs.getBundleId());
}
}
public void addServiceListener(String classNameFilter, Filter eventFilter,
final ExtendedServiceListener<ExtendedServiceEvent> listener) {
if (eventFilter != null && eventFilter.toString().contains(PrivateRegistryWrapper.PRIVATE)) {
synchronized (privateListeners) {
ServiceListener l = new ServiceListener() {
@Override
public void serviceChanged(ServiceEvent event) {
listener.serviceChanged(new ExtendedServiceEvent(event));
}
};
privateListeners.put(listener, l);
try {
bundleContext.addServiceListener(l, "(&" + classNameFilter + eventFilter.toString() + ")");
} catch (InvalidSyntaxException e) {
throw (IllegalArgumentException) new IllegalArgumentException(
"invalid class name filter").initCause(e);
}
}
return;
}
ListenerInfo listenerInfo;
synchronized (listenerMap) {
log(LogService.LOG_DEBUG, "classNameFilter: " + classNameFilter
+ " event filter: " + eventFilter, null, null, null);
listenerInfo = listenerMap.get(classNameFilter);
if (listenerInfo == null) {
listenerInfo = new ListenerInfo();
listenerMap.put(classNameFilter, listenerInfo);
try {
bundleContext.addServiceListener(listenerInfo, classNameFilter);
} catch (InvalidSyntaxException e) {
throw (IllegalArgumentException) new IllegalArgumentException(
"invalid class name filter").initCause(e);
}
}
}
listenerInfo.add(eventFilter, listener);
}
public void removeServiceListener(String className, Filter filter,
ExtendedServiceListener<ExtendedServiceEvent> listener) {
if (filter != null && filter.toString().contains(PrivateRegistryWrapper.PRIVATE)) {
synchronized (privateListeners) {
ServiceListener l = privateListeners.remove(listener);
bundleContext.removeServiceListener(l);
}
}
synchronized (listenerMap) {
ListenerInfo listenerInfo = listenerMap.get(className);
if (listenerInfo != null) {
if (listenerInfo.remove(filter, listener)) {
listenerMap.remove(className);
bundleContext.removeServiceListener(listenerInfo);
}
}
}
}
public Collection<ComponentHolder<?>> getComponentHoldersByPid(TargetedPID targetedPid) {
String pid = targetedPid.getServicePid();
Set<ComponentHolder<?>> componentHoldersUsingPid = new HashSet<>();
synchronized (holdersByPid) {
Set<ComponentHolder<?>> set = holdersByPid.get(pid);
// only return the entry if non-null and not a reservation
if (set != null) {
for (ComponentHolder<?> holder : set) {
if (targetedPid.matchesTarget(holder.getActivator().getBundleContext().getBundle())) {
componentHoldersUsingPid.add(holder);
}
}
}
}
return componentHoldersUsingPid;
}
public List<ComponentHolder<?>> getComponentHolders() {
synchronized (holdersByName) {
return new ArrayList<>(holdersByName.values());
}
}
public ComponentHolder<?> getComponentHolder(String name) {
return holdersByName.get(name);
}
public Collection<ComponentHolder<?>> getComponentHoldersByName(String name) {
if (name == null) {
return holders;
}
ComponentHolder<?> componentHolder = holdersByName.get(name);
if (componentHolder != null) {
return Collections.<ComponentHolder<?>>singletonList(componentHolder);
}
return Collections.emptyList();
}
@Override
public boolean isLogEnabled(int level) {
if (level >= LogService.LOG_DEBUG) {
return log.isDebugEnabled();
} else if (level >= LogService.LOG_INFO) {
return log.isInfoEnabled();
} else if (level >= LogService.LOG_WARNING) {
return log.isWarnEnabled();
} else {
return log.isErrorEnabled();
}
}
@Override
public void log(int level, String pattern, Object[] arguments, ComponentMetadata metadata, Long componentId, Throwable ex) {
if (isLogEnabled(level)) {
final String message = MessageFormat.format(pattern, arguments);
log(level, message, metadata, componentId, ex);
}
}
@Override
public void log(int level, String message, ComponentMetadata metadata, Long componentId, Throwable ex) {
if (isLogEnabled(level)) {
if (metadata != null) {
if (componentId != null) {
message = "[" + metadata.getName() + "(" + componentId + ")] " + message;
} else {
message = "[" + metadata.getName() + "] " + message;
}
}
if (level >= LogService.LOG_DEBUG) {
log.debug(message, ex);
} else if (level >= LogService.LOG_INFO) {
log.info(message, ex);
} else if (level >= LogService.LOG_WARNING) {
log.warn(message, ex);
} else {
log.error(message, ex);
}
}
}
@Override
public void log(int level, String message, Throwable ex) {
log(level, message, null, ex);
}
@Override
public void log(int level, String message, Object[] arguments, Throwable ex) {
log(level, message, arguments, null, 0L, ex);
}
private static class ListenerInfo implements ServiceListener {
private Map<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>> filterMap = new HashMap<>();
public void serviceChanged(ServiceEvent event) {
ServiceReference<?> ref = event.getServiceReference();
ExtendedServiceEvent extEvent = null;
ExtendedServiceEvent endMatchEvent = null;
Map<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>> filterMap;
synchronized (this) {
filterMap = this.filterMap;
}
for (Map.Entry<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>> entry : filterMap.entrySet()) {
Filter filter = entry.getKey();
if (filter == null || filter.match(ref)) {
if (extEvent == null) {
extEvent = new ExtendedServiceEvent(event);
}
for (ExtendedServiceListener<ExtendedServiceEvent> forwardTo : entry.getValue()) {
forwardTo.serviceChanged(extEvent);
}
} else if (event.getType() == ServiceEvent.MODIFIED) {
if (endMatchEvent == null) {
endMatchEvent = new ExtendedServiceEvent(ServiceEvent.MODIFIED_ENDMATCH, ref);
}
for (ExtendedServiceListener<ExtendedServiceEvent> forwardTo : entry.getValue()) {
forwardTo.serviceChanged(endMatchEvent);
}
}
}
if (extEvent != null) {
extEvent.activateManagers();
}
if (endMatchEvent != null) {
endMatchEvent.activateManagers();
}
}
public synchronized void add(Filter filter, ExtendedServiceListener<ExtendedServiceEvent> listener) {
filterMap = new HashMap<>(filterMap);
List<ExtendedServiceListener<ExtendedServiceEvent>> listeners = filterMap.get(filter);
if (listeners == null) {
listeners = Collections.singletonList(listener);
} else {
listeners = new ArrayList<>(listeners);
listeners.add(listener);
}
filterMap.put(filter, listeners);
}
public synchronized boolean remove(Filter filter, ExtendedServiceListener<ExtendedServiceEvent> listener) {
List<ExtendedServiceListener<ExtendedServiceEvent>> listeners = filterMap.get(filter);
if (listeners != null) {
filterMap = new HashMap<>(filterMap);
listeners = new ArrayList<>(listeners);
listeners.remove(listener);
if (listeners.isEmpty()) {
filterMap.remove(filter);
} else {
filterMap.put(filter, listeners);
}
}
return filterMap.isEmpty();
}
}
private static class Entry {
private final DependencyManager<?, ?> dm;
private final int trackingCount;
private Entry(DependencyManager<?, ?> dm, int trackingCount) {
this.dm = dm;
this.trackingCount = trackingCount;
}
@SuppressWarnings("unchecked")
public <S, T> DependencyManager<S, T> getDm() {
return (DependencyManager<S, T>) dm;
}
public int getTrackingCount() {
return trackingCount;
}
}
private static class CdiComponentHolder<S> extends ConfigurableComponentHolder<S> {
public CdiComponentHolder(ComponentActivator activator, ComponentMetadata metadata) {
super(activator, metadata);
}
@Override
protected ComponentMethods createComponentMethods() {
return new EmptyMethods();
}
@Override
protected AbstractComponentManager<S> createComponentManager(boolean factoryConfiguration) {
ComponentMetadata metadata = getComponentMetadata();
ComponentMethods componentMethods = getComponentMethods();
switch (metadata.getServiceScope()) {
case singleton:
return new CdiSingletonComponentManager<>(this, componentMethods);
case bundle:
return new CdiBundleComponentManager<>(this, componentMethods);
case prototype:
return createPrototypeComponentManager(componentMethods);
default:
throw new IllegalStateException();
}
}
protected AbstractComponentManager<S> createPrototypeComponentManager(ComponentMethods componentMethods) {
return new CdiPrototypeComponentManager<>(this, componentMethods);
}
}
private static class EmptyMethods implements ComponentMethods, ReferenceMethods, ReferenceMethod {
@Override
public void initComponentMethods(ComponentMetadata componentMetadata, Class<?> implementationObjectClass) {
}
@Override
public ComponentMethod getActivateMethod() {
return null;
}
@Override
public ComponentMethod getDeactivateMethod() {
return null;
}
@Override
public ComponentMethod getModifiedMethod() {
return null;
}
@Override
public ReferenceMethods getBindMethods(String refName) {
return this;
}
@Override
public ReferenceMethod getBind() {
return this;
}
@Override
public ReferenceMethod getUnbind() {
return null;
}
@Override
public ReferenceMethod getUpdated() {
return null;
}
@Override
public InitReferenceMethod getInit() {
return null;
}
@Override
public MethodResult invoke(Object componentInstance, ComponentContextImpl<?> componentContext, RefPair<?, ?> refPair, MethodResult methodCallFailureResult, SimpleLogger logger) {
return null;
}
@Override
public <S, T> boolean getServiceObject(ComponentContextImpl<S> key, RefPair<S, T> refPair, BundleContext context, SimpleLogger logger) {
return true;
}
}
private static class CdiPrototypeComponentManager<S> extends PrototypeServiceFactoryComponentManager<S> {
public CdiPrototypeComponentManager(ComponentContainer<S> container, ComponentMethods componentMethods) {
super(container, componentMethods);
}
protected S createImplementationObject(Bundle usingBundle, final SetImplementationObject<S> setter, ComponentContextImpl<S> componentContext) {
return doCreate(this, componentContext, new Consumer<ComponentContextImpl<S>>() {
@Override
public void accept(ComponentContextImpl<S> cc) {
setter.presetComponentContext(cc);
}
});
}
protected void disposeImplementationObject(ComponentContextImpl<S> componentContext, int reason) {
doDestroy(this, componentContext);
}
}
private static class CdiBundleComponentManager<S> extends ServiceFactoryComponentManager<S> {
public CdiBundleComponentManager(ComponentContainer<S> container, ComponentMethods componentMethods) {
super(container, componentMethods);
}
protected S createImplementationObject(Bundle usingBundle, final SetImplementationObject<S> setter, ComponentContextImpl<S> componentContext) {
return doCreate(this, componentContext, new Consumer<ComponentContextImpl<S>>() {
@Override
public void accept(ComponentContextImpl<S> cc) {
setter.presetComponentContext(cc);
}
});
}
protected void disposeImplementationObject(ComponentContextImpl<S> componentContext, int reason) {
doDestroy(this, componentContext);
}
}
private static class CdiSingletonComponentManager<S> extends SingleComponentManager<S> {
public CdiSingletonComponentManager(ComponentContainer<S> container, ComponentMethods componentMethods) {
super(container, componentMethods);
}
protected S createImplementationObject(Bundle usingBundle, final SetImplementationObject<S> setter, ComponentContextImpl<S> componentContext) {
return doCreate(this, componentContext, new Consumer<ComponentContextImpl<S>>() {
@Override
public void accept(ComponentContextImpl<S> cc) {
setter.presetComponentContext(cc);
}
});
}
protected void disposeImplementationObject(ComponentContextImpl<S> componentContext, int reason) {
doDestroy(this, componentContext);
}
}
private static <S> S doCreate(AbstractComponentManager<S> manager, ComponentContextImpl<S> componentContext, Consumer<ComponentContextImpl<S>> setter) {
AbstractDescriptor descriptor = (AbstractDescriptor) manager.getComponentMetadata();
S s = (S) descriptor.activate(componentContext);
componentContext.setImplementationObject( s );
setter.accept(componentContext);
componentContext.setImplementationAccessible( true );
return s;
}
private static <S> void doDestroy(AbstractComponentManager<S> manager, ComponentContextImpl<S> componentContext) {
AbstractDescriptor descriptor = (AbstractDescriptor) manager.getComponentMetadata();
descriptor.deactivate(componentContext);
}
static class ScrConfigurationImpl implements ScrConfiguration {
@Override
public int getLogLevel() {
return 0;
}
@Override
public boolean isFactoryEnabled() {
return false;
}
@Override
public boolean keepInstances() {
return false;
}
@Override
public boolean infoAsService() {
return false;
}
@Override
public long lockTimeout() {
return DEFAULT_LOCK_TIMEOUT_MILLISECONDS;
}
@Override
public long stopTimeout() {
return DEFAULT_STOP_TIMEOUT_MILLISECONDS;
}
}
}