Example usage for java.lang.instrument ClassFileTransformer getClass

List of usage examples for java.lang.instrument ClassFileTransformer getClass

Introduction

In this page you can find the example usage for java.lang.instrument ClassFileTransformer getClass.

Prototype

@HotSpotIntrinsicCandidate
public final native Class<?> getClass();

Source Link

Document

Returns the runtime class of this Object .

Usage

From source file:io.spotnext.maven.mojo.TransformTypesMojo.java

/** {@inheritDoc} */
@Override/*from w w  w  .j a v  a2s  .c  o  m*/
public void execute() throws MojoExecutionException {
    if (skip) {
        getLog().info("Skipping type transformation!");
        return;
    }

    trackExecution("start");

    final ClassLoader classLoader = getClassloader();
    final List<ClassFileTransformer> transformers = getClassFileTransformers(classLoader);

    List<File> classFiles = FileUtils.getFiles(project.getBuild().getOutputDirectory(),
            f -> f.getAbsolutePath().endsWith(".class"));
    getLog().debug("Found class files for processing: "
            + classFiles.stream().map(f -> f.getName()).collect(Collectors.joining(", ")));

    if (CollectionUtils.isNotEmpty(transformers)) {
        if (CollectionUtils.isNotEmpty(classFiles)) {
            getLog().info(String.format("Transforming %s classes", classFiles.size()));

            for (final File f : classFiles) {
                if (f.getName().endsWith(Constants.CLASS_EXTENSION)) {
                    String relativeClassFilePath = StringUtils.remove(f.getPath(),
                            project.getBuild().getOutputDirectory());
                    relativeClassFilePath = StringUtils.removeStart(relativeClassFilePath, "/");
                    final String className = relativeClassFilePath.substring(0,
                            relativeClassFilePath.length() - Constants.CLASS_EXTENSION.length());

                    trackExecution("Loading class: " + f.getAbsolutePath());

                    byte[] byteCode;
                    try {
                        byteCode = Files.readAllBytes(f.toPath());
                    } catch (final IOException e) {
                        String message = String.format("Can't read bytecode for class %s", className);
                        buildContext.addMessage(f, 0, 0, message, BuildContext.SEVERITY_ERROR, e);
                        throw new IllegalStateException(message, e);
                    }

                    trackExecution("Loaded class: " + f.getAbsolutePath());

                    for (final ClassFileTransformer t : transformers) {
                        try {

                            // log exceptions into separate folder, to be able to inspect them even if Eclipse swallows them ...
                            if (t instanceof AbstractBaseClassTransformer) {
                                ((AbstractBaseClassTransformer) t).setErrorLogger(this::logError);
                            }

                            // returns null if nothing has been transformed
                            byteCode = t.transform(classLoader, className, null, null, byteCode);
                        } catch (final Exception e) {
                            String exception = "Exception during transformation of class: "
                                    + f.getAbsolutePath() + "\n" + e.getMessage();
                            trackExecution(exception);
                            String message = String.format("Can't transform class %s, transformer %s: %s",
                                    className, t.getClass().getSimpleName(), ExceptionUtils.getStackTrace(e));
                            buildContext.addMessage(f, 0, 0, message, BuildContext.SEVERITY_ERROR, e);
                            throw new MojoExecutionException(exception, e);
                        }
                    }

                    if (byteCode != null && byteCode.length > 0) {
                        try {
                            Files.write(f.toPath(), byteCode, StandardOpenOption.CREATE,
                                    StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);

                            trackExecution("Saved transformed class: " + f.getAbsolutePath());
                        } catch (final IOException e) {
                            String message = "Could not write modified class: " + relativeClassFilePath;
                            buildContext.addMessage(f, 0, 0, message, BuildContext.SEVERITY_ERROR, e);
                            throw new IllegalStateException(message);
                        } finally {
                            buildContext.refresh(f);
                            getLog().info("Applied transformation to type: " + f.getAbsolutePath());
                        }
                    } else {
                        trackExecution("No changes made for class: " + f.getAbsolutePath());
                        getLog().debug("No transformation was applied to type: " + f.getAbsolutePath());
                    }
                }
            }
        } else {
            getLog().info("No class files found");
        }

        trackExecution("All classes in build output folder transformed");

        if (includeJars) {
            final String packaging = project.getPackaging();
            final Artifact artifact = project.getArtifact();

            if ("jar".equals(packaging) && artifact != null) {
                try {
                    final File source = artifact.getFile();

                    if (source.isFile()) {
                        final File destination = new File(source.getParent(), "instrument.jar");

                        final JarTransformer transformer = new JarTransformer(getLog(), classLoader,
                                Arrays.asList(source), transformers);
                        transformer.transform(destination);

                        final File sourceRename = new File(source.getParent(),
                                "notransform-" + source.getName());

                        if (source.renameTo(sourceRename)) {
                            throw new MojoExecutionException(String.format("Could not move %s to %s",
                                    source.toString(), sourceRename.toString()));
                        }

                        if (destination.renameTo(sourceRename)) {
                            throw new MojoExecutionException(String.format("Could not move %s to %s",
                                    destination.toString(), sourceRename.toString()));
                        }

                        buildContext.refresh(destination);
                    }
                } catch (final Exception e) {
                    buildContext.addMessage(artifact.getFile(), 0, 0, e.getMessage(),
                            BuildContext.SEVERITY_ERROR, e);
                    throw new MojoExecutionException(e.getMessage(), e);
                }
            } else {
                getLog().debug(String.format("Artifact %s not a jar file",
                        artifact != null ? (artifact.getGroupId() + ":" + artifact.getArtifactId())
                                : "<null>"));
            }
        }
    } else {
        getLog().info("No class transformers configured");
    }
}