blob: d1df3e390cf040208c152caaf82c6ef77f6d7559 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hop.core.plugins;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.ProtectionDomain;
public class HopURLClassLoader extends URLClassLoader {
private String name;
public HopURLClassLoader(URL[] url, ClassLoader classLoader) {
super(url, classLoader);
}
public HopURLClassLoader(URL[] url, ClassLoader classLoader, String name) {
this(url, classLoader);
this.name = name;
}
@Override
protected void addURL(URL url) {
super.addURL(url);
}
@Override
public String toString() {
return super.toString() + " : " + name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
protected Class<?> loadClassFromThisLoader(String arg0, boolean arg1)
throws ClassNotFoundException {
Class<?> clz;
if ((clz = findLoadedClass(arg0)) != null) {
if (arg1) {
resolveClass(clz);
}
return clz;
}
if ((clz = findClass(arg0)) != null) {
if (arg1) {
resolveClass(clz);
}
return clz;
}
return clz;
}
protected Class<?> loadClassFromParent(String name, boolean resolve)
throws ClassNotFoundException {
Class<?> clz;
if ((clz = getParent().loadClass(name)) != null) {
if (resolve) {
resolveClass(clz);
}
return clz;
}
throw new ClassNotFoundException("Could not find :" + name);
}
@Override
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
try {
return loadClassFromThisLoader(name, resolve);
} catch (ClassNotFoundException | NoClassDefFoundError | SecurityException exception) {
try {
return loadClassFromParent(name, resolve);
} catch (Exception parentException) {
throw new ClassNotFoundException(
"Unable to load class '" + name + "' in this classloader or in the parent", exception);
}
}
}
/*
* Cglib doe's not creates custom class loader (to access package methods and classes ) it uses reflection to invoke
* "defineClass", but you can call protected method in subclass without problems:
*/
public Class<?> loadClass(String name, ProtectionDomain protectionDomain) {
Class<?> loaded = findLoadedClass(name);
if (loaded == null) {
// Get the jar, load the bytes from the jar file, construct class from scratch as in snippet
// below...
String newName = name.replace('.', '/');
InputStream is = getResourceAsStream(newName);
byte[] driverBytes = toBytes(is);
loaded = super.defineClass(name, driverBytes, 0, driverBytes.length, protectionDomain);
}
return loaded;
}
private byte[] toBytes(InputStream is) {
byte[] retval = new byte[0];
try {
int a = is.available();
while (a > 0) {
byte[] buffer = new byte[a];
is.read(buffer);
byte[] newretval = new byte[retval.length + a];
for (int i = 0; i < retval.length; i++) {
newretval[i] = retval[i]; // old part
}
for (int i = 0; i < a; i++) {
newretval[retval.length + i] = buffer[i]; // new part
}
retval = newretval;
a = is.available(); // see what's left
}
return retval;
} catch (Exception e) {
// TODO: Throw error here!!
return null;
}
}
@Override
public URL getResource(String name) {
URL url = findResource(name);
if (url == null && getParent() != null) {
url = getParent().getResource(name);
}
return url;
}
}