| /* |
| * 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.netbeans; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.net.URLClassLoader; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Enumeration; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.jar.JarEntry; |
| import java.util.jar.JarFile; |
| import java.util.jar.JarOutputStream; |
| import java.util.jar.Manifest; |
| import org.fakepkg.FakeIfceHidden; |
| import org.openide.modules.SpecificationVersion; |
| import org.openide.util.Enumerations; |
| import org.openide.util.Utilities; |
| import org.openide.util.test.MockLookup; |
| |
| /** Verify contracts needed by Netigso. |
| */ |
| public class ModuleFactoryAlienTest extends SetupHid { |
| |
| static { |
| MockLookup.setInstances(new Factory()); |
| } |
| |
| public ModuleFactoryAlienTest(String name) { |
| super(name); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| } |
| |
| |
| |
| public void testFactoryCreatesAlienModules() throws Exception { |
| MockModuleInstaller installer = new MockModuleInstaller(); |
| MockEvents ev = new MockEvents(); |
| ModuleManager mgr = new ModuleManager(installer, ev); |
| mgr.mutexPrivileged().enterWriteAccess(); |
| |
| Module m2, m3; |
| try { |
| String mf = "AlienName: test-name.m2\n" + |
| "AlienVersion: 1.1.0\n" + |
| "AlienExport: org.fakepkg\n\n"; |
| File j2 = changeManifest(new File(jars, "simple-module.jar"), mf); |
| m2 = mgr.create(j2, null, false, false, false); |
| mf = "AlienName: test-name\n" + |
| "AlienVersion: 1.1.0\n" + |
| "AlienExport: org.fakepkg\n\n"; |
| File j3 = changeManifest(new File(jars, "depends-on-simple-module.jar"), mf); |
| m3 = mgr.create(j3, null, false, false, false); |
| mgr.enable(new HashSet<Module>(Arrays.asList(m2, m3))); |
| } finally { |
| mgr.mutexPrivileged().exitWriteAccess(); |
| } |
| ClassLoader l; |
| URL u; |
| Class<?> clazz; |
| |
| |
| l = Thread.currentThread().getContextClassLoader(); |
| u = l.getResource("org/fakepkg/Something.txt"); |
| assertNotNull("Resource found", u); |
| |
| assertEquals("No dependencies", 0, m3.getDependencies().size()); |
| |
| clazz = l.loadClass("org.fakepkg.FakeIfce"); |
| assertNotNull("Class loaded", clazz); |
| assertEquals("it is our fake class", FakeIfceHidden.class, clazz); |
| |
| |
| l = m3.getClassLoader(); |
| |
| assertNotNull("Classloader found", l); |
| assertEquals("My classloader", Loader.class, l.getClass()); |
| |
| u = l.getResource("org/fakepkg/Something.txt"); |
| assertNotNull("Resource found", u); |
| |
| clazz = l.loadClass("org.fakepkg.FakeIfce"); |
| assertNotNull("Class loaded", clazz); |
| assertEquals("it is our fake class", FakeIfceHidden.class, clazz); |
| |
| assertEquals("No dependencies", 0, m3.getDependencies().size()); |
| } |
| |
| public void testAlienCanDependOnNetBeans() throws Exception { |
| MockModuleInstaller installer = new MockModuleInstaller(); |
| MockEvents ev = new MockEvents(); |
| ModuleManager mgr = new ModuleManager(installer, ev); |
| mgr.mutexPrivileged().enterWriteAccess(); |
| HashSet<Module> both = null; |
| try { |
| String mfBar = "AlienName: org.bar\n" + |
| "AlienExport: org.bar\n" + |
| "AlienImport: org.foo\n" + |
| "\n\n"; |
| |
| File j1 = new File(jars, "simple-module.jar"); |
| File j2 = changeManifest(new File(jars, "depends-on-simple-module.jar"), mfBar); |
| Module m1 = mgr.create(j1, null, false, false, false); |
| Module m2 = mgr.create(j2, null, false, false, false); |
| HashSet<Module> b = new HashSet<Module>(Arrays.asList(m1, m2)); |
| mgr.enable(b); |
| both = b; |
| |
| AlienModule am = (AlienModule)m2; |
| am.loader.l = new URLClassLoader(new URL[] { Utilities.toURI(am.jar).toURL() }, m1.getClassLoader()); |
| |
| assertFalse("Finish without exception", m2.provides("false")); |
| |
| |
| Class<?> clazz = m2.getClassLoader().loadClass("org.bar.SomethingElse"); |
| Class<?> sprclass = m2.getClassLoader().loadClass("org.foo.Something"); |
| |
| assertEquals("Correct parent is used", sprclass, clazz.getSuperclass()); |
| } finally { |
| if (both != null) { |
| mgr.disable(both); |
| } |
| mgr.mutexPrivileged().exitWriteAccess(); |
| } |
| } |
| |
| public static class Factory extends ModuleFactory { |
| |
| static void clear() { |
| } |
| |
| public Factory() { |
| } |
| |
| static void registerBundle(Module m) throws IOException { |
| |
| } |
| |
| @Override |
| public Module createFixed(Manifest mani, Object history, ClassLoader loader, boolean autoload, boolean eager, ModuleManager mgr, Events ev) throws InvalidException { |
| Module m = super.createFixed(mani, history, loader, autoload, eager, mgr, ev); |
| try { |
| registerBundle(m); |
| } catch (IOException ex) { |
| throw (InvalidException)new InvalidException(m, ex.getMessage()).initCause(ex); |
| } |
| return m; |
| } |
| |
| @Override |
| public Module create( |
| File jar, Object history, |
| boolean reloadable, boolean autoload, boolean eager, |
| ModuleManager mgr, Events ev |
| ) throws IOException { |
| try { |
| Module m = super.create(jar, history, reloadable, autoload, eager, mgr, ev); |
| registerBundle(m); |
| return m; |
| } catch (InvalidException ex) { |
| Manifest mani = ex.getManifest(); |
| if (mani != null) { |
| String name = mani.getMainAttributes().getValue("AlienName"); // NOI18N |
| if (name == null) { |
| throw ex; |
| } |
| return new AlienModule(mani, jar, mgr, ev, history, reloadable, autoload, eager); |
| } |
| throw ex; |
| } |
| } |
| |
| } |
| |
| static final class AlienModule extends Module { |
| private Manifest manifest; |
| private Loader loader; |
| private String name; |
| private File jar; |
| |
| public AlienModule(Manifest m, File jar, ModuleManager mgr, Events ev, Object history, boolean reloadable, boolean autoload, boolean eager) throws IOException { |
| super(mgr, ev, history, reloadable, autoload, eager); |
| |
| this.manifest = m; |
| this.name = manifest.getMainAttributes().getValue("AlienName"); |
| this.jar = jar; |
| } |
| |
| @Override |
| public String[] getProvides() { |
| return new String[0]; |
| } |
| |
| @Override |
| public String getCodeName() { |
| return name; |
| } |
| |
| @Override |
| public String getCodeNameBase() { |
| return getCodeName(); |
| } |
| |
| @Override |
| public int getCodeNameRelease() { |
| return -1; |
| } |
| |
| @Override |
| public SpecificationVersion getSpecificationVersion() { |
| return new SpecificationVersion("1.0"); |
| } |
| |
| @Override |
| public String getImplementationVersion() { |
| return "testimpl"; // NOI18N |
| } |
| |
| @Override |
| protected void parseManifest() throws InvalidException { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public List<File> getAllJars() { |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| public void setReloadable(boolean r) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public void reload() throws IOException { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected void classLoaderUp(Set<Module> parents) throws IOException { |
| loader = new Loader(this); |
| } |
| |
| @Override |
| protected void classLoaderDown() { |
| loader = null; |
| } |
| |
| @Override |
| public ClassLoader getClassLoader() throws IllegalArgumentException { |
| if (loader == null) { |
| throw new IllegalArgumentException("No classloader for " + getCodeNameBase()); // NOI18N |
| } |
| return loader; |
| } |
| |
| @Override |
| protected void cleanup() { |
| } |
| |
| @Override |
| protected void destroy() { |
| } |
| |
| @Override |
| public boolean isFixed() { |
| return false; |
| } |
| |
| @Override |
| public Manifest getManifest() { |
| return manifest; |
| } |
| |
| @Override |
| public Object getLocalizedAttribute(String attr) { |
| // TBD; |
| return null; |
| } |
| |
| @Override |
| public String toString() { |
| return "Alien: " + getCodeName(); |
| } |
| } |
| |
| static final class Loader extends ProxyClassLoader { |
| final AlienModule am; |
| ClassLoader l; |
| |
| public Loader(AlienModule mf) throws MalformedURLException { |
| super(new ClassLoader[0], true); |
| Set<String> pkgs = new HashSet<String>(); |
| pkgs.add(mf.getManifest().getMainAttributes().getValue("AlienExport")); |
| addCoveredPackages(pkgs); |
| this.am = mf; |
| } |
| |
| @Override |
| public URL findResource(String name) { |
| if ("org/fakepkg/Something.txt".equals(name)) { |
| URL u = ModuleFactoryAlienTest.class.getResource("/org/fakepkg/resource1.txt"); |
| assertNotNull("text found", u); |
| return u; |
| } |
| return null; |
| } |
| |
| @Override |
| public Enumeration<URL> findResources(String name) { |
| return Enumerations.empty(); |
| } |
| |
| @Override |
| protected Class<?> doLoadClass(String pkg, String name) { |
| if (name.equals("org.fakepkg.FakeIfce")) { |
| return FakeIfceHidden.class; |
| } |
| return null; |
| } |
| |
| @Override |
| protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { |
| Class c = findLoadedClass(name); |
| if (c != null) { |
| return c; |
| } |
| if (l != null) { |
| try { |
| c = l.loadClass(name); |
| if (resolve) { |
| resolveClass(c); |
| } |
| return c; |
| } catch (ClassNotFoundException x) {} |
| } |
| return super.loadClass(name, resolve); |
| } |
| |
| @Override |
| public String toString() { |
| return "Alien[test]"; |
| } |
| } |
| |
| } |