Completes JIRA improvement SGF-294 allowing GemFire Gateway Receivers to be configured for manual start using the Spring Data GemFire XML namespace. This commit completes the improvement in the 1.4 XSD first in order to backport the feature to the SDG 1.4.2 release.
This commit is contained in:
@@ -24,9 +24,11 @@ import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser
|
||||
*/
|
||||
class GatewayReceiverParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return GatewayReceiverFactoryBean.class;
|
||||
@@ -34,15 +36,19 @@ class GatewayReceiverParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
builder.setLazyInit(false);
|
||||
String cacheRef = element.getAttribute("cache-ref");
|
||||
// add cache reference (fallback to default if nothing is specified)
|
||||
builder.addConstructorArgReference((StringUtils.hasText(cacheRef) ? cacheRef : "gemfireCache"));
|
||||
|
||||
builder.addConstructorArgReference((StringUtils.hasText(cacheRef) ? cacheRef
|
||||
: GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
|
||||
builder.setLazyInit(false);
|
||||
|
||||
ParsingUtils.setPropertyValue(element, builder, "bind-address");
|
||||
ParsingUtils.setPropertyValue(element, builder, "start-port");
|
||||
ParsingUtils.setPropertyValue(element, builder, "end-port");
|
||||
ParsingUtils.setPropertyValue(element, builder, "socket-buffer-size");
|
||||
ParsingUtils.setPropertyValue(element, builder, "manual-start");
|
||||
ParsingUtils.setPropertyValue(element, builder, "maximum-time-between-pings");
|
||||
ParsingUtils.setPropertyValue(element, builder, "bind-address");
|
||||
ParsingUtils.setPropertyValue(element, builder, "socket-buffer-size");
|
||||
ParsingUtils.parseTransportFilters(element, parserContext, builder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser
|
||||
*/
|
||||
class GatewaySenderParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@@ -36,12 +37,12 @@ class GatewaySenderParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
|
||||
String cacheRef = element.getAttribute("cache-ref");
|
||||
|
||||
// add cache reference (fallback to default if nothing is specified)
|
||||
builder.addConstructorArgReference((StringUtils.hasText(cacheRef) ? cacheRef
|
||||
: GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
|
||||
: GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
|
||||
|
||||
ParsingUtils.setPropertyValue(element, builder, NAME_ATTRIBUTE);
|
||||
ParsingUtils.setPropertyValue(element, builder, "alert-threshold");
|
||||
ParsingUtils.setPropertyValue(element, builder, "batch-size");
|
||||
ParsingUtils.setPropertyValue(element, builder, "batch-time-interval");
|
||||
@@ -52,39 +53,40 @@ class GatewaySenderParser extends AbstractSimpleBeanDefinitionParser {
|
||||
ParsingUtils.setPropertyValue(element, builder, "manual-start");
|
||||
ParsingUtils.setPropertyValue(element, builder, "maximum-queue-memory");
|
||||
ParsingUtils.setPropertyValue(element, builder, "order-policy");
|
||||
ParsingUtils.setPropertyValue(element, builder, "parallel");
|
||||
ParsingUtils.setPropertyValue(element, builder, "persistent");
|
||||
ParsingUtils.setPropertyValue(element, builder, "remote-distributed-system-id");
|
||||
ParsingUtils.setPropertyValue(element, builder, "socket-buffer-size");
|
||||
ParsingUtils.setPropertyValue(element, builder, "socket-read-timeout");
|
||||
ParsingUtils.setPropertyValue(element, builder, "persistent");
|
||||
ParsingUtils.setPropertyValue(element, builder, "parallel");
|
||||
ParsingUtils.setPropertyValue(element, builder, NAME_ATTRIBUTE);
|
||||
|
||||
Element eventFilterElement = DomUtils.getChildElementByTagName(element, "event-filter");
|
||||
|
||||
if (eventFilterElement != null) {
|
||||
builder.addPropertyValue("eventFilters",
|
||||
ParsingUtils.parseRefOrNestedBeanDeclaration(parserContext, eventFilterElement, builder));
|
||||
builder.addPropertyValue("eventFilters", ParsingUtils.parseRefOrNestedBeanDeclaration(
|
||||
parserContext, eventFilterElement, builder));
|
||||
}
|
||||
|
||||
ParsingUtils.parseTransportFilters(element, parserContext, builder);
|
||||
|
||||
/**
|
||||
* set the name for an inner bean
|
||||
*/
|
||||
// set the name for the GatewaySender as an inner bean
|
||||
if (!StringUtils.hasText(element.getAttribute(NAME_ATTRIBUTE))) {
|
||||
if (element.getParentNode().getNodeName().endsWith("region")) {
|
||||
Element region = (Element) element.getParentNode();
|
||||
String regionName = StringUtils.hasText(region.getAttribute("name")) ? region.getAttribute("name")
|
||||
: region.getAttribute("id");
|
||||
|
||||
int i = 0;
|
||||
String name = regionName + ".gatewaySender#" + i;
|
||||
while (parserContext.getRegistry().isBeanNameInUse(name)) {
|
||||
i++;
|
||||
name = regionName + ".gatewaySender#" + i;
|
||||
String regionName = (StringUtils.hasText(region.getAttribute(NAME_ATTRIBUTE))
|
||||
? region.getAttribute(NAME_ATTRIBUTE) : region.getAttribute(ID_ATTRIBUTE));
|
||||
|
||||
int number = 0;
|
||||
|
||||
String gatewaySenderName = (regionName + ".gatewaySender#" + number);
|
||||
|
||||
while (parserContext.getRegistry().isBeanNameInUse(gatewaySenderName)) {
|
||||
gatewaySenderName = (regionName + ".gatewaySender#" + (++number));
|
||||
}
|
||||
|
||||
builder.addPropertyValue("name", name);
|
||||
builder.addPropertyValue("name", gatewaySenderName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.gemstone.gemfire.cache.Cache;
|
||||
import com.gemstone.gemfire.management.internal.cli.util.spring.StringUtils;
|
||||
|
||||
/**
|
||||
* Base class for GemFire WAN Gateway component factory beans.
|
||||
@@ -34,7 +35,7 @@ import com.gemstone.gemfire.cache.Cache;
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
*/
|
||||
public abstract class AbstractWANComponentFactoryBean<T> implements FactoryBean<T>, InitializingBean, BeanNameAware,
|
||||
public abstract class AbstractWANComponentFactoryBean<T> implements BeanNameAware, FactoryBean<T>, InitializingBean,
|
||||
DisposableBean {
|
||||
|
||||
protected static final List<String> VALID_ORDER_POLICIES = Arrays.asList("KEY", "PARTITION", "THREAD");
|
||||
@@ -51,34 +52,24 @@ public abstract class AbstractWANComponentFactoryBean<T> implements FactoryBean<
|
||||
protected AbstractWANComponentFactoryBean(final Cache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
|
||||
@Override
|
||||
public final void setBeanName(final String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
public void setFactory(Object factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return (name != null ? name: beanName);
|
||||
return (StringUtils.hasText(name) ? name: beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(getName(), "Name cannot be null");
|
||||
Assert.notNull(cache, "Cache cannot be null");
|
||||
doInit();
|
||||
}
|
||||
|
||||
protected abstract void doInit() throws Exception;
|
||||
|
||||
@Override
|
||||
public abstract T getObject() throws Exception;
|
||||
|
||||
@@ -89,9 +80,18 @@ public abstract class AbstractWANComponentFactoryBean<T> implements FactoryBean<
|
||||
public final boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setFactory(Object factory) {
|
||||
this.factory = factory;
|
||||
|
||||
@Override
|
||||
public final void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(getName(), "Name must not be null.");
|
||||
Assert.notNull(cache, "Cache must not be null.");
|
||||
doInit();
|
||||
}
|
||||
|
||||
|
||||
protected abstract void doInit() throws Exception;
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.gemfire.wan;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@@ -29,20 +31,26 @@ import com.gemstone.gemfire.cache.wan.GatewayTransportFilter;
|
||||
* FactoryBean for creating a GemFire {@link GatewayReceiver}.
|
||||
*
|
||||
* @author David Turanski
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.wan.AbstractWANComponentFactoryBean
|
||||
* @see com.gemstone.gemfire.cache.Cache
|
||||
* @see com.gemstone.gemfire.cache.wan.GatewayReceiver
|
||||
* @see com.gemstone.gemfire.cache.wan.GatewayReceiverFactory
|
||||
* @since 1.2.2
|
||||
*/
|
||||
public class GatewayReceiverFactoryBean extends AbstractWANComponentFactoryBean<GatewayReceiver> {
|
||||
private GatewayReceiver gatewayReceiver;
|
||||
public class GatewayReceiverFactoryBean extends AbstractWANComponentFactoryBean<GatewayReceiver>
|
||||
implements SmartLifecycle {
|
||||
|
||||
private List<GatewayTransportFilter> transportFilters;
|
||||
private boolean manualStart = false;
|
||||
|
||||
private Integer startPort;
|
||||
private volatile GatewayReceiver gatewayReceiver;
|
||||
|
||||
private Integer endPort;
|
||||
|
||||
private Integer maximumTimeBetweenPings;
|
||||
|
||||
private Integer socketBufferSize;
|
||||
private Integer startPort;
|
||||
|
||||
private List<GatewayTransportFilter> transportFilters;
|
||||
|
||||
private String bindAddress;
|
||||
|
||||
@@ -63,44 +71,48 @@ public class GatewayReceiverFactoryBean extends AbstractWANComponentFactoryBean<
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return GatewayReceiver.class;
|
||||
return (gatewayReceiver != null ? gatewayReceiver.getClass() : GatewayReceiver.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInit() throws Exception {
|
||||
GatewayReceiverFactory gatewayReceiverFactory = cache.createGatewayReceiverFactory();
|
||||
|
||||
if (!CollectionUtils.isEmpty(transportFilters)) {
|
||||
for (GatewayTransportFilter transportFilter : transportFilters) {
|
||||
gatewayReceiverFactory.addGatewayTransportFilter(transportFilter);
|
||||
}
|
||||
}
|
||||
int minPort = (startPort == null) ? GatewayReceiver.DEFAULT_START_PORT : startPort;
|
||||
int maxPort = (endPort == null) ? GatewayReceiver.DEFAULT_END_PORT : endPort;
|
||||
Assert.isTrue(minPort <= maxPort, "startPort must be less then or equal to " + maxPort);
|
||||
gatewayReceiverFactory.setStartPort(minPort);
|
||||
gatewayReceiverFactory.setEndPort(maxPort);
|
||||
if (socketBufferSize != null) {
|
||||
gatewayReceiverFactory.setSocketBufferSize(socketBufferSize);
|
||||
}
|
||||
if (maximumTimeBetweenPings != null) {
|
||||
gatewayReceiverFactory.setMaximumTimeBetweenPings(maximumTimeBetweenPings);
|
||||
}
|
||||
|
||||
if (bindAddress != null) {
|
||||
gatewayReceiverFactory.setBindAddress(bindAddress);
|
||||
}
|
||||
|
||||
int minPort = (startPort != null ? startPort : GatewayReceiver.DEFAULT_START_PORT);
|
||||
int maxPort = (endPort != null ? endPort : GatewayReceiver.DEFAULT_END_PORT);
|
||||
|
||||
Assert.isTrue(minPort <= maxPort, String.format("'startPort' must be less than or equal to %1$d.", maxPort));
|
||||
|
||||
gatewayReceiverFactory.setStartPort(minPort);
|
||||
gatewayReceiverFactory.setEndPort(maxPort);
|
||||
|
||||
if (maximumTimeBetweenPings != null) {
|
||||
gatewayReceiverFactory.setMaximumTimeBetweenPings(maximumTimeBetweenPings);
|
||||
}
|
||||
|
||||
if (socketBufferSize != null) {
|
||||
gatewayReceiverFactory.setSocketBufferSize(socketBufferSize);
|
||||
}
|
||||
|
||||
gatewayReceiver = gatewayReceiverFactory.create();
|
||||
|
||||
gatewayReceiver.start();
|
||||
|
||||
}
|
||||
|
||||
public void setGatewayReceiver(GatewayReceiver gatewayReceiver) {
|
||||
public void setGatewayReceiver(final GatewayReceiver gatewayReceiver) {
|
||||
this.gatewayReceiver = gatewayReceiver;
|
||||
}
|
||||
|
||||
public void setTransportFilters(List<GatewayTransportFilter> transportFilters) {
|
||||
this.transportFilters = transportFilters;
|
||||
public void setBindAddress(String bindAddress) {
|
||||
this.bindAddress = bindAddress;
|
||||
}
|
||||
|
||||
public void setStartPort(Integer startPort) {
|
||||
@@ -111,6 +123,10 @@ public class GatewayReceiverFactoryBean extends AbstractWANComponentFactoryBean<
|
||||
this.endPort = endPort;
|
||||
}
|
||||
|
||||
public void setManualStart(Boolean manualStart) {
|
||||
this.manualStart = Boolean.TRUE.equals(manualStart);
|
||||
}
|
||||
|
||||
public void setMaximumTimeBetweenPings(Integer maximumTimeBetweenPings) {
|
||||
this.maximumTimeBetweenPings = maximumTimeBetweenPings;
|
||||
}
|
||||
@@ -119,8 +135,48 @@ public class GatewayReceiverFactoryBean extends AbstractWANComponentFactoryBean<
|
||||
this.socketBufferSize = socketBufferSize;
|
||||
}
|
||||
|
||||
public void setBindAddress(String bindAddress) {
|
||||
this.bindAddress = bindAddress;
|
||||
public void setTransportFilters(List<GatewayTransportFilter> transportFilters) {
|
||||
this.transportFilters = transportFilters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoStartup() {
|
||||
return !manualStart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPhase() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return gatewayReceiver.isRunning();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
Assert.state(gatewayReceiver != null, "The GatewayReceiver was not properly configured and initialized!");
|
||||
|
||||
if (!isRunning()) {
|
||||
try {
|
||||
gatewayReceiver.start();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException("Failed to start Gateway Receiver due to I/O error.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
gatewayReceiver.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(final Runnable callback) {
|
||||
stop();
|
||||
callback.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,6 +33,13 @@ import com.gemstone.gemfire.cache.wan.GatewayTransportFilter;
|
||||
*
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
* @see org.springframework.context.SmartLifecycle
|
||||
* @see org.springframework.data.gemfire.wan.AbstractWANComponentFactoryBean
|
||||
* @see com.gemstone.gemfire.cache.Cache
|
||||
* @see com.gemstone.gemfire.cache.util.Gateway
|
||||
* @see com.gemstone.gemfire.cache.wan.GatewaySender
|
||||
* @see com.gemstone.gemfire.cache.wan.GatewaySenderFactory
|
||||
* @since 1.2.2
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<GatewaySender>
|
||||
@@ -81,7 +88,7 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return GatewaySender.class;
|
||||
return (gatewaySender != null ? gatewaySender.getClass() : GatewaySender.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,6 +166,7 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
|
||||
|
||||
GatewaySenderWrapper wrapper = new GatewaySenderWrapper(gatewaySenderFactory.create(getName(),
|
||||
remoteDistributedSystemId));
|
||||
|
||||
wrapper.setManualStart(manualStart);
|
||||
gatewaySender = wrapper;
|
||||
}
|
||||
@@ -204,7 +212,7 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
|
||||
}
|
||||
|
||||
public void setManualStart(Boolean manualStart) {
|
||||
this.manualStart = manualStart;
|
||||
this.manualStart = Boolean.TRUE.equals(manualStart);
|
||||
}
|
||||
|
||||
public void setMaximumQueueMemory(Integer maximumQueueMemory) {
|
||||
@@ -247,12 +255,38 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
|
||||
this.socketReadTimeout = socketReadTimeout;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.SmartLifecycle#isAutoStartup()
|
||||
*/
|
||||
@Override
|
||||
public boolean isAutoStartup() {
|
||||
return !manualStart;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.Phased#getPhase()
|
||||
*/
|
||||
@Override
|
||||
public int getPhase() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.Lifecycle#isRunning()
|
||||
*/
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return gatewaySender.isRunning();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.Lifecycle#start()
|
||||
*/
|
||||
@Override
|
||||
public synchronized void start() {
|
||||
if (!gatewaySender.isRunning()){
|
||||
Assert.notNull(gatewaySender, "The GatewaySender was not properly configured and initialized!");
|
||||
|
||||
if (!isRunning()){
|
||||
gatewaySender.start();
|
||||
}
|
||||
}
|
||||
@@ -265,30 +299,6 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
|
||||
gatewaySender.stop();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.Lifecycle#isRunning()
|
||||
*/
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return gatewaySender.isRunning();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.Phased#getPhase()
|
||||
*/
|
||||
@Override
|
||||
public int getPhase() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.SmartLifecycle#isAutoStartup()
|
||||
*/
|
||||
@Override
|
||||
public boolean isAutoStartup() {
|
||||
return !manualStart;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.SmartLifecycle#stop(java.lang.Runnable)
|
||||
*/
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
package org.springframework.data.gemfire.wan;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.gemstone.gemfire.cache.util.Gateway;
|
||||
import com.gemstone.gemfire.cache.wan.GatewayEventFilter;
|
||||
import com.gemstone.gemfire.cache.wan.GatewaySender;
|
||||
import com.gemstone.gemfire.cache.wan.GatewayTransportFilter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by dturanski on 9/16/13.
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
* @see com.gemstone.gemfire.cache.util.Gateway
|
||||
* @see com.gemstone.gemfire.cache.wan.GatewaySender
|
||||
*/
|
||||
public class GatewaySenderWrapper implements GatewaySender {
|
||||
private final GatewaySender delegate;
|
||||
|
||||
private boolean manualStart;
|
||||
|
||||
public GatewaySenderWrapper(GatewaySender delegate) {
|
||||
this.delegate = delegate;
|
||||
private final GatewaySender delegate;
|
||||
|
||||
public GatewaySenderWrapper(final GatewaySender gatewaySender) {
|
||||
Assert.notNull(gatewaySender, "The target Gateway Sender must not be null.");
|
||||
this.delegate = gatewaySender;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -151,4 +159,10 @@ public class GatewaySenderWrapper implements GatewaySender {
|
||||
public void setManualStart(boolean manualStart) {
|
||||
this.manualStart = manualStart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.delegate.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user