Search in sources :

Example 1 with DevModeType

use of io.quarkus.dev.spi.DevModeType in project quarkus by quarkusio.

the class ExtensionLoader method loadStepsFrom.

/**
 * Load all the build steps from the given class loader.
 *
 * @param classLoader the class loader
 * @param buildSystemProps the build system properties to use
 * @param launchMode launch mode
 * @param configCustomizer configuration customizer
 * @return a consumer which adds the steps to the given chain builder
 * @throws IOException if the class loader could not load a resource
 * @throws ClassNotFoundException if a build step class is not found
 */
public static Consumer<BuildChainBuilder> loadStepsFrom(ClassLoader classLoader, Properties buildSystemProps, ApplicationModel appModel, LaunchMode launchMode, DevModeType devModeType) throws IOException, ClassNotFoundException {
    // populate with all known types
    List<Class<?>> roots = new ArrayList<>();
    for (Class<?> clazz : ServiceUtil.classesNamedIn(classLoader, CONFIG_ROOTS_LIST)) {
        final ConfigRoot annotation = clazz.getAnnotation(ConfigRoot.class);
        if (annotation == null) {
            cfgLog.warnf("Ignoring configuration root %s because it has no annotation", clazz);
        } else {
            roots.add(clazz);
        }
    }
    final BuildTimeConfigurationReader reader = new BuildTimeConfigurationReader(roots);
    // now prepare & load the build configuration
    final SmallRyeConfigBuilder builder = ConfigUtils.configBuilder(false, launchMode);
    final DefaultValuesConfigurationSource ds1 = new DefaultValuesConfigurationSource(reader.getBuildTimePatternMap());
    final DefaultValuesConfigurationSource ds2 = new DefaultValuesConfigurationSource(reader.getBuildTimeRunTimePatternMap());
    final PropertiesConfigSource pcs = new PropertiesConfigSource(buildSystemProps, "Build system");
    final Map<String, String> platformProperties = appModel.getPlatformProperties();
    if (platformProperties.isEmpty()) {
        builder.withSources(ds1, ds2, pcs);
    } else {
        final KeyMap<String> props = new KeyMap<>(platformProperties.size());
        for (Map.Entry<String, String> prop : platformProperties.entrySet()) {
            props.findOrAdd(new NameIterator(prop.getKey())).putRootValue(prop.getValue());
        }
        final KeyMapBackedConfigSource platformConfigSource = new KeyMapBackedConfigSource("Quarkus platform", // (see io.quarkus.deployment.configuration.DefaultValuesConfigurationSource)
        Integer.MIN_VALUE + 1000, props);
        builder.withSources(ds1, ds2, platformConfigSource, pcs);
    }
    for (ConfigClassWithPrefix mapping : reader.getBuildTimeVisibleMappings()) {
        builder.withMapping(mapping.getKlass(), mapping.getPrefix());
    }
    final SmallRyeConfig src = builder.build();
    // install globally
    QuarkusConfigFactory.setConfig(src);
    final ConfigProviderResolver cpr = ConfigProviderResolver.instance();
    try {
        cpr.releaseConfig(cpr.getConfig());
    } catch (IllegalStateException ignored) {
    // just means no config was installed, which is fine
    }
    final BuildTimeConfigurationReader.ReadResult readResult = reader.readConfiguration(src);
    final BooleanSupplierFactoryBuildItem bsf = new BooleanSupplierFactoryBuildItem(readResult, launchMode, devModeType);
    Consumer<BuildChainBuilder> result = Functions.discardingConsumer();
    // BooleanSupplier factory
    result = result.andThen(bcb -> bcb.addBuildStep(bc -> {
        bc.produce(bsf);
    }).produces(BooleanSupplierFactoryBuildItem.class).build());
    // the proxy objects used for run time config in the recorders
    Map<Class<?>, Object> proxies = new HashMap<>();
    for (Class<?> clazz : ServiceUtil.classesNamedIn(classLoader, "META-INF/quarkus-build-steps.list")) {
        try {
            result = result.andThen(ExtensionLoader.loadStepsFromClass(clazz, readResult, proxies, bsf));
        } catch (Throwable e) {
            throw new RuntimeException("Failed to load steps from " + clazz, e);
        }
    }
    // this has to be an identity hash map else the recorder will get angry
    Map<Object, FieldDescriptor> rootFields = new IdentityHashMap<>();
    Map<Object, ConfigClassWithPrefix> mappingClasses = new IdentityHashMap<>();
    for (Map.Entry<Class<?>, Object> entry : proxies.entrySet()) {
        // ConfigRoot
        RootDefinition root = readResult.getAllRootsByClass().get(entry.getKey());
        if (root != null) {
            rootFields.put(entry.getValue(), root.getDescriptor());
            continue;
        }
        // ConfigMapping
        ConfigClassWithPrefix mapping = readResult.getAllMappings().get(entry.getKey());
        if (mapping != null) {
            mappingClasses.put(entry.getValue(), mapping);
            continue;
        }
        throw new IllegalStateException("No config found for " + entry.getKey());
    }
    result = result.andThen(bcb -> bcb.addBuildStep(bc -> {
        bc.produce(new ConfigurationBuildItem(readResult));
        bc.produce(new RunTimeConfigurationProxyBuildItem(proxies));
        ObjectLoader rootLoader = new ObjectLoader() {

            public ResultHandle load(final BytecodeCreator body, final Object obj, final boolean staticInit) {
                return body.readStaticField(rootFields.get(obj));
            }

            public boolean canHandleObject(final Object obj, final boolean staticInit) {
                return rootFields.containsKey(obj);
            }
        };
        ObjectLoader mappingLoader = new ObjectLoader() {

            @Override
            public ResultHandle load(final BytecodeCreator body, final Object obj, final boolean staticInit) {
                ConfigClassWithPrefix mapping = mappingClasses.get(obj);
                MethodDescriptor getConfig = MethodDescriptor.ofMethod(ConfigProvider.class, "getConfig", Config.class);
                ResultHandle config = body.invokeStaticMethod(getConfig);
                MethodDescriptor getMapping = MethodDescriptor.ofMethod(SmallRyeConfig.class, "getConfigMapping", Object.class, Class.class, String.class);
                return body.invokeVirtualMethod(getMapping, config, body.loadClass(mapping.getKlass()), body.load(mapping.getPrefix()));
            }

            @Override
            public boolean canHandleObject(final Object obj, final boolean staticInit) {
                return mappingClasses.containsKey(obj);
            }
        };
        bc.produce(new BytecodeRecorderObjectLoaderBuildItem(rootLoader));
        bc.produce(new BytecodeRecorderObjectLoaderBuildItem(mappingLoader));
    }).produces(ConfigurationBuildItem.class).produces(RunTimeConfigurationProxyBuildItem.class).produces(BytecodeRecorderObjectLoaderBuildItem.class).build());
    return result;
}
Also used : RootDefinition(io.quarkus.deployment.configuration.definition.RootDefinition) ReflectUtil.isSupplierOfOptionalOf(io.quarkus.deployment.util.ReflectUtil.isSupplierOfOptionalOf) RecorderContext(io.quarkus.deployment.recording.RecorderContext) BooleanSupplier(java.util.function.BooleanSupplier) Functions(org.wildfly.common.function.Functions) ReflectUtil.isSupplierOf(io.quarkus.deployment.util.ReflectUtil.isSupplierOf) Arrays.asList(java.util.Arrays.asList) Map(java.util.Map) BytecodeCreator(io.quarkus.gizmo.BytecodeCreator) Recorder(io.quarkus.runtime.annotations.Recorder) ConsumeFlags(io.quarkus.builder.ConsumeFlags) RunTimeConfigurationProxyBuildItem(io.quarkus.deployment.builditem.RunTimeConfigurationProxyBuildItem) ReflectUtil.rawTypeIs(io.quarkus.deployment.util.ReflectUtil.rawTypeIs) KeyMap(io.smallrye.config.KeyMap) EnumSet(java.util.EnumSet) Consume(io.quarkus.deployment.annotations.Consume) Member(java.lang.reflect.Member) MainBytecodeRecorderBuildItem(io.quarkus.deployment.builditem.MainBytecodeRecorderBuildItem) StaticBytecodeRecorderBuildItem(io.quarkus.deployment.builditem.StaticBytecodeRecorderBuildItem) ReflectUtil.isBuildProducerOf(io.quarkus.deployment.util.ReflectUtil.isBuildProducerOf) InvocationTargetException(java.lang.reflect.InvocationTargetException) Weak(io.quarkus.deployment.annotations.Weak) ApplicationModel(io.quarkus.bootstrap.model.ApplicationModel) ConfigProvider(org.eclipse.microprofile.config.ConfigProvider) ConsumeFlag(io.quarkus.builder.ConsumeFlag) PropertiesConfigSource(io.smallrye.config.PropertiesConfigSource) ConfigClassWithPrefix(io.smallrye.config.ConfigMappings.ConfigClassWithPrefix) ResultHandle(io.quarkus.gizmo.ResultHandle) AnnotatedElement(java.lang.reflect.AnnotatedElement) Record(io.quarkus.deployment.annotations.Record) ProduceWeak(io.quarkus.deployment.annotations.ProduceWeak) DevModeType(io.quarkus.dev.spi.DevModeType) ReflectUtil.rawTypeOf(io.quarkus.deployment.util.ReflectUtil.rawTypeOf) BuildStepBuilder(io.quarkus.builder.BuildStepBuilder) BuildItem(io.quarkus.builder.item.BuildItem) SimpleBuildItem(io.quarkus.builder.item.SimpleBuildItem) Constructor(java.lang.reflect.Constructor) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) ConfigRoot(io.quarkus.runtime.annotations.ConfigRoot) BuildChainBuilder(io.quarkus.builder.BuildChainBuilder) Parameter(java.lang.reflect.Parameter) BiConsumer(java.util.function.BiConsumer) KeyMapBackedConfigSource(io.smallrye.config.KeyMapBackedConfigSource) Properties(java.util.Properties) Executor(java.util.concurrent.Executor) IOException(java.io.IOException) Field(java.lang.reflect.Field) FieldDescriptor(io.quarkus.gizmo.FieldDescriptor) ParameterizedType(java.lang.reflect.ParameterizedType) SmallRyeConfigBuilder(io.smallrye.config.SmallRyeConfigBuilder) ConfigPhase(io.quarkus.runtime.annotations.ConfigPhase) BiFunction(java.util.function.BiFunction) ProduceFlags(io.quarkus.builder.ProduceFlags) Overridable(io.quarkus.deployment.annotations.Overridable) BuildProducer(io.quarkus.deployment.annotations.BuildProducer) ConfigProviderResolver(org.eclipse.microprofile.config.spi.ConfigProviderResolver) ProduceFlag(io.quarkus.builder.ProduceFlag) ReflectUtil(io.quarkus.deployment.util.ReflectUtil) Method(java.lang.reflect.Method) BootstrapConfigSetupCompleteBuildItem(io.quarkus.deployment.builditem.BootstrapConfigSetupCompleteBuildItem) IdentityHashMap(java.util.IdentityHashMap) ReflectUtil.isOptionalOf(io.quarkus.deployment.util.ReflectUtil.isOptionalOf) ReflectUtil.rawTypeExtends(io.quarkus.deployment.util.ReflectUtil.rawTypeExtends) ExecutionTime(io.quarkus.deployment.annotations.ExecutionTime) Config(org.eclipse.microprofile.config.Config) DefaultValuesConfigurationSource(io.quarkus.deployment.configuration.DefaultValuesConfigurationSource) List(java.util.List) BuildContext(io.quarkus.builder.BuildContext) Type(java.lang.reflect.Type) Modifier(java.lang.reflect.Modifier) Optional(java.util.Optional) ConfigMappingUtils(io.quarkus.deployment.configuration.ConfigMappingUtils) ConfigUtils(io.quarkus.runtime.configuration.ConfigUtils) Logger(org.jboss.logging.Logger) LaunchMode(io.quarkus.runtime.LaunchMode) HashMap(java.util.HashMap) Function(java.util.function.Function) ReflectUtil.isConsumerOf(io.quarkus.deployment.util.ReflectUtil.isConsumerOf) Inject(javax.inject.Inject) ConfigurationBuildItem(io.quarkus.deployment.builditem.ConfigurationBuildItem) BuildStep(io.quarkus.deployment.annotations.BuildStep) ReflectUtil.isListOf(io.quarkus.deployment.util.ReflectUtil.isListOf) RuntimeValue(io.quarkus.runtime.RuntimeValue) RuntimeConfigSetupCompleteBuildItem(io.quarkus.deployment.builditem.RuntimeConfigSetupCompleteBuildItem) ObjectLoader(io.quarkus.deployment.recording.ObjectLoader) QuarkusConfigFactory(io.quarkus.runtime.configuration.QuarkusConfigFactory) BytecodeRecorderObjectLoaderBuildItem(io.quarkus.deployment.builditem.BytecodeRecorderObjectLoaderBuildItem) MethodDescriptor(io.quarkus.gizmo.MethodDescriptor) SmallRyeConfig(io.smallrye.config.SmallRyeConfig) BuildTimeConfigurationReader(io.quarkus.deployment.configuration.BuildTimeConfigurationReader) Produce(io.quarkus.deployment.annotations.Produce) Consumer(java.util.function.Consumer) MultiBuildItem(io.quarkus.builder.item.MultiBuildItem) NameIterator(io.smallrye.config.NameIterator) ReflectUtil.rawTypeOfParameter(io.quarkus.deployment.util.ReflectUtil.rawTypeOfParameter) ServiceUtil(io.quarkus.deployment.util.ServiceUtil) BytecodeRecorderImpl(io.quarkus.deployment.recording.BytecodeRecorderImpl) Collections(java.util.Collections) PropertiesConfigSource(io.smallrye.config.PropertiesConfigSource) ConfigRoot(io.quarkus.runtime.annotations.ConfigRoot) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) DefaultValuesConfigurationSource(io.quarkus.deployment.configuration.DefaultValuesConfigurationSource) IdentityHashMap(java.util.IdentityHashMap) ArrayList(java.util.ArrayList) BuildTimeConfigurationReader(io.quarkus.deployment.configuration.BuildTimeConfigurationReader) FieldDescriptor(io.quarkus.gizmo.FieldDescriptor) SmallRyeConfigBuilder(io.smallrye.config.SmallRyeConfigBuilder) NameIterator(io.smallrye.config.NameIterator) ResultHandle(io.quarkus.gizmo.ResultHandle) ConfigurationBuildItem(io.quarkus.deployment.builditem.ConfigurationBuildItem) KeyMap(io.smallrye.config.KeyMap) RootDefinition(io.quarkus.deployment.configuration.definition.RootDefinition) ConfigClassWithPrefix(io.smallrye.config.ConfigMappings.ConfigClassWithPrefix) BytecodeCreator(io.quarkus.gizmo.BytecodeCreator) MethodDescriptor(io.quarkus.gizmo.MethodDescriptor) KeyMapBackedConfigSource(io.smallrye.config.KeyMapBackedConfigSource) SmallRyeConfig(io.smallrye.config.SmallRyeConfig) BuildChainBuilder(io.quarkus.builder.BuildChainBuilder) RunTimeConfigurationProxyBuildItem(io.quarkus.deployment.builditem.RunTimeConfigurationProxyBuildItem) ConfigProviderResolver(org.eclipse.microprofile.config.spi.ConfigProviderResolver) BytecodeRecorderObjectLoaderBuildItem(io.quarkus.deployment.builditem.BytecodeRecorderObjectLoaderBuildItem) ObjectLoader(io.quarkus.deployment.recording.ObjectLoader) Map(java.util.Map) KeyMap(io.smallrye.config.KeyMap) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap)

Example 2 with DevModeType

use of io.quarkus.dev.spi.DevModeType 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 3 with DevModeType

use of io.quarkus.dev.spi.DevModeType in project quarkus by quarkusio.

the class RuntimeUpdatesProcessor method doScan.

public boolean doScan(boolean userInitiated, boolean forceRestart) {
    if (!liveReloadEnabled && !forceRestart) {
        return false;
    }
    scanLock.lock();
    try {
        final long startNanoseconds = System.nanoTime();
        for (Runnable step : preScanSteps) {
            try {
                step.run();
            } catch (Throwable t) {
                log.error("Pre Scan step failed", t);
            }
        }
        ClassScanResult changedClassResults = checkForChangedClasses(compiler, DevModeContext.ModuleInfo::getMain, false, main, false);
        Set<String> filesChanged = checkForFileChange(DevModeContext.ModuleInfo::getMain, main);
        boolean configFileRestartNeeded = forceRestart || filesChanged.stream().map(main.watchedFilePaths::get).anyMatch(Boolean.TRUE::equals);
        boolean instrumentationChange = false;
        List<Path> changedFilesForRestart = new ArrayList<>();
        if (configFileRestartNeeded) {
            changedFilesForRestart.addAll(filesChanged.stream().filter(fn -> Boolean.TRUE.equals(main.watchedFilePaths.get(fn))).map(Paths::get).collect(Collectors.toList()));
        }
        changedFilesForRestart.addAll(changedClassResults.getChangedClasses());
        changedFilesForRestart.addAll(changedClassResults.getAddedClasses());
        changedFilesForRestart.addAll(changedClassResults.getDeletedClasses());
        if (ClassChangeAgent.getInstrumentation() != null && lastStartIndex != null && !configFileRestartNeeded && devModeType != DevModeType.REMOTE_LOCAL_SIDE && instrumentationEnabled()) {
            // using the JDK instrumentation API (assuming we were started with the javaagent)
            if (changedClassResults.deletedClasses.isEmpty() && changedClassResults.addedClasses.isEmpty() && !changedClassResults.changedClasses.isEmpty()) {
                try {
                    Indexer indexer = new Indexer();
                    // attempt to use the instrumentation API
                    ClassDefinition[] defs = new ClassDefinition[changedClassResults.changedClasses.size()];
                    int index = 0;
                    for (Path i : changedClassResults.changedClasses) {
                        byte[] bytes = Files.readAllBytes(i);
                        String name = indexer.index(new ByteArrayInputStream(bytes)).name().toString();
                        defs[index++] = new ClassDefinition(Thread.currentThread().getContextClassLoader().loadClass(name), classTransformers.apply(name, bytes));
                    }
                    Index current = indexer.complete();
                    boolean ok = !disableInstrumentationForIndexPredicate.test(current);
                    if (ok) {
                        for (ClassInfo clazz : current.getKnownClasses()) {
                            ClassInfo old = lastStartIndex.getClassByName(clazz.name());
                            if (!ClassComparisonUtil.isSameStructure(clazz, old) || disableInstrumentationForClassPredicate.test(clazz)) {
                                ok = false;
                                break;
                            }
                        }
                    }
                    if (ok) {
                        log.info("Application restart not required, replacing classes via instrumentation");
                        ClassChangeAgent.getInstrumentation().redefineClasses(defs);
                        instrumentationChange = true;
                    }
                } catch (Exception e) {
                    log.error("Failed to replace classes via instrumentation", e);
                    instrumentationChange = false;
                }
            }
        }
        if (compileProblem != null) {
            return false;
        }
        // if there is a deployment problem we always restart on scan
        // this is because we can't setup the config file watches
        // in an ideal world we would just check every resource file for changes, however as everything is already
        // all broken we just assume the reason that they have refreshed is because they have fixed something
        // trying to watch all resource files is complex and this is likely a good enough solution for what is already an edge case
        boolean restartNeeded = !instrumentationChange && (changedClassResults.isChanged() || (IsolatedDevModeMain.deploymentProblem != null && userInitiated) || configFileRestartNeeded);
        if (restartNeeded) {
            String changeString = changedFilesForRestart.stream().map(Path::getFileName).map(Object::toString).collect(Collectors.joining(", "));
            if (!changeString.isEmpty()) {
                log.infof("Restarting quarkus due to changes in %s.", changeString);
            } else if (forceRestart && userInitiated) {
                log.info("Restarting as requested by the user.");
            }
            restartCallback.accept(filesChanged, changedClassResults);
            long timeNanoSeconds = System.nanoTime() - startNanoseconds;
            log.infof("Live reload total time: %ss ", Timing.convertToBigDecimalSeconds(timeNanoSeconds));
            if (TimeUnit.SECONDS.convert(timeNanoSeconds, TimeUnit.NANOSECONDS) >= 4 && !instrumentationEnabled()) {
                if (!instrumentationLogPrinted) {
                    instrumentationLogPrinted = true;
                    log.info("Live reload took more than 4 seconds, you may want to enable instrumentation based reload (quarkus.live-reload.instrumentation=true). This allows small changes to take effect without restarting Quarkus.");
                }
            }
            return true;
        } else if (!filesChanged.isEmpty()) {
            for (Consumer<Set<String>> consumer : noRestartChangesConsumers) {
                try {
                    consumer.accept(filesChanged);
                } catch (Throwable t) {
                    log.error("Changed files consumer failed", t);
                }
            }
            log.infof("Files changed but restart not needed - notified extensions in: %ss ", Timing.convertToBigDecimalSeconds(System.nanoTime() - startNanoseconds));
        } else if (instrumentationChange) {
            log.infof("Live reload performed via instrumentation, no restart needed, total time: %ss ", Timing.convertToBigDecimalSeconds(System.nanoTime() - startNanoseconds));
        }
        return false;
    } finally {
        scanLock.unlock();
    }
}
Also used : TestScanningLock(io.quarkus.dev.testing.TestScanningLock) BiFunction(java.util.function.BiFunction) FileTime(java.nio.file.attribute.FileTime) Timer(java.util.Timer) ModuleInfo(io.quarkus.deployment.dev.DevModeContext.ModuleInfo) ClassInfo(org.jboss.jandex.ClassInfo) Collections.singletonList(java.util.Collections.singletonList) ByteArrayInputStream(java.io.ByteArrayInputStream) Arrays.asList(java.util.Arrays.asList) Locale(java.util.Locale) Map(java.util.Map) PathMatcher(java.nio.file.PathMatcher) TimerTask(java.util.TimerTask) Path(java.nio.file.Path) TestListener(io.quarkus.deployment.dev.testing.TestListener) SimpleFileVisitor(java.nio.file.SimpleFileVisitor) StatusLine(io.quarkus.dev.console.StatusLine) Predicate(java.util.function.Predicate) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) ClassChangeAgent(io.quarkus.changeagent.ClassChangeAgent) Collectors(java.util.stream.Collectors) UncheckedIOException(java.io.UncheckedIOException) Objects(java.util.Objects) FileUtil(io.quarkus.deployment.util.FileUtil) FileVisitResult(java.nio.file.FileVisitResult) List(java.util.List) Stream(java.util.stream.Stream) Optional(java.util.Optional) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) FileChangeEvent(io.quarkus.deployment.dev.filewatch.FileChangeEvent) PathList(io.quarkus.paths.PathList) DevModeType(io.quarkus.dev.spi.DevModeType) Logger(org.jboss.logging.Logger) Collectors.groupingBy(java.util.stream.Collectors.groupingBy) FileChangeCallback(io.quarkus.deployment.dev.filewatch.FileChangeCallback) HashMap(java.util.HashMap) Timing(io.quarkus.bootstrap.runner.Timing) TestSupport(io.quarkus.deployment.dev.testing.TestSupport) Function(java.util.function.Function) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Indexer(org.jboss.jandex.Indexer) QuarkusConsole(io.quarkus.dev.console.QuarkusConsole) BiConsumer(java.util.function.BiConsumer) Index(org.jboss.jandex.Index) IndexView(org.jboss.jandex.IndexView) HotReplacementSetup(io.quarkus.dev.spi.HotReplacementSetup) Iterator(java.util.Iterator) ReentrantLock(java.util.concurrent.locks.ReentrantLock) Files(java.nio.file.Files) FileOutputStream(java.io.FileOutputStream) IOException(java.io.IOException) BasicFileAttributes(java.nio.file.attribute.BasicFileAttributes) File(java.io.File) WatchServiceFileSystemWatcher(io.quarkus.deployment.dev.filewatch.WatchServiceFileSystemWatcher) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) ClassDefinition(java.lang.instrument.ClassDefinition) HotReplacementContext(io.quarkus.dev.spi.HotReplacementContext) ConcurrentSkipListSet(java.util.concurrent.ConcurrentSkipListSet) Paths(java.nio.file.Paths) PathCollection(io.quarkus.paths.PathCollection) Closeable(java.io.Closeable) Collections(java.util.Collections) FileSystems(java.nio.file.FileSystems) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) Index(org.jboss.jandex.Index) ClassDefinition(java.lang.instrument.ClassDefinition) Indexer(org.jboss.jandex.Indexer) BiConsumer(java.util.function.BiConsumer) Consumer(java.util.function.Consumer) Paths(java.nio.file.Paths) Path(java.nio.file.Path) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) ModuleInfo(io.quarkus.deployment.dev.DevModeContext.ModuleInfo) ByteArrayInputStream(java.io.ByteArrayInputStream) ClassInfo(org.jboss.jandex.ClassInfo)

Example 4 with DevModeType

use of io.quarkus.dev.spi.DevModeType in project quarkus by quarkusio.

the class TestTracingProcessor method startTesting.

@BuildStep(onlyIf = IsDevelopment.class)
@Produce(LogHandlerBuildItem.class)
@Produce(TestSetupBuildItem.class)
@Produce(ServiceStartBuildItem.class)
void startTesting(TestConfig config, LiveReloadBuildItem liveReloadBuildItem, LaunchModeBuildItem launchModeBuildItem, List<TestListenerBuildItem> testListenerBuildItems) {
    if (TestSupport.instance().isEmpty() || config.continuousTesting == TestConfig.Mode.DISABLED || config.flatClassPath) {
        return;
    }
    DevModeType devModeType = launchModeBuildItem.getDevModeType().orElse(null);
    if (devModeType == null || !devModeType.isContinuousTestingSupported()) {
        return;
    }
    if (testingSetup) {
        return;
    }
    testingSetup = true;
    TestSupport testSupport = TestSupport.instance().get();
    for (TestListenerBuildItem i : testListenerBuildItems) {
        testSupport.addListener(i.listener);
    }
    testSupport.setConfig(config);
    testSupport.setTags(config.includeTags.orElse(Collections.emptyList()), config.excludeTags.orElse(Collections.emptyList()));
    testSupport.setPatterns(config.includePattern.orElse(null), config.excludePattern.orElse(null));
    testSupport.setEngines(config.includeEngines.orElse(Collections.emptyList()), config.excludeEngines.orElse(Collections.emptyList()));
    testSupport.setConfiguredDisplayTestOutput(config.displayTestOutput);
    testSupport.setTestType(config.type);
    if (!liveReloadBuildItem.isLiveReload()) {
        if (config.continuousTesting == TestConfig.Mode.ENABLED) {
            testSupport.start();
        } else if (config.continuousTesting == TestConfig.Mode.PAUSED) {
            testSupport.stop();
        }
    }
    QuarkusClassLoader cl = (QuarkusClassLoader) Thread.currentThread().getContextClassLoader();
    ((QuarkusClassLoader) cl.parent()).addCloseTask(ContinuousTestingSharedStateManager::reset);
}
Also used : ContinuousTestingSharedStateManager(io.quarkus.dev.testing.ContinuousTestingSharedStateManager) DevModeType(io.quarkus.dev.spi.DevModeType) QuarkusClassLoader(io.quarkus.bootstrap.classloading.QuarkusClassLoader) Produce(io.quarkus.deployment.annotations.Produce) BuildStep(io.quarkus.deployment.annotations.BuildStep)

Aggregations

DevModeType (io.quarkus.dev.spi.DevModeType)4 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 Collections (java.util.Collections)3 List (java.util.List)3 Map (java.util.Map)3 BiConsumer (java.util.function.BiConsumer)3 BiFunction (java.util.function.BiFunction)3 Consumer (java.util.function.Consumer)3 Logger (org.jboss.logging.Logger)3 QuarkusClassLoader (io.quarkus.bootstrap.classloading.QuarkusClassLoader)2 Timing (io.quarkus.bootstrap.runner.Timing)2 BuildChainBuilder (io.quarkus.builder.BuildChainBuilder)2 BuildContext (io.quarkus.builder.BuildContext)2 TestSupport (io.quarkus.deployment.dev.testing.TestSupport)2 HotReplacementSetup (io.quarkus.dev.spi.HotReplacementSetup)2 LaunchMode (io.quarkus.runtime.LaunchMode)2 QuarkusConfigFactory (io.quarkus.runtime.configuration.QuarkusConfigFactory)2 ByteArrayInputStream (java.io.ByteArrayInputStream)2 Closeable (java.io.Closeable)2