Search in sources :

Example 1 with CuratedApplication

use of io.quarkus.bootstrap.app.CuratedApplication in project quarkus by quarkusio.

the class QuarkusDeployableContainer method deploy.

@SuppressWarnings("rawtypes")
@Override
public ProtocolMetaData deploy(Archive<?> archive) throws DeploymentException {
    old = Thread.currentThread().getContextClassLoader();
    if (testClass.get() == null) {
        throw new IllegalStateException("Test class not available");
    }
    Class testJavaClass = testClass.get().getJavaClass();
    // some TCK tests embed random libraries such as old versions of Jackson databind
    // this breaks quarkus, so we just skip them
    boolean skipLibraries = Boolean.getBoolean("io.quarkus.arquillian.skip-libraries");
    try {
        // Export the test archive
        Path tmpLocation = Files.createTempDirectory("quarkus-arquillian-test");
        deploymentLocation.set(tmpLocation);
        archive.as(ExplodedExporter.class).exportExplodedInto(tmpLocation.toFile());
        Path appLocation;
        Set<Path> libraries = new HashSet<>();
        if (archive instanceof WebArchive) {
            // Quarkus does not support the WAR layout and so adapt the layout (similarly to quarkus-war-launcher)
            appLocation = tmpLocation.resolve("app").toAbsolutePath();
            // WEB-INF/lib -> lib/
            if (!skipLibraries) {
                if (Files.exists(tmpLocation.resolve("WEB-INF/lib"))) {
                    Files.move(tmpLocation.resolve("WEB-INF/lib"), tmpLocation.resolve("lib"));
                }
            }
            // WEB-INF/classes -> archive/
            if (Files.exists(tmpLocation.resolve("WEB-INF/classes"))) {
                Files.move(tmpLocation.resolve("WEB-INF/classes"), appLocation);
            } else {
                Files.createDirectory(appLocation);
            }
            // META-INF -> archive/META-INF/
            if (Files.exists(tmpLocation.resolve("META-INF"))) {
                if (Files.exists(appLocation.resolve("META-INF"))) {
                    // Target directory not empty.
                    try (Stream<Path> fileTreeElements = Files.walk(tmpLocation.resolve("META-INF"), 2)) {
                        fileTreeElements.forEach(p -> {
                            try {
                                Files.createFile(p);
                            } catch (FileAlreadyExistsException faee) {
                            // Do Nothing
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        });
                    }
                } else {
                    Files.move(tmpLocation.resolve("META-INF"), appLocation.resolve("META-INF"));
                }
            }
            // WEB-INF -> archive/WEB-INF
            if (Files.exists(tmpLocation.resolve("WEB-INF"))) {
                Files.move(tmpLocation.resolve("WEB-INF"), appLocation.resolve("WEB-INF"));
            }
            // Collect all libraries
            if (Files.exists(tmpLocation.resolve("lib"))) {
                try (Stream<Path> libs = Files.walk(tmpLocation.resolve("lib"), 1)) {
                    libs.forEach((i) -> {
                        if (i.getFileName().toString().endsWith(".jar")) {
                            libraries.add(i);
                        }
                    });
                }
            }
        } else {
            appLocation = tmpLocation;
        }
        List<Consumer<BuildChainBuilder>> customizers = new ArrayList<>();
        // Test class is a bean
        customizers.add(new Consumer<BuildChainBuilder>() {

            @Override
            public void accept(BuildChainBuilder buildChainBuilder) {
                buildChainBuilder.addBuildStep(new BuildStep() {

                    @Override
                    public void execute(BuildContext context) {
                        context.produce(AdditionalBeanBuildItem.unremovableOf(testJavaClass));
                    }
                }).produces(AdditionalBeanBuildItem.class).build();
            }
        });
        QuarkusBootstrap.Builder bootstrapBuilder = QuarkusBootstrap.builder().setApplicationRoot(appLocation).setProjectRoot(appLocation).setIsolateDeployment(false).setFlatClassPath(true).setMode(QuarkusBootstrap.Mode.TEST);
        for (Path i : libraries) {
            bootstrapBuilder.addAdditionalApplicationArchive(new AdditionalDependency(i, false, true));
        }
        // Path testLocation = PathTestHelper.getTestClassesLocation(testJavaClass);
        // bootstrapBuilder.setProjectRoot(PathTestHelper.getTestClassesLocation(testJavaClass));
        CuratedApplication curatedApplication = bootstrapBuilder.build().bootstrap();
        AugmentAction augmentAction = new AugmentActionImpl(curatedApplication, customizers);
        StartupAction app = augmentAction.createInitialRuntimeApplication();
        RunningQuarkusApplication runningQuarkusApplication = app.run();
        appClassloader.set(runningQuarkusApplication.getClassLoader());
        runningApp.set(runningQuarkusApplication);
        Thread.currentThread().setContextClassLoader(runningQuarkusApplication.getClassLoader());
        // Instantiate the real test instance
        testInstance = TestInstantiator.instantiateTest(testJavaClass, runningQuarkusApplication.getClassLoader());
        // its pretty bogus
        if (Boolean.getBoolean("io.quarkus.arquillian.copy-fields")) {
            Class<?> dest = testInstance.getClass();
            Class<?> source = testClass.get().getJavaClass();
            while (source != Object.class) {
                for (Field f : source.getDeclaredFields()) {
                    try {
                        if (Modifier.isStatic(f.getModifiers()) && !Modifier.isFinal(f.getModifiers())) {
                            Field df = dest.getDeclaredField(f.getName());
                            df.setAccessible(true);
                            f.setAccessible(true);
                            df.set(null, f.get(null));
                        }
                    } catch (Exception e) {
                        LOGGER.error("Failed to copy static field", e);
                    }
                }
                source = source.getSuperclass();
                dest = dest.getSuperclass();
            }
        }
    } catch (Throwable t) {
        // clone the exception into the correct class loader
        Throwable nt;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (ObjectOutputStream a = new ObjectOutputStream(out)) {
            a.writeObject(t);
            a.close();
            nt = (Throwable) new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())).readObject();
        } catch (Exception e) {
            throw new DeploymentException("Unable to start the runtime runner", t);
        }
        throw new DeploymentException("Unable to start the runtime runner", nt);
    } finally {
        Thread.currentThread().setContextClassLoader(old);
    }
    ProtocolMetaData metadata = new ProtocolMetaData();
    // TODO: fix this
    String testUri = TestHTTPResourceManager.getUri(runningApp.get());
    System.setProperty("test.url", testUri);
    URI uri = URI.create(testUri);
    HTTPContext httpContext = new HTTPContext(uri.getHost(), uri.getPort());
    // This is to work around https://github.com/arquillian/arquillian-core/issues/216
    httpContext.add(new Servlet("dummy", "/"));
    metadata.addContext(httpContext);
    return metadata;
}
Also used : FileAlreadyExistsException(java.nio.file.FileAlreadyExistsException) ArrayList(java.util.ArrayList) BuildStep(io.quarkus.builder.BuildStep) ObjectOutputStream(java.io.ObjectOutputStream) URI(java.net.URI) Field(java.lang.reflect.Field) Consumer(java.util.function.Consumer) Servlet(org.jboss.arquillian.container.spi.client.protocol.metadata.Servlet) AdditionalDependency(io.quarkus.bootstrap.app.AdditionalDependency) ProtocolMetaData(org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData) ExplodedExporter(org.jboss.shrinkwrap.api.exporter.ExplodedExporter) HashSet(java.util.HashSet) AugmentActionImpl(io.quarkus.runner.bootstrap.AugmentActionImpl) Path(java.nio.file.Path) AugmentAction(io.quarkus.bootstrap.app.AugmentAction) StartupAction(io.quarkus.bootstrap.app.StartupAction) RunningQuarkusApplication(io.quarkus.bootstrap.app.RunningQuarkusApplication) WebArchive(org.jboss.shrinkwrap.api.spec.WebArchive) HTTPContext(org.jboss.arquillian.container.spi.client.protocol.metadata.HTTPContext) IOException(java.io.IOException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) LifecycleException(org.jboss.arquillian.container.spi.client.container.LifecycleException) IOException(java.io.IOException) FileAlreadyExistsException(java.nio.file.FileAlreadyExistsException) DeploymentException(org.jboss.arquillian.container.spi.client.container.DeploymentException) BuildContext(io.quarkus.builder.BuildContext) BuildChainBuilder(io.quarkus.builder.BuildChainBuilder) CuratedApplication(io.quarkus.bootstrap.app.CuratedApplication) ByteArrayInputStream(java.io.ByteArrayInputStream) QuarkusBootstrap(io.quarkus.bootstrap.app.QuarkusBootstrap) TestClass(org.jboss.arquillian.test.spi.TestClass) DeploymentException(org.jboss.arquillian.container.spi.client.container.DeploymentException) ObjectInputStream(java.io.ObjectInputStream)

Example 2 with CuratedApplication

use of io.quarkus.bootstrap.app.CuratedApplication in project quarkus by quarkusio.

the class IntegrationTestUtil method handleDevServices.

static ArtifactLauncher.InitContext.DevServicesLaunchResult handleDevServices(ExtensionContext context, boolean isDockerAppLaunch) throws Exception {
    Class<?> requiredTestClass = context.getRequiredTestClass();
    Path testClassLocation = getTestClassesLocation(requiredTestClass);
    final Path appClassLocation = getAppClassLocationForTestLocation(testClassLocation.toString());
    final PathList.Builder rootBuilder = PathList.builder();
    if (!appClassLocation.equals(testClassLocation)) {
        rootBuilder.add(testClassLocation);
        // if test classes is a dir, we should also check whether test resources dir exists as a separate dir (gradle)
        // TODO: this whole app/test path resolution logic is pretty dumb, it needs be re-worked using proper workspace discovery
        final Path testResourcesLocation = PathTestHelper.getResourcesForClassesDirOrNull(testClassLocation, "test");
        if (testResourcesLocation != null) {
            rootBuilder.add(testResourcesLocation);
        }
    }
    final QuarkusBootstrap.Builder runnerBuilder = QuarkusBootstrap.builder().setIsolateDeployment(true).setMode(QuarkusBootstrap.Mode.TEST);
    final Path projectRoot = Paths.get("").normalize().toAbsolutePath();
    runnerBuilder.setProjectRoot(projectRoot);
    runnerBuilder.setTargetDirectory(PathTestHelper.getProjectBuildDir(projectRoot, testClassLocation));
    rootBuilder.add(appClassLocation);
    final Path appResourcesLocation = PathTestHelper.getResourcesForClassesDirOrNull(appClassLocation, "main");
    if (appResourcesLocation != null) {
        rootBuilder.add(appResourcesLocation);
    }
    // If gradle project running directly with IDE
    if (System.getProperty(BootstrapConstants.SERIALIZED_TEST_APP_MODEL) == null) {
        ApplicationModel model = BuildToolHelper.enableGradleAppModelForTest(projectRoot);
        if (model != null && model.getApplicationModule() != null) {
            final ArtifactSources testSources = model.getApplicationModule().getTestSources();
            if (testSources != null) {
                for (SourceDir src : testSources.getSourceDirs()) {
                    if (!Files.exists(src.getOutputDir())) {
                        final Path classes = src.getOutputDir();
                        if (!rootBuilder.contains(classes)) {
                            rootBuilder.add(classes);
                        }
                    }
                }
            }
            for (SourceDir src : model.getApplicationModule().getMainSources().getSourceDirs()) {
                if (!Files.exists(src.getOutputDir())) {
                    final Path classes = src.getOutputDir();
                    if (!rootBuilder.contains(classes)) {
                        rootBuilder.add(classes);
                    }
                }
            }
        }
    } else if (System.getProperty(BootstrapConstants.OUTPUT_SOURCES_DIR) != null) {
        final String[] sourceDirectories = System.getProperty(BootstrapConstants.OUTPUT_SOURCES_DIR).split(",");
        for (String sourceDirectory : sourceDirectories) {
            final Path directory = Paths.get(sourceDirectory);
            if (Files.exists(directory) && !rootBuilder.contains(directory)) {
                rootBuilder.add(directory);
            }
        }
    }
    runnerBuilder.setApplicationRoot(rootBuilder.build());
    CuratedApplication curatedApplication = runnerBuilder.setTest(true).build().bootstrap();
    Index testClassesIndex = TestClassIndexer.indexTestClasses(requiredTestClass);
    // we need to write the Index to make it reusable from other parts of the testing infrastructure that run in different ClassLoaders
    TestClassIndexer.writeIndex(testClassesIndex, requiredTestClass);
    Map<String, String> propertyMap = new HashMap<>();
    AugmentAction augmentAction;
    String networkId = null;
    if (isDockerAppLaunch) {
        // when the application is going to be launched as a docker container, we need to make containers started by DevServices
        // use a shared network that the application container can then use as well
        augmentAction = curatedApplication.createAugmentor("io.quarkus.deployment.builditem.DevServicesSharedNetworkBuildItem$Factory", Collections.emptyMap());
    } else {
        augmentAction = curatedApplication.createAugmentor();
    }
    augmentAction.performCustomBuild(NativeDevServicesHandler.class.getName(), new BiConsumer<String, String>() {

        @Override
        public void accept(String s, String s2) {
            propertyMap.put(s, s2);
        }
    }, DevServicesLauncherConfigResultBuildItem.class.getName());
    boolean manageNetwork = false;
    if (isDockerAppLaunch) {
        // or else we run into various ClassLoader problems
        try {
            Class<?> networkClass = curatedApplication.getAugmentClassLoader().loadClass("org.testcontainers.containers.Network");
            Object sharedNetwork = networkClass.getField("SHARED").get(null);
            networkId = (String) networkClass.getMethod("getId").invoke(sharedNetwork);
        } catch (Exception e) {
            // use the network the use has specified or else just generate one if none is configured
            Config config = LauncherUtil.installAndGetSomeConfig();
            Optional<String> networkIdOpt = config.getOptionalValue("quarkus.test.container.network", String.class);
            if (networkIdOpt.isPresent()) {
                networkId = networkIdOpt.get();
            } else {
                networkId = "quarkus-integration-test-" + RandomStringUtils.random(5, true, false);
                manageNetwork = true;
            }
        }
    }
    DefaultDevServicesLaunchResult result = new DefaultDevServicesLaunchResult(propertyMap, networkId, manageNetwork, curatedApplication);
    createNetworkIfNecessary(result);
    return result;
}
Also used : DevServicesLauncherConfigResultBuildItem(io.quarkus.deployment.builditem.DevServicesLauncherConfigResultBuildItem) HashMap(java.util.HashMap) Config(org.eclipse.microprofile.config.Config) ApplicationModel(io.quarkus.bootstrap.model.ApplicationModel) Index(org.jboss.jandex.Index) Path(java.nio.file.Path) AugmentAction(io.quarkus.bootstrap.app.AugmentAction) SourceDir(io.quarkus.bootstrap.workspace.SourceDir) Optional(java.util.Optional) PathList(io.quarkus.paths.PathList) URISyntaxException(java.net.URISyntaxException) JUnitException(org.junit.platform.commons.JUnitException) InvocationTargetException(java.lang.reflect.InvocationTargetException) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) CuratedApplication(io.quarkus.bootstrap.app.CuratedApplication) QuarkusBootstrap(io.quarkus.bootstrap.app.QuarkusBootstrap) ArtifactSources(io.quarkus.bootstrap.workspace.ArtifactSources)

Example 3 with CuratedApplication

use of io.quarkus.bootstrap.app.CuratedApplication in project quarkus by quarkusio.

the class AbstractJvmQuarkusTestExtension method createAugmentor.

protected PrepareResult createAugmentor(ExtensionContext context, Class<? extends QuarkusTestProfile> profile, Collection<Runnable> shutdownTasks) throws Exception {
    Class<?> requiredTestClass = context.getRequiredTestClass();
    currentJUnitTestClass = requiredTestClass;
    Path testClassLocation = getTestClassesLocation(requiredTestClass);
    final Path appClassLocation = getAppClassLocationForTestLocation(testClassLocation.toString());
    final PathList.Builder rootBuilder = PathList.builder();
    if (!appClassLocation.equals(testClassLocation)) {
        rootBuilder.add(testClassLocation);
        // if test classes is a dir, we should also check whether test resources dir exists as a separate dir (gradle)
        // TODO: this whole app/test path resolution logic is pretty dumb, it needs be re-worked using proper workspace discovery
        final Path testResourcesLocation = PathTestHelper.getResourcesForClassesDirOrNull(testClassLocation, "test");
        if (testResourcesLocation != null) {
            rootBuilder.add(testResourcesLocation);
        }
    }
    originalCl = Thread.currentThread().getContextClassLoader();
    Map<String, String> sysPropRestore = new HashMap<>();
    sysPropRestore.put(ProfileManager.QUARKUS_TEST_PROFILE_PROP, System.getProperty(ProfileManager.QUARKUS_TEST_PROFILE_PROP));
    // clear the test.url system property as the value leaks into the run when using different profiles
    System.clearProperty("test.url");
    Map<String, String> additional = new HashMap<>();
    QuarkusTestProfile profileInstance = null;
    if (profile != null) {
        profileInstance = profile.getConstructor().newInstance();
        additional.putAll(profileInstance.getConfigOverrides());
        if (!profileInstance.getEnabledAlternatives().isEmpty()) {
            additional.put("quarkus.arc.selected-alternatives", profileInstance.getEnabledAlternatives().stream().peek((c) -> {
                if (!c.isAnnotationPresent(Alternative.class)) {
                    throw new RuntimeException("Enabled alternative " + c + " is not annotated with @Alternative");
                }
            }).map(Class::getName).collect(Collectors.joining(",")));
        }
        if (profileInstance.disableApplicationLifecycleObservers()) {
            additional.put("quarkus.arc.test.disable-application-lifecycle-observers", "true");
        }
        if (profileInstance.getConfigProfile() != null) {
            additional.put(ProfileManager.QUARKUS_TEST_PROFILE_PROP, profileInstance.getConfigProfile());
        }
        // we just use system properties for now
        // its a lot simpler
        shutdownTasks.add(RestorableSystemProperties.setProperties(additional)::close);
    }
    final Path projectRoot = Paths.get("").normalize().toAbsolutePath();
    rootBuilder.add(appClassLocation);
    final Path appResourcesLocation = PathTestHelper.getResourcesForClassesDirOrNull(appClassLocation, "main");
    if (appResourcesLocation != null) {
        rootBuilder.add(appResourcesLocation);
    }
    // If gradle project running directly with IDE
    if (System.getProperty(BootstrapConstants.SERIALIZED_TEST_APP_MODEL) == null) {
        ApplicationModel model = BuildToolHelper.enableGradleAppModelForTest(projectRoot);
        if (model != null && model.getApplicationModule() != null) {
            final ArtifactSources artifactSrc = model.getApplicationModule().getTestSources();
            if (artifactSrc != null) {
                for (SourceDir src : artifactSrc.getSourceDirs()) {
                    if (Files.exists(src.getOutputDir())) {
                        final Path classesDir = src.getOutputDir();
                        if (!rootBuilder.contains(classesDir)) {
                            rootBuilder.add(classesDir);
                        }
                    }
                }
            }
            for (SourceDir src : model.getApplicationModule().getMainSources().getSourceDirs()) {
                if (Files.exists(src.getOutputDir())) {
                    final Path classesDir = src.getOutputDir();
                    if (!rootBuilder.contains(classesDir)) {
                        rootBuilder.add(classesDir);
                    }
                }
            }
        }
    } else if (System.getProperty(BootstrapConstants.OUTPUT_SOURCES_DIR) != null) {
        final String[] sourceDirectories = System.getProperty(BootstrapConstants.OUTPUT_SOURCES_DIR).split(",");
        for (String sourceDirectory : sourceDirectories) {
            final Path directory = Paths.get(sourceDirectory);
            if (Files.exists(directory) && !rootBuilder.contains(directory)) {
                rootBuilder.add(directory);
            }
        }
    }
    CuratedApplication curatedApplication;
    if (CurrentTestApplication.curatedApplication != null) {
        curatedApplication = CurrentTestApplication.curatedApplication;
    } else {
        final QuarkusBootstrap.Builder runnerBuilder = QuarkusBootstrap.builder().setIsolateDeployment(true).setMode(QuarkusBootstrap.Mode.TEST);
        runnerBuilder.setTargetDirectory(PathTestHelper.getProjectBuildDir(projectRoot, testClassLocation));
        runnerBuilder.setProjectRoot(projectRoot);
        runnerBuilder.setApplicationRoot(rootBuilder.build());
        curatedApplication = runnerBuilder.setTest(true).build().bootstrap();
        shutdownTasks.add(curatedApplication::close);
    }
    if (curatedApplication.getApplicationModel().getRuntimeDependencies().isEmpty()) {
        throw new RuntimeException("The tests were run against a directory that does not contain a Quarkus project. Please ensure that the test is configured to use the proper working directory.");
    }
    Index testClassesIndex = TestClassIndexer.indexTestClasses(requiredTestClass);
    // we need to write the Index to make it reusable from other parts of the testing infrastructure that run in different ClassLoaders
    TestClassIndexer.writeIndex(testClassesIndex, requiredTestClass);
    Timing.staticInitStarted(curatedApplication.getBaseRuntimeClassLoader(), curatedApplication.getQuarkusBootstrap().isAuxiliaryApplication());
    final Map<String, Object> props = new HashMap<>();
    props.put(TEST_LOCATION, testClassLocation);
    props.put(TEST_CLASS, requiredTestClass);
    quarkusTestProfile = profile;
    return new PrepareResult(curatedApplication.createAugmentor(QuarkusTestExtension.TestBuildChainFunction.class.getName(), props), profileInstance, curatedApplication);
}
Also used : Path(java.nio.file.Path) CuratedApplication(io.quarkus.bootstrap.app.CuratedApplication) PathTestHelper(io.quarkus.test.common.PathTestHelper) TestClassIndexer(io.quarkus.test.common.TestClassIndexer) PathList(io.quarkus.paths.PathList) PathTestHelper.getTestClassesLocation(io.quarkus.test.common.PathTestHelper.getTestClassesLocation) Alternative(javax.enterprise.inject.Alternative) HashMap(java.util.HashMap) Timing(io.quarkus.bootstrap.runner.Timing) Deque(java.util.Deque) ExtensionContext(org.junit.jupiter.api.extension.ExtensionContext) RestorableSystemProperties(io.quarkus.test.common.RestorableSystemProperties) PathTestHelper.getAppClassLocationForTestLocation(io.quarkus.test.common.PathTestHelper.getAppClassLocationForTestLocation) ArtifactSources(io.quarkus.bootstrap.workspace.ArtifactSources) SourceDir(io.quarkus.bootstrap.workspace.SourceDir) Map(java.util.Map) AugmentAction(io.quarkus.bootstrap.app.AugmentAction) Index(org.jboss.jandex.Index) Path(java.nio.file.Path) QuarkusTestResource(io.quarkus.test.common.QuarkusTestResource) Files(java.nio.file.Files) Collection(java.util.Collection) BootstrapConstants(io.quarkus.bootstrap.BootstrapConstants) Collectors(java.util.stream.Collectors) QuarkusBootstrap(io.quarkus.bootstrap.app.QuarkusBootstrap) ApplicationModel(io.quarkus.bootstrap.model.ApplicationModel) CurrentTestApplication(io.quarkus.deployment.dev.testing.CurrentTestApplication) Paths(java.nio.file.Paths) Annotation(java.lang.annotation.Annotation) ProfileManager(io.quarkus.runtime.configuration.ProfileManager) BuildToolHelper(io.quarkus.bootstrap.utils.BuildToolHelper) ArrayDeque(java.util.ArrayDeque) SourceDir(io.quarkus.bootstrap.workspace.SourceDir) HashMap(java.util.HashMap) PathList(io.quarkus.paths.PathList) ApplicationModel(io.quarkus.bootstrap.model.ApplicationModel) Index(org.jboss.jandex.Index) CuratedApplication(io.quarkus.bootstrap.app.CuratedApplication) QuarkusBootstrap(io.quarkus.bootstrap.app.QuarkusBootstrap) ArtifactSources(io.quarkus.bootstrap.workspace.ArtifactSources)

Example 4 with CuratedApplication

use of io.quarkus.bootstrap.app.CuratedApplication in project quarkus by quarkusio.

the class IsolatedDevModeMain method accept.

// the main entry point, but loaded inside the augmentation class loader
@Override
public void accept(CuratedApplication o, Map<String, Object> params) {
    // setup the dev mode thread pool for NIO
    System.setProperty("java.nio.channels.DefaultThreadPool.threadFactory", "io.quarkus.dev.io.NioThreadPoolThreadFactory");
    Timing.staticInitStarted(o.getBaseRuntimeClassLoader(), false);
    // https://github.com/quarkusio/quarkus/issues/9748
    // if you have an app with all daemon threads then the app thread
    // may be the only thread keeping the JVM alive
    // during the restart process when this thread is stopped then
    // the JVM will die
    // we start this thread to keep the JVM alive until the shutdown hook is run
    // even for command mode we still want the JVM to live until it receives
    // a signal to make the 'press enter to restart' function to work
    new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                shutdownLatch.await();
            } catch (InterruptedException ignore) {
            }
        }
    }, "Quarkus Devmode keep alive thread").start();
    try {
        curatedApplication = o;
        Object potentialContext = params.get(DevModeContext.class.getName());
        if (potentialContext instanceof DevModeContext) {
            context = (DevModeContext) potentialContext;
        } else {
            // this was from the external class loader
            // we need to copy it into this one
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream oo = new ObjectOutputStream(out);
            oo.writeObject(potentialContext);
            context = (DevModeContext) new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())).readObject();
        }
        augmentAction = new AugmentActionImpl(curatedApplication, Collections.singletonList(new Consumer<BuildChainBuilder>() {

            @Override
            public void accept(BuildChainBuilder buildChainBuilder) {
                buildChainBuilder.addBuildStep(new BuildStep() {

                    @Override
                    public void execute(BuildContext context) {
                        // we need to make sure all hot reloadable classes are application classes
                        context.produce(new ApplicationClassPredicateBuildItem(new Predicate<String>() {

                            @Override
                            public boolean test(String s) {
                                QuarkusClassLoader cl = (QuarkusClassLoader) Thread.currentThread().getContextClassLoader();
                                // if the class file is present in this (and not the parent) CL then it is an application class
                                List<ClassPathElement> res = cl.getElementsWithResource(s.replace('.', '/') + ".class", true);
                                return !res.isEmpty();
                            }
                        }));
                    }
                }).produces(ApplicationClassPredicateBuildItem.class).build();
            }
        }), Collections.emptyList());
        List<CodeGenData> codeGens = new ArrayList<>();
        QuarkusClassLoader deploymentClassLoader = curatedApplication.createDeploymentClassLoader();
        for (DevModeContext.ModuleInfo module : context.getAllModules()) {
            if (!module.getSourceParents().isEmpty() && module.getPreBuildOutputDir() != null) {
                // it's null for remote dev
                codeGens.addAll(CodeGenerator.init(deploymentClassLoader, module.getSourceParents(), Paths.get(module.getPreBuildOutputDir()), Paths.get(module.getTargetDir()), sourcePath -> module.addSourcePathFirst(sourcePath.toAbsolutePath().toString())));
            }
        }
        RuntimeUpdatesProcessor.INSTANCE = setupRuntimeCompilation(context, (Path) params.get(APP_ROOT), (DevModeType) params.get(DevModeType.class.getName()));
        if (RuntimeUpdatesProcessor.INSTANCE != null) {
            RuntimeUpdatesProcessor.INSTANCE.checkForFileChange();
            RuntimeUpdatesProcessor.INSTANCE.checkForChangedClasses(true);
        }
        firstStart(deploymentClassLoader, codeGens);
        // doStart(false, Collections.emptySet());
        if (deploymentProblem != null || RuntimeUpdatesProcessor.INSTANCE.getCompileProblem() != null) {
            if (context.isAbortOnFailedStart()) {
                throw new RuntimeException(deploymentProblem == null ? RuntimeUpdatesProcessor.INSTANCE.getCompileProblem() : deploymentProblem);
            }
        }
        shutdownThread = new Thread(new Runnable() {

            @Override
            public void run() {
                shutdownLatch.countDown();
                synchronized (DevModeMain.class) {
                    if (runner != null) {
                        try {
                            close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }, "Quarkus Shutdown Thread");
        Runtime.getRuntime().addShutdownHook(shutdownThread);
    } catch (Exception e) {
        close();
        throw new RuntimeException(e);
    }
}
Also used : BiFunction(java.util.function.BiFunction) ObjectInputStream(java.io.ObjectInputStream) ClassTransformingBuildStep(io.quarkus.deployment.steps.ClassTransformingBuildStep) CommandLineUtils(org.apache.maven.shared.utils.cli.CommandLineUtils) ConfigProviderResolver(org.eclipse.microprofile.config.spi.ConfigProviderResolver) ApplicationLifecycleManager(io.quarkus.runtime.ApplicationLifecycleManager) ByteArrayInputStream(java.io.ByteArrayInputStream) Map(java.util.Map) AugmentAction(io.quarkus.bootstrap.app.AugmentAction) ConsoleStateManager(io.quarkus.deployment.console.ConsoleStateManager) DevConsoleManager(io.quarkus.dev.console.DevConsoleManager) InitialConfigurator(io.quarkus.bootstrap.logging.InitialConfigurator) Path(java.nio.file.Path) ConsoleHandler(org.jboss.logmanager.handlers.ConsoleHandler) LoggingSetupRecorder(io.quarkus.runtime.logging.LoggingSetupRecorder) Predicate(java.util.function.Predicate) Collection(java.util.Collection) AugmentActionImpl(io.quarkus.runner.bootstrap.AugmentActionImpl) Set(java.util.Set) BLUE(io.quarkus.deployment.dev.testing.MessageFormat.BLUE) ServiceLoader(java.util.ServiceLoader) QuarkusClassLoader(io.quarkus.bootstrap.classloading.QuarkusClassLoader) StartupAction(io.quarkus.bootstrap.app.StartupAction) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) MessageFormat(io.quarkus.deployment.dev.testing.MessageFormat) BuildStep(io.quarkus.builder.BuildStep) ColorPatternFormatter(org.jboss.logmanager.formatters.ColorPatternFormatter) BuildContext(io.quarkus.builder.BuildContext) CuratedApplication(io.quarkus.bootstrap.app.CuratedApplication) ByteArrayOutputStream(java.io.ByteArrayOutputStream) RunningQuarkusApplication(io.quarkus.bootstrap.app.RunningQuarkusApplication) DevModeType(io.quarkus.dev.spi.DevModeType) Logger(org.jboss.logging.Logger) DeploymentFailedStartHandler(io.quarkus.dev.spi.DeploymentFailedStartHandler) LaunchMode(io.quarkus.runtime.LaunchMode) ClassChangeInformation(io.quarkus.bootstrap.app.ClassChangeInformation) Timing(io.quarkus.bootstrap.runner.Timing) BindException(java.net.BindException) TestSupport(io.quarkus.deployment.dev.testing.TestSupport) CodeGenData(io.quarkus.deployment.codegen.CodeGenData) ArrayList(java.util.ArrayList) BuildChainBuilder(io.quarkus.builder.BuildChainBuilder) ApplicationClassPredicateBuildItem(io.quarkus.deployment.builditem.ApplicationClassPredicateBuildItem) BiConsumer(java.util.function.BiConsumer) ObjectOutputStream(java.io.ObjectOutputStream) ApplicationStartException(io.quarkus.dev.appstate.ApplicationStartException) QuarkusConfigFactory(io.quarkus.runtime.configuration.QuarkusConfigFactory) HotReplacementSetup(io.quarkus.dev.spi.HotReplacementSetup) Properties(java.util.Properties) ClassPathElement(io.quarkus.bootstrap.classloading.ClassPathElement) CommandLineException(org.apache.maven.shared.utils.cli.CommandLineException) IOException(java.io.IOException) ConsoleCommand(io.quarkus.deployment.console.ConsoleCommand) Consumer(java.util.function.Consumer) Paths(java.nio.file.Paths) Closeable(java.io.Closeable) CodeGenerator(io.quarkus.deployment.CodeGenerator) Comparator(java.util.Comparator) FSWatchUtil(io.quarkus.deployment.util.FSWatchUtil) Collections(java.util.Collections) ArrayList(java.util.ArrayList) ClassTransformingBuildStep(io.quarkus.deployment.steps.ClassTransformingBuildStep) BuildStep(io.quarkus.builder.BuildStep) ApplicationClassPredicateBuildItem(io.quarkus.deployment.builditem.ApplicationClassPredicateBuildItem) ClassPathElement(io.quarkus.bootstrap.classloading.ClassPathElement) ObjectOutputStream(java.io.ObjectOutputStream) Predicate(java.util.function.Predicate) AugmentActionImpl(io.quarkus.runner.bootstrap.AugmentActionImpl) Path(java.nio.file.Path) CodeGenData(io.quarkus.deployment.codegen.CodeGenData) ByteArrayOutputStream(java.io.ByteArrayOutputStream) QuarkusClassLoader(io.quarkus.bootstrap.classloading.QuarkusClassLoader) BindException(java.net.BindException) ApplicationStartException(io.quarkus.dev.appstate.ApplicationStartException) CommandLineException(org.apache.maven.shared.utils.cli.CommandLineException) IOException(java.io.IOException) BuildContext(io.quarkus.builder.BuildContext) ByteArrayInputStream(java.io.ByteArrayInputStream) BuildChainBuilder(io.quarkus.builder.BuildChainBuilder) DevModeType(io.quarkus.dev.spi.DevModeType) ObjectInputStream(java.io.ObjectInputStream)

Example 5 with CuratedApplication

use of io.quarkus.bootstrap.app.CuratedApplication in project quarkus by quarkusio.

the class ReaugmentTask method main.

public static void main(Path appRoot) throws Exception {
    Path deploymentLib = appRoot.resolve(LIB).resolve(DEPLOYMENT_LIB);
    Path buildSystemProps = appRoot.resolve(QUARKUS).resolve(BUILD_SYSTEM_PROPERTIES);
    try (ObjectInputStream in = new ObjectInputStream(Files.newInputStream(deploymentLib.resolve(JarResultBuildStep.APPMODEL_DAT)))) {
        Properties buildSystemProperties = new Properties();
        try (InputStream buildIn = Files.newInputStream(buildSystemProps)) {
            buildSystemProperties.load(buildIn);
        }
        MutableJarApplicationModel appModel = (MutableJarApplicationModel) in.readObject();
        List<AdditionalDependency> additional = new ArrayList<>();
        if (appModel.getUserProvidersDirectory() != null) {
            // bit of a hack, but keeps things simple
            System.setProperty("quarkus.package.user-providers-directory", appModel.getUserProvidersDirectory());
            try (Stream<Path> files = Files.list(appRoot.resolve(appModel.getUserProvidersDirectory()))) {
                files.forEach(new Consumer<Path>() {

                    @Override
                    public void accept(Path path) {
                        if (path.toString().endsWith(".jar")) {
                            additional.add(new AdditionalDependency(path, false, true));
                        }
                    }
                });
            }
        }
        final ApplicationModel existingModel = appModel.getAppModel(appRoot);
        System.setProperty("quarkus.package.type", "mutable-jar");
        try (CuratedApplication bootstrap = QuarkusBootstrap.builder().setAppArtifact(existingModel.getAppArtifact()).setExistingModel(existingModel).setRebuild(true).setBuildSystemProperties(buildSystemProperties).setBaseName(appModel.getBaseName()).addAdditionalApplicationArchives(additional).setApplicationRoot(existingModel.getAppArtifact().getResolvedPaths().getSinglePath()).setTargetDirectory(appRoot.getParent()).setBaseClassLoader(ReaugmentTask.class.getClassLoader()).build().bootstrap()) {
            bootstrap.createAugmentor().createProductionApplication();
        }
    }
}
Also used : Path(java.nio.file.Path) ObjectInputStream(java.io.ObjectInputStream) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) MutableJarApplicationModel(io.quarkus.bootstrap.model.MutableJarApplicationModel) ApplicationModel(io.quarkus.bootstrap.model.ApplicationModel) Properties(java.util.Properties) MutableJarApplicationModel(io.quarkus.bootstrap.model.MutableJarApplicationModel) CuratedApplication(io.quarkus.bootstrap.app.CuratedApplication) AdditionalDependency(io.quarkus.bootstrap.app.AdditionalDependency) ObjectInputStream(java.io.ObjectInputStream)

Aggregations

CuratedApplication (io.quarkus.bootstrap.app.CuratedApplication)19 Path (java.nio.file.Path)14 QuarkusBootstrap (io.quarkus.bootstrap.app.QuarkusBootstrap)11 IOException (java.io.IOException)9 AugmentAction (io.quarkus.bootstrap.app.AugmentAction)8 ApplicationModel (io.quarkus.bootstrap.model.ApplicationModel)8 ArrayList (java.util.ArrayList)8 Map (java.util.Map)7 HashMap (java.util.HashMap)6 AugmentResult (io.quarkus.bootstrap.app.AugmentResult)5 QuarkusClassLoader (io.quarkus.bootstrap.classloading.QuarkusClassLoader)5 LaunchMode (io.quarkus.runtime.LaunchMode)5 HashSet (java.util.HashSet)5 List (java.util.List)5 Properties (java.util.Properties)5 AdditionalDependency (io.quarkus.bootstrap.app.AdditionalDependency)4 ByteArrayOutputStream (java.io.ByteArrayOutputStream)4 Closeable (java.io.Closeable)4 ObjectInputStream (java.io.ObjectInputStream)4 Files (java.nio.file.Files)4