001package org.nuxeo.webengine.gwt.codeserver;
002
003import java.io.IOException;
004import java.net.URI;
005import java.net.URISyntaxException;
006import java.net.URL;
007import java.net.URLClassLoader;
008import java.nio.file.FileSystemNotFoundException;
009import java.nio.file.FileSystems;
010import java.nio.file.Files;
011import java.nio.file.Path;
012import java.nio.file.Paths;
013import java.util.Collections;
014import java.util.HashMap;
015import java.util.Map;
016
017public class CodeServerLoader extends URLClassLoader {
018
019        CodeServerLoader(URL[] jars) {
020                super(jars, CodeServerLoader.class.getClassLoader());
021        }
022
023        @Override
024        protected java.lang.Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
025                Class<?> clazz = findLoadedClass(name);
026                if (clazz != null) {
027                        return clazz;
028                }
029
030                if (name.equals(CodeServerLauncher.class.getName())) {
031                        return getParent().loadClass(name);
032                }
033
034                if (name.equals(CodeServerWrapper.class.getName())) {
035                        try {
036                                return reloadClass(CodeServerWrapper.class);
037                        } catch (URISyntaxException | IOException cause) {
038                                throw new ClassNotFoundException("Cannot reload wrapper in gwt dev class loader", cause);
039                        }
040                }
041                try {
042                        return ClassLoader.getSystemClassLoader().loadClass(name);
043                } catch (ClassNotFoundException cause) {
044                        ;
045                }
046                synchronized (getClassLoadingLock(name)) {
047                        clazz = findClass(name);
048                        if (clazz != null) {
049                                return clazz;
050                        }
051                }
052                throw new ClassNotFoundException("Cannot find " + name + " in gwt class loader");
053        };
054
055        Class<?> reloadClass(Class<?> clazz) throws URISyntaxException, IOException {
056                URI location = clazz.getResource(clazz.getSimpleName().concat(".class")).toURI();
057                byte[] content = Files.readAllBytes(getPath(location));
058                return defineClass(clazz.getName(), content, 0, content.length);
059        }
060
061        private Path getPath(URI location) throws IOException {
062                try {
063                        return Paths.get(location);
064                } catch (FileSystemNotFoundException cause) {
065                        Map<String, Object> env = Collections.emptyMap();
066                        FileSystems.newFileSystem(location, env);
067                        return Paths.get(location);
068                }
069        }
070
071        CodeServerLauncher load() throws ReflectiveOperationException {
072                return (CodeServerLauncher) loadClass(CodeServerWrapper.class.getName()).newInstance();
073        }
074
075}