Skip to content

Commit

Permalink
FORGE-2106: Added ClassLoaderFacet to projects addon with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gastaldi committed Jan 21, 2015
1 parent 80dc820 commit 26232ed
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/

package org.jboss.forge.addon.projects.facets;

import java.net.URL;
import java.net.URLClassLoader;

import org.jboss.forge.addon.projects.Project;
import org.jboss.forge.addon.projects.ProjectFacet;

/**
* A {@link ProjectFacet} with the {@link Project}'s {@link ClassLoader}
*
* @author <a href="ggastald@redhat.com">George Gastaldi</a>
*/
public interface ClassLoaderFacet extends ProjectFacet
{
/**
* Returns the {@link URLClassLoader} with the {@link URL}s that this project depends on.
*
* WARNING: Remember to close this {@link URLClassLoader} when no longer in use.
* <p/>
* Leaving it open could introduce memory leaks.
*/
URLClassLoader getClassLoader();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/

package org.jboss.forge.addon.projects.impl.facets;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import org.jboss.forge.addon.dependencies.Dependency;
import org.jboss.forge.addon.facets.AbstractFacet;
import org.jboss.forge.addon.facets.constraints.FacetConstraint;
import org.jboss.forge.addon.projects.Project;
import org.jboss.forge.addon.projects.facets.ClassLoaderFacet;
import org.jboss.forge.addon.projects.facets.DependencyFacet;
import org.jboss.forge.addon.projects.facets.PackagingFacet;
import org.jboss.forge.addon.resource.FileResource;
import org.jboss.forge.addon.resource.Resource;

/**
* Implementation of the {@link ClassLoaderFacet} interface
*
* @author <a href="ggastald@redhat.com">George Gastaldi</a>
*/
@FacetConstraint(DependencyFacet.class)
class ClassLoaderFacetImpl extends AbstractFacet<Project> implements
ClassLoaderFacet
{
private static final Logger log = Logger
.getLogger(ClassLoaderFacetImpl.class.getName());

@Override
public boolean install()
{
return isInstalled();
}

@Override
public boolean isInstalled()
{
return true;
}

@Override
public URLClassLoader getClassLoader()
{
Project project = getFaceted();
DependencyFacet facet = project.getFacet(DependencyFacet.class);
List<Dependency> effectiveDependencies = facet
.getEffectiveDependencies();
List<URL> urls = new ArrayList<>();
// Add project dependencies
for (Dependency dependency : effectiveDependencies)
{
FileResource<?> artifact = dependency.getArtifact();
if (artifact != null)
{
File artifactFile = artifact.getUnderlyingResourceObject();
try
{
urls.add(artifactFile.toURI().toURL());
}
catch (MalformedURLException e)
{
log.warning("Error while configuring Reflections: "
+ e.getMessage());
}
}
}
// Add project build
PackagingFacet packagingFacet = project.getFacet(PackagingFacet.class);
Resource<?> finalArtifact = packagingFacet.getFinalArtifact();
if (!finalArtifact.exists())
{
// Force build
finalArtifact = packagingFacet.createBuilder().quiet(true).build();
}
if (finalArtifact instanceof FileResource)
{
File artifact = ((FileResource<?>) finalArtifact).getUnderlyingResourceObject();
try
{
urls.add(artifact.toURI().toURL());
}
catch (MalformedURLException e)
{
log.warning("Error while configuring Reflections: "
+ e.getMessage());
}
}
// Project Classloader. May introduce memory leaks if not closed properly
URLClassLoader urlClassLoader = URLClassLoader.newInstance(urls.toArray(new URL[urls.size()]));
return urlClassLoader;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/

package org.jboss.forge.addon.projects.impl.facets;

import java.net.URLClassLoader;
import java.util.Arrays;

import javax.inject.Inject;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.forge.addon.parser.java.facets.JavaSourceFacet;
import org.jboss.forge.addon.projects.Project;
import org.jboss.forge.addon.projects.ProjectFacet;
import org.jboss.forge.addon.projects.ProjectFactory;
import org.jboss.forge.addon.projects.facets.ClassLoaderFacet;
import org.jboss.forge.arquillian.AddonDependency;
import org.jboss.forge.arquillian.Dependencies;
import org.jboss.forge.arquillian.archive.ForgeArchive;
import org.jboss.forge.furnace.repositories.AddonDependencyEntry;
import org.jboss.forge.roaster.Roaster;
import org.jboss.forge.roaster.model.source.JavaClassSource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
*
* @author <a href="ggastald@redhat.com">George Gastaldi</a>
*/
@RunWith(Arquillian.class)
public class ClassLoaderFacetTest
{
@Deployment
@Dependencies({
@AddonDependency(name = "org.jboss.forge.addon:parser-java"),
@AddonDependency(name = "org.jboss.forge.addon:resources"),
@AddonDependency(name = "org.jboss.forge.addon:maven"),
@AddonDependency(name = "org.jboss.forge.addon:projects")
})
public static ForgeArchive getDeployment()
{
ForgeArchive archive = ShrinkWrap
.create(ForgeArchive.class)
.addBeansXML()
.addAsAddonDependencies(
AddonDependencyEntry.create("org.jboss.forge.furnace.container:cdi"),
AddonDependencyEntry.create("org.jboss.forge.addon:projects"),
AddonDependencyEntry.create("org.jboss.forge.addon:parser-java")
);

return archive;
}

@Inject
private ProjectFactory projectFactory;

@Test
public void testNewClassReflection() throws Exception
{
Project project = projectFactory.createTempProject(Arrays
.<Class<? extends ProjectFacet>> asList(JavaSourceFacet.class));
JavaSourceFacet facet = project.getFacet(JavaSourceFacet.class);
Assert.assertNotNull(facet);
JavaClassSource javaClass = Roaster.create(JavaClassSource.class).setName("Foo").setPackage("com.example");
javaClass.addMethod("public static String hello() {return \"Hello\";}");
facet.saveJavaSource(javaClass);
Assert.assertTrue(project.hasFacet(ClassLoaderFacet.class));
ClassLoaderFacet classLoaderFacet = project.getFacet(ClassLoaderFacet.class);
try (URLClassLoader classLoader = classLoaderFacet.getClassLoader())
{
Assert.assertNotNull(classLoader);
Class<?> clazz = classLoader.loadClass(javaClass.getQualifiedName());
Assert.assertSame(classLoader, clazz.getClassLoader());
Assert.assertEquals("Hello", clazz.getMethod("hello").invoke(null));
}
}

}

0 comments on commit 26232ed

Please sign in to comment.