blob: b40ad183977720c5fd3ee272dc25629e02e6c86f [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.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]";
}
}
}