Jakarta EE 9 migration

Upgrades many dependency declarations; removes old EJB 2.x support and outdated Servlet-based integrations (Commons FileUpload, FreeMarker JSP support, Tiles).

Closes gh-22093
Closes gh-25354
Closes gh-26185
Closes gh-27423
See gh-27424
This commit is contained in:
Juergen Hoeller
2021-09-17 09:14:07 +02:00
parent 5822f1bf85
commit d84ca2ba90
1291 changed files with 4992 additions and 25322 deletions

View File

@@ -1,171 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* 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
*
* https://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.springframework.cache.ehcache;
import java.util.concurrent.Callable;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.Status;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* {@link Cache} implementation on top of an {@link Ehcache} instance.
*
* @author Costin Leau
* @author Juergen Hoeller
* @author Stephane Nicoll
* @since 3.1
* @see EhCacheCacheManager
*/
public class EhCacheCache implements Cache {
private final Ehcache cache;
/**
* Create an {@link EhCacheCache} instance.
* @param ehcache the backing Ehcache instance
*/
public EhCacheCache(Ehcache ehcache) {
Assert.notNull(ehcache, "Ehcache must not be null");
Status status = ehcache.getStatus();
if (!Status.STATUS_ALIVE.equals(status)) {
throw new IllegalArgumentException(
"An 'alive' Ehcache is required - current cache is " + status.toString());
}
this.cache = ehcache;
}
@Override
public final String getName() {
return this.cache.getName();
}
@Override
public final Ehcache getNativeCache() {
return this.cache;
}
@Override
@Nullable
public ValueWrapper get(Object key) {
Element element = lookup(key);
return toValueWrapper(element);
}
@SuppressWarnings("unchecked")
@Override
@Nullable
public <T> T get(Object key, @Nullable Class<T> type) {
Element element = this.cache.get(key);
Object value = (element != null ? element.getObjectValue() : null);
if (value != null && type != null && !type.isInstance(value)) {
throw new IllegalStateException(
"Cached value is not of required type [" + type.getName() + "]: " + value);
}
return (T) value;
}
@SuppressWarnings("unchecked")
@Override
@Nullable
public <T> T get(Object key, Callable<T> valueLoader) {
Element element = lookup(key);
if (element != null) {
return (T) element.getObjectValue();
}
else {
this.cache.acquireWriteLockOnKey(key);
try {
element = lookup(key); // one more attempt with the write lock
if (element != null) {
return (T) element.getObjectValue();
}
else {
return loadValue(key, valueLoader);
}
}
finally {
this.cache.releaseWriteLockOnKey(key);
}
}
}
private <T> T loadValue(Object key, Callable<T> valueLoader) {
T value;
try {
value = valueLoader.call();
}
catch (Throwable ex) {
throw new ValueRetrievalException(key, valueLoader, ex);
}
put(key, value);
return value;
}
@Override
public void put(Object key, @Nullable Object value) {
this.cache.put(new Element(key, value));
}
@Override
@Nullable
public ValueWrapper putIfAbsent(Object key, @Nullable Object value) {
Element existingElement = this.cache.putIfAbsent(new Element(key, value));
return toValueWrapper(existingElement);
}
@Override
public void evict(Object key) {
this.cache.remove(key);
}
@Override
public boolean evictIfPresent(Object key) {
return this.cache.remove(key);
}
@Override
public void clear() {
this.cache.removeAll();
}
@Override
public boolean invalidate() {
boolean notEmpty = (this.cache.getSize() > 0);
this.cache.removeAll();
return notEmpty;
}
@Nullable
private Element lookup(Object key) {
return this.cache.get(key);
}
@Nullable
private ValueWrapper toValueWrapper(@Nullable Element element) {
return (element != null ? new SimpleValueWrapper(element.getObjectValue()) : null);
}
}

View File

@@ -1,117 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* 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
*
* https://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.springframework.cache.ehcache;
import java.util.Collection;
import java.util.LinkedHashSet;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Status;
import org.springframework.cache.Cache;
import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* CacheManager backed by an EhCache {@link net.sf.ehcache.CacheManager}.
*
* @author Costin Leau
* @author Juergen Hoeller
* @author Stephane Nicoll
* @since 3.1
* @see EhCacheCache
*/
public class EhCacheCacheManager extends AbstractTransactionSupportingCacheManager {
@Nullable
private net.sf.ehcache.CacheManager cacheManager;
/**
* Create a new EhCacheCacheManager, setting the target EhCache CacheManager
* through the {@link #setCacheManager} bean property.
*/
public EhCacheCacheManager() {
}
/**
* Create a new EhCacheCacheManager for the given backing EhCache CacheManager.
* @param cacheManager the backing EhCache {@link net.sf.ehcache.CacheManager}
*/
public EhCacheCacheManager(net.sf.ehcache.CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
/**
* Set the backing EhCache {@link net.sf.ehcache.CacheManager}.
*/
public void setCacheManager(@Nullable net.sf.ehcache.CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
/**
* Return the backing EhCache {@link net.sf.ehcache.CacheManager}.
*/
@Nullable
public net.sf.ehcache.CacheManager getCacheManager() {
return this.cacheManager;
}
@Override
public void afterPropertiesSet() {
if (getCacheManager() == null) {
setCacheManager(EhCacheManagerUtils.buildCacheManager());
}
super.afterPropertiesSet();
}
@Override
protected Collection<Cache> loadCaches() {
net.sf.ehcache.CacheManager cacheManager = getCacheManager();
Assert.state(cacheManager != null, "No CacheManager set");
Status status = cacheManager.getStatus();
if (!Status.STATUS_ALIVE.equals(status)) {
throw new IllegalStateException(
"An 'alive' EhCache CacheManager is required - current cache is " + status.toString());
}
String[] names = getCacheManager().getCacheNames();
Collection<Cache> caches = new LinkedHashSet<>(names.length);
for (String name : names) {
caches.add(new EhCacheCache(getCacheManager().getEhcache(name)));
}
return caches;
}
@Override
protected Cache getMissingCache(String name) {
net.sf.ehcache.CacheManager cacheManager = getCacheManager();
Assert.state(cacheManager != null, "No CacheManager set");
// Check the EhCache cache again (in case the cache was added at runtime)
Ehcache ehcache = cacheManager.getEhcache(name);
if (ehcache != null) {
return new EhCacheCache(ehcache);
}
return null;
}
}

View File

@@ -1,329 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* 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
*
* https://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.springframework.cache.ehcache;
import java.util.Set;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.constructs.blocking.BlockingCache;
import net.sf.ehcache.constructs.blocking.CacheEntryFactory;
import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;
import net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory;
import net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache;
import net.sf.ehcache.event.CacheEventListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
/**
* {@link FactoryBean} that creates a named EhCache {@link net.sf.ehcache.Cache} instance
* (or a decorator that implements the {@link net.sf.ehcache.Ehcache} interface),
* representing a cache region within an EhCache {@link net.sf.ehcache.CacheManager}.
*
* <p>If the specified named cache is not configured in the cache configuration descriptor,
* this FactoryBean will construct an instance of a Cache with the provided name and the
* specified cache properties and add it to the CacheManager for later retrieval. If some
* or all properties are not set at configuration time, this FactoryBean will use defaults.
*
* <p>Note: If the named Cache instance is found, the properties will be ignored and the
* Cache instance will be retrieved from the CacheManager.
*
* <p>Note: As of Spring 5.0, Spring's EhCache support requires EhCache 2.10 or higher.
*
* @author Juergen Hoeller
* @author Dmitriy Kopylenko
* @since 1.1.1
* @see #setCacheManager
* @see EhCacheManagerFactoryBean
* @see net.sf.ehcache.Cache
*/
public class EhCacheFactoryBean extends CacheConfiguration implements FactoryBean<Ehcache>, BeanNameAware, InitializingBean {
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private CacheManager cacheManager;
private boolean blocking = false;
@Nullable
private CacheEntryFactory cacheEntryFactory;
@Nullable
private BootstrapCacheLoader bootstrapCacheLoader;
@Nullable
private Set<CacheEventListener> cacheEventListeners;
private boolean disabled = false;
@Nullable
private String beanName;
@Nullable
private Ehcache cache;
public EhCacheFactoryBean() {
setMaxEntriesLocalHeap(10000);
setMaxEntriesLocalDisk(10000000);
setTimeToLiveSeconds(120);
setTimeToIdleSeconds(120);
}
/**
* Set a CacheManager from which to retrieve a named Cache instance.
* By default, {@code CacheManager.getInstance()} will be called.
* <p>Note that in particular for persistent caches, it is advisable to
* properly handle the shutdown of the CacheManager: Set up a separate
* EhCacheManagerFactoryBean and pass a reference to this bean property.
* <p>A separate EhCacheManagerFactoryBean is also necessary for loading
* EhCache configuration from a non-default config location.
* @see EhCacheManagerFactoryBean
* @see net.sf.ehcache.CacheManager#getInstance
*/
public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
/**
* Set a name for which to retrieve or create a cache instance.
* Default is the bean name of this EhCacheFactoryBean.
*/
public void setCacheName(String cacheName) {
setName(cacheName);
}
/**
* Set the time to live.
* @see #setTimeToLiveSeconds(long)
*/
public void setTimeToLive(int timeToLive) {
setTimeToLiveSeconds(timeToLive);
}
/**
* Set the time to idle.
* @see #setTimeToIdleSeconds(long)
*/
public void setTimeToIdle(int timeToIdle) {
setTimeToIdleSeconds(timeToIdle);
}
/**
* Set the disk spool buffer size (in MB).
* @see #setDiskSpoolBufferSizeMB(int)
*/
public void setDiskSpoolBufferSize(int diskSpoolBufferSize) {
setDiskSpoolBufferSizeMB(diskSpoolBufferSize);
}
/**
* Set whether to use a blocking cache that lets read attempts block
* until the requested element is created.
* <p>If you intend to build a self-populating blocking cache,
* consider specifying a {@link #setCacheEntryFactory CacheEntryFactory}.
* @see net.sf.ehcache.constructs.blocking.BlockingCache
* @see #setCacheEntryFactory
*/
public void setBlocking(boolean blocking) {
this.blocking = blocking;
}
/**
* Set an EhCache {@link net.sf.ehcache.constructs.blocking.CacheEntryFactory}
* to use for a self-populating cache. If such a factory is specified,
* the cache will be decorated with EhCache's
* {@link net.sf.ehcache.constructs.blocking.SelfPopulatingCache}.
* <p>The specified factory can be of type
* {@link net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory},
* which will lead to the use of an
* {@link net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache}.
* <p>Note: Any such self-populating cache is automatically a blocking cache.
* @see net.sf.ehcache.constructs.blocking.SelfPopulatingCache
* @see net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache
* @see net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory
*/
public void setCacheEntryFactory(CacheEntryFactory cacheEntryFactory) {
this.cacheEntryFactory = cacheEntryFactory;
}
/**
* Set an EhCache {@link net.sf.ehcache.bootstrap.BootstrapCacheLoader}
* for this cache, if any.
*/
public void setBootstrapCacheLoader(BootstrapCacheLoader bootstrapCacheLoader) {
this.bootstrapCacheLoader = bootstrapCacheLoader;
}
/**
* Specify EhCache {@link net.sf.ehcache.event.CacheEventListener cache event listeners}
* to registered with this cache.
*/
public void setCacheEventListeners(Set<CacheEventListener> cacheEventListeners) {
this.cacheEventListeners = cacheEventListeners;
}
/**
* Set whether this cache should be marked as disabled.
* @see net.sf.ehcache.Cache#setDisabled
*/
public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void afterPropertiesSet() throws CacheException {
// If no cache name given, use bean name as cache name.
String cacheName = getName();
if (cacheName == null) {
cacheName = this.beanName;
if (cacheName != null) {
setName(cacheName);
}
}
// If no CacheManager given, fetch the default.
if (this.cacheManager == null) {
if (logger.isDebugEnabled()) {
logger.debug("Using default EhCache CacheManager for cache region '" + cacheName + "'");
}
this.cacheManager = CacheManager.getInstance();
}
synchronized (this.cacheManager) {
// Fetch cache region: If none with the given name exists, create one on the fly.
Ehcache rawCache;
boolean cacheExists = this.cacheManager.cacheExists(cacheName);
if (cacheExists) {
if (logger.isDebugEnabled()) {
logger.debug("Using existing EhCache cache region '" + cacheName + "'");
}
rawCache = this.cacheManager.getEhcache(cacheName);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Creating new EhCache cache region '" + cacheName + "'");
}
rawCache = createCache();
rawCache.setBootstrapCacheLoader(this.bootstrapCacheLoader);
}
if (this.cacheEventListeners != null) {
for (CacheEventListener listener : this.cacheEventListeners) {
rawCache.getCacheEventNotificationService().registerListener(listener);
}
}
// Needs to happen after listener registration but before setStatisticsEnabled
if (!cacheExists) {
this.cacheManager.addCache(rawCache);
}
if (this.disabled) {
rawCache.setDisabled(true);
}
Ehcache decoratedCache = decorateCache(rawCache);
if (decoratedCache != rawCache) {
this.cacheManager.replaceCacheWithDecoratedCache(rawCache, decoratedCache);
}
this.cache = decoratedCache;
}
}
/**
* Create a raw Cache object based on the configuration of this FactoryBean.
*/
protected Cache createCache() {
return new Cache(this);
}
/**
* Decorate the given Cache, if necessary.
* @param cache the raw Cache object, based on the configuration of this FactoryBean
* @return the (potentially decorated) cache object to be registered with the CacheManager
*/
protected Ehcache decorateCache(Ehcache cache) {
if (this.cacheEntryFactory != null) {
if (this.cacheEntryFactory instanceof UpdatingCacheEntryFactory) {
return new UpdatingSelfPopulatingCache(cache, (UpdatingCacheEntryFactory) this.cacheEntryFactory);
}
else {
return new SelfPopulatingCache(cache, this.cacheEntryFactory);
}
}
if (this.blocking) {
return new BlockingCache(cache);
}
return cache;
}
@Override
@Nullable
public Ehcache getObject() {
return this.cache;
}
/**
* Predict the particular {@code Ehcache} implementation that will be returned from
* {@link #getObject()} based on logic in {@link #createCache()} and
* {@link #decorateCache(Ehcache)} as orchestrated by {@link #afterPropertiesSet()}.
*/
@Override
public Class<? extends Ehcache> getObjectType() {
if (this.cache != null) {
return this.cache.getClass();
}
if (this.cacheEntryFactory != null) {
if (this.cacheEntryFactory instanceof UpdatingCacheEntryFactory) {
return UpdatingSelfPopulatingCache.class;
}
else {
return SelfPopulatingCache.class;
}
}
if (this.blocking) {
return BlockingCache.class;
}
return Cache.class;
}
@Override
public boolean isSingleton() {
return true;
}
}

View File

@@ -1,199 +0,0 @@
/*
* Copyright 2002-2021 the original author or authors.
*
* 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
*
* https://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.springframework.cache.ehcache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.ConfigurationFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
/**
* {@link FactoryBean} that exposes an EhCache {@link net.sf.ehcache.CacheManager}
* instance (independent or shared), configured from a specified config location.
*
* <p>If no config location is specified, a CacheManager will be configured from
* "ehcache.xml" in the root of the class path (that is, default EhCache initialization
* - as defined in the EhCache docs - will apply).
*
* <p>Setting up a separate EhCacheManagerFactoryBean is also advisable when using
* EhCacheFactoryBean, as it provides a (by default) independent CacheManager instance
* and cares for proper shutdown of the CacheManager. EhCacheManagerFactoryBean is
* also necessary for loading EhCache configuration from a non-default config location.
*
* <p>Note: As of Spring 5.0, Spring's EhCache support requires EhCache 2.10 or higher.
*
* @author Juergen Hoeller
* @author Dmitriy Kopylenko
* @since 1.1.1
* @see #setConfigLocation
* @see #setShared
* @see EhCacheFactoryBean
* @see net.sf.ehcache.CacheManager
*/
public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, InitializingBean, DisposableBean {
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private Resource configLocation;
@Nullable
private String cacheManagerName;
private boolean acceptExisting = false;
private boolean shared = false;
@Nullable
private CacheManager cacheManager;
private boolean locallyManaged = true;
/**
* Set the location of the EhCache config file. A typical value is "/WEB-INF/ehcache.xml".
* <p>Default is "ehcache.xml" in the root of the class path, or if not found,
* "ehcache-failsafe.xml" in the EhCache jar (default EhCache initialization).
* @see net.sf.ehcache.CacheManager#create(java.io.InputStream)
* @see net.sf.ehcache.CacheManager#CacheManager(java.io.InputStream)
*/
public void setConfigLocation(Resource configLocation) {
this.configLocation = configLocation;
}
/**
* Set the name of the EhCache CacheManager (if a specific name is desired).
* @see net.sf.ehcache.config.Configuration#setName(String)
*/
public void setCacheManagerName(String cacheManagerName) {
this.cacheManagerName = cacheManagerName;
}
/**
* Set whether an existing EhCache CacheManager of the same name will be accepted
* for this EhCacheManagerFactoryBean setup. Default is "false".
* <p>Typically used in combination with {@link #setCacheManagerName "cacheManagerName"}
* but will simply work with the default CacheManager name if none specified.
* All references to the same CacheManager name (or the same default) in the
* same ClassLoader space will share the specified CacheManager then.
* @see #setCacheManagerName
* #see #setShared
* @see net.sf.ehcache.CacheManager#getCacheManager(String)
* @see net.sf.ehcache.CacheManager#CacheManager()
*/
public void setAcceptExisting(boolean acceptExisting) {
this.acceptExisting = acceptExisting;
}
/**
* Set whether the EhCache CacheManager should be shared (as a singleton at the
* ClassLoader level) or independent (typically local within the application).
* Default is "false", creating an independent local instance.
* <p><b>NOTE:</b> This feature allows for sharing this EhCacheManagerFactoryBean's
* CacheManager with any code calling <code>CacheManager.create()</code> in the same
* ClassLoader space, with no need to agree on a specific CacheManager name.
* However, it only supports a single EhCacheManagerFactoryBean involved which will
* control the lifecycle of the underlying CacheManager (in particular, its shutdown).
* <p>This flag overrides {@link #setAcceptExisting "acceptExisting"} if both are set,
* since it indicates the 'stronger' mode of sharing.
* @see #setCacheManagerName
* @see #setAcceptExisting
* @see net.sf.ehcache.CacheManager#create()
* @see net.sf.ehcache.CacheManager#CacheManager()
*/
public void setShared(boolean shared) {
this.shared = shared;
}
@Override
public void afterPropertiesSet() throws CacheException {
if (logger.isDebugEnabled()) {
logger.debug("Initializing EhCache CacheManager" +
(this.cacheManagerName != null ? " '" + this.cacheManagerName + "'" : ""));
}
Configuration configuration = (this.configLocation != null ?
EhCacheManagerUtils.parseConfiguration(this.configLocation) : ConfigurationFactory.parseConfiguration());
if (this.cacheManagerName != null) {
configuration.setName(this.cacheManagerName);
}
if (this.shared) {
// Old-school EhCache singleton sharing...
// No way to find out whether we actually created a new CacheManager
// or just received an existing singleton reference.
this.cacheManager = CacheManager.create(configuration);
}
else if (this.acceptExisting) {
// EhCache 2.5+: Reusing an existing CacheManager of the same name.
// Basically the same code as in CacheManager.getInstance(String),
// just storing whether we're dealing with an existing instance.
synchronized (CacheManager.class) {
this.cacheManager = CacheManager.getCacheManager(this.cacheManagerName);
if (this.cacheManager == null) {
this.cacheManager = new CacheManager(configuration);
}
else {
this.locallyManaged = false;
}
}
}
else {
// Throwing an exception if a CacheManager of the same name exists already...
this.cacheManager = new CacheManager(configuration);
}
}
@Override
@Nullable
public CacheManager getObject() {
return this.cacheManager;
}
@Override
public Class<? extends CacheManager> getObjectType() {
return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class);
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public void destroy() {
if (this.cacheManager != null && this.locallyManaged) {
if (logger.isDebugEnabled()) {
logger.debug("Shutting down EhCache CacheManager" +
(this.cacheManagerName != null ? " '" + this.cacheManagerName + "'" : ""));
}
this.cacheManager.shutdown();
}
}
}

View File

@@ -1,125 +0,0 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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
*
* https://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.springframework.cache.ehcache;
import java.io.IOException;
import java.io.InputStream;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.ConfigurationFactory;
import org.springframework.core.io.Resource;
/**
* Convenient builder methods for EhCache 2.5+ {@link CacheManager} setup,
* providing easy programmatic bootstrapping from a Spring-provided resource.
* This is primarily intended for use within {@code @Bean} methods in a
* Spring configuration class.
*
* <p>These methods are a simple alternative to custom {@link CacheManager} setup
* code. For any advanced purposes, consider using {@link #parseConfiguration},
* customizing the configuration object, and then calling the
* {@link CacheManager#CacheManager(Configuration)} constructor.
*
* @author Juergen Hoeller
* @since 4.1
*/
public abstract class EhCacheManagerUtils {
/**
* Build an EhCache {@link CacheManager} from the default configuration.
* <p>The CacheManager will be configured from "ehcache.xml" in the root of the class path
* (that is, default EhCache initialization - as defined in the EhCache docs - will apply).
* If no configuration file can be found, a fail-safe fallback configuration will be used.
* @return the new EhCache CacheManager
* @throws CacheException in case of configuration parsing failure
*/
public static CacheManager buildCacheManager() throws CacheException {
return new CacheManager(ConfigurationFactory.parseConfiguration());
}
/**
* Build an EhCache {@link CacheManager} from the default configuration.
* <p>The CacheManager will be configured from "ehcache.xml" in the root of the class path
* (that is, default EhCache initialization - as defined in the EhCache docs - will apply).
* If no configuration file can be found, a fail-safe fallback configuration will be used.
* @param name the desired name of the cache manager
* @return the new EhCache CacheManager
* @throws CacheException in case of configuration parsing failure
*/
public static CacheManager buildCacheManager(String name) throws CacheException {
Configuration configuration = ConfigurationFactory.parseConfiguration();
configuration.setName(name);
return new CacheManager(configuration);
}
/**
* Build an EhCache {@link CacheManager} from the given configuration resource.
* @param configLocation the location of the configuration file (as a Spring resource)
* @return the new EhCache CacheManager
* @throws CacheException in case of configuration parsing failure
*/
public static CacheManager buildCacheManager(Resource configLocation) throws CacheException {
return new CacheManager(parseConfiguration(configLocation));
}
/**
* Build an EhCache {@link CacheManager} from the given configuration resource.
* @param name the desired name of the cache manager
* @param configLocation the location of the configuration file (as a Spring resource)
* @return the new EhCache CacheManager
* @throws CacheException in case of configuration parsing failure
*/
public static CacheManager buildCacheManager(String name, Resource configLocation) throws CacheException {
Configuration configuration = parseConfiguration(configLocation);
configuration.setName(name);
return new CacheManager(configuration);
}
/**
* Parse EhCache configuration from the given resource, for further use with
* custom {@link CacheManager} creation.
* @param configLocation the location of the configuration file (as a Spring resource)
* @return the EhCache Configuration handle
* @throws CacheException in case of configuration parsing failure
* @see CacheManager#CacheManager(Configuration)
* @see CacheManager#create(Configuration)
*/
public static Configuration parseConfiguration(Resource configLocation) throws CacheException {
InputStream is = null;
try {
is = configLocation.getInputStream();
return ConfigurationFactory.parseConfiguration(is);
}
catch (IOException ex) {
throw new CacheException("Failed to parse EhCache configuration resource", ex);
}
finally {
if (is != null) {
try {
is.close();
}
catch (IOException ex) {
// ignore
}
}
}
}
}

View File

@@ -1,17 +0,0 @@
/**
* Support classes for the open source cache
* <a href="https://www.ehcache.org/">EhCache 2.x</a>,
* allowing to set up an EhCache CacheManager and Caches
* as beans in a Spring context.
*
* <p>Note: EhCache 3.x lives in a different package namespace
* and is not covered by the traditional support classes here.
* Instead, consider using it through JCache (JSR-107), with
* Spring's support in {@code org.springframework.cache.jcache}.
*/
@NonNullApi
@NonNullFields
package org.springframework.cache.ehcache;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

View File

@@ -104,7 +104,7 @@ public class MailSendException extends MailException {
* be available after serialization as well.
* @return the Map of failed messages as keys and thrown exceptions as values
* @see SimpleMailMessage
* @see javax.mail.internet.MimeMessage
* @see jakarta.mail.internet.MimeMessage
*/
public final Map<Object, Exception> getFailedMessages() {
return this.failedMessages;

View File

@@ -20,8 +20,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.activation.FileTypeMap;
import javax.activation.MimetypesFileTypeMap;
import jakarta.activation.FileTypeMap;
import jakarta.activation.MimetypesFileTypeMap;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
@@ -58,7 +58,7 @@ import org.springframework.lang.Nullable;
* @since 1.2
* @see #setMappingLocation
* @see #setMappings
* @see javax.activation.MimetypesFileTypeMap
* @see jakarta.activation.MimetypesFileTypeMap
*/
public class ConfigurableMimeFileTypeMap extends FileTypeMap implements InitializingBean {
@@ -140,8 +140,8 @@ public class ConfigurableMimeFileTypeMap extends FileTypeMap implements Initiali
* @param mappings an array of MIME type mapping lines (can be {@code null})
* @return the compiled FileTypeMap
* @throws IOException if resource access failed
* @see javax.activation.MimetypesFileTypeMap#MimetypesFileTypeMap(java.io.InputStream)
* @see javax.activation.MimetypesFileTypeMap#addMimeTypes(String)
* @see jakarta.activation.MimetypesFileTypeMap#MimetypesFileTypeMap(java.io.InputStream)
* @see jakarta.activation.MimetypesFileTypeMap#addMimeTypes(String)
*/
protected FileTypeMap createFileTypeMap(@Nullable Resource mappingLocation, @Nullable String[] mappings) throws IOException {
MimetypesFileTypeMap fileTypeMap = null;

View File

@@ -18,8 +18,8 @@ package org.springframework.mail.javamail;
import java.beans.PropertyEditorSupport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import org.springframework.util.StringUtils;
@@ -32,7 +32,7 @@ import org.springframework.util.StringUtils;
*
* @author Juergen Hoeller
* @since 1.2.3
* @see javax.mail.internet.InternetAddress
* @see jakarta.mail.internet.InternetAddress
*/
public class InternetAddressEditor extends PropertyEditorSupport {

View File

@@ -18,7 +18,7 @@ package org.springframework.mail.javamail;
import java.io.InputStream;
import javax.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMessage;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
@@ -40,7 +40,7 @@ import org.springframework.mail.MailSender;
* mechanism, possibly using a {@link MimeMessageHelper} for populating the message.
* See {@link MimeMessageHelper MimeMessageHelper's javadoc} for an example.
*
* <p>The entire JavaMail {@link javax.mail.Session} management is abstracted
* <p>The entire JavaMail {@link jakarta.mail.Session} management is abstracted
* by the JavaMailSender. Client code should not deal with a Session in any way,
* rather leave the entire JavaMail configuration and resource handling to the
* JavaMailSender implementation. This also increases testability.
@@ -54,8 +54,8 @@ import org.springframework.mail.MailSender;
*
* @author Juergen Hoeller
* @since 07.10.2003
* @see javax.mail.internet.MimeMessage
* @see javax.mail.Session
* @see jakarta.mail.internet.MimeMessage
* @see jakarta.mail.Session
* @see JavaMailSenderImpl
* @see MimeMessagePreparator
* @see MimeMessageHelper

View File

@@ -24,14 +24,14 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.activation.FileTypeMap;
import javax.mail.Address;
import javax.mail.AuthenticationFailedException;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.MimeMessage;
import jakarta.activation.FileTypeMap;
import jakarta.mail.Address;
import jakarta.mail.AuthenticationFailedException;
import jakarta.mail.MessagingException;
import jakarta.mail.NoSuchProviderException;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.internet.MimeMessage;
import org.springframework.lang.Nullable;
import org.springframework.mail.MailAuthenticationException;
@@ -49,7 +49,7 @@ import org.springframework.util.Assert;
* plain {@link org.springframework.mail.MailSender} implementation.
*
* <p>Allows for defining all settings locally as bean properties.
* Alternatively, a pre-configured JavaMail {@link javax.mail.Session} can be
* Alternatively, a pre-configured JavaMail {@link jakarta.mail.Session} can be
* specified, possibly pulled from an application server's JNDI environment.
*
* <p>Non-default properties in this object will always override the settings
@@ -59,8 +59,8 @@ import org.springframework.util.Assert;
* @author Dmitriy Kopylenko
* @author Juergen Hoeller
* @since 10.09.2003
* @see javax.mail.internet.MimeMessage
* @see javax.mail.Session
* @see jakarta.mail.internet.MimeMessage
* @see jakarta.mail.Session
* @see #setSession
* @see #setJavaMailProperties
* @see #setHost
@@ -523,7 +523,7 @@ public class JavaMailSenderImpl implements JavaMailSender {
* Obtain a Transport object from the given JavaMail Session,
* using the configured protocol.
* <p>Can be overridden in subclasses, e.g. to return a mock Transport object.
* @see javax.mail.Session#getTransport(String)
* @see jakarta.mail.Session#getTransport(String)
* @see #getSession()
* @see #getProtocol()
*/

View File

@@ -18,8 +18,8 @@ package org.springframework.mail.javamail;
import java.util.Date;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.springframework.mail.MailMessage;
import org.springframework.mail.MailParseException;
@@ -35,7 +35,7 @@ import org.springframework.mail.MailParseException;
* @author Juergen Hoeller
* @since 1.1.5
* @see MimeMessageHelper
* @see javax.mail.internet.MimeMessage
* @see jakarta.mail.internet.MimeMessage
*/
public class MimeMailMessage implements MailMessage {

View File

@@ -23,20 +23,20 @@ import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.activation.FileTypeMap;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimePart;
import javax.mail.internet.MimeUtility;
import jakarta.activation.DataHandler;
import jakarta.activation.DataSource;
import jakarta.activation.FileDataSource;
import jakarta.activation.FileTypeMap;
import jakarta.mail.BodyPart;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;
import jakarta.mail.internet.MimePart;
import jakarta.mail.internet.MimeUtility;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
@@ -44,7 +44,7 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Helper class for populating a {@link javax.mail.internet.MimeMessage}.
* Helper class for populating a {@link jakarta.mail.internet.MimeMessage}.
*
* <p>Mirrors the simple setters of {@link org.springframework.mail.SimpleMailMessage},
* directly applying the values to the underlying MimeMessage. Allows for defining
@@ -186,8 +186,8 @@ public class MimeMessageHelper {
* the passed-in MimeMessage object, if carried there. Else,
* JavaMail's default encoding will be used.
* @param mimeMessage the mime message to work on
* @see #MimeMessageHelper(javax.mail.internet.MimeMessage, boolean)
* @see #getDefaultEncoding(javax.mail.internet.MimeMessage)
* @see #MimeMessageHelper(jakarta.mail.internet.MimeMessage, boolean)
* @see #getDefaultEncoding(jakarta.mail.internet.MimeMessage)
* @see JavaMailSenderImpl#setDefaultEncoding
*/
public MimeMessageHelper(MimeMessage mimeMessage) {
@@ -200,7 +200,7 @@ public class MimeMessageHelper {
* i.e. no alternative texts and no inline elements or attachments).
* @param mimeMessage the mime message to work on
* @param encoding the character encoding to use for the message
* @see #MimeMessageHelper(javax.mail.internet.MimeMessage, boolean)
* @see #MimeMessageHelper(jakarta.mail.internet.MimeMessage, boolean)
*/
public MimeMessageHelper(MimeMessage mimeMessage, @Nullable String encoding) {
this.mimeMessage = mimeMessage;
@@ -223,8 +223,8 @@ public class MimeMessageHelper {
* supports alternative texts, inline elements and attachments
* (corresponds to MULTIPART_MODE_MIXED_RELATED)
* @throws MessagingException if multipart creation failed
* @see #MimeMessageHelper(javax.mail.internet.MimeMessage, int)
* @see #getDefaultEncoding(javax.mail.internet.MimeMessage)
* @see #MimeMessageHelper(jakarta.mail.internet.MimeMessage, int)
* @see #getDefaultEncoding(jakarta.mail.internet.MimeMessage)
* @see JavaMailSenderImpl#setDefaultEncoding
*/
public MimeMessageHelper(MimeMessage mimeMessage, boolean multipart) throws MessagingException {
@@ -244,7 +244,7 @@ public class MimeMessageHelper {
* (corresponds to MULTIPART_MODE_MIXED_RELATED)
* @param encoding the character encoding to use for the message
* @throws MessagingException if multipart creation failed
* @see #MimeMessageHelper(javax.mail.internet.MimeMessage, int, String)
* @see #MimeMessageHelper(jakarta.mail.internet.MimeMessage, int, String)
*/
public MimeMessageHelper(MimeMessage mimeMessage, boolean multipart, @Nullable String encoding)
throws MessagingException {
@@ -267,7 +267,7 @@ public class MimeMessageHelper {
* @see #MULTIPART_MODE_MIXED
* @see #MULTIPART_MODE_RELATED
* @see #MULTIPART_MODE_MIXED_RELATED
* @see #getDefaultEncoding(javax.mail.internet.MimeMessage)
* @see #getDefaultEncoding(jakarta.mail.internet.MimeMessage)
* @see JavaMailSenderImpl#setDefaultEncoding
*/
public MimeMessageHelper(MimeMessage mimeMessage, int multipartMode) throws MessagingException {
@@ -388,7 +388,7 @@ public class MimeMessageHelper {
* @throws IllegalStateException if this helper is not in multipart mode
* @see #isMultipart
* @see #getMimeMessage
* @see javax.mail.internet.MimeMultipart#addBodyPart
* @see jakarta.mail.internet.MimeMultipart#addBodyPart
*/
public final MimeMultipart getRootMimeMultipart() throws IllegalStateException {
if (this.rootMimeMultipart == null) {
@@ -407,7 +407,7 @@ public class MimeMessageHelper {
* @throws IllegalStateException if this helper is not in multipart mode
* @see #isMultipart
* @see #getRootMimeMultipart
* @see javax.mail.internet.MimeMultipart#addBodyPart
* @see jakarta.mail.internet.MimeMultipart#addBodyPart
*/
public final MimeMultipart getMimeMultipart() throws IllegalStateException {
if (this.mimeMultipart == null) {
@@ -469,9 +469,9 @@ public class MimeMessageHelper {
* {@code FileTypeMap} instance else.
* @see #addInline
* @see #addAttachment
* @see #getDefaultFileTypeMap(javax.mail.internet.MimeMessage)
* @see #getDefaultFileTypeMap(jakarta.mail.internet.MimeMessage)
* @see JavaMailSenderImpl#setDefaultFileTypeMap
* @see javax.activation.FileTypeMap#getDefaultFileTypeMap
* @see jakarta.activation.FileTypeMap#getDefaultFileTypeMap
* @see ConfigurableMimeFileTypeMap
*/
public void setFileTypeMap(@Nullable FileTypeMap fileTypeMap) {
@@ -538,7 +538,7 @@ public class MimeMessageHelper {
* @param address the address to validate
* @throws AddressException if validation failed
* @see #isValidateAddresses()
* @see javax.mail.internet.InternetAddress#validate()
* @see jakarta.mail.internet.InternetAddress#validate()
*/
protected void validateAddress(InternetAddress address) throws AddressException {
if (isValidateAddresses()) {
@@ -889,7 +889,7 @@ public class MimeMessageHelper {
/**
* Add an inline element to the MimeMessage, taking the content from a
* {@code javax.activation.DataSource}.
* {@code jakarta.activation.DataSource}.
* <p>Note that the InputStream returned by the DataSource implementation
* needs to be a <i>fresh one on each call</i>, as JavaMail will invoke
* {@code getInputStream()} multiple times.
@@ -898,7 +898,7 @@ public class MimeMessageHelper {
* @param contentId the content ID to use. Will end up as "Content-ID" header
* in the body part, surrounded by angle brackets: e.g. "myId" -> "&lt;myId&gt;".
* Can be referenced in HTML source via src="cid:myId" expressions.
* @param dataSource the {@code javax.activation.DataSource} to take
* @param dataSource the {@code jakarta.activation.DataSource} to take
* the content from, determining the InputStream and the content type
* @throws MessagingException in case of errors
* @see #addInline(String, java.io.File)
@@ -929,7 +929,7 @@ public class MimeMessageHelper {
* @throws MessagingException in case of errors
* @see #setText
* @see #addInline(String, org.springframework.core.io.Resource)
* @see #addInline(String, javax.activation.DataSource)
* @see #addInline(String, jakarta.activation.DataSource)
*/
public void addInline(String contentId, File file) throws MessagingException {
Assert.notNull(file, "File must not be null");
@@ -956,7 +956,7 @@ public class MimeMessageHelper {
* @throws MessagingException in case of errors
* @see #setText
* @see #addInline(String, java.io.File)
* @see #addInline(String, javax.activation.DataSource)
* @see #addInline(String, jakarta.activation.DataSource)
*/
public void addInline(String contentId, Resource resource) throws MessagingException {
Assert.notNull(resource, "Resource must not be null");
@@ -984,7 +984,7 @@ public class MimeMessageHelper {
* @see #setText
* @see #getFileTypeMap
* @see #addInline(String, org.springframework.core.io.Resource)
* @see #addInline(String, javax.activation.DataSource)
* @see #addInline(String, jakarta.activation.DataSource)
*/
public void addInline(String contentId, InputStreamSource inputStreamSource, String contentType)
throws MessagingException {
@@ -1001,13 +1001,13 @@ public class MimeMessageHelper {
/**
* Add an attachment to the MimeMessage, taking the content from a
* {@code javax.activation.DataSource}.
* {@code jakarta.activation.DataSource}.
* <p>Note that the InputStream returned by the DataSource implementation
* needs to be a <i>fresh one on each call</i>, as JavaMail will invoke
* {@code getInputStream()} multiple times.
* @param attachmentFilename the name of the attachment as it will
* appear in the mail (the content type will be determined by this)
* @param dataSource the {@code javax.activation.DataSource} to take
* @param dataSource the {@code jakarta.activation.DataSource} to take
* the content from, determining the InputStream and the content type
* @throws MessagingException in case of errors
* @see #addAttachment(String, org.springframework.core.io.InputStreamSource)
@@ -1040,7 +1040,7 @@ public class MimeMessageHelper {
* @param file the File resource to take the content from
* @throws MessagingException in case of errors
* @see #addAttachment(String, org.springframework.core.io.InputStreamSource)
* @see #addAttachment(String, javax.activation.DataSource)
* @see #addAttachment(String, jakarta.activation.DataSource)
*/
public void addAttachment(String attachmentFilename, File file) throws MessagingException {
Assert.notNull(file, "File must not be null");
@@ -1064,7 +1064,7 @@ public class MimeMessageHelper {
* (all of Spring's Resource implementations can be passed in here)
* @throws MessagingException in case of errors
* @see #addAttachment(String, java.io.File)
* @see #addAttachment(String, javax.activation.DataSource)
* @see #addAttachment(String, jakarta.activation.DataSource)
* @see org.springframework.core.io.Resource
*/
public void addAttachment(String attachmentFilename, InputStreamSource inputStreamSource)
@@ -1087,7 +1087,7 @@ public class MimeMessageHelper {
* @param contentType the content type to use for the element
* @throws MessagingException in case of errors
* @see #addAttachment(String, java.io.File)
* @see #addAttachment(String, javax.activation.DataSource)
* @see #addAttachment(String, jakarta.activation.DataSource)
* @see org.springframework.core.io.Resource
*/
public void addAttachment(
@@ -1121,7 +1121,7 @@ public class MimeMessageHelper {
}
@Override
public OutputStream getOutputStream() {
throw new UnsupportedOperationException("Read-only javax.activation.DataSource");
throw new UnsupportedOperationException("Read-only jakarta.activation.DataSource");
}
@Override
public String getContentType() {

View File

@@ -16,7 +16,7 @@
package org.springframework.mail.javamail;
import javax.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMessage;
/**
* Callback interface for the preparation of JavaMail MIME messages.
@@ -42,7 +42,7 @@ public interface MimeMessagePreparator {
/**
* Prepare the given new MimeMessage instance.
* @param mimeMessage the message to prepare
* @throws javax.mail.MessagingException passing any exceptions thrown by MimeMessage
* @throws jakarta.mail.MessagingException passing any exceptions thrown by MimeMessage
* methods through for automatic conversion to the MailException hierarchy
* @throws java.io.IOException passing any exceptions thrown by MimeMessage methods
* through for automatic conversion to the MailException hierarchy

View File

@@ -16,9 +16,9 @@
package org.springframework.mail.javamail;
import javax.activation.FileTypeMap;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import jakarta.activation.FileTypeMap;
import jakarta.mail.Session;
import jakarta.mail.internet.MimeMessage;
import org.springframework.lang.Nullable;
@@ -34,8 +34,8 @@ import org.springframework.lang.Nullable;
* @author Juergen Hoeller
* @since 1.2
* @see JavaMailSenderImpl#createMimeMessage()
* @see MimeMessageHelper#getDefaultEncoding(javax.mail.internet.MimeMessage)
* @see MimeMessageHelper#getDefaultFileTypeMap(javax.mail.internet.MimeMessage)
* @see MimeMessageHelper#getDefaultEncoding(jakarta.mail.internet.MimeMessage)
* @see MimeMessageHelper#getDefaultFileTypeMap(jakarta.mail.internet.MimeMessage)
*/
class SmartMimeMessage extends MimeMessage {

View File

@@ -1,58 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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
*
* https://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.springframework.scheduling.commonj;
import commonj.timers.Timer;
import commonj.timers.TimerListener;
import org.springframework.util.Assert;
/**
* Simple TimerListener adapter that delegates to a given Runnable.
*
* @author Juergen Hoeller
* @since 2.0
* @see commonj.timers.TimerListener
* @see java.lang.Runnable
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler}
*/
@Deprecated
public class DelegatingTimerListener implements TimerListener {
private final Runnable runnable;
/**
* Create a new DelegatingTimerListener.
* @param runnable the Runnable implementation to delegate to
*/
public DelegatingTimerListener(Runnable runnable) {
Assert.notNull(runnable, "Runnable is required");
this.runnable = runnable;
}
/**
* Delegates execution to the underlying Runnable.
*/
@Override
public void timerExpired(Timer timer) {
this.runnable.run();
}
}

View File

@@ -1,85 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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
*
* https://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.springframework.scheduling.commonj;
import commonj.work.Work;
import org.springframework.scheduling.SchedulingAwareRunnable;
import org.springframework.util.Assert;
/**
* Simple Work adapter that delegates to a given Runnable.
*
* @author Juergen Hoeller
* @since 2.0
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskExecutor}
*/
@Deprecated
public class DelegatingWork implements Work {
private final Runnable delegate;
/**
* Create a new DelegatingWork.
* @param delegate the Runnable implementation to delegate to
* (may be a SchedulingAwareRunnable for extended support)
* @see org.springframework.scheduling.SchedulingAwareRunnable
* @see #isDaemon()
*/
public DelegatingWork(Runnable delegate) {
Assert.notNull(delegate, "Delegate must not be null");
this.delegate = delegate;
}
/**
* Return the wrapped Runnable implementation.
*/
public final Runnable getDelegate() {
return this.delegate;
}
/**
* Delegates execution to the underlying Runnable.
*/
@Override
public void run() {
this.delegate.run();
}
/**
* This implementation delegates to
* {@link org.springframework.scheduling.SchedulingAwareRunnable#isLongLived()},
* if available.
*/
@Override
public boolean isDaemon() {
return (this.delegate instanceof SchedulingAwareRunnable &&
((SchedulingAwareRunnable) this.delegate).isLongLived());
}
/**
* This implementation is empty, since we expect the Runnable
* to terminate based on some specific shutdown signal.
*/
@Override
public void release() {
}
}

View File

@@ -1,229 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* 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
*
* https://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.springframework.scheduling.commonj;
import commonj.timers.TimerListener;
import org.springframework.lang.Nullable;
/**
* JavaBean that describes a scheduled TimerListener, consisting of
* the TimerListener itself (or a Runnable to create a TimerListener for)
* and a delay plus period. Period needs to be specified;
* there is no point in a default for it.
*
* <p>The CommonJ TimerManager does not offer more sophisticated scheduling
* options such as cron expressions. Consider using Quartz for such
* advanced needs.
*
* <p>Note that the TimerManager uses a TimerListener instance that is
* shared between repeated executions, in contrast to Quartz which
* instantiates a new Job for each execution.
*
* @author Juergen Hoeller
* @since 2.0
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler}
*/
@Deprecated
public class ScheduledTimerListener {
@Nullable
private TimerListener timerListener;
private long delay = 0;
private long period = -1;
private boolean fixedRate = false;
/**
* Create a new ScheduledTimerListener,
* to be populated via bean properties.
* @see #setTimerListener
* @see #setDelay
* @see #setPeriod
* @see #setFixedRate
*/
public ScheduledTimerListener() {
}
/**
* Create a new ScheduledTimerListener, with default
* one-time execution without delay.
* @param timerListener the TimerListener to schedule
*/
public ScheduledTimerListener(TimerListener timerListener) {
this.timerListener = timerListener;
}
/**
* Create a new ScheduledTimerListener, with default
* one-time execution with the given delay.
* @param timerListener the TimerListener to schedule
* @param delay the delay before starting the task for the first time (ms)
*/
public ScheduledTimerListener(TimerListener timerListener, long delay) {
this.timerListener = timerListener;
this.delay = delay;
}
/**
* Create a new ScheduledTimerListener.
* @param timerListener the TimerListener to schedule
* @param delay the delay before starting the task for the first time (ms)
* @param period the period between repeated task executions (ms)
* @param fixedRate whether to schedule as fixed-rate execution
*/
public ScheduledTimerListener(TimerListener timerListener, long delay, long period, boolean fixedRate) {
this.timerListener = timerListener;
this.delay = delay;
this.period = period;
this.fixedRate = fixedRate;
}
/**
* Create a new ScheduledTimerListener, with default
* one-time execution without delay.
* @param timerTask the Runnable to schedule as TimerListener
*/
public ScheduledTimerListener(Runnable timerTask) {
setRunnable(timerTask);
}
/**
* Create a new ScheduledTimerListener, with default
* one-time execution with the given delay.
* @param timerTask the Runnable to schedule as TimerListener
* @param delay the delay before starting the task for the first time (ms)
*/
public ScheduledTimerListener(Runnable timerTask, long delay) {
setRunnable(timerTask);
this.delay = delay;
}
/**
* Create a new ScheduledTimerListener.
* @param timerTask the Runnable to schedule as TimerListener
* @param delay the delay before starting the task for the first time (ms)
* @param period the period between repeated task executions (ms)
* @param fixedRate whether to schedule as fixed-rate execution
*/
public ScheduledTimerListener(Runnable timerTask, long delay, long period, boolean fixedRate) {
setRunnable(timerTask);
this.delay = delay;
this.period = period;
this.fixedRate = fixedRate;
}
/**
* Set the Runnable to schedule as TimerListener.
* @see DelegatingTimerListener
*/
public void setRunnable(Runnable timerTask) {
this.timerListener = new DelegatingTimerListener(timerTask);
}
/**
* Set the TimerListener to schedule.
*/
public void setTimerListener(@Nullable TimerListener timerListener) {
this.timerListener = timerListener;
}
/**
* Return the TimerListener to schedule.
*/
@Nullable
public TimerListener getTimerListener() {
return this.timerListener;
}
/**
* Set the delay before starting the task for the first time,
* in milliseconds. Default is 0, immediately starting the
* task after successful scheduling.
* <p>If the "firstTime" property is specified, this property will be ignored.
* Specify one or the other, not both.
*/
public void setDelay(long delay) {
this.delay = delay;
}
/**
* Return the delay before starting the job for the first time.
*/
public long getDelay() {
return this.delay;
}
/**
* Set the period between repeated task executions, in milliseconds.
* <p>Default is -1, leading to one-time execution. In case of zero or a
* positive value, the task will be executed repeatedly, with the given
* interval in-between executions.
* <p>Note that the semantics of the period value vary between fixed-rate
* and fixed-delay execution.
* <p><b>Note:</b> A period of 0 (for example as fixed delay) <i>is</i>
* supported, because the CommonJ specification defines this as a legal value.
* Hence a value of 0 will result in immediate re-execution after a job has
* finished (not in one-time execution like with {@code java.util.Timer}).
* @see #setFixedRate
* @see #isOneTimeTask()
* @see commonj.timers.TimerManager#schedule(commonj.timers.TimerListener, long, long)
*/
public void setPeriod(long period) {
this.period = period;
}
/**
* Return the period between repeated task executions.
*/
public long getPeriod() {
return this.period;
}
/**
* Is this task only ever going to execute once?
* @return {@code true} if this task is only ever going to execute once
* @see #getPeriod()
*/
public boolean isOneTimeTask() {
return (this.period < 0);
}
/**
* Set whether to schedule as fixed-rate execution, rather than
* fixed-delay execution. Default is "false", i.e. fixed delay.
* <p>See TimerManager javadoc for details on those execution modes.
* @see commonj.timers.TimerManager#schedule(commonj.timers.TimerListener, long, long)
* @see commonj.timers.TimerManager#scheduleAtFixedRate(commonj.timers.TimerListener, long, long)
*/
public void setFixedRate(boolean fixedRate) {
this.fixedRate = fixedRate;
}
/**
* Return whether to schedule as fixed-rate execution.
*/
public boolean isFixedRate() {
return this.fixedRate;
}
}

View File

@@ -1,192 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* 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
*
* https://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.springframework.scheduling.commonj;
import javax.naming.NamingException;
import commonj.timers.TimerManager;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.Lifecycle;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Base class for classes that are accessing a CommonJ {@link commonj.timers.TimerManager}
* Defines common configuration settings and common lifecycle handling.
*
* @author Juergen Hoeller
* @since 3.0
* @see commonj.timers.TimerManager
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler}
*/
@Deprecated
public abstract class TimerManagerAccessor extends JndiLocatorSupport
implements InitializingBean, DisposableBean, Lifecycle {
@Nullable
private TimerManager timerManager;
@Nullable
private String timerManagerName;
private boolean shared = false;
/**
* Specify the CommonJ TimerManager to delegate to.
* <p>Note that the given TimerManager's lifecycle will be managed
* by this FactoryBean.
* <p>Alternatively (and typically), you can specify the JNDI name
* of the target TimerManager.
* @see #setTimerManagerName
*/
public void setTimerManager(TimerManager timerManager) {
this.timerManager = timerManager;
}
/**
* Set the JNDI name of the CommonJ TimerManager.
* <p>This can either be a fully qualified JNDI name, or the JNDI name relative
* to the current environment naming context if "resourceRef" is set to "true".
* @see #setTimerManager
* @see #setResourceRef
*/
public void setTimerManagerName(String timerManagerName) {
this.timerManagerName = timerManagerName;
}
/**
* Specify whether the TimerManager obtained by this FactoryBean
* is a shared instance ("true") or an independent instance ("false").
* The lifecycle of the former is supposed to be managed by the application
* server, while the lifecycle of the latter is up to the application.
* <p>Default is "false", i.e. managing an independent TimerManager instance.
* This is what the CommonJ specification suggests that application servers
* are supposed to offer via JNDI lookups, typically declared as a
* {@code resource-ref} of type {@code commonj.timers.TimerManager}
* in {@code web.xml}, with {@code res-sharing-scope} set to 'Unshareable'.
* <p>Switch this flag to "true" if you are obtaining a shared TimerManager,
* typically through specifying the JNDI location of a TimerManager that
* has been explicitly declared as 'Shareable'. Note that WebLogic's
* cluster-aware Job Scheduler is a shared TimerManager too.
* <p>The sole difference between this FactoryBean being in shared or
* non-shared mode is that it will only attempt to suspend / resume / stop
* the underlying TimerManager in case of an independent (non-shared) instance.
* This only affects the {@link org.springframework.context.Lifecycle} support
* as well as application context shutdown.
* @see #stop()
* @see #start()
* @see #destroy()
* @see commonj.timers.TimerManager
*/
public void setShared(boolean shared) {
this.shared = shared;
}
@Override
public void afterPropertiesSet() throws NamingException {
if (this.timerManager == null) {
if (this.timerManagerName == null) {
throw new IllegalArgumentException("Either 'timerManager' or 'timerManagerName' must be specified");
}
this.timerManager = lookup(this.timerManagerName, TimerManager.class);
}
}
/**
* Return the configured TimerManager, if any.
* @return the TimerManager, or {@code null} if not available
*/
@Nullable
protected final TimerManager getTimerManager() {
return this.timerManager;
}
/**
* Obtain the TimerManager for actual use.
* @return the TimerManager (never {@code null})
* @throws IllegalStateException in case of no TimerManager set
* @since 5.0
*/
protected TimerManager obtainTimerManager() {
Assert.notNull(this.timerManager, "No TimerManager set");
return this.timerManager;
}
//---------------------------------------------------------------------
// Implementation of Lifecycle interface
//---------------------------------------------------------------------
/**
* Resumes the underlying TimerManager (if not shared).
* @see commonj.timers.TimerManager#resume()
*/
@Override
public void start() {
if (!this.shared) {
obtainTimerManager().resume();
}
}
/**
* Suspends the underlying TimerManager (if not shared).
* @see commonj.timers.TimerManager#suspend()
*/
@Override
public void stop() {
if (!this.shared) {
obtainTimerManager().suspend();
}
}
/**
* Considers the underlying TimerManager as running if it is
* neither suspending nor stopping.
* @see commonj.timers.TimerManager#isSuspending()
* @see commonj.timers.TimerManager#isStopping()
*/
@Override
public boolean isRunning() {
TimerManager tm = obtainTimerManager();
return (!tm.isSuspending() && !tm.isStopping());
}
//---------------------------------------------------------------------
// Implementation of DisposableBean interface
//---------------------------------------------------------------------
/**
* Stops the underlying TimerManager (if not shared).
* @see commonj.timers.TimerManager#stop()
*/
@Override
public void destroy() {
// Stop the entire TimerManager, if necessary.
if (this.timerManager != null && !this.shared) {
// May return early, but at least we already cancelled all known Timers.
this.timerManager.stop();
}
}
}

View File

@@ -1,165 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* 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
*
* https://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.springframework.scheduling.commonj;
import java.util.ArrayList;
import java.util.List;
import javax.naming.NamingException;
import commonj.timers.Timer;
import commonj.timers.TimerManager;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.Lifecycle;
import org.springframework.lang.Nullable;
/**
* {@link org.springframework.beans.factory.FactoryBean} that retrieves a
* CommonJ {@link commonj.timers.TimerManager} and exposes it for bean references.
*
* <p><b>This is the central convenience class for setting up a
* CommonJ TimerManager in a Spring context.</b>
*
* <p>Allows for registration of ScheduledTimerListeners. This is the main
* purpose of this class; the TimerManager itself could also be fetched
* from JNDI via {@link org.springframework.jndi.JndiObjectFactoryBean}.
* In scenarios that just require static registration of tasks at startup,
* there is no need to access the TimerManager itself in application code.
*
* <p>Note that the TimerManager uses a TimerListener instance that is
* shared between repeated executions, in contrast to Quartz which
* instantiates a new Job for each execution.
*
* @author Juergen Hoeller
* @since 2.0
* @see ScheduledTimerListener
* @see commonj.timers.TimerManager
* @see commonj.timers.TimerListener
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler}
*/
@Deprecated
public class TimerManagerFactoryBean extends TimerManagerAccessor
implements FactoryBean<TimerManager>, InitializingBean, DisposableBean, Lifecycle {
@Nullable
private ScheduledTimerListener[] scheduledTimerListeners;
@Nullable
private List<Timer> timers;
/**
* Register a list of ScheduledTimerListener objects with the TimerManager
* that this FactoryBean creates. Depending on each ScheduledTimerListener's settings,
* it will be registered via one of TimerManager's schedule methods.
* @see commonj.timers.TimerManager#schedule(commonj.timers.TimerListener, long)
* @see commonj.timers.TimerManager#schedule(commonj.timers.TimerListener, long, long)
* @see commonj.timers.TimerManager#scheduleAtFixedRate(commonj.timers.TimerListener, long, long)
*/
public void setScheduledTimerListeners(ScheduledTimerListener[] scheduledTimerListeners) {
this.scheduledTimerListeners = scheduledTimerListeners;
}
//---------------------------------------------------------------------
// Implementation of InitializingBean interface
//---------------------------------------------------------------------
@Override
public void afterPropertiesSet() throws NamingException {
super.afterPropertiesSet();
if (this.scheduledTimerListeners != null) {
this.timers = new ArrayList<>(this.scheduledTimerListeners.length);
TimerManager timerManager = obtainTimerManager();
for (ScheduledTimerListener scheduledTask : this.scheduledTimerListeners) {
Timer timer;
if (scheduledTask.isOneTimeTask()) {
timer = timerManager.schedule(scheduledTask.getTimerListener(), scheduledTask.getDelay());
}
else {
if (scheduledTask.isFixedRate()) {
timer = timerManager.scheduleAtFixedRate(
scheduledTask.getTimerListener(), scheduledTask.getDelay(), scheduledTask.getPeriod());
}
else {
timer = timerManager.schedule(
scheduledTask.getTimerListener(), scheduledTask.getDelay(), scheduledTask.getPeriod());
}
}
this.timers.add(timer);
}
}
}
//---------------------------------------------------------------------
// Implementation of FactoryBean interface
//---------------------------------------------------------------------
@Override
@Nullable
public TimerManager getObject() {
return getTimerManager();
}
@Override
public Class<? extends TimerManager> getObjectType() {
TimerManager timerManager = getTimerManager();
return (timerManager != null ? timerManager.getClass() : TimerManager.class);
}
@Override
public boolean isSingleton() {
return true;
}
//---------------------------------------------------------------------
// Implementation of DisposableBean interface
//---------------------------------------------------------------------
/**
* Cancels all statically registered Timers on shutdown,
* and stops the underlying TimerManager (if not shared).
* @see commonj.timers.Timer#cancel()
* @see commonj.timers.TimerManager#stop()
*/
@Override
public void destroy() {
// Cancel all registered timers.
if (this.timers != null) {
for (Timer timer : this.timers) {
try {
timer.cancel();
}
catch (Throwable ex) {
logger.debug("Could not cancel CommonJ Timer", ex);
}
}
this.timers.clear();
}
// Stop the TimerManager itself.
super.destroy();
}
}

View File

@@ -1,201 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* 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
*
* https://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.springframework.scheduling.commonj;
import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import commonj.timers.Timer;
import commonj.timers.TimerListener;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.SimpleTriggerContext;
import org.springframework.scheduling.support.TaskUtils;
import org.springframework.util.Assert;
import org.springframework.util.ErrorHandler;
/**
* Implementation of Spring's {@link TaskScheduler} interface, wrapping
* a CommonJ {@link commonj.timers.TimerManager}.
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 3.0
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler}
*/
@Deprecated
public class TimerManagerTaskScheduler extends TimerManagerAccessor implements TaskScheduler {
@Nullable
private volatile ErrorHandler errorHandler;
/**
* Provide an {@link ErrorHandler} strategy.
*/
public void setErrorHandler(ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
@Override
@Nullable
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
return new ReschedulingTimerListener(errorHandlingTask(task, true), trigger).schedule();
}
@Override
public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, false));
Timer timer = obtainTimerManager().schedule(futureTask, startTime);
futureTask.setTimer(timer);
return futureTask;
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
Timer timer = obtainTimerManager().scheduleAtFixedRate(futureTask, startTime, period);
futureTask.setTimer(timer);
return futureTask;
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
Timer timer = obtainTimerManager().scheduleAtFixedRate(futureTask, 0, period);
futureTask.setTimer(timer);
return futureTask;
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
Timer timer = obtainTimerManager().schedule(futureTask, startTime, delay);
futureTask.setTimer(timer);
return futureTask;
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
Timer timer = obtainTimerManager().schedule(futureTask, 0, delay);
futureTask.setTimer(timer);
return futureTask;
}
private Runnable errorHandlingTask(Runnable delegate, boolean isRepeatingTask) {
return TaskUtils.decorateTaskWithErrorHandler(delegate, this.errorHandler, isRepeatingTask);
}
/**
* ScheduledFuture adapter that wraps a CommonJ Timer.
*/
private static class TimerScheduledFuture extends FutureTask<Object> implements TimerListener, ScheduledFuture<Object> {
@Nullable
protected transient Timer timer;
protected transient boolean cancelled = false;
public TimerScheduledFuture(Runnable runnable) {
super(runnable, null);
}
public void setTimer(Timer timer) {
this.timer = timer;
}
@Override
public void timerExpired(Timer timer) {
runAndReset();
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
boolean result = super.cancel(mayInterruptIfRunning);
if (this.timer != null) {
this.timer.cancel();
}
this.cancelled = true;
return result;
}
@Override
public long getDelay(TimeUnit unit) {
Assert.state(this.timer != null, "No Timer available");
return unit.convert(this.timer.getScheduledExecutionTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed other) {
if (this == other) {
return 0;
}
long diff = getDelay(TimeUnit.MILLISECONDS) - other.getDelay(TimeUnit.MILLISECONDS);
return (diff == 0 ? 0 : ((diff < 0) ? -1 : 1));
}
}
/**
* ScheduledFuture adapter for trigger-based rescheduling.
*/
private class ReschedulingTimerListener extends TimerScheduledFuture {
private final Trigger trigger;
private final SimpleTriggerContext triggerContext = new SimpleTriggerContext();
private volatile Date scheduledExecutionTime = new Date();
public ReschedulingTimerListener(Runnable runnable, Trigger trigger) {
super(runnable);
this.trigger = trigger;
}
@Nullable
public ScheduledFuture<?> schedule() {
Date nextExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
if (nextExecutionTime == null) {
return null;
}
this.scheduledExecutionTime = nextExecutionTime;
setTimer(obtainTimerManager().schedule(this, this.scheduledExecutionTime));
return this;
}
@Override
public void timerExpired(Timer timer) {
Date actualExecutionTime = new Date();
super.timerExpired(timer);
Date completionTime = new Date();
this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
if (!this.cancelled) {
schedule();
}
}
}
}

View File

@@ -1,234 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* 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
*
* https://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.springframework.scheduling.commonj;
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import javax.naming.NamingException;
import commonj.work.Work;
import commonj.work.WorkException;
import commonj.work.WorkItem;
import commonj.work.WorkListener;
import commonj.work.WorkManager;
import commonj.work.WorkRejectedException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.TaskDecorator;
import org.springframework.core.task.TaskRejectedException;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.SchedulingTaskExecutor;
import org.springframework.util.Assert;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
/**
* TaskExecutor implementation that delegates to a CommonJ WorkManager,
* implementing the {@link commonj.work.WorkManager} interface,
* which either needs to be specified as reference or through the JNDI name.
*
* <p><b>This is the central convenience class for setting up a
* CommonJ WorkManager in a Spring context.</b>
*
* <p>Also implements the CommonJ WorkManager interface itself, delegating all
* calls to the target WorkManager. Hence, a caller can choose whether it wants
* to talk to this executor through the Spring TaskExecutor interface or the
* CommonJ WorkManager interface.
*
* <p>The CommonJ WorkManager will usually be retrieved from the application
* server's JNDI environment, as defined in the server's management console.
*
* <p>Note: On EE 7/8 compliant versions of WebLogic and WebSphere, a
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskExecutor}
* should be preferred, following JSR-236 support in Java EE 7/8.
*
* @author Juergen Hoeller
* @since 2.0
* @deprecated as of 5.1, in favor of the EE 7/8 based
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskExecutor}
*/
@Deprecated
public class WorkManagerTaskExecutor extends JndiLocatorSupport
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, WorkManager, InitializingBean {
@Nullable
private WorkManager workManager;
@Nullable
private String workManagerName;
@Nullable
private WorkListener workListener;
@Nullable
private TaskDecorator taskDecorator;
/**
* Specify the CommonJ WorkManager to delegate to.
* <p>Alternatively, you can also specify the JNDI name of the target WorkManager.
* @see #setWorkManagerName
*/
public void setWorkManager(WorkManager workManager) {
this.workManager = workManager;
}
/**
* Set the JNDI name of the CommonJ WorkManager.
* <p>This can either be a fully qualified JNDI name, or the JNDI name relative
* to the current environment naming context if "resourceRef" is set to "true".
* @see #setWorkManager
* @see #setResourceRef
*/
public void setWorkManagerName(String workManagerName) {
this.workManagerName = workManagerName;
}
/**
* Specify a CommonJ WorkListener to apply, if any.
* <p>This shared WorkListener instance will be passed on to the
* WorkManager by all {@link #execute} calls on this TaskExecutor.
*/
public void setWorkListener(WorkListener workListener) {
this.workListener = workListener;
}
/**
* Specify a custom {@link TaskDecorator} to be applied to any {@link Runnable}
* about to be executed.
* <p>Note that such a decorator is not necessarily being applied to the
* user-supplied {@code Runnable}/{@code Callable} but rather to the actual
* execution callback (which may be a wrapper around the user-supplied task).
* <p>The primary use case is to set some execution context around the task's
* invocation, or to provide some monitoring/statistics for task execution.
* <p><b>NOTE:</b> Exception handling in {@code TaskDecorator} implementations
* is limited to plain {@code Runnable} execution via {@code execute} calls.
* In case of {@code #submit} calls, the exposed {@code Runnable} will be a
* {@code FutureTask} which does not propagate any exceptions; you might
* have to cast it and call {@code Future#get} to evaluate exceptions.
* @since 4.3
*/
public void setTaskDecorator(TaskDecorator taskDecorator) {
this.taskDecorator = taskDecorator;
}
@Override
public void afterPropertiesSet() throws NamingException {
if (this.workManager == null) {
if (this.workManagerName == null) {
throw new IllegalArgumentException("Either 'workManager' or 'workManagerName' must be specified");
}
this.workManager = lookup(this.workManagerName, WorkManager.class);
}
}
private WorkManager obtainWorkManager() {
Assert.state(this.workManager != null, "No WorkManager specified");
return this.workManager;
}
//-------------------------------------------------------------------------
// Implementation of the Spring SchedulingTaskExecutor interface
//-------------------------------------------------------------------------
@Override
public void execute(Runnable task) {
Work work = new DelegatingWork(this.taskDecorator != null ? this.taskDecorator.decorate(task) : task);
try {
if (this.workListener != null) {
obtainWorkManager().schedule(work, this.workListener);
}
else {
obtainWorkManager().schedule(work);
}
}
catch (WorkRejectedException ex) {
throw new TaskRejectedException("CommonJ WorkManager did not accept task: " + task, ex);
}
catch (WorkException ex) {
throw new SchedulingException("Could not schedule task on CommonJ WorkManager", ex);
}
}
@Override
public void execute(Runnable task, long startTimeout) {
execute(task);
}
@Override
public Future<?> submit(Runnable task) {
FutureTask<Object> future = new FutureTask<>(task, null);
execute(future);
return future;
}
@Override
public <T> Future<T> submit(Callable<T> task) {
FutureTask<T> future = new FutureTask<>(task);
execute(future);
return future;
}
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null);
execute(future);
return future;
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
ListenableFutureTask<T> future = new ListenableFutureTask<>(task);
execute(future);
return future;
}
//-------------------------------------------------------------------------
// Implementation of the CommonJ WorkManager interface
//-------------------------------------------------------------------------
@Override
public WorkItem schedule(Work work) throws WorkException, IllegalArgumentException {
return obtainWorkManager().schedule(work);
}
@Override
public WorkItem schedule(Work work, WorkListener workListener) throws WorkException {
return obtainWorkManager().schedule(work, workListener);
}
@Override
@SuppressWarnings("rawtypes")
public boolean waitForAll(Collection workItems, long timeout) throws InterruptedException {
return obtainWorkManager().waitForAll(workItems, timeout);
}
@Override
@SuppressWarnings("rawtypes")
public Collection waitForAny(Collection workItems, long timeout) throws InterruptedException {
return obtainWorkManager().waitForAny(workItems, timeout);
}
}

View File

@@ -1,10 +0,0 @@
/**
* Convenience classes for scheduling based on the CommonJ WorkManager/TimerManager
* facility, as supported by IBM WebSphere 6.0+ and BEA WebLogic 9.0+.
*/
@NonNullApi
@NonNullFields
package org.springframework.scheduling.commonj;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;