[forge-issues] [JBoss JIRA] (FORGE-2106) Expose the underlying Project's ClassLoader via a new ProjectFacet

Lincoln Baxter III (JIRA) issues at jboss.org
Wed Oct 29 11:33:35 EDT 2014


    [ https://issues.jboss.org/browse/FORGE-2106?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13015882#comment-13015882 ] 

Lincoln Baxter III commented on FORGE-2106:
-------------------------------------------

{code}
    public URLClassLoader getProjectClassLoader(Project selectedProject) {
        try {
            MetadataFacet metadataFacet = selectedProject.getFacet(MetadataFacet.class);
            MavenFacet mavenFacet = selectedProject.getFacet(MavenFacet.class);
            DependencyQuery projectDependencyQuery = create(metadataFacet.getOutputDependency(), mavenFacet.getModel()
                .getPackaging());
            Resource<?> projectArtifact = getProjectArtifact(selectedProject);
            List<URL> dependenciesURL = new ArrayList<>();

            dependenciesURL.add(new URL(formatJarUrl(projectArtifact, getPackageRootPath(mavenFacet))));

            for (Dependency dependency : dependencyResolver.resolveDependencies(projectDependencyQuery)) {
                dependenciesURL.add(new URL(formatJarUrl(dependency.getArtifact(), "/")));
            }

            PicketLinkBaseFacet picketLinkFacet = selectedProject.getFacet(PicketLinkBaseFacet.class);

            DependencyQuery query = create(DependencyBuilder
                .create(MavenDependencies.PICKETLINK_IDM_SIMPLE_SCHEMA_DEPENDENCY)
                .setVersion(picketLinkFacet.getPicketLinkVersion()),
                "jar");

            Dependency simpleSchemeDependency = this.dependencyResolver.resolveArtifact(query);

            dependenciesURL.add(new URL(formatJarUrl(simpleSchemeDependency.getArtifact(), "/")));

            Set<Dependency> basicModelDependencies = this.dependencyResolver.resolveDependencies(query);

            for (Dependency dependency : basicModelDependencies) {
                dependency = this.dependencyResolver.resolveArtifact(create(dependency, "jar"));
                dependenciesURL.add(new URL(formatJarUrl(dependency.getArtifact(), "/")));
            }

            DependencyFacet dependencyFacet = selectedProject.getFacet(DependencyFacet.class);
            List<Dependency> effectiveDependencies = dependencyFacet.getEffectiveDependencies();

            for (Dependency dependency : effectiveDependencies) {
                dependency = this.dependencyResolver.resolveArtifact(create(dependency, "jar"));
                dependenciesURL.add(new URL(formatJarUrl(dependency.getArtifact(), "/")));
            }

            return new URLClassLoader(dependenciesURL.toArray(new URL[dependenciesURL.size()]));
        } catch (Exception e) {
            throw new RuntimeException("Could not create project's class loader.", e);
        }
    }

    private Resource<?> getProjectArtifact(Project selectedProject) {
        if (this.projectArtifact == null) {
            this.projectArtifact = performBuild(selectedProject);
        }

        return this.projectArtifact ;
    }

    private String formatJarUrl(Resource<?> artifact, String packageRootPath) {
        return "jar:file:" + artifact.getFullyQualifiedName() + "!" + packageRootPath;
    }

    private DependencyQuery create(Dependency dependency, String packaging) {
        return DependencyQueryBuilder
            .create(DependencyBuilder
                .create(dependency)
                .setPackaging(packaging)
                .getCoordinate());
    }

    private boolean isMappedEntity(Class<?> cls) {
        while (!cls.equals(Object.class)) {
            for (Annotation a : cls.getAnnotations()) {
                if (a.annotationType().getName().startsWith(JPA_ANNOTATION_PACKAGE)) {
                    return true;
                }
            }

            // No class annotation was found, check the fields
            for (Field f : cls.getDeclaredFields()) {
                for (Annotation a : f.getAnnotations()) {
                    if (a.annotationType().getName().startsWith(JPA_ANNOTATION_PACKAGE)) {
                        return true;
                    }
                }
            }

            // Check the superclass
            cls = cls.getSuperclass();
        }

        return false;
    }

    private Resource<?> performBuild(Project selectedProject) {
        PackagingFacet packagingFacet = selectedProject.getFacet(PackagingFacet.class);

        return packagingFacet
            .createBuilder()
            .addArguments("clean", "install")
            .runTests(false)
            .build();
    }
{code}

> Expose the underlying Project's ClassLoader via a new ProjectFacet
> ------------------------------------------------------------------
>
>                 Key: FORGE-2106
>                 URL: https://issues.jboss.org/browse/FORGE-2106
>             Project: Forge
>          Issue Type: Feature Request
>          Components: Developer Tools - Java, Projects
>    Affects Versions: 2.12.1.Final
>            Reporter: Lincoln Baxter III
>
> https://github.com/picketlink/picketlink-forge-addon/blob/master/impl/src/main/java/org/picketlink/tools/forge/operations/PersistenceOperations.java#L204
> Some Addons need to be able to ClassLoad projects in order to reflect on types in dependencies. This is likely a dangerous operation, however, since it can lead to ClassLoader memory leaks, so some protection/patterns will need to be put in place to make this less likely.



--
This message was sent by Atlassian JIRA
(v6.3.1#6329)


More information about the forge-issues mailing list