org.jboss.modules.ClassTransformer Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2018 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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 org.jboss.modules;
import java.nio.ByteBuffer;
import java.security.ProtectionDomain;
import java.util.Collection;
/**
* A class file transformer which operates on byte buffers.
*/
public interface ClassTransformer {
/**
* Transform the bytes of a class. The position and limit of both the passed-in and returned buffers must mark
* the start and end of the class bytes.
*
* @param loader the class loader of the class being transformed
* @param className the internal name of the class being transformed (not {@code null})
* @param protectionDomain the protection domain of the class, if any
* @param classBytes the class bytes being transformed (not {@code null}; may be a direct or heap buffer)
* @return the transformation result (may be a direct or heap buffer)
* @throws IllegalArgumentException if the class could not be transformed for some reason
*/
ByteBuffer transform(ClassLoader loader, String className, ProtectionDomain protectionDomain, ByteBuffer classBytes)
throws IllegalArgumentException;
/**
* Get a new transformer which applies this transformation followed by another transformation.
*
* @param other the other transformation (must not be {@code null})
* @return the new transformer (not {@code null})
*/
default ClassTransformer andThen(ClassTransformer other) {
if (other == null) throw new IllegalArgumentException("other is null");
if (other == IDENTITY) return this;
return new ClassTransformer() {
public ByteBuffer transform(final ClassLoader loader, final String className, final ProtectionDomain protectionDomain, final ByteBuffer classBytes) throws IllegalArgumentException {
ByteBuffer firstStage = ClassTransformer.this.transform(loader, className, protectionDomain, classBytes);
if (firstStage == null) firstStage = classBytes;
return other.transform(loader, className, protectionDomain, firstStage);
}
};
}
/**
* Get a new transformer which applies all the transformations in the given collection. The collection should either be
* immutable or safe for concurrent iteration. A synchronized collection is insufficiently thread-safe.
*
* @param transformers the transformer collection (must not be {@code null})
* @return the new transformer (not {@code null})
*/
static ClassTransformer allOf(Collection extends ClassTransformer> transformers) {
if (transformers == null) throw new IllegalArgumentException("transformers is null");
return new ClassTransformer() {
public ByteBuffer transform(final ClassLoader loader, final String className, final ProtectionDomain protectionDomain, ByteBuffer classBytes) throws IllegalArgumentException {
ByteBuffer transformed;
for (final ClassTransformer transformer : transformers) {
if (transformer != null) {
transformed = transformer.transform(loader, className, protectionDomain, classBytes);
if (transformed != null) {
classBytes = transformed;
}
}
}
return classBytes;
}
};
}
/**
* The identity transformation, which does not modify the class bytes at all.
*/
ClassTransformer IDENTITY = new ClassTransformer() {
public ByteBuffer transform(final ClassLoader loader, final String className, final ProtectionDomain protectionDomain, final ByteBuffer classBytes) throws IllegalArgumentException {
return classBytes;
}
public ClassTransformer andThen(final ClassTransformer other) {
if (other == null) throw new IllegalArgumentException("other is null");
return other;
}
};
}