1 /*
2  * Copyright (c) 2013, 2014, 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 
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.net.URL;
29 import java.nio.file.Files;
30 import java.nio.file.Path;
31 import java.nio.file.Paths;
32 import java.nio.file.StandardCopyOption;
33 import java.util.Arrays;
34 
35 /**
36  * A utility to copy the class and all it's inner classes to the specified directory.
37  * <p>
38  * Usage in jtreg:
39  *
40  * @build CopyClassFile
41  * @run main CopyClassFile package.class dest_directory
42  *
43  * In case the source file should be removed add -r option
44  */
45 public class CopyClassFile {
46 
47     private static final ClassLoader cl = CopyClassFile.class.getClassLoader();
48 
49     private static String destinationDir;
50     private static String className;
51     private static String classFile;
52 
53     private static boolean removeSource = false;
54 
main(String[] args)55     public static void main(String[] args) throws Exception {
56         if (args.length < 2) {
57             throw new IllegalArgumentException("Illegal usage: class name and destination directory should be specified");
58         }
59 
60         int classNameIndex = parseOptions(args);
61 
62         className = args[classNameIndex];
63         destinationDir = args[classNameIndex + 1];
64         classFile = className.replaceAll("\\.", File.separator) + ".class";
65 
66         URL url = cl.getResource(classFile);
67         if (url == null) {
68             throw new RuntimeException("Could not find a class: " + classFile);
69         }
70 
71         File[] files = new File(url.toURI())
72                 .getParentFile()
73                 .listFiles((dir, name) -> name.startsWith(cutPackageName(className)) && name.endsWith(".class"));
74 
75         Arrays.stream(files).forEach(CopyClassFile::copyFile);
76     }
77 
parseOptions(String[] args)78     private static int parseOptions(String[] args) {
79         int optionsEnd = 0;
80         while (args[optionsEnd].startsWith("-")) {
81             switch (args[optionsEnd].substring(1)) {
82                 case "r" :
83                     removeSource = true;
84                     break;
85                 default:
86                     throw new RuntimeException("Unrecognized option passed to CopyClassFile: " + args[optionsEnd]);
87             }
88             optionsEnd++;
89         }
90         return optionsEnd;
91     }
92 
cutPackageName(String className)93     private static String cutPackageName(String className) {
94         int dotIndex = className.lastIndexOf(".") + 1;
95         if (dotIndex <= 0) {
96             return className;
97         } else {
98             return className.substring(dotIndex);
99         }
100     }
101 
copyFile(File f)102     private static void copyFile(File f) {
103         try {
104             Path classFilePath = Paths.get(classFile);
105             String packagePath = classFilePath.getParent() == null ? "" : classFilePath.getParent().toString();
106             Path p = Paths.get(destinationDir + packagePath + File.separator + f.getName());
107             Files.createDirectories(p.getParent());
108             try (InputStream is = new FileInputStream(f)) {
109                 Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
110             }
111 
112             if (removeSource && !f.delete()) {
113                 throw new RuntimeException("Failed to delete a file");
114             }
115 
116         } catch (IOException ex) {
117             throw new RuntimeException("Could not copy file " + f, ex);
118         }
119     }
120 }
121