/*
 * Copyright 2014 - 2020 Rafael Winterhalter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.bytebuddy;

import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.utility.RandomString;

A naming strategy for determining a fully qualified name for a dynamically created Java type.

Note that subclasses that lie within the same package as their superclass can access package-private methods of super types within the same package.

/** * <p> * A naming strategy for determining a fully qualified name for a dynamically created Java type. * </p> * <p> * Note that subclasses that lie within the same package as their superclass can access package-private methods * of super types within the same package. * </p> */
public interface NamingStrategy {
Determines a new name when creating a new type that subclasses the provided type.
Params:
  • superClass – The super type of the created type.
Returns:The name of the dynamic type.
/** * Determines a new name when creating a new type that subclasses the provided type. * * @param superClass The super type of the created type. * @return The name of the dynamic type. */
String subclass(TypeDescription.Generic superClass);
Determines a name for the dynamic type when redefining the provided type.
Params:
  • typeDescription – The type being redefined.
Returns:The name of the dynamic type.
/** * Determines a name for the dynamic type when redefining the provided type. * * @param typeDescription The type being redefined. * @return The name of the dynamic type. */
String redefine(TypeDescription typeDescription);
Determines a name for the dynamic type when rebasing the provided type.
Params:
  • typeDescription – The type being redefined.
Returns:The name of the dynamic type.
/** * Determines a name for the dynamic type when rebasing the provided type. * * @param typeDescription The type being redefined. * @return The name of the dynamic type. */
String rebase(TypeDescription typeDescription);
An abstract base implementation where the names of redefined and rebased types are retained.
/** * An abstract base implementation where the names of redefined and rebased types are retained. */
abstract class AbstractBase implements NamingStrategy {
{@inheritDoc}
/** * {@inheritDoc} */
public String subclass(TypeDescription.Generic superClass) { return name(superClass.asErasure()); }
Determines a new name when creating a new type that subclasses the provided type.
Params:
  • superClass – The super type of the created type.
Returns:The name of the dynamic type.
/** * Determines a new name when creating a new type that subclasses the provided type. * * @param superClass The super type of the created type. * @return The name of the dynamic type. */
protected abstract String name(TypeDescription superClass);
{@inheritDoc}
/** * {@inheritDoc} */
public String redefine(TypeDescription typeDescription) { return typeDescription.getName(); }
{@inheritDoc}
/** * {@inheritDoc} */
public String rebase(TypeDescription typeDescription) { return typeDescription.getName(); } }
A naming strategy that creates a name by concatenating:
  1. The super classes package and name
  2. A given suffix string
  3. A random number
Between all these elements, a $ sign is included into the name to improve readability. As an exception, types that subclass classes from the java.** packages are prefixed with a given package. This is necessary as it is illegal to define non-bootstrap classes in this name space. The same strategy is applied when subclassing a signed type which is equally illegal.
/** * A naming strategy that creates a name by concatenating: * <ol> * <li>The super classes package and name</li> * <li>A given suffix string</li> * <li>A random number</li> * </ol> * Between all these elements, a {@code $} sign is included into the name to improve readability. As an exception, * types that subclass classes from the {@code java.**} packages are prefixed with a given package. This is * necessary as it is illegal to define non-bootstrap classes in this name space. The same strategy is applied * when subclassing a signed type which is equally illegal. */
@HashCodeAndEqualsPlugin.Enhance class SuffixingRandom extends AbstractBase {
The default package for defining types that are renamed to not be contained in the JAVA_PACKAGE package.
/** * The default package for defining types that are renamed to not be contained in the * {@link net.bytebuddy.NamingStrategy.SuffixingRandom#JAVA_PACKAGE} package. */
public static final String BYTE_BUDDY_RENAME_PACKAGE = "net.bytebuddy.renamed";
Indicates that types of the java.* package should not be prefixed.
/** * Indicates that types of the {@code java.*} package should not be prefixed. */
public static final String NO_PREFIX = "";
The package prefix of the java.* packages for which the definition of non-bootstrap types is illegal.
/** * The package prefix of the {@code java.*} packages for which the definition of * non-bootstrap types is illegal. */
private static final String JAVA_PACKAGE = "java.";
The suffix to attach to a super type name.
/** * The suffix to attach to a super type name. */
private final String suffix;
The renaming location for types of the JAVA_PACKAGE.
/** * The renaming location for types of the {@link net.bytebuddy.NamingStrategy.SuffixingRandom#JAVA_PACKAGE}. */
private final String javaLangPackagePrefix;
An instance for creating random seed values.
/** * An instance for creating random seed values. */
@HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.IGNORE) private final RandomString randomString;
A resolver for the base name for naming the unnamed type.
/** * A resolver for the base name for naming the unnamed type. */
private final BaseNameResolver baseNameResolver;
Creates an immutable naming strategy with a given suffix but moves types that subclass types within the java.lang package into Byte Buddy's package namespace. All names are derived from the unnamed type's super type.
Params:
  • suffix – The suffix for the generated class.
/** * Creates an immutable naming strategy with a given suffix but moves types that subclass types within * the {@code java.lang} package into Byte Buddy's package namespace. All names are derived from the * unnamed type's super type. * * @param suffix The suffix for the generated class. */
public SuffixingRandom(String suffix) { this(suffix, BaseNameResolver.ForUnnamedType.INSTANCE); }
Creates an immutable naming strategy with a given suffix but moves types that subclass types within the java.lang package into Byte Buddy's package namespace.
Params:
  • suffix – The suffix for the generated class.
  • javaLangPackagePrefix – The fallback namespace for type's that subclass types within the java.* namespace. If The prefix is set to the empty string, no prefix is added.
/** * Creates an immutable naming strategy with a given suffix but moves types that subclass types within * the {@code java.lang} package into Byte Buddy's package namespace. * * @param suffix The suffix for the generated class. * @param javaLangPackagePrefix The fallback namespace for type's that subclass types within the * {@code java.*} namespace. If The prefix is set to the empty string, * no prefix is added. */
public SuffixingRandom(String suffix, String javaLangPackagePrefix) { this(suffix, BaseNameResolver.ForUnnamedType.INSTANCE, javaLangPackagePrefix); }
Creates an immutable naming strategy with a given suffix but moves types that subclass types within the java.lang package into Byte Buddy's package namespace.
Params:
  • suffix – The suffix for the generated class.
  • baseNameResolver – The base name resolver that is queried for locating the base name.
/** * Creates an immutable naming strategy with a given suffix but moves types that subclass types within * the {@code java.lang} package into Byte Buddy's package namespace. * * @param suffix The suffix for the generated class. * @param baseNameResolver The base name resolver that is queried for locating the base name. */
public SuffixingRandom(String suffix, BaseNameResolver baseNameResolver) { this(suffix, baseNameResolver, BYTE_BUDDY_RENAME_PACKAGE); }
Creates an immutable naming strategy with a given suffix but moves types that subclass types within the java.lang package into a given namespace.
Params:
  • suffix – The suffix for the generated class.
  • baseNameResolver – The base name resolver that is queried for locating the base name.
  • javaLangPackagePrefix – The fallback namespace for type's that subclass types within the java.* namespace. If The prefix is set to the empty string, no prefix is added.
/** * Creates an immutable naming strategy with a given suffix but moves types that subclass types within * the {@code java.lang} package into a given namespace. * * @param suffix The suffix for the generated class. * @param baseNameResolver The base name resolver that is queried for locating the base name. * @param javaLangPackagePrefix The fallback namespace for type's that subclass types within the * {@code java.*} namespace. If The prefix is set to the empty string, * no prefix is added. */
public SuffixingRandom(String suffix, BaseNameResolver baseNameResolver, String javaLangPackagePrefix) { this.suffix = suffix; this.baseNameResolver = baseNameResolver; this.javaLangPackagePrefix = javaLangPackagePrefix; randomString = new RandomString(); } @Override protected String name(TypeDescription superClass) { String baseName = baseNameResolver.resolve(superClass); if (baseName.startsWith(JAVA_PACKAGE) && !javaLangPackagePrefix.equals("")) { baseName = javaLangPackagePrefix + "." + baseName; } return baseName + "$" + suffix + "$" + randomString.nextString(); }
A base name resolver is responsible for resolving a name onto which the suffix is appended.
/** * A base name resolver is responsible for resolving a name onto which the suffix is appended. */
public interface BaseNameResolver {
Resolves the base name for a given type description.
Params:
  • typeDescription – The type for which the base name is resolved.
Returns:The base name for the given type.
/** * Resolves the base name for a given type description. * * @param typeDescription The type for which the base name is resolved. * @return The base name for the given type. */
String resolve(TypeDescription typeDescription);
Uses the unnamed type's super type's name as the resolved name.
/** * Uses the unnamed type's super type's name as the resolved name. */
enum ForUnnamedType implements BaseNameResolver {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public String resolve(TypeDescription typeDescription) { return typeDescription.getName(); } }
Uses a specific type's name as the resolved name.
/** * Uses a specific type's name as the resolved name. */
@HashCodeAndEqualsPlugin.Enhance class ForGivenType implements BaseNameResolver {
The type description which represents the resolved name.
/** * The type description which represents the resolved name. */
private final TypeDescription typeDescription;
Creates a new base name resolver that resolves a using the name of a given type.
Params:
  • typeDescription – The type description which represents the resolved name.
/** * Creates a new base name resolver that resolves a using the name of a given type. * * @param typeDescription The type description which represents the resolved name. */
public ForGivenType(TypeDescription typeDescription) { this.typeDescription = typeDescription; }
{@inheritDoc}
/** * {@inheritDoc} */
public String resolve(TypeDescription typeDescription) { return this.typeDescription.getName(); } }
A base name resolver that simply returns a fixed value.
/** * A base name resolver that simply returns a fixed value. */
@HashCodeAndEqualsPlugin.Enhance class ForFixedValue implements BaseNameResolver {
The fixed base name.
/** * The fixed base name. */
private final String name;
Creates a new base name resolver for a fixed name.
Params:
  • name – The fixed name
/** * Creates a new base name resolver for a fixed name. * * @param name The fixed name */
public ForFixedValue(String name) { this.name = name; }
{@inheritDoc}
/** * {@inheritDoc} */
public String resolve(TypeDescription typeDescription) { return name; } } } }
A naming strategy that creates a name by prefixing a given class and its package with another package and by appending a random number to the class's simple name.
/** * A naming strategy that creates a name by prefixing a given class and its package with another package and * by appending a random number to the class's simple name. */
@HashCodeAndEqualsPlugin.Enhance class PrefixingRandom extends AbstractBase {
The package to prefix.
/** * The package to prefix. */
private final String prefix;
A seed generator.
/** * A seed generator. */
@HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.IGNORE) private final RandomString randomString;
Creates a new prefixing random naming strategy.
Params:
  • prefix – The prefix to append.
/** * Creates a new prefixing random naming strategy. * * @param prefix The prefix to append. */
public PrefixingRandom(String prefix) { this.prefix = prefix; randomString = new RandomString(); } @Override protected String name(TypeDescription superClass) { return prefix + "." + superClass.getName() + "$" + randomString.nextString(); } } }