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:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
*/
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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" -> "<myId>".
|
||||
* 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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user