Home | History | Annotate | Download | only in ReferenceType
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *
     15  *  See the License for the specific language governing permissions and
     16  *  limitations under the License.
     17  */
     18 
     19 /**
     20  * @author Anatoly F. Bondarenko
     21  */
     22 
     23 /**
     24  * Created on 24.02.2005
     25  */
     26 package org.apache.harmony.jpda.tests.jdwp.ReferenceType;
     27 
     28 import java.lang.reflect.Constructor;
     29 import java.lang.reflect.Proxy;
     30 import java.net.URLClassLoader;
     31 import java.net.URL;
     32 import java.nio.ByteBuffer;
     33 import java.nio.file.Files;
     34 import java.nio.file.Path;
     35 import java.util.Base64;
     36 
     37 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
     38 import org.apache.harmony.jpda.tests.share.SyncDebuggee;
     39 
     40 public class SourceDebugExtensionDebuggee extends SyncDebuggee {
     41 
     42     private final static String classWithSourceDebugExtension =
     43         "org.apache.harmony.jpda.tests.jdwp.Events.SourceDebugExtensionMockClass";
     44 
     45     private final static String inMemoryDexClassLoaderClass =
     46         "dalvik.system.InMemoryDexClassLoader";
     47 
     48     /*
     49      * A base64 string of a dex file built from the
     50      * class packaged with apache-harmony for JSR45 testing:
     51      *
     52      *  cd apache-harmony/jdwp/src/test/resources
     53      *  dx --dex --output=classes.dex \
     54      *      org/apache/harmony/jpda/tests/jdwp/Events/SourceDebugExtensionMockClass.class
     55      *
     56      * This simplifies dealing with multiple dex files in the Android
     57      * build system and with Jack which discards the JSR45 metadata.
     58      */
     59     private final static String base64DexWithExtensionClass =
     60 "ZGV4CjAzNQAktKYbHXK+eDSBH4IRfDw2pS8X3+CKeds0BAAAcAAAAHhWNBIAAAAAAAAAAHADAAAT" +
     61 "AAAAcAAAAAgAAAC8AAAAAwAAANwAAAABAAAAAAEAAAQAAAAIAQAAAQAAACgBAADsAgAASAEAAKYB" +
     62 "AACuAQAAuwEAAOUBAAD8AQAAEAIAACQCAAA4AgAAgwIAAOkCAAANAwAAEAMAABQDAAApAwAALwMA" +
     63 "ADUDAAA6AwAAQwMAAEkDAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAKAAAADAAAAAoAAAAGAAAA" +
     64 "AAAAAAsAAAAGAAAAmAEAAAsAAAAGAAAAoAEAAAQAAQAPAAAAAQABABAAAAACAAAAAAAAAAUAAAAA" +
     65 "AAAABQACAA4AAAAFAAAAAQAAAAIAAAAAAAAACQAAAIgBAABiAwAAAAAAAAEAAABcAwAAAQABAAEA" +
     66 "AABQAwAABAAAAHAQAQAAAA4AAwABAAIAAABVAwAACAAAAGIAAAAaAQEAbiAAABAADgBIAQAAAAAA" +
     67 "AAAAAAAAAAAAAQAAAAMAAAABAAAABwAGPGluaXQ+AAtIZWxsbyBXb3JsZAAoTGRhbHZpay9hbm5v" +
     68 "dGF0aW9uL1NvdXJjZURlYnVnRXh0ZW5zaW9uOwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2" +
     69 "YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AElM" +
     70 "b3JnL2FwYWNoZS9oYXJtb255L2pwZGEvdGVzdHMvamR3cC9FdmVudHMvU291cmNlRGVidWdFeHRl" +
     71 "bnNpb25Nb2NrQ2xhc3M7AGRTTUFQCmhlbGxvd29ybGRfanNwLmphdmEKSlNQCipTIEpTUAoqRgor" +
     72 "IDAgaGVsbG93b3JsZC5qc3AKaGVsbG93b3JsZC5qc3AKKkwKMSw1OjUzCjY6NTgsMwo3LDQ6NjEK" +
     73 "KkUKACJTb3VyY2VEZWJ1Z0V4dGVuc2lvbk1vY2tDbGFzcy5qYXZhAAFWAAJWTAATW0xqYXZhL2xh" +
     74 "bmcvU3RyaW5nOwAEYXJncwAEbWFpbgADb3V0AAdwcmludGxuAAR0aGlzAAV2YWx1ZQADAAcOAAYB" +
     75 "DgcOeAACAAESFwgAAAIAAoGABNACAQnoAhAAAAAAAAAAAQAAAAAAAAABAAAAEwAAAHAAAAACAAAA" +
     76 "CAAAALwAAAADAAAAAwAAANwAAAAEAAAAAQAAAAABAAAFAAAABAAAAAgBAAAGAAAAAQAAACgBAAAD" +
     77 "EAAAAQAAAEgBAAABIAAAAgAAAFABAAAGIAAAAQAAAIgBAAABEAAAAgAAAJgBAAACIAAAEwAAAKYB" +
     78 "AAADIAAAAgAAAFADAAAEIAAAAQAAAFwDAAAAIAAAAQAAAGIDAAAAEAAAAQAAAHADAAA=";
     79 
     80     /*
     81      * A base64 string of a jar file containing:
     82      * org/apache/harmony/jpda/tests/jdwp/Events/SourceDebugExtensionMockClass.class
     83      */
     84     private final static String base64JarWithExtensionClass =
     85 "UEsDBBQACAgIAAZwmUoAAAAAAAAAAAAAAAAJAAQATUVUQS1JTkYv/soAAAMAUEsHCAAAAAACAAAA" +
     86 "AAAAAFBLAwQUAAgICAAGcJlKAAAAAAAAAAAAAAAAFAAAAE1FVEEtSU5GL01BTklGRVNULk1G803M" +
     87 "y0xLLS7RDUstKs7Mz7NSMNQz4OVyLkpNLElN0XWqBAlY6BnEm5jqZuaVpBblJeYoaPgXJSbnpCo4" +
     88 "5xcV5BcllgD1afJy8XIBAFBLBwiUuAa1TAAAAE0AAABQSwMECgAACAAATYIRSQAAAAAAAAAAAAAA" +
     89 "AAQAAABvcmcvUEsDBAoAAAgAAE2CEUkAAAAAAAAAAAAAAAALAAAAb3JnL2FwYWNoZS9QSwMECgAA" +
     90 "CAAATYIRSQAAAAAAAAAAAAAAABMAAABvcmcvYXBhY2hlL2hhcm1vbnkvUEsDBAoAAAgAAE2CEUkA" +
     91 "AAAAAAAAAAAAAAAYAAAAb3JnL2FwYWNoZS9oYXJtb255L2pwZGEvUEsDBAoAAAgAAE2CEUkAAAAA" +
     92 "AAAAAAAAAAAeAAAAb3JnL2FwYWNoZS9oYXJtb255L2pwZGEvdGVzdHMvUEsDBAoAAAgAAE2CEUkA" +
     93 "AAAAAAAAAAAAAAAjAAAAb3JnL2FwYWNoZS9oYXJtb255L2pwZGEvdGVzdHMvamR3cC9QSwMECgAA" +
     94 "CAAAHUmYSgAAAAAAAAAAAAAAACoAAABvcmcvYXBhY2hlL2hhcm1vbnkvanBkYS90ZXN0cy9qZHdw" +
     95 "L0V2ZW50cy9QSwMEFAAICAgATYIRSQAAAAAAAAAAAAAAAE0AAABvcmcvYXBhY2hlL2hhcm1vbnkv" +
     96 "anBkYS90ZXN0cy9qZHdwL0V2ZW50cy9Tb3VyY2VEZWJ1Z0V4dGVuc2lvbk1vY2tDbGFzcy5jbGFz" +
     97 "c61RTW/TQBB926Rxsg20JE35Brdc0hDVRCUtShASKikfciGSUThwQBt75TjYXst2Wvqz4AASB34A" +
     98 "PwoxdipFoIgTe5i3M/tm9N7sz1/ffwDo4J6GFYbnKnYNEQl7Io2JiAMVnhvTyBFGKpM0MabOWWQM" +
     99 "TmVId0vNYls+k+OZO/iUyjDxVHii7I9HvkgSDUWGjak4FYYvQtd4M55KO2UoPfZCL33CUGjujhiK" +
    100 "R8qRHAVUqlhFiWHd9EL5ehaMZfxWjH3JUDOVLfyRiL0svygW04mXMLw0/5PcPo0MhBcybDXfmwvZ" +
    101 "Vhp7odvfHVVwBXUNtT9MWedJKoMqNtEgQ2pG/hrzZk8ZQ+pMqV+KoF/GVYa1F9L3lf5Oxb7DcR03" +
    102 "NdxgqC/hV3ELtxm0KCv5JKrRXKaJNIvYpTXUl0hm4HPHx162sJ1/2t/L2hk2l5GwDTKH7KzQjX6J" +
    103 "okaZQcgIV1vfUP6cP3OKpbxYwBrF6pxAeImwgstYv2g+zIdR7Qs2altfcW0xgBNmY8pEXAyp4A7u" +
    104 "5hw9j9vYIXSsk6dDPskWe5bt9cM0iXIz/JU15C1Lz+GY39cf6AvWHrH4X2nL5J12t9fd5we97qP2" +
    105 "Pj9sP+wddHhrwH8DUEsHCFc9MsLTAQAAIwMAAFBLAQIUABQACAgIAAZwmUoAAAAAAgAAAAAAAAAJ" +
    106 "AAQAAAAAAAAAAAAAAAAAAABNRVRBLUlORi/+ygAAUEsBAhQAFAAICAgABnCZSpS4BrVMAAAATQAA" +
    107 "ABQAAAAAAAAAAAAAAAAAPQAAAE1FVEEtSU5GL01BTklGRVNULk1GUEsBAgoACgAACAAATYIRSQAA" +
    108 "AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAywAAAG9yZy9QSwECCgAKAAAIAABNghFJAAAAAAAAAAAA" +
    109 "AAAACwAAAAAAAAAAAAAAAADtAAAAb3JnL2FwYWNoZS9QSwECCgAKAAAIAABNghFJAAAAAAAAAAAA" +
    110 "AAAAEwAAAAAAAAAAAAAAAAAWAQAAb3JnL2FwYWNoZS9oYXJtb255L1BLAQIKAAoAAAgAAE2CEUkA" +
    111 "AAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAEcBAABvcmcvYXBhY2hlL2hhcm1vbnkvanBkYS9QSwEC" +
    112 "CgAKAAAIAABNghFJAAAAAAAAAAAAAAAAHgAAAAAAAAAAAAAAAAB9AQAAb3JnL2FwYWNoZS9oYXJt" +
    113 "b255L2pwZGEvdGVzdHMvUEsBAgoACgAACAAATYIRSQAAAAAAAAAAAAAAACMAAAAAAAAAAAAAAAAA" +
    114 "uQEAAG9yZy9hcGFjaGUvaGFybW9ueS9qcGRhL3Rlc3RzL2pkd3AvUEsBAgoACgAACAAAHUmYSgAA" +
    115 "AAAAAAAAAAAAACoAAAAAAAAAAAAAAAAA+gEAAG9yZy9hcGFjaGUvaGFybW9ueS9qcGRhL3Rlc3Rz" +
    116 "L2pkd3AvRXZlbnRzL1BLAQIUABQACAgIAE2CEUlXPTLC0wEAACMDAABNAAAAAAAAAAAAAAAAAEIC" +
    117 "AABvcmcvYXBhY2hlL2hhcm1vbnkvanBkYS90ZXN0cy9qZHdwL0V2ZW50cy9Tb3VyY2VEZWJ1Z0V4" +
    118 "dGVuc2lvbk1vY2tDbGFzcy5jbGFzc1BLBQYAAAAACgAKAN8CAACQBAAAAAA=";
    119 
    120     private ClassLoader getClassLoaderInitializedWithDexFile() {
    121         try {
    122             byte[] dexBytes = Base64.getDecoder().decode(base64DexWithExtensionClass);
    123             ByteBuffer dexBuffer = ByteBuffer.wrap(dexBytes);
    124             Class<?> klass = Class.forName(inMemoryDexClassLoaderClass);
    125             Constructor<?> constructor = klass.getConstructor(ByteBuffer.class, ClassLoader.class);
    126             return (ClassLoader) constructor.newInstance(dexBuffer,
    127                                                          ClassLoader.getSystemClassLoader());
    128         } catch (Exception e) {
    129             logWriter.println("--> Debuggee: Failed to instantiate " + inMemoryDexClassLoaderClass
    130                               + " " + e);
    131             return null;
    132         }
    133     }
    134 
    135     private ClassLoader getClassLoaderInitializedWithClassFile() {
    136         try {
    137             byte[] jarBytes = Base64.getDecoder().decode(base64JarWithExtensionClass);
    138             Path jarPath = Files.createTempFile(null, "jar");
    139             jarPath.toFile().deleteOnExit();
    140             Files.write(jarPath, jarBytes);
    141             return new URLClassLoader(new URL[] { jarPath.toUri().toURL() });
    142         } catch (Exception e) {
    143             logWriter.println("--> Debuggee: Failed to instantiate URLClassLoader: " + e);
    144             return null;
    145         }
    146     }
    147 
    148     @Override
    149     public void run() {
    150         ClassLoader classLoader = null;
    151         if (System.getProperty("java.vendor").contains("Android")) {
    152             classLoader = getClassLoaderInitializedWithDexFile();
    153         } else {
    154             classLoader = getClassLoaderInitializedWithClassFile();
    155         }
    156 
    157         Class<?> klass = null;
    158         try {
    159             klass = classLoader.loadClass(classWithSourceDebugExtension);
    160         } catch (ClassNotFoundException e) {
    161             logWriter.println("--> Debuggee: Could not find class " +
    162                               classWithSourceDebugExtension);
    163         }
    164 
    165         // Create an instance of classWithSourceDebugExtension so the
    166         // SourceDebugExtension metadata can be reported back to the debugger.
    167         Object o = null;
    168         if (klass != null) {
    169             try {
    170                 o = klass.getConstructor().newInstance();
    171             } catch (Exception e) {
    172                 logWriter.println("--> Debuggee: Failed to instantiate " +
    173                                   classWithSourceDebugExtension + ": " + e);
    174             }
    175         }
    176 
    177         // Instantiate a proxy whose name should contain "$Proxy".
    178         Class proxy = Proxy.getProxyClass(SomeInterface.class.getClassLoader(),
    179                                           new Class[] { SomeInterface.class });
    180 
    181         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY);
    182         logWriter.println("--> Debuggee: SourceDebugExtensionDebuggee...");
    183         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
    184     }
    185 
    186     interface SomeInterface {}
    187 
    188     public static void main(String [] args) {
    189         runDebuggee(SourceDebugExtensionDebuggee.class);
    190     }
    191 
    192 }
    193