Browse Source

Remove close method on ClassPath. Add unit tests for new behaviour.

tags/rel_3_23_0_ga
Christian Melchior 6 years ago
parent
commit
f4769c7ad7

+ 8
- 0
Readme.html View File



<h2>Changes</h2> <h2>Changes</h2>


<p>-version 3.23 on MMM DD, YYYY

<ul>
<li>Fix leaking file handlers in ClassPool and removed ClassPath.close(). Github issue #165.
</ul>
</p>


<p>-version 3.22 on October 10, 2017 <p>-version 3.22 on October 10, 2017


<ul> <ul>

+ 9
- 1
pom.xml View File

<build> <build>
<sourceDirectory>src/main/</sourceDirectory> <sourceDirectory>src/main/</sourceDirectory>
<testSourceDirectory>src/test/</testSourceDirectory> <testSourceDirectory>src/test/</testSourceDirectory>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<includes> <includes>
<include>javassist/JvstTest.java</include> <include>javassist/JvstTest.java</include>
</includes> </includes>
<forkMode>once</forkMode>
<additionalClasspathElements>
<additionalClasspathElement>resources</additionalClasspathElement>
</additionalClasspathElements>
<forkMode>once</forkMode>
<workingDirectory>runtest</workingDirectory> <workingDirectory>runtest</workingDirectory>
</configuration> </configuration>
</plugin> </plugin>

+ 0
- 5
src/main/javassist/ByteArrayClassPath.java View File

this.classfile = classfile; this.classfile = classfile;
} }


/**
* Closes this class path.
*/
public void close() {}

public String toString() { public String toString() {
return "byte[]:" + classname; return "byte[]:" + classname;
} }

+ 0
- 6
src/main/javassist/ClassClassPath.java View File

return thisClass.getResource(filename); return thisClass.getResource(filename);
} }


/**
* Does nothing.
*/
public void close() {
}

public String toString() { public String toString() {
return thisClass.getName() + ".class"; return thisClass.getName() + ".class";
} }

+ 0
- 7
src/main/javassist/ClassPath.java View File

* @return null if the specified class file could not be found. * @return null if the specified class file could not be found.
*/ */
URL find(String classname); URL find(String classname);

/**
* This method is invoked when the <code>ClassPath</code> object is
* detached from the search path. It will be an empty method in most of
* classes.
*/
void close();
} }

+ 33
- 38
src/main/javassist/ClassPoolTail.java View File

import java.io.OutputStream; import java.io.OutputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;


return null; return null;
} }


public void close() {}

public String toString() { public String toString() {
return directory; return directory;
} }


return null; // not found return null; // not found
} }

public void close() {
if (jars != null)
for (int i = 0; i < jars.length; i++)
jars[i].close();
}
} }


final class JarClassPath implements ClassPath { final class JarClassPath implements ClassPath {
JarFile jarfile;
List<String> jarfileEntries;
String jarfileURL; String jarfileURL;


JarClassPath(String pathname) throws NotFoundException { JarClassPath(String pathname) throws NotFoundException {
JarFile jarfile = null;
try { try {
jarfile = new JarFile(pathname); jarfile = new JarFile(pathname);
jarfileEntries = new ArrayList<String>();
for (JarEntry je:Collections.list(jarfile.entries()))
if (je.getName().endsWith(".class"))
jarfileEntries.add(je.getName());
jarfileURL = new File(pathname).getCanonicalFile() jarfileURL = new File(pathname).getCanonicalFile()
.toURI().toURL().toString();
.toURI().toURL().toString();
return; return;
} catch (IOException e) {}
finally {
if (null != jarfile)
try {
jarfile.close();
} catch (IOException e) {}
} }
catch (IOException e) {}
throw new NotFoundException(pathname); throw new NotFoundException(pathname);
} }


@Override
public InputStream openClassfile(String classname) public InputStream openClassfile(String classname)
throws NotFoundException
throws NotFoundException
{ {
try {
String jarname = classname.replace('.', '/') + ".class";
JarEntry je = jarfile.getJarEntry(jarname);
if (je != null)
return jarfile.getInputStream(je);
else
return null; // not found
}
catch (IOException e) {}
throw new NotFoundException("broken jar file?: "
+ jarfile.getName());
URL jarURL = find(classname);
if (null != jarURL)
try {
return jarURL.openConnection().getInputStream();
}
catch (IOException e) {
throw new NotFoundException("broken jar file?: "
+ classname);
}
return null;
} }


@Override
public URL find(String classname) { public URL find(String classname) {
String jarname = classname.replace('.', '/') + ".class"; String jarname = classname.replace('.', '/') + ".class";
JarEntry je = jarfile.getJarEntry(jarname);
if (je != null)
if (jarfileEntries.contains(jarname))
try { try {
return new URL("jar:" + jarfileURL + "!/" + jarname);
return new URL(String.format("jar:%s!/%s", jarfileURL, jarname));
} }
catch (MalformedURLException e) {} catch (MalformedURLException e) {}

return null; // not found return null; // not found
} }


public void close() {
try {
jarfile.close();
jarfile = null;
}
catch (IOException e) {}
}

@Override
public String toString() { public String toString() {
return jarfile == null ? "<null>" : jarfile.toString();
return jarfileURL == null ? "<null>" : jarfileURL.toString();
} }
} }


else else
list = list.next; list = list.next;
} }

cp.close();
} }


public ClassPath appendSystemPath() { public ClassPath appendSystemPath() {

+ 0
- 7
src/main/javassist/LoaderClassPath.java View File

return url; return url;
} }
} }

/**
* Closes this class path.
*/
public void close() {
clref = null;
}
} }

+ 0
- 5
src/main/javassist/URLClassPath.java View File

return null; return null;
} }


/**
* Closes this class path.
*/
public void close() {}

/** /**
* Reads a class file on an http server. * Reads a class file on an http server.
* *

+ 22
- 0
src/test/javassist/JvstTest.java View File

package javassist; package javassist;


import junit.framework.*; import junit.framework.*;
import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import javassist.bytecode.*; import javassist.bytecode.*;
assertTrue("[class path: ]".equals(pool.toString())); assertTrue("[class path: ]".equals(pool.toString()));
} }


public void testReleaseJarClassPathFileHandle() throws Exception {
String jarFileName = "./empty.jar";
ClassLoader classLoader = getClass().getClassLoader();
File jarFile = new File(classLoader.getResource(jarFileName).getFile());
assertTrue(jarFile.exists());

// Prepare class pool and force it to open the Jar file
ClassPool pool = ClassPool.getDefault();
ClassPath cp = pool.appendClassPath(jarFile.getAbsolutePath());
assertNull(cp.openClassfile("nothere.Dummy"));

// Assert that it is possible to delete the jar file.
// On Windows deleting an open file will fail, while on on Mac/Linux this is always possible.
// This check will thus only fail on Windos if the file is still open.
assertTrue(jarFile.delete());
}

public void testJarClassPath() throws Exception {
// TODO: Verify that classes can be loaded from a JarClassPath
}

public void testSubtype() throws Exception { public void testSubtype() throws Exception {
CtClass cc = sloader.get("test1.Subtype"); CtClass cc = sloader.get("test1.Subtype");
assertTrue(cc.subtypeOf(cc)); assertTrue(cc.subtypeOf(cc));

+ 7
- 0
src/test/resources/Readme.txt View File

This directory contains files used by the unit tests.

empty.jar:
An empty, but valid, jar file.




BIN
src/test/resources/empty.jar View File


Loading…
Cancel
Save