/*
* Copyright, Aspect Security, Inc.
*
* This file is part of JavaSnoop.
*
* JavaSnoop is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JavaSnoop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with JavaSnoop. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aspect.snoop.agent.manager;
import com.aspect.snoop.util.IOUtil;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import javassist.ClassPath;
public class SmartURLClassPath implements ClassPath {
protected URL url;
private Map<String,Integer> classesResponsibleFor;
public SmartURLClassPath(URL url) {
this.url = url;
this.classesResponsibleFor = new HashMap<String,Integer>();
}
public void addClass(String className) {
classesResponsibleFor.put(className, 1);
}
@Override
public String toString() {
return url.toString();
}
/**
* Opens a class file with http.
*
* @return null if the class file could not be found.
*/
public InputStream openClassfile(String classname) {
if ( classesResponsibleFor.get(classname) == null ) {
return null;
}
try {
return openClassfile0(classname);
}
catch (IOException e) {e.printStackTrace();}
return null; // not found
}
private InputStream openClassfile0(String classname) throws IOException {
return fetchClass( getURL(classname) );
}
private URL getURL(String classname) throws MalformedURLException {
URL finalUrl;
if ( url.getPath().endsWith(".jar") || url.getPath().endsWith(".zip") ) {
String finalPath = url.getPath() + "!" + "/" + classname.replace('.', '/') + ".class";
URL tmp = new URL(url.getProtocol(), url.getHost(), url.getPort(), finalPath);
String s = "jar:" + tmp.toString();
finalUrl = new URL(s);
} else {
String finalPath = url.getPath() + classname.replace('.', '/') + ".class";
finalUrl = new URL(url.getProtocol(), url.getHost(), url.getPort(), finalPath);
}
return finalUrl;
}
public InputStream fetchClass(URL url) throws IOException {
return url.openStream();
}
/**
* Returns the URL.
*
* @return null if the class file could not be obtained.
*/
public URL find(String classname) {
if ( classesResponsibleFor.get(classname) == null ) {
return null;
}
try {
InputStream is = openClassfile0(classname);
if (is != null) {
is.close();
return getURL(classname);
}
} catch (IOException e) {e.printStackTrace();}
return null;
}
/**
* Closes this class path.
*/
public void close() {}
public static byte[] getBytesFromURL(URL url)
throws IOException
{
byte[] b;
URLConnection con = url.openConnection();
int size = con.getContentLength();
InputStream s = con.getInputStream();
try {
if (size <= 0)
b = IOUtil.getBytesFromStream(s);
else {
b = new byte[size];
int len = 0;
do {
int n = s.read(b, len, size - len);
if (n < 0)
throw new IOException("the stream was closed: " + url.toString());
len += n;
} while (len < size);
}
}
finally {
s.close();
}
return b;
}
}