Early removal of 5.x-deprecated code
Closes gh-27686
This commit is contained in:
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.mock.jndi;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.springframework.jndi.JndiTemplate;
|
||||
|
||||
/**
|
||||
* Simple extension of the JndiTemplate class that always returns a given object.
|
||||
*
|
||||
* <p>Very useful for testing. Effectively a mock object.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @deprecated Deprecated as of Spring Framework 5.2 in favor of complete solutions from
|
||||
* third parties such as <a href="https://github.com/h-thurow/Simple-JNDI">Simple-JNDI</a>
|
||||
*/
|
||||
@Deprecated
|
||||
public class ExpectedLookupTemplate extends JndiTemplate {
|
||||
|
||||
private final Map<String, Object> jndiObjects = new ConcurrentHashMap<>(16);
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new JndiTemplate that will always return given objects for
|
||||
* given names. To be populated through {@code addObject} calls.
|
||||
* @see #addObject(String, Object)
|
||||
*/
|
||||
public ExpectedLookupTemplate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new JndiTemplate that will always return the given object,
|
||||
* but honour only requests for the given name.
|
||||
* @param name the name the client is expected to look up
|
||||
* @param object the object that will be returned
|
||||
*/
|
||||
public ExpectedLookupTemplate(String name, Object object) {
|
||||
addObject(name, object);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the given object to the list of JNDI objects that this template will expose.
|
||||
* @param name the name the client is expected to look up
|
||||
* @param object the object that will be returned
|
||||
*/
|
||||
public void addObject(String name, Object object) {
|
||||
this.jndiObjects.put(name, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the name is the expected name specified in the constructor, return the
|
||||
* object provided in the constructor. If the name is unexpected, a
|
||||
* respective NamingException gets thrown.
|
||||
*/
|
||||
@Override
|
||||
public Object lookup(String name) throws NamingException {
|
||||
Object object = this.jndiObjects.get(name);
|
||||
if (object == null) {
|
||||
throw new NamingException("Unexpected JNDI name '" + name + "': expecting " + this.jndiObjects.keySet());
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,389 +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.mock.jndi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.Binding;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NameClassPair;
|
||||
import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NameParser;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.OperationNotSupportedException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Simple implementation of a JNDI naming context.
|
||||
* Only supports binding plain Objects to String names.
|
||||
* Mainly for test environments, but also usable for standalone applications.
|
||||
*
|
||||
* <p>This class is not intended for direct usage by applications, although it
|
||||
* can be used for example to override JndiTemplate's {@code createInitialContext}
|
||||
* method in unit tests. Typically, SimpleNamingContextBuilder will be used to
|
||||
* set up a JVM-level JNDI environment.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @see SimpleNamingContextBuilder
|
||||
* @see org.springframework.jndi.JndiTemplate#createInitialContext
|
||||
* @deprecated Deprecated as of Spring Framework 5.2 in favor of complete solutions from
|
||||
* third parties such as <a href="https://github.com/h-thurow/Simple-JNDI">Simple-JNDI</a>
|
||||
*/
|
||||
@Deprecated
|
||||
public class SimpleNamingContext implements Context {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final String root;
|
||||
|
||||
private final Hashtable<String, Object> boundObjects;
|
||||
|
||||
private final Hashtable<String, Object> environment = new Hashtable<>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new naming context.
|
||||
*/
|
||||
public SimpleNamingContext() {
|
||||
this("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new naming context with the given naming root.
|
||||
*/
|
||||
public SimpleNamingContext(String root) {
|
||||
this.root = root;
|
||||
this.boundObjects = new Hashtable<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new naming context with the given naming root,
|
||||
* the given name/object map, and the JNDI environment entries.
|
||||
*/
|
||||
public SimpleNamingContext(
|
||||
String root, Hashtable<String, Object> boundObjects, @Nullable Hashtable<String, Object> env) {
|
||||
|
||||
this.root = root;
|
||||
this.boundObjects = boundObjects;
|
||||
if (env != null) {
|
||||
this.environment.putAll(env);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Actual implementations of Context methods follow
|
||||
|
||||
@Override
|
||||
public NamingEnumeration<NameClassPair> list(String root) throws NamingException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Listing name/class pairs under [" + root + "]");
|
||||
}
|
||||
return new NameClassPairEnumeration(this, root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamingEnumeration<Binding> listBindings(String root) throws NamingException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Listing bindings under [" + root + "]");
|
||||
}
|
||||
return new BindingEnumeration(this, root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the object with the given name.
|
||||
* <p>Note: Not intended for direct use by applications.
|
||||
* Will be used by any standard InitialContext JNDI lookups.
|
||||
* @throws javax.naming.NameNotFoundException if the object could not be found
|
||||
*/
|
||||
@Override
|
||||
public Object lookup(String lookupName) throws NameNotFoundException {
|
||||
String name = this.root + lookupName;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Static JNDI lookup: [" + name + "]");
|
||||
}
|
||||
if (name.isEmpty()) {
|
||||
return new SimpleNamingContext(this.root, this.boundObjects, this.environment);
|
||||
}
|
||||
Object found = this.boundObjects.get(name);
|
||||
if (found == null) {
|
||||
if (!name.endsWith("/")) {
|
||||
name = name + "/";
|
||||
}
|
||||
for (String boundName : this.boundObjects.keySet()) {
|
||||
if (boundName.startsWith(name)) {
|
||||
return new SimpleNamingContext(name, this.boundObjects, this.environment);
|
||||
}
|
||||
}
|
||||
throw new NameNotFoundException(
|
||||
"Name [" + this.root + lookupName + "] not bound; " + this.boundObjects.size() + " bindings: [" +
|
||||
StringUtils.collectionToDelimitedString(this.boundObjects.keySet(), ",") + "]");
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object lookupLink(String name) throws NameNotFoundException {
|
||||
return lookup(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the given object to the given name.
|
||||
* Note: Not intended for direct use by applications
|
||||
* if setting up a JVM-level JNDI environment.
|
||||
* Use SimpleNamingContextBuilder to set up JNDI bindings then.
|
||||
* @see org.springframework.mock.jndi.SimpleNamingContextBuilder#bind
|
||||
*/
|
||||
@Override
|
||||
public void bind(String name, Object obj) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Static JNDI binding: [" + this.root + name + "] = [" + obj + "]");
|
||||
}
|
||||
this.boundObjects.put(this.root + name, obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind(String name) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Static JNDI remove: [" + this.root + name + "]");
|
||||
}
|
||||
this.boundObjects.remove(this.root + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebind(String name, Object obj) {
|
||||
bind(name, obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rename(String oldName, String newName) throws NameNotFoundException {
|
||||
Object obj = lookup(oldName);
|
||||
unbind(oldName);
|
||||
bind(newName, obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context createSubcontext(String name) {
|
||||
String subcontextName = this.root + name;
|
||||
if (!subcontextName.endsWith("/")) {
|
||||
subcontextName += "/";
|
||||
}
|
||||
Context subcontext = new SimpleNamingContext(subcontextName, this.boundObjects, this.environment);
|
||||
bind(name, subcontext);
|
||||
return subcontext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroySubcontext(String name) {
|
||||
unbind(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String composeName(String name, String prefix) {
|
||||
return prefix + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hashtable<String, Object> getEnvironment() {
|
||||
return this.environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object addToEnvironment(String propName, Object propVal) {
|
||||
return this.environment.put(propName, propVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object removeFromEnvironment(String propName) {
|
||||
return this.environment.remove(propName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
|
||||
// Unsupported methods follow: no support for javax.naming.Name
|
||||
|
||||
@Override
|
||||
public NamingEnumeration<NameClassPair> list(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamingEnumeration<Binding> listBindings(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object lookup(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object lookupLink(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(Name name, Object obj) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebind(Name name, Object obj) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rename(Name oldName, Name newName) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context createSubcontext(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroySubcontext(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameInNamespace() throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public NameParser getNameParser(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public NameParser getNameParser(String name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Name composeName(Name name, Name prefix) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
|
||||
private abstract static class AbstractNamingEnumeration<T> implements NamingEnumeration<T> {
|
||||
|
||||
private final Iterator<T> iterator;
|
||||
|
||||
private AbstractNamingEnumeration(SimpleNamingContext context, String proot) throws NamingException {
|
||||
if (!proot.isEmpty() && !proot.endsWith("/")) {
|
||||
proot = proot + "/";
|
||||
}
|
||||
String root = context.root + proot;
|
||||
Map<String, T> contents = new HashMap<>();
|
||||
for (String boundName : context.boundObjects.keySet()) {
|
||||
if (boundName.startsWith(root)) {
|
||||
int startIndex = root.length();
|
||||
int endIndex = boundName.indexOf('/', startIndex);
|
||||
String strippedName =
|
||||
(endIndex != -1 ? boundName.substring(startIndex, endIndex) : boundName.substring(startIndex));
|
||||
if (!contents.containsKey(strippedName)) {
|
||||
try {
|
||||
contents.put(strippedName, createObject(strippedName, context.lookup(proot + strippedName)));
|
||||
}
|
||||
catch (NameNotFoundException ex) {
|
||||
// cannot happen
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (contents.size() == 0) {
|
||||
throw new NamingException("Invalid root: [" + context.root + proot + "]");
|
||||
}
|
||||
this.iterator = contents.values().iterator();
|
||||
}
|
||||
|
||||
protected abstract T createObject(String strippedName, Object obj);
|
||||
|
||||
@Override
|
||||
public boolean hasMore() {
|
||||
return this.iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
return this.iterator.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreElements() {
|
||||
return this.iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T nextElement() {
|
||||
return this.iterator.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class NameClassPairEnumeration extends AbstractNamingEnumeration<NameClassPair> {
|
||||
|
||||
private NameClassPairEnumeration(SimpleNamingContext context, String root) throws NamingException {
|
||||
super(context, root);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NameClassPair createObject(String strippedName, Object obj) {
|
||||
return new NameClassPair(strippedName, obj.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class BindingEnumeration extends AbstractNamingEnumeration<Binding> {
|
||||
|
||||
private BindingEnumeration(SimpleNamingContext context, String root) throws NamingException {
|
||||
super(context, root);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Binding createObject(String strippedName, Object obj) {
|
||||
return new Binding(strippedName, obj);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.mock.jndi;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.spi.InitialContextFactory;
|
||||
import javax.naming.spi.InitialContextFactoryBuilder;
|
||||
import javax.naming.spi.NamingManager;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Simple implementation of a JNDI naming context builder.
|
||||
*
|
||||
* <p>Mainly targeted at test environments, where each test case can
|
||||
* configure JNDI appropriately, so that {@code new InitialContext()}
|
||||
* will expose the required objects. Also usable for standalone applications,
|
||||
* e.g. for binding a JDBC DataSource to a well-known JNDI location, to be
|
||||
* able to use traditional Jakarta EE data access code outside of a Jakarta EE
|
||||
* container.
|
||||
*
|
||||
* <p>There are various choices for DataSource implementations:
|
||||
* <ul>
|
||||
* <li>{@code SingleConnectionDataSource} (using the same Connection for all getConnection calls)
|
||||
* <li>{@code DriverManagerDataSource} (creating a new Connection on each getConnection call)
|
||||
* <li>Apache's Commons DBCP offers {@code org.apache.commons.dbcp.BasicDataSource} (a real pool)
|
||||
* </ul>
|
||||
*
|
||||
* <p>Typical usage in bootstrap code:
|
||||
*
|
||||
* <pre class="code">
|
||||
* SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
|
||||
* DataSource ds = new DriverManagerDataSource(...);
|
||||
* builder.bind("java:comp/env/jdbc/myds", ds);
|
||||
* builder.activate();</pre>
|
||||
*
|
||||
* Note that it's impossible to activate multiple builders within the same JVM,
|
||||
* due to JNDI restrictions. Thus to configure a fresh builder repeatedly, use
|
||||
* the following code to get a reference to either an already activated builder
|
||||
* or a newly activated one:
|
||||
*
|
||||
* <pre class="code">
|
||||
* SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
|
||||
* DataSource ds = new DriverManagerDataSource(...);
|
||||
* builder.bind("java:comp/env/jdbc/myds", ds);</pre>
|
||||
*
|
||||
* Note that you <i>should not</i> call {@code activate()} on a builder from
|
||||
* this factory method, as there will already be an activated one in any case.
|
||||
*
|
||||
* <p>An instance of this class is only necessary at setup time.
|
||||
* An application does not need to keep a reference to it after activation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
* @see #emptyActivatedContextBuilder()
|
||||
* @see #bind(String, Object)
|
||||
* @see #activate()
|
||||
* @see SimpleNamingContext
|
||||
* @see org.springframework.jdbc.datasource.SingleConnectionDataSource
|
||||
* @see org.springframework.jdbc.datasource.DriverManagerDataSource
|
||||
* @deprecated Deprecated as of Spring Framework 5.2 in favor of complete solutions from
|
||||
* third parties such as <a href="https://github.com/h-thurow/Simple-JNDI">Simple-JNDI</a>
|
||||
*/
|
||||
@Deprecated
|
||||
public class SimpleNamingContextBuilder implements InitialContextFactoryBuilder {
|
||||
|
||||
/** An instance of this class bound to JNDI. */
|
||||
@Nullable
|
||||
private static volatile SimpleNamingContextBuilder activated;
|
||||
|
||||
private static boolean initialized = false;
|
||||
|
||||
private static final Object initializationLock = new Object();
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a SimpleNamingContextBuilder is active.
|
||||
* @return the current SimpleNamingContextBuilder instance,
|
||||
* or {@code null} if none
|
||||
*/
|
||||
@Nullable
|
||||
public static SimpleNamingContextBuilder getCurrentContextBuilder() {
|
||||
return activated;
|
||||
}
|
||||
|
||||
/**
|
||||
* If no SimpleNamingContextBuilder is already configuring JNDI,
|
||||
* create and activate one. Otherwise take the existing activated
|
||||
* SimpleNamingContextBuilder, clear it and return it.
|
||||
* <p>This is mainly intended for test suites that want to
|
||||
* reinitialize JNDI bindings from scratch repeatedly.
|
||||
* @return an empty SimpleNamingContextBuilder that can be used
|
||||
* to control JNDI bindings
|
||||
*/
|
||||
public static SimpleNamingContextBuilder emptyActivatedContextBuilder() throws NamingException {
|
||||
SimpleNamingContextBuilder builder = activated;
|
||||
if (builder != null) {
|
||||
// Clear already activated context builder.
|
||||
builder.clear();
|
||||
}
|
||||
else {
|
||||
// Create and activate new context builder.
|
||||
builder = new SimpleNamingContextBuilder();
|
||||
// The activate() call will cause an assignment to the activated variable.
|
||||
builder.activate();
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final Hashtable<String,Object> boundObjects = new Hashtable<>();
|
||||
|
||||
|
||||
/**
|
||||
* Register the context builder by registering it with the JNDI NamingManager.
|
||||
* Note that once this has been done, {@code new InitialContext()} will always
|
||||
* return a context from this factory. Use the {@code emptyActivatedContextBuilder()}
|
||||
* static method to get an empty context (for example, in test methods).
|
||||
* @throws IllegalStateException if there's already a naming context builder
|
||||
* registered with the JNDI NamingManager
|
||||
*/
|
||||
public void activate() throws IllegalStateException, NamingException {
|
||||
logger.info("Activating simple JNDI environment");
|
||||
synchronized (initializationLock) {
|
||||
if (!initialized) {
|
||||
Assert.state(!NamingManager.hasInitialContextFactoryBuilder(),
|
||||
"Cannot activate SimpleNamingContextBuilder: there is already a JNDI provider registered. " +
|
||||
"Note that JNDI is a JVM-wide service, shared at the JVM system class loader level, " +
|
||||
"with no reset option. As a consequence, a JNDI provider must only be registered once per JVM.");
|
||||
NamingManager.setInitialContextFactoryBuilder(this);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
activated = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily deactivate this context builder. It will remain registered with
|
||||
* the JNDI NamingManager but will delegate to the standard JNDI InitialContextFactory
|
||||
* (if configured) instead of exposing its own bound objects.
|
||||
* <p>Call {@code activate()} again in order to expose this context builder's own
|
||||
* bound objects again. Such activate/deactivate sequences can be applied any number
|
||||
* of times (e.g. within a larger integration test suite running in the same VM).
|
||||
* @see #activate()
|
||||
*/
|
||||
public void deactivate() {
|
||||
logger.info("Deactivating simple JNDI environment");
|
||||
activated = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all bindings in this context builder, while keeping it active.
|
||||
*/
|
||||
public void clear() {
|
||||
this.boundObjects.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the given object under the given name, for all naming contexts
|
||||
* that this context builder will generate.
|
||||
* @param name the JNDI name of the object (e.g. "java:comp/env/jdbc/myds")
|
||||
* @param obj the object to bind (e.g. a DataSource implementation)
|
||||
*/
|
||||
public void bind(String name, Object obj) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Static JNDI binding: [" + name + "] = [" + obj + "]");
|
||||
}
|
||||
this.boundObjects.put(name, obj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple InitialContextFactoryBuilder implementation,
|
||||
* creating a new SimpleNamingContext instance.
|
||||
* @see SimpleNamingContext
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public InitialContextFactory createInitialContextFactory(@Nullable Hashtable<?,?> environment) {
|
||||
if (activated == null && environment != null) {
|
||||
Object icf = environment.get(Context.INITIAL_CONTEXT_FACTORY);
|
||||
if (icf != null) {
|
||||
Class<?> icfClass;
|
||||
if (icf instanceof Class) {
|
||||
icfClass = (Class<?>) icf;
|
||||
}
|
||||
else if (icf instanceof String) {
|
||||
icfClass = ClassUtils.resolveClassName((String) icf, getClass().getClassLoader());
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Invalid value type for environment key [" +
|
||||
Context.INITIAL_CONTEXT_FACTORY + "]: " + icf.getClass().getName());
|
||||
}
|
||||
if (!InitialContextFactory.class.isAssignableFrom(icfClass)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Specified class does not implement [" + InitialContextFactory.class.getName() + "]: " + icf);
|
||||
}
|
||||
try {
|
||||
return (InitialContextFactory) ReflectionUtils.accessibleConstructor(icfClass).newInstance();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException("Unable to instantiate specified InitialContextFactory: " + icf, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default case...
|
||||
return env -> new SimpleNamingContext("", this.boundObjects, (Hashtable<String, Object>) env);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* <strong>Deprecated</strong> as of Spring Framework 5.2 in favor of complete
|
||||
* solutions from third parties such as
|
||||
* <a href="https://github.com/h-thurow/Simple-JNDI">Simple-JNDI</a>.
|
||||
*
|
||||
* <p>The simplest implementation of the JNDI SPI that could possibly work.
|
||||
*
|
||||
* <p>Useful for setting up a simple JNDI environment for test suites
|
||||
* or stand-alone applications. If, for example, JDBC DataSources get bound to the
|
||||
* same JNDI names as within a Jakarta EE container, both application code and
|
||||
* configuration can be reused without changes.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.mock.jndi;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* 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.
|
||||
@@ -300,13 +300,6 @@ public final class MockServerRequest implements ServerRequest {
|
||||
|
||||
Builder session(WebSession session);
|
||||
|
||||
/**
|
||||
* Sets the request {@link Principal}.
|
||||
* @deprecated in favor of {@link #principal(Principal)}
|
||||
*/
|
||||
@Deprecated
|
||||
Builder session(Principal principal);
|
||||
|
||||
Builder principal(Principal principal);
|
||||
|
||||
Builder remoteAddress(InetSocketAddress remoteAddress);
|
||||
@@ -463,12 +456,6 @@ public final class MockServerRequest implements ServerRequest {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Builder session(Principal principal) {
|
||||
return principal(principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder principal(Principal principal) {
|
||||
Assert.notNull(principal, "'principal' must not be null");
|
||||
|
||||
@@ -1,409 +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.test.util;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@code MetaAnnotationUtils} is a collection of utility methods that complements
|
||||
* the standard support already available in {@link AnnotationUtils}.
|
||||
*
|
||||
* <p>Whereas {@code AnnotationUtils} provides utilities for <em>getting</em> or
|
||||
* <em>finding</em> an annotation, {@code MetaAnnotationUtils} goes a step further
|
||||
* by providing support for determining the <em>root class</em> on which an
|
||||
* annotation is declared, either directly or indirectly via a <em>composed
|
||||
* annotation</em>. This additional information is encapsulated in an
|
||||
* {@link AnnotationDescriptor}.
|
||||
*
|
||||
* <p>The additional information provided by an {@code AnnotationDescriptor} is
|
||||
* required by the <em>Spring TestContext Framework</em> in order to be able to
|
||||
* support class hierarchy traversals for annotations such as
|
||||
* {@link org.springframework.test.context.ContextConfiguration @ContextConfiguration},
|
||||
* {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners},
|
||||
* and {@link org.springframework.test.context.ActiveProfiles @ActiveProfiles}
|
||||
* which offer support for merging and overriding various <em>inherited</em>
|
||||
* annotation attributes (e.g.
|
||||
* {@link org.springframework.test.context.ContextConfiguration#inheritLocations}).
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.0
|
||||
* @see AnnotationUtils
|
||||
* @see AnnotationDescriptor
|
||||
* @deprecated as of Spring Framework 5.3 in favor of
|
||||
* {@link org.springframework.test.context.TestContextAnnotationUtils}
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class MetaAnnotationUtils {
|
||||
|
||||
/**
|
||||
* Find the {@link AnnotationDescriptor} for the supplied {@code annotationType}
|
||||
* on the supplied {@link Class}, traversing its annotations, interfaces, and
|
||||
* superclasses if no annotation can be found on the given class itself.
|
||||
* <p>This method explicitly handles class-level annotations which are not
|
||||
* declared as {@linkplain java.lang.annotation.Inherited inherited} <em>as
|
||||
* well as meta-annotations</em>.
|
||||
* <p>The algorithm operates as follows:
|
||||
* <ol>
|
||||
* <li>Search for the annotation on the given class and return a corresponding
|
||||
* {@code AnnotationDescriptor} if found.
|
||||
* <li>Recursively search through all annotations that the given class declares.
|
||||
* <li>Recursively search through all interfaces implemented by the given class.
|
||||
* <li>Recursively search through the superclass hierarchy of the given class.
|
||||
* </ol>
|
||||
* <p>In this context, the term <em>recursively</em> means that the search
|
||||
* process continues by returning to step #1 with the current annotation,
|
||||
* interface, or superclass as the class to look for annotations on.
|
||||
* @param clazz the class to look for annotations on
|
||||
* @param annotationType the type of annotation to look for
|
||||
* @return the corresponding annotation descriptor if the annotation was found;
|
||||
* otherwise {@code null}
|
||||
* @see #findAnnotationDescriptorForTypes(Class, Class...)
|
||||
*/
|
||||
@Nullable
|
||||
public static <T extends Annotation> AnnotationDescriptor<T> findAnnotationDescriptor(
|
||||
Class<?> clazz, Class<T> annotationType) {
|
||||
|
||||
return findAnnotationDescriptor(clazz, new HashSet<>(), annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the search algorithm for {@link #findAnnotationDescriptor(Class, Class)},
|
||||
* avoiding endless recursion by tracking which annotations have already been
|
||||
* <em>visited</em>.
|
||||
* @param clazz the class to look for annotations on
|
||||
* @param visited the set of annotations that have already been visited
|
||||
* @param annotationType the type of annotation to look for
|
||||
* @return the corresponding annotation descriptor if the annotation was found;
|
||||
* otherwise {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
private static <T extends Annotation> AnnotationDescriptor<T> findAnnotationDescriptor(
|
||||
@Nullable Class<?> clazz, Set<Annotation> visited, Class<T> annotationType) {
|
||||
|
||||
Assert.notNull(annotationType, "Annotation type must not be null");
|
||||
if (clazz == null || Object.class == clazz) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Declared locally?
|
||||
if (AnnotationUtils.isAnnotationDeclaredLocally(annotationType, clazz)) {
|
||||
return new AnnotationDescriptor<>(clazz, clazz.getAnnotation(annotationType));
|
||||
}
|
||||
|
||||
// Declared on a composed annotation (i.e., as a meta-annotation)?
|
||||
for (Annotation composedAnn : clazz.getDeclaredAnnotations()) {
|
||||
Class<? extends Annotation> composedType = composedAnn.annotationType();
|
||||
if (!AnnotationUtils.isInJavaLangAnnotationPackage(composedType.getName()) && visited.add(composedAnn)) {
|
||||
AnnotationDescriptor<T> descriptor = findAnnotationDescriptor(composedType, visited, annotationType);
|
||||
if (descriptor != null) {
|
||||
return new AnnotationDescriptor<>(
|
||||
clazz, descriptor.getDeclaringClass(), composedAnn, descriptor.getAnnotation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Declared on an interface?
|
||||
for (Class<?> ifc : clazz.getInterfaces()) {
|
||||
AnnotationDescriptor<T> descriptor = findAnnotationDescriptor(ifc, visited, annotationType);
|
||||
if (descriptor != null) {
|
||||
return new AnnotationDescriptor<>(clazz, descriptor.getDeclaringClass(),
|
||||
descriptor.getComposedAnnotation(), descriptor.getAnnotation());
|
||||
}
|
||||
}
|
||||
|
||||
// Declared on a superclass?
|
||||
return findAnnotationDescriptor(clazz.getSuperclass(), visited, annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the {@link UntypedAnnotationDescriptor} for the first {@link Class}
|
||||
* in the inheritance hierarchy of the specified {@code clazz} (including
|
||||
* the specified {@code clazz} itself) which declares at least one of the
|
||||
* specified {@code annotationTypes}.
|
||||
* <p>This method traverses the annotations, interfaces, and superclasses
|
||||
* of the specified {@code clazz} if no annotation can be found on the given
|
||||
* class itself.
|
||||
* <p>This method explicitly handles class-level annotations which are not
|
||||
* declared as {@linkplain java.lang.annotation.Inherited inherited} <em>as
|
||||
* well as meta-annotations</em>.
|
||||
* <p>The algorithm operates as follows:
|
||||
* <ol>
|
||||
* <li>Search for a local declaration of one of the annotation types on
|
||||
* the given class and return a corresponding {@code UntypedAnnotationDescriptor}
|
||||
* if found.
|
||||
* <li>Recursively search through all annotations that the given class declares.
|
||||
* <li>Recursively search through all interfaces implemented by the given class.
|
||||
* <li>Recursively search through the superclass hierarchy of the given class.
|
||||
* </ol>
|
||||
* <p>In this context, the term <em>recursively</em> means that the search
|
||||
* process continues by returning to step #1 with the current annotation,
|
||||
* interface, or superclass as the class to look for annotations on.
|
||||
* @param clazz the class to look for annotations on
|
||||
* @param annotationTypes the types of annotations to look for
|
||||
* @return the corresponding annotation descriptor if one of the annotations
|
||||
* was found; otherwise {@code null}
|
||||
* @see #findAnnotationDescriptor(Class, Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
public static UntypedAnnotationDescriptor findAnnotationDescriptorForTypes(
|
||||
Class<?> clazz, Class<? extends Annotation>... annotationTypes) {
|
||||
|
||||
return findAnnotationDescriptorForTypes(clazz, new HashSet<>(), annotationTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the search algorithm for {@link #findAnnotationDescriptorForTypes(Class, Class...)},
|
||||
* avoiding endless recursion by tracking which annotations have already been
|
||||
* <em>visited</em>.
|
||||
* @param clazz the class to look for annotations on
|
||||
* @param visited the set of annotations that have already been visited
|
||||
* @param annotationTypes the types of annotations to look for
|
||||
* @return the corresponding annotation descriptor if one of the annotations
|
||||
* was found; otherwise {@code null}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private static UntypedAnnotationDescriptor findAnnotationDescriptorForTypes(@Nullable Class<?> clazz,
|
||||
Set<Annotation> visited, Class<? extends Annotation>... annotationTypes) {
|
||||
|
||||
assertNonEmptyAnnotationTypeArray(annotationTypes, "The list of annotation types must not be empty");
|
||||
if (clazz == null || Object.class == clazz) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Declared locally?
|
||||
for (Class<? extends Annotation> annotationType : annotationTypes) {
|
||||
if (AnnotationUtils.isAnnotationDeclaredLocally(annotationType, clazz)) {
|
||||
return new UntypedAnnotationDescriptor(clazz, clazz.getAnnotation(annotationType));
|
||||
}
|
||||
}
|
||||
|
||||
// Declared on a composed annotation (i.e., as a meta-annotation)?
|
||||
for (Annotation composedAnnotation : clazz.getDeclaredAnnotations()) {
|
||||
if (!AnnotationUtils.isInJavaLangAnnotationPackage(composedAnnotation) && visited.add(composedAnnotation)) {
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
composedAnnotation.annotationType(), visited, annotationTypes);
|
||||
if (descriptor != null) {
|
||||
return new UntypedAnnotationDescriptor(clazz, descriptor.getDeclaringClass(),
|
||||
composedAnnotation, descriptor.getAnnotation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Declared on an interface?
|
||||
for (Class<?> ifc : clazz.getInterfaces()) {
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(ifc, visited, annotationTypes);
|
||||
if (descriptor != null) {
|
||||
return new UntypedAnnotationDescriptor(clazz, descriptor.getDeclaringClass(),
|
||||
descriptor.getComposedAnnotation(), descriptor.getAnnotation());
|
||||
}
|
||||
}
|
||||
|
||||
// Declared on a superclass?
|
||||
return findAnnotationDescriptorForTypes(clazz.getSuperclass(), visited, annotationTypes);
|
||||
}
|
||||
|
||||
private static void assertNonEmptyAnnotationTypeArray(Class<?>[] annotationTypes, String message) {
|
||||
if (ObjectUtils.isEmpty(annotationTypes)) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
for (Class<?> clazz : annotationTypes) {
|
||||
if (!Annotation.class.isAssignableFrom(clazz)) {
|
||||
throw new IllegalArgumentException("Array elements must be of type Annotation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Descriptor for an {@link Annotation}, including the {@linkplain
|
||||
* #getDeclaringClass() class} on which the annotation is <em>declared</em>
|
||||
* as well as the actual {@linkplain #getAnnotation() annotation} instance.
|
||||
* <p>If the annotation is used as a meta-annotation, the descriptor also includes
|
||||
* the {@linkplain #getComposedAnnotation() composed annotation} on which the
|
||||
* annotation is present. In such cases, the <em>root declaring class</em> is
|
||||
* not directly annotated with the annotation but rather indirectly via the
|
||||
* composed annotation.
|
||||
* <p>Given the following example, if we are searching for the {@code @Transactional}
|
||||
* annotation <em>on</em> the {@code TransactionalTests} class, then the
|
||||
* properties of the {@code AnnotationDescriptor} would be as follows.
|
||||
* <ul>
|
||||
* <li>rootDeclaringClass: {@code TransactionalTests} class object</li>
|
||||
* <li>declaringClass: {@code TransactionalTests} class object</li>
|
||||
* <li>composedAnnotation: {@code null}</li>
|
||||
* <li>annotation: instance of the {@code Transactional} annotation</li>
|
||||
* </ul>
|
||||
* <p><pre style="code">
|
||||
* @Transactional
|
||||
* @ContextConfiguration({"/test-datasource.xml", "/repository-config.xml"})
|
||||
* public class TransactionalTests { }
|
||||
* </pre>
|
||||
* <p>Given the following example, if we are searching for the {@code @Transactional}
|
||||
* annotation <em>on</em> the {@code UserRepositoryTests} class, then the
|
||||
* properties of the {@code AnnotationDescriptor} would be as follows.
|
||||
* <ul>
|
||||
* <li>rootDeclaringClass: {@code UserRepositoryTests} class object</li>
|
||||
* <li>declaringClass: {@code RepositoryTests} class object</li>
|
||||
* <li>composedAnnotation: instance of the {@code RepositoryTests} annotation</li>
|
||||
* <li>annotation: instance of the {@code Transactional} annotation</li>
|
||||
* </ul>
|
||||
* <p><pre style="code">
|
||||
* @Transactional
|
||||
* @ContextConfiguration({"/test-datasource.xml", "/repository-config.xml"})
|
||||
* @Retention(RetentionPolicy.RUNTIME)
|
||||
* public @interface RepositoryTests { }
|
||||
*
|
||||
* @RepositoryTests
|
||||
* public class UserRepositoryTests { }
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> the annotation type
|
||||
*/
|
||||
public static class AnnotationDescriptor<T extends Annotation> {
|
||||
|
||||
private final Class<?> rootDeclaringClass;
|
||||
|
||||
private final Class<?> declaringClass;
|
||||
|
||||
@Nullable
|
||||
private final Annotation composedAnnotation;
|
||||
|
||||
private final T annotation;
|
||||
|
||||
private final AnnotationAttributes annotationAttributes;
|
||||
|
||||
public AnnotationDescriptor(Class<?> rootDeclaringClass, T annotation) {
|
||||
this(rootDeclaringClass, rootDeclaringClass, null, annotation);
|
||||
}
|
||||
|
||||
public AnnotationDescriptor(Class<?> rootDeclaringClass, Class<?> declaringClass,
|
||||
@Nullable Annotation composedAnnotation, T annotation) {
|
||||
|
||||
Assert.notNull(rootDeclaringClass, "'rootDeclaringClass' must not be null");
|
||||
Assert.notNull(annotation, "Annotation must not be null");
|
||||
this.rootDeclaringClass = rootDeclaringClass;
|
||||
this.declaringClass = declaringClass;
|
||||
this.composedAnnotation = composedAnnotation;
|
||||
this.annotation = annotation;
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
|
||||
rootDeclaringClass, annotation.annotationType().getName(), false, false);
|
||||
Assert.state(attributes != null, "No annotation attributes");
|
||||
this.annotationAttributes = attributes;
|
||||
}
|
||||
|
||||
public Class<?> getRootDeclaringClass() {
|
||||
return this.rootDeclaringClass;
|
||||
}
|
||||
|
||||
public Class<?> getDeclaringClass() {
|
||||
return this.declaringClass;
|
||||
}
|
||||
|
||||
public T getAnnotation() {
|
||||
return this.annotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize the merged {@link #getAnnotationAttributes AnnotationAttributes}
|
||||
* in this descriptor back into an annotation of the target
|
||||
* {@linkplain #getAnnotationType annotation type}.
|
||||
* @since 4.2
|
||||
* @see #getAnnotationAttributes()
|
||||
* @see #getAnnotationType()
|
||||
* @see AnnotationUtils#synthesizeAnnotation(java.util.Map, Class, java.lang.reflect.AnnotatedElement)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T synthesizeAnnotation() {
|
||||
return AnnotationUtils.synthesizeAnnotation(
|
||||
getAnnotationAttributes(), (Class<T>) getAnnotationType(), getRootDeclaringClass());
|
||||
}
|
||||
|
||||
public Class<? extends Annotation> getAnnotationType() {
|
||||
return this.annotation.annotationType();
|
||||
}
|
||||
|
||||
public AnnotationAttributes getAnnotationAttributes() {
|
||||
return this.annotationAttributes;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Annotation getComposedAnnotation() {
|
||||
return this.composedAnnotation;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Class<? extends Annotation> getComposedAnnotationType() {
|
||||
return (this.composedAnnotation != null ? this.composedAnnotation.annotationType() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a textual representation of this {@code AnnotationDescriptor}.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this)
|
||||
.append("rootDeclaringClass", this.rootDeclaringClass)
|
||||
.append("declaringClass", this.declaringClass)
|
||||
.append("composedAnnotation", this.composedAnnotation)
|
||||
.append("annotation", this.annotation)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <em>Untyped</em> extension of {@link AnnotationDescriptor} that is used
|
||||
* to describe the declaration of one of several candidate annotation types
|
||||
* where the actual annotation type cannot be predetermined.
|
||||
*/
|
||||
public static class UntypedAnnotationDescriptor extends AnnotationDescriptor<Annotation> {
|
||||
|
||||
public UntypedAnnotationDescriptor(Class<?> rootDeclaringClass, Annotation annotation) {
|
||||
this(rootDeclaringClass, rootDeclaringClass, null, annotation);
|
||||
}
|
||||
|
||||
public UntypedAnnotationDescriptor(Class<?> rootDeclaringClass, Class<?> declaringClass,
|
||||
@Nullable Annotation composedAnnotation, Annotation annotation) {
|
||||
|
||||
super(rootDeclaringClass, declaringClass, composedAnnotation, annotation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an {@link UnsupportedOperationException} since the type of annotation
|
||||
* represented by the {@link #getAnnotationAttributes AnnotationAttributes} in
|
||||
* an {@code UntypedAnnotationDescriptor} is unknown.
|
||||
* @since 4.2
|
||||
*/
|
||||
@Override
|
||||
public Annotation synthesizeAnnotation() {
|
||||
throw new UnsupportedOperationException(
|
||||
"synthesizeAnnotation() is unsupported in UntypedAnnotationDescriptor");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -88,14 +88,7 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect
|
||||
afterExpectationsDeclared();
|
||||
}
|
||||
try {
|
||||
// Try this first for backwards compatibility
|
||||
ClientHttpResponse response = validateRequestInternal(request);
|
||||
if (response != null) {
|
||||
return response;
|
||||
}
|
||||
else {
|
||||
expectation = matchRequest(request);
|
||||
}
|
||||
expectation = matchRequest(request);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
this.requestFailures.put(request, ex);
|
||||
@@ -115,19 +108,6 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect
|
||||
protected void afterExpectationsDeclared() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must implement the actual validation of the request
|
||||
* matching to declared expectations.
|
||||
* @deprecated as of 5.0.3, subclasses should implement {@link #matchRequest(ClientHttpRequest)}
|
||||
* instead and return only the matched expectation, leaving the call to create the response
|
||||
* as a separate step (to be invoked by this class).
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
protected ClientHttpResponse validateRequestInternal(ClientHttpRequest request) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* As of 5.0.3 subclasses should implement this method instead of
|
||||
* {@link #validateRequestInternal(ClientHttpRequest)} in order to match the
|
||||
@@ -272,15 +252,6 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add expectations to this group.
|
||||
* @deprecated as of 5.0.3, if favor of {@link #addAllExpectations}
|
||||
*/
|
||||
@Deprecated
|
||||
public void updateAll(Collection<RequestExpectation> expectations) {
|
||||
expectations.forEach(this::updateInternal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all expectations for this group.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* 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.
|
||||
@@ -223,28 +223,6 @@ public abstract class MockMvcRequestBuilders {
|
||||
return new MockMultipartHttpServletRequestBuilder(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockMultipartHttpServletRequestBuilder} for a multipart request.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @deprecated in favor of {@link #multipart(String, Object...)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object... uriVars) {
|
||||
return new MockMultipartHttpServletRequestBuilder(urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockMultipartHttpServletRequestBuilder} for a multipart request.
|
||||
* @param uri the URL
|
||||
* @since 4.0.3
|
||||
* @deprecated in favor of {@link #multipart(URI)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static MockMultipartHttpServletRequestBuilder fileUpload(URI uri) {
|
||||
return new MockMultipartHttpServletRequestBuilder(uri);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a {@link RequestBuilder} for an async dispatch from the
|
||||
|
||||
Reference in New Issue
Block a user