mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-541: Merge prioritize extension classes over inherited in webapp.
This commit is contained in:
@@ -21,12 +21,6 @@ package org.apache.guacamole.extension;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -387,34 +381,8 @@ public class Extension {
|
||||
extension.close();
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// Create isolated classloader for this extension
|
||||
classLoader = AccessController.doPrivileged(new PrivilegedExceptionAction<ClassLoader>() {
|
||||
|
||||
@Override
|
||||
public ClassLoader run() throws GuacamoleException {
|
||||
|
||||
try {
|
||||
|
||||
// Classloader must contain only the extension itself
|
||||
return new URLClassLoader(new URL[]{file.toURI().toURL()}, parent);
|
||||
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
throw new GuacamoleException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Rethrow any GuacamoleException
|
||||
catch (PrivilegedActionException e) {
|
||||
throw (GuacamoleException) e.getException();
|
||||
}
|
||||
// Create isolated classloader for this extension
|
||||
classLoader = ExtensionClassLoader.getInstance(file, parent);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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.guacamole.extension;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleServerException;
|
||||
|
||||
/**
|
||||
* ClassLoader implementation which prioritizes the classes defined within a
|
||||
* given extension .jar file. Unlike the standard URLClassLoader, classes
|
||||
* within the parent ClassLoader are only used if they are not defined within
|
||||
* the given .jar. If classes are defined in both the parent and the extension
|
||||
* .jar, the versions defined within the extension .jar are used.
|
||||
*/
|
||||
public class ExtensionClassLoader extends URLClassLoader {
|
||||
|
||||
/**
|
||||
* The ClassLoader to use if class resolution through the extension .jar
|
||||
* fails.
|
||||
*/
|
||||
private final ClassLoader parent;
|
||||
|
||||
/**
|
||||
* Returns an instance of ExtensionClassLoader configured to load classes
|
||||
* from the given extension .jar. If a necessary class cannot be found
|
||||
* within the .jar, the given parent ClassLoader is used. Calling this
|
||||
* function multiple times will not affect previously-returned instances of
|
||||
* ExtensionClassLoader.
|
||||
*
|
||||
* @param extension
|
||||
* The extension .jar file from which classes should be loaded.
|
||||
*
|
||||
* @param parent
|
||||
* The ClassLoader to use if class resolution through the extension
|
||||
* .jar fails.
|
||||
*
|
||||
* @return
|
||||
* A ExtensionClassLoader instance which loads classes from the
|
||||
* given extension .jar file.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the given file is not actually a file, or the contents of the
|
||||
* file cannot be read.
|
||||
*/
|
||||
public static ExtensionClassLoader getInstance(final File extension,
|
||||
final ClassLoader parent) throws GuacamoleException {
|
||||
|
||||
try {
|
||||
// Attempt to create classloader which loads classes from the given
|
||||
// .jar file
|
||||
return AccessController.doPrivileged(new PrivilegedExceptionAction<ExtensionClassLoader>() {
|
||||
|
||||
@Override
|
||||
public ExtensionClassLoader run() throws GuacamoleException {
|
||||
return new ExtensionClassLoader(extension, parent);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
catch (PrivilegedActionException e) {
|
||||
throw (GuacamoleException) e.getException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL which points to the given extension .jar file.
|
||||
*
|
||||
* @param extension
|
||||
* The extension .jar file to generate a URL for.
|
||||
*
|
||||
* @return
|
||||
* A URL which points to the given extension .jar.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the given file is not actually a file, or the contents of the
|
||||
* file cannot be read.
|
||||
*/
|
||||
private static URL getExtensionURL(File extension)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Validate extension file is indeed a file
|
||||
if (!extension.isFile())
|
||||
throw new GuacamoleException(extension + " is not a file.");
|
||||
|
||||
try {
|
||||
return extension.toURI().toURL();
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
throw new GuacamoleServerException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ExtensionClassLoader configured to load classes from the
|
||||
* given extension .jar. If a necessary class cannot be found within the
|
||||
* .jar, the given parent ClassLoader is used. Calling this function
|
||||
* multiple times will not affect previously-returned instances of
|
||||
* ExtensionClassLoader.
|
||||
*
|
||||
* @param extension
|
||||
* The extension .jar file from which classes should be loaded.
|
||||
*
|
||||
* @param parent
|
||||
* The ClassLoader to use if class resolution through the extension
|
||||
* .jar fails.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the given file is not actually a file, or the contents of the
|
||||
* file cannot be read.
|
||||
*/
|
||||
private ExtensionClassLoader(File extension, ClassLoader parent)
|
||||
throws GuacamoleException {
|
||||
super(new URL[]{ getExtensionURL(extension) }, null);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String string) throws ClassNotFoundException {
|
||||
|
||||
// Search only within the given URLs
|
||||
try {
|
||||
return super.findClass(string);
|
||||
}
|
||||
|
||||
// Search parent classloader ONLY if not found within given URLs
|
||||
catch (ClassNotFoundException e) {
|
||||
return parent.loadClass(string);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user