I have this class in Java (it's from JaCoCo Project):
public class MemoryMultiReportOutput implements IMultiReportOutput {
private final Map<String, ByteArrayOutputStream> files = new HashMap<String, ByteArrayOutputStream>();
private final Set<String> open = new HashSet<String>();
private boolean closed = false;
public OutputStream createFile(final String path) throws IOException {
assertFalse("Duplicate output " + path, files.containsKey(path));
open.add(path);
final ByteArrayOutputStream out = new ByteArrayOutputStream() {
#Override
public void close() throws IOException {
open.remove(path);
super.close();
}
};
files.put(path, out);
return out;
}
public void close() throws IOException {
closed = true;
}
public void assertEmpty() {
assertEquals(Collections.emptySet(), files.keySet());
}
public void assertFile(String path) {
assertNotNull(String.format("Missing file %s. Actual files are %s.",
path, files.keySet()), files.get(path));
}
public void assertSingleFile(String path) {
assertEquals(Collections.singleton(path), files.keySet());
}
public byte[] getFile(String path) {
assertFile(path);
return files.get(path).toByteArray();
}
public InputStream getFileAsStream(String path) {
return new ByteArrayInputStream(getFile(path));
}
public void assertAllClosed() {
assertEquals(Collections.emptySet(), open);
assertTrue(closed);
}
}
When I compile this class the Eclipse create MemoryMultiReportOutput.class and MemoryMultiReportOutput$1.class.
First question: Why Eclipse create the MemoryMultiReportOutput$1.class? Eclipse considers the ByteArrayOutputStream out a InnerClass?
But my problem is, when I load the MemoryMultiReportOutput.class how can I load the all innerclasses present in parent class?
To answer your first question:
final ByteArrayOutputStream out = new ByteArrayOutputStream() {
#Override
public void close() throws IOException {
open.remove(path);
super.close();
}
};
Here you are creating a subclass of the ByteArrayOutputStream on the fly, i.e anonymous. This is why you have another .class file.
To answer your second question:
You can only load parent inner classes, visible to the subclass, through the Superclass's instance object :
Superclass s = new Superclass();
Superclass.Subclass sub = s.new Subclass();
If the inner class is static i.e a top-level nested class (since there is no such thing as inner static class) can be instantiated like this:
Superclass.Subclass s = new Superclass.Subclass();
and it does not require an object instance of the superclass.
Hope this helps!
Your creating an anonymous inner class with the
new ByteArrayOutputStream()
That's why you see the MemoryMultiReportOutput$1.class file.
You don't need to do anything to load the inner classes. That will happen automatically.
If your asking how to access the inner class from another class that's a bit different. You would need to mark it public or provide an accessor that would return an instance of the class. Is that what you were asking?
Related
My university professor shared this class with us (it's essentially a generic parser using Gson):
public abstract class GenericDAO<T> {
final Class<T> clase;
protected File archivo;
public GenericDAO(Class<T> clase, String file) throws Exception {
this.clase = clase;
this.archivo = new File(file);
this.archivo.createNewFile();
}
public List<T> getAll(Class<T> clase) throws Exception {
List<T> list = new ArrayList<T>();
FileReader f = new FileReader(archivo);
BufferedReader b = new BufferedReader(f);
Gson g = new Gson();
String line = "";
try {
while ((line = b.readLine()) != null && !line.equals("")) {
JsonParser parser = new JsonParser();
JsonObject jsonObject = parser.parse(line).getAsJsonObject();
list.add(g.fromJson(jsonObject, clase));
}
b.close();
} catch (Exception e) {
e.printStackTrace();
return list;
}
return list;
}
// a lot of other methods to read/write to json files
}
I created a class that inherits from it so I can read a Business from a file:
public class Business extends GenericDAO<Business> {
private String name;
// a lot of other members
// this was automatically generated by Intellij:
public Business(Class<Business> clase, String file) throws Exception {
super(clase, file);
}
}
Intellij automatically generated a constructor for it, but I don't understand it. Why does the constructor has a class as a parameter, do I have to pass an instance of itself to it? That doesn't make sense.
I would be grateful if you can point me to either some documentation to read through, or explain the pattern my professor is using.
Edit: to sum up, how do I instantiate my business class then? This is throwing an error:
Business client = new Business(Business, "path_to_json_file.json");
This wouldn't fit well in a comment: you could use a different style of constructor if you want. Replace this:
// this was automatically generated by Intellij:
public Business(Class<Business> clase, String file) throws Exception {
super(clase, file);
}
With this:
public Business(String file) throws Exception {
super( Business.class, file);
}
Which I think is more like your instructor may have intended.
I'm trying to load a class at runtime from a byte array.
It works fine, the custom class loader returns a valid class object with the correct name. I can use the class object and I can use the class via reflection.
My problem is, if I try to use the class directly it is still throwing a ClassNotFoundException. So my question is, how to load a class that I can direct use it?
The custom ClassLoader will be about loading library's, so I directly refer to the classes
My code:
public class ByteClassLoader extends ClassLoader {
private final HashMap<String, byte[]> classBytes;
public ByteClassLoader(final ClassLoader loader, HashMap<String, byte[]> classes) {
super(loader);
classBytes = classes;
}
#Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
final byte[] arr = classBytes.remove(name);
if (arr != null)
return defineClass(name, arr, 0, arr.length);
return super.findClass(name);
}
public static void main(String[] args) throws Exception {
final HashMap<String, byte[]> map = new HashMap<>();
// Load class file
final byte[] data = Files.readAllBytes(
new File("/Users/Florian/Desktop/AC.class").toPath()
);
map.put("dyn.AC", data);
// Create new Custom classloader
final ByteClassLoader loader = new ByteClassLoader(
Thread.currentThread().getContextClassLoader(), map
);
// Set context class loader
Thread.currentThread().setContextClassLoader(loader);
// Loading the class
Class<?> acc = loader.findClass("dyn.AC");
// Works. -_-
acc.getMethod("trigger").invoke(null);
// Works
System.out.println(acc.getName());
// Test method, only contains System.out method, DOESNT WORK
AC.trigger();
}
}
Content of AC: http://paste.reflex.rip/umecoruwer.cs
Stacktrace: http://paste.reflex.rip/exezividuz.swift
I've learnt how to unit test basic things within Android, e.g. getting and setting of methods as below etc. but when it comes to the more complex stuff like my actual code below, I'm a little flummoxed at what to do.
public class SurveyTest extends TestCase {
private Survey survey;
protected void setUp() throws Exception {
super.setUp();
survey = new Survey();
}
public void testGetId() {
long expected = (long) Math.random();
survey.setId(expected);
long actual = survey.getId();
Assert.assertEquals(expected, actual);
}
public void testGetTitle() {
String expected = "surveytitle";
survey.setTitle(expected);
String actual = survey.getTitle();
Assert.assertEquals(expected, actual);
}
My small code that I'm stuck on how to Junit Test in the format as above:
public abstract class PrimaryModel extends Observable implements Serializable{
protected void notifyModelChange()
{
setChanged();
notifyObservers();
}
public String serialize() throws IOException
{
ObjectOutputStream objOutStream = null;
ByteArrayOutputStream bytArrOutStream = null;
try
{
bytArrOutStream = new ByteArrayOutputStream();
objOutStream = new ObjectOutputStream(bytArrOutStream);
objOutStream.writeObject(this);
}
finally
{
String main = new String(bytArrOutStream.toByteArray());
objOutStream.close();
bytArrOutStream.close();
return main;
}
}
public static PrimaryModel deserialize(String data) throws IOException, ClassNotFoundException
{
ObjectInputStream objInputStream = new ObjectInputStream(new ByteArrayInputStream(data.getBytes()));
PrimaryModel obj = (PrimaryModel) objInputStream.readObject();
objInputStream.close();
return obj;
}
}
Something like a serialize/deserialize pair of methods is generally easily tested. You need to know that a round trip returns an object which is equivalent to the original.
private static class PrimaryModelSubclass extends PrimaryModel {
/* add methods as needed */
}
final PrimaryModel original = new PrimaryModelSubclass(7, "some string", 43.7);
final PrimaryModel wellTravelled = PrimaryModel.deserialize(original.serialize());
assertEquals(original, wellTravelled);
You will need hashCode and equals methods to be correctly defined as well.
Updated in response to comment
I'm newbie in reflection. Is there any way to detect where is an specific method invoked? For example:
public class MyClass {
public static void method(){
//DO SOMETHING
}
}
public class Test {
public test(){
MyClass.method();
}
}
public class MyProcessor extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Method method = MyClass.class.getDeclaredMethod("method");
Class classWhereMethodIsInvoked = obtainClassWhereMethodIsInvoked(method);
}
public Class obtainClassWhereMethodIsInvoked(Method method) {
//here I want to search one class that invoke that method, in this case Test.class
}
}
is something like this possible or I am going crazy?
As mentioned in the comments, Apache BCEL is suitable for your problem. Such libraries are often particularly used for determining compile-time information such as method usage and control flow analysis from the generated bytecode, and such information are difficult, if not impossible, to retrieve using reflection. If you use the BCEL solution, you probably no longer require a custom annotation processor.
But since you already seem to be using a custom annotation processor, the whole point of it is to be able to process annotations in the source files. So one way is to define a custom annotation that marks a method being called, and have the custom processor read these annotations to know which classes call which methods:
#CallerClass("MyClass.method")
public class Test {
public test() {
MyClass.method();
}
}
In the above (trivial) example, a custom CallerClass annotation marks that a class calls the method specified in the annotation's element inside parentheses. The annotation processor can read this annotation and construct the caller information.
Yes it doable if you really want it. You can use the classLoader to search through the class path and scan for the method name through all the class files. Below is a very simplistic example to show that it is doable. In the example below I find usage of the "println" method being used in this class. Essentially you can just broaden the scope from one file in my example to all the class files.
public class SearchClasses {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException {
// InputStream is = SearchClasses.class.getClassLoader().getResourceAsStream("resources.SearchClasses.class");
InputStream is = new FileInputStream(new File("build/classes/resources/SearchClasses.class"));
boolean found = false;
Scanner scanner = new Scanner(is);
while (scanner.hasNext()) {
if (scanner.nextLine().contains("println")) {
System.out.print("println found");
found = true;
break;
}
}
if (!found) {
System.out.print("println NOT found");
}
}
public static void testMethod() {
System.out.println("testing");
}
}
In my IDE I had to use the FileInputStream to access the class file I was searching in.... but if you are searching through jar files then you can use the classLoader instead. You would need mechanism to search through all of the class path... this is not impossible but I left it our for brevity.
EDIT: Here is an attempt to get it working completely.. searches all files in class path for your method.
public class SearchClasses {
/**
* #param args the command line arguments
* #throws java.io.FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException, IOException {
printAllFileWithMethod("println");
}
public static void printAllFileWithMethod(String methodName) throws FileNotFoundException, IOException {
Enumeration<URL> roots = SearchClasses.class.getClassLoader().getResources("");
List<File> allClassFiles = new ArrayList<>();
while (roots.hasMoreElements()) {
File root = new File(roots.nextElement().getPath());
allClassFiles.addAll(getFilesInDirectoryWithSuffix(root, "class"));
}
for (File classFile : allClassFiles) {
InputStream is = new FileInputStream(classFile);
boolean found = false;
Scanner scanner = new Scanner(is);
while (scanner.hasNext()) {
if (scanner.nextLine().contains(methodName)) {
System.out.print(methodName + " found in " + classFile.getName() + "\n");
found = true;
break;
}
}
}
}
public static void testMethod() {
System.out.println("testing");
}
static List<File> getFilesInDirectoryWithSuffix(File dir, String suffix) {
List<File> foundFiles = new ArrayList<>();
if (!dir.isDirectory()) {
return foundFiles;
}
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
foundFiles.addAll(getFilesInDirectoryWithSuffix(file, suffix));
} else {
String name = file.getName();
if (name.endsWith(suffix)) {
foundFiles.add(file);
}
}
}
return foundFiles;
}
}
You could define your own mechanism. Use a Map to store the caller of each method :
public static Map<Method, List<String>> callStack = new HashMap<Method, List<String>>();
public static void registerCaller(Method m)
{
List<String> callers = callStack.get(m);
if (callers == null)
{
callers = new ArrayList<String>();
callStack.put(m, callers);
}
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
callers.add(stackTraceElements[3].getClassName());
}
The target class :
class MyClass
{
public static void method()
{
registerCaller(new Object(){}.getClass().getEnclosingMethod());
// DO SOMETHING
}
}
Some caller classes :
package the.package.of;
class Test
{
public void test()
{
MyClass.method();
}
}
class Foo
{
public void bar()
{
MyClass.method();
}
}
And finally, the test :
new Test().test();
new Foo().bar();
Method method = MyClass.class.getDeclaredMethod("method");
for (String clazz : callStack.get(method))
{
System.out.println(clazz);
}
Prints :
the.package.of.Test
the.package.of.Foo
Well, if you use Eclipse as an IDE, you can find the complete call hierarchy via "Open Call Hierarchy" function. This will find all usages of your method in any open Eclipse projects.
However, if you want to find out during runtime programmatically, then you need to integrate some library, that can statically analyze the bytecode of your classpath for use of your method.
You can obtain stack trace right inside the test method:
public class Test {
public void test() {
System.out.println(getCallerClass());
}
public static String getCallerClass() {
for (StackTraceElement e: Thread.currentThread().getStackTrace()) {
if (!"java.lang.Thread".equals(e.getClassName()) && !e.getClassName().equals(Test.class.getName()))
return e.getClassName();
}
return null;
}
}
I'm not sure if I'm asking this right, as I'm attempting to teach myself Java. I have a class which contains my main method, and within this class are several subclasses that need access to my user settings using java.util.Properties. I have to create the properties object in every subclass in order to make it work, and I can't reference the object using configFilePath, it must be null. I'm wondering if I can create this public object within the parent class, so I don't need to create it in all of its subclasses? Here is my code, I'm really not sure I'm doing this right although it works.
public class Frame1 extends JFrame {
Settings config = new Settings(); //this is the object I want to reference within subclasses
class Update extends SwingWorker<Integer, Void> { //first subclass
#Override
protected Integer doInBackground() throws Exception {
Settings config = new Settings(configFilePath); //yet I have to create the object within every subclass, this time an argument is required.
String templateDir = config.getProperty("templatedir");
String writePath = config.getProperty("outputdir");
//do some logic code, not required for my question
}
#Override
protected void done() {
Update2 update2 = new Update2();
update2.execute(); //start the next subclass which also needs access to Settings(configFilePath)
}
}
}
public class Settings extends JFrame {
String configFilePath = "C:/path/to/settings.properties";
Properties properties = new Properties();
public Settings(String configFilePath) throws IOException {
this.configFilePath = configFilePath;
FileInputStream fis = null;
try {
fis = new FileInputStream(configFilePath);
properties.load(fis);
} catch (FileNotFoundException e) {
setDefaults();
} finally {
if (fis != null) {
fis.close();
}
}
}
}
I'm not sure if I'm doing this right or not, it seems to work but seems to be rather redundant having to create the config object every time I need to access my user settings. I hope this hasn't been asked before, and if it has please link me, as I could not find it.
You can create the Setting class as a Singleton pattern, here is one example:
public class Settings extends JFrame{
String configFilePath = "C:/path/to/settings.properties";
Properties properties = new Properties();
private static Settings instance;
public static Settings getInstance(){
if(instance==null){
instance = new Setting();
}
return instance;
}
private Settings() throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(configFilePath);
properties.load(fis);
} catch (FileNotFoundException e) {
setDefaults();
} finally {
if (fis != null) {
fis.close();
}
}
}
}
Usage in any other class of your system:
Settings.getInstance().getProperty("...");
From Update you can use Frame1.this to access the this of Frame1 (because Update is an inner class of Frame1).
Then to access config you can use Frame1.this.config.
Here is a working example:
public class PrefixerFactory {
private String prefix; // Used by Prefixer
public PrefixerFactory(String prefix) {
this.prefix = prefix;
}
public Prefixer createPrefixer() {
return new Prefixer();
}
public class Prefixer { // Inner class
public String addPrefix(String value) {
// Using "prefix" from PrefixerFactory
return PrefixerFactory.this.prefix + value;
}
}
public static void main(String[] args) {
Prefixer helloPrefixer = new PrefixerFactory("Hello ").createPrefixer();
Prefixer goodbyePrefixer = new PrefixerFactory("Good bye ").createPrefixer();
System.out.println(helloPrefixer.addPrefix("world")); // Hello world
System.out.println(goodbyePrefixer.addPrefix("world")); // Good bye world
}
}