use of io.cdap.cdap.api.artifact.CloseableClassLoader in project cdap by caskdata.
the class AbstractArtifactManager method createClassLoader.
@Override
public CloseableClassLoader createClassLoader(@Nullable String namespace, ArtifactInfo artifactInfo, @Nullable ClassLoader parentClassLoader) throws IOException, UnauthorizedException {
ClassLoaderFolder folder = BundleJarUtil.prepareClassLoaderFolder(getArtifactLocation(artifactInfo, namespace), () -> DirUtils.createTempDir(tmpDir));
DirectoryClassLoader directoryClassLoader = new DirectoryClassLoader(folder.getDir(), parentClassLoader == null ? bootstrapClassLoader : parentClassLoader, "lib");
return new CloseableClassLoader(directoryClassLoader, new ClassLoaderCleanup(directoryClassLoader, folder));
}
use of io.cdap.cdap.api.artifact.CloseableClassLoader in project cdap by caskdata.
the class ArtifactClassLoaderFactory method createClassLoader.
/**
* Create a classloader that loads classes from a directory where an artifact jar has been expanded, with access to
* packages that all program type has access to. The classloader created is only for artifact inspection purpose
* and shouldn't be used for program execution as it doesn't have the proper class filtering for the specific
* program type for the program being executed.
*
* @param unpackDir the directory where the artifact jar has been expanded
* @return a closeable classloader based off the specified artifact; on closing the returned {@link ClassLoader},
* all temporary resources created for the classloader will be removed
*/
CloseableClassLoader createClassLoader(File unpackDir) {
ProgramRunner programRunner = null;
try {
// Try to create a ProgramClassLoader from the Spark runtime system if it is available.
// It is needed because we don't know what program types that an artifact might have.
// TODO: CDAP-5613. We shouldn't always expose the Spark classes.
programRunner = programRunnerFactory.create(ProgramType.SPARK);
} catch (Exception e) {
// If Spark is not supported, exception is expected. We'll use the default filter.
LOG.trace("Spark is not supported. Not using ProgramClassLoader from Spark", e);
}
ProgramClassLoader programClassLoader = null;
if (programRunner instanceof ProgramClassLoaderProvider) {
programClassLoader = new ProgramClassLoader(cConf, unpackDir, ((ProgramClassLoaderProvider) programRunner).createProgramClassLoaderParent());
}
if (programClassLoader == null) {
programClassLoader = new ProgramClassLoader(cConf, unpackDir, FilterClassLoader.create(getClass().getClassLoader()));
}
final ClassLoader finalProgramClassLoader = programClassLoader;
final ProgramRunner finalProgramRunner = programRunner;
return new CloseableClassLoader(programClassLoader, () -> {
Closeables.closeQuietly((Closeable) finalProgramClassLoader);
if (finalProgramRunner instanceof Closeable) {
Closeables.closeQuietly((Closeable) finalProgramRunner);
}
});
}
use of io.cdap.cdap.api.artifact.CloseableClassLoader in project cdap by caskdata.
the class ArtifactClassLoaderFactory method createClassLoader.
/**
* Creates a multi level classloader where each location in the specified iterator corresponds to a classloader whose
* parent is built from the location behind it.
*
* @param artifactLocations the locations of the artifact to create the classloader from
* @return a closeable classloader based off the specified artifacts; on closing the returned {@link ClassLoader},
* all temporary resources created for the classloader will be removed
* @see #createClassLoader(File)
*/
CloseableClassLoader createClassLoader(Iterator<Location> artifactLocations, EntityImpersonator entityImpersonator) {
if (!artifactLocations.hasNext()) {
throw new IllegalArgumentException("Cannot create a classloader without an artifact.");
}
Location artifactLocation = artifactLocations.next();
if (!artifactLocations.hasNext()) {
return createClassLoader(artifactLocation, entityImpersonator);
}
try {
ClassLoaderFolder classLoaderFolder = entityImpersonator.impersonate(() -> BundleJarUtil.prepareClassLoaderFolder(artifactLocation, () -> DirUtils.createTempDir(tmpDir)));
CloseableClassLoader parentClassLoader = createClassLoader(artifactLocations, entityImpersonator);
return new CloseableClassLoader(new DirectoryClassLoader(classLoaderFolder.getDir(), parentClassLoader, "lib"), () -> {
Closeables.closeQuietly(parentClassLoader);
Closeables.closeQuietly(classLoaderFolder);
});
} catch (Exception e) {
throw Throwables.propagate(e);
}
}
use of io.cdap.cdap.api.artifact.CloseableClassLoader in project cdap by caskdata.
the class DefaultArtifactRepository method addArtifact.
@Override
public ArtifactDetail addArtifact(final Id.Artifact artifactId, final File artifactFile, @Nullable Set<ArtifactRange> parentArtifacts, @Nullable Set<PluginClass> additionalPlugins, Map<String, String> properties) throws Exception {
if (additionalPlugins != null) {
validatePluginSet(additionalPlugins);
}
parentArtifacts = parentArtifacts == null ? Collections.emptySet() : parentArtifacts;
CloseableClassLoader parentClassLoader = null;
EntityImpersonator entityImpersonator = new EntityImpersonator(artifactId.toEntityId(), impersonator);
List<ArtifactDescriptor> parentDescriptors = new ArrayList<>();
if (!parentArtifacts.isEmpty()) {
validateParentSet(artifactId, parentArtifacts);
parentDescriptors = getParentArtifactDescriptors(artifactId, parentArtifacts);
}
additionalPlugins = additionalPlugins == null ? Collections.emptySet() : additionalPlugins;
ArtifactClassesWithMetadata artifactClassesWithMetadata = inspectArtifact(artifactId, artifactFile, parentDescriptors, additionalPlugins);
ArtifactMeta meta = new ArtifactMeta(artifactClassesWithMetadata.getArtifactClasses(), parentArtifacts, properties);
ArtifactDetail artifactDetail = artifactStore.write(artifactId, meta, artifactFile, entityImpersonator);
ArtifactDescriptor descriptor = artifactDetail.getDescriptor();
// info hides some fields that are available in detail, such as the location of the artifact
ArtifactInfo artifactInfo = new ArtifactInfo(descriptor.getArtifactId(), artifactDetail.getMeta().getClasses(), artifactDetail.getMeta().getProperties());
// add system metadata for artifacts
writeSystemMetadata(artifactId.toEntityId(), artifactInfo);
// add plugin metadata, these metadata can be in any scope depending on the artifact scope
metadataServiceClient.batch(artifactClassesWithMetadata.getMutations());
return artifactDetail;
}
use of io.cdap.cdap.api.artifact.CloseableClassLoader in project cdap by caskdata.
the class InMemoryConfigurator method config.
/**
* Executes the <code>Application.configure</code> within the same JVM.
* <p>
* This method could be dangerous and should be used only in standalone mode.
* </p>
*
* @return A instance of {@link ListenableFuture}.
*/
@Override
public ListenableFuture<ConfigResponse> config() {
// Create the classloader
EntityImpersonator classLoaderImpersonator = new EntityImpersonator(artifactId.toEntityId(), impersonator);
try (CloseableClassLoader classLoader = artifactRepository.createArtifactClassLoader(new ArtifactDescriptor(artifactId.getNamespace().getId(), artifactId.toArtifactId(), artifactLocation), classLoaderImpersonator)) {
SettableFuture<ConfigResponse> result = SettableFuture.create();
Object appMain = classLoader.loadClass(appClassName).newInstance();
if (!(appMain instanceof Application)) {
throw new IllegalStateException(String.format("Application main class is of invalid type: %s", appMain.getClass().getName()));
}
Application<?> app = (Application<?>) appMain;
ConfigResponse response = createResponse(app, classLoader);
result.set(response);
return result;
} catch (Throwable t) {
return Futures.immediateFailedFuture(t);
}
}
Aggregations