1/*
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24import java.lang.instrument.ClassFileTransformer;
25import java.lang.instrument.IllegalClassFormatException;
26import java.lang.instrument.Instrumentation;
27import java.security.ProtectionDomain;
28import java.util.HashMap;
29
30// This is a test utility class used to transform
31// specified classes via initial transformation (ClassFileLoadHook).
32// Names of classes to be transformed are supplied as arguments,
33// the phrase to be transformed is a hard-coded predefined
34// fairly unique phrase.
35
36public class TransformerAgent {
37    private static String[] classesToTransform;
38
39
40    private static void log(String msg) {
41        System.out.println("TransformerAgent: " + msg);
42    }
43
44
45    // arguments are comma-separated list of classes to transform
46    public static void premain(String agentArguments, Instrumentation instrumentation) {
47        log("premain() is called, arguments = " + agentArguments);
48        classesToTransform = agentArguments.split(",");
49        instrumentation.addTransformer(new SimpleTransformer(), /*canRetransform=*/true);
50    }
51
52
53    public static void agentmain(String args, Instrumentation inst) throws Exception {
54        log("agentmain() is called");
55        premain(args, inst);
56    }
57
58
59    static class SimpleTransformer implements ClassFileTransformer {
60       public byte[] transform(ClassLoader loader, String name, Class<?> classBeingRedefined,
61                            ProtectionDomain pd, byte[] buffer) throws IllegalClassFormatException {
62
63            log("SimpleTransformer called for: " + name + "@" + incrCounter(name));
64            if (!shouldTransform(name))
65                return null;
66
67            log("transforming: class name = " + name);
68            int nrOfReplacements = TransformUtil.replace(buffer, TransformUtil.BeforePattern,
69                                                         TransformUtil.AfterPattern);
70            log("replaced the string, nrOfReplacements = " + nrOfReplacements);
71            return buffer;
72        }
73
74        // Check class name pattern, since test should only transform certain classes
75        private static boolean shouldTransform(String name) {
76            for (String match : classesToTransform) {
77                if (name.matches(match)) {
78                    log("shouldTransform: match-found, match = " + match);
79                    return true;
80                }
81            }
82
83            return false;
84        }
85    }
86
87
88    static HashMap<String, Integer> counterMap = new HashMap<>();
89
90    static Integer incrCounter(String className) {
91        Integer i = counterMap.get(className);
92        if (i == null) {
93            i = new Integer(1);
94        } else {
95            i = new Integer(i.intValue() + 1);
96        }
97        counterMap.put(className, i);
98        return i;
99    }
100}
101