All Downloads are FREE. Search and download functionalities are using the official Maven repository.

bear.main.FXConf Maven / Gradle / Ivy

/*
 * Copyright (C) 2013 Andrey Chaschev.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package bear.main;

import bear.annotations.Project;
import bear.core.*;
import bear.main.event.LogEventToUI;
import bear.main.event.NoticeEventToUI;
import bear.main.event.RMIEventToUI;
import bear.main.phaser.ComputingGrid;
import bear.main.phaser.SettableFuture;
import bear.plugins.CommandInterpreter;
import bear.plugins.Plugin;
import bear.plugins.PomPlugin;
import bear.plugins.groovy.Replacement;
import bear.plugins.groovy.Replacements;
import bear.plugins.sh.GenericUnixRemoteEnvironmentPlugin;
import bear.task.*;
import chaschev.json.JacksonMapper;
import chaschev.lang.Lists2;
import chaschev.lang.OpenBean;
import chaschev.lang.Predicates2;
import chaschev.lang.reflect.MethodDesc;
import chaschev.util.Exceptions;
import com.fasterxml.jackson.core.JsonGenerator;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.io.CharStreams;
import com.google.common.io.Files;
import javafx.scene.input.Clipboard;
import javafx.scene.input.DataFormat;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

import static com.google.common.collect.Lists.transform;
import static java.util.Collections.singletonList;

/**
 * @author Andrey Chaschev [email protected]
 */
public class FXConf extends BearMain {
    private static final Logger logger = LoggerFactory.getLogger(FXConf.class);
    private static final org.apache.logging.log4j.Logger ui = LogManager.getLogger("ui");

    protected BearCommandInterpreter commandInterpreter;

    public FXConf(String... args) {
        super(GlobalContextFactory.INSTANCE.getGlobal(), getCompilerManager(), args);

        fxApp = true;
    }

    public String getFileText(String className) {
        return compileManager.findClass(className).get().getText();
    }

    public void saveFileText(String className, String text) {
        compileManager.findClass(className).get().saveText(text);
    }

    public String getSelectedSettings() {
        return FilenameUtils.getBaseName($(projectFile).getName());
    }

    public Response run(String uiContextS) throws Exception {
        logger.info("running a script with params: {}", uiContextS);

        BearScriptRunner.UIContext uiContext = commandInterpreter.mapper.fromJSON(uiContextS, BearScriptRunner.UIContext.class);

        BearProject project = newProject(uiContext);

        project.invoke(uiContext.projectMethodName);

//        run(newProject(new File(uiContext.projectPath)).setInteractiveMode(), null, false, true);

        return sendHostsEtc(lastRunner);
    }

    private BearProject newProject(BearScriptRunner.UIContext uiContext) {
        return newProject(new File(uiContext.projectPath));
    }

    public BearProject newProject(File file) {
        return ((BearProject) OpenBean.newInstance((Class) findEntry(file).get().aClass))
                .injectMain(this)
                .setInteractiveMode();
    }

    private Response sendHostsEtc(GlobalTaskRunner runner) {
        List hosts = getHosts(runner.getSessions());

        ui.info(new RMIEventToUI("terminals", "onScriptStart", hosts));

        return new BearScriptRunner.RunResponse(runner, hosts);
    }

    public static List getHosts(List $s) {
        return transform($s, new Function() {
            public BearScriptRunner.RunResponse.Host apply(SessionContext $) {
                return new BearScriptRunner.RunResponse.Host($.sys.getName(), $.sys.getAddress());
            }
        });
    }

    public Response interpret(String command, String uiContextS) throws Exception {
        return commandInterpreter.interpret(command, uiContextS);
    }

    public String pasteFromClipboard() {
        return Clipboard.getSystemClipboard().getString();
    }

    public void copyToClipboard(String text) {
        HashMap map = new HashMap();
        map.put(DataFormat.PLAIN_TEXT, text);

        Clipboard.getSystemClipboard().setContent(map);
    }

    public String completeCode(String script, int caretPos) {
        return commandInterpreter.completeCode(script, caretPos);
    }

    public void evaluateInFX(Runnable runnable) {
        bearFX.bearFXApp.runLater(runnable);
    }

    public  Future evaluateInFX(final Callable callable) {
        final SettableFuture future = new SettableFuture();

        bearFX.bearFXApp.runLater(new Runnable() {
            @Override
            public void run() {
                try {
                    future.set(callable.call());
                } catch (Exception e) {
                    future.setException(e);
                }
            }
        });

        return future;
    }

    public FileResponse getPropertyAsFile(String property) {
        String file = bearFX.bearProperties.getProperty(property);

        Preconditions.checkNotNull(file, "no such property: %s", property);

        if (file.indexOf('/') == -1 && file.indexOf('\'') == -1) {
            return new FileResponse(new File($(scriptsDir), file));
        }

        return new FileResponse(new File(file));
    }

    public void createPom() {
        try {
            File file = new File(".bear/pom.xml");

            logger.info("writing POM to {}...", file.getAbsolutePath());

            CharStreams.write(
                bear.getGlobal().plugin(PomPlugin.class).generate(),
                Files.newWriterSupplier(file, Charsets.UTF_8)
            );

            ui.info(new NoticeEventToUI("Create POM",
                "POM has been created in " + file.getAbsolutePath()));
        } catch (IOException e) {
            throw Exceptions.runtime(e);
        }
    }

    @Override
    public FXConf configure() throws IOException {
        super.configure();

        commandInterpreter = $.wire(new BearCommandInterpreter());
        commandInterpreter.switchToPlugin(GenericUnixRemoteEnvironmentPlugin.class);

        return this;
    }

    public static class FileResponse {
        public String dir;
        public String filename;
        public String path;
        public String absPath;

        public FileResponse(File file) {
            dir = file.getParent();
            filename = file.getName();
            path = file.getPath();
            absPath = file.getAbsolutePath();
        }
    }

    private String[] getNames(List classes) {
        return (String[]) Lists2.projectMethod(classes, "getName").toArray(new String[classes.size()]);
    }

    public void cancelAll(){
        GlobalTaskRunner runContext = global.currentGlobalRunner;

        if(runContext == null){
            ui.warn(new LogEventToUI("shell", "not running"));
            return;
        }

        List entries = runContext.getSessions();

        for (SessionContext $ : entries) {
            if($.isRunning()){
                try {
                    $.terminate();
                } catch (Exception e) {
                    logger.warn("could not terminate", e);
                }
            }
        }

        global.interruptAll();
    }

    public void cancelThread(String name){
        GlobalTaskRunner runContext = global.currentGlobalRunner;

        if(runContext == null){
            ui.warn(new LogEventToUI("shell", "not running"));
            return;
        }

        SessionContext $ = Iterables.find(runContext.getSessions(), Predicates2.methodEquals("getName", name));

        $.terminate();
    }

    public class BearCommandInterpreter {
        GlobalContext global;

        Plugin currentShellPlugin;

        public CommandInterpreter currentInterpreter() {
            return currentShellPlugin.getShell();
        }

        public final JacksonMapper mapper = new JacksonMapper();


        /**
         * Scope: GLOBAL
         *
         * : -> system command
         * :help
         * :use shell 
         *
         * @param command
         */
        public Response interpret(final String command, String uiContextS) throws Exception {
            String firstLine = StringUtils.substringBefore(command, "\n");

            ui.info("interpreting command: '{}', params: {}", firstLine.trim(), uiContextS);

            final BearScriptRunner.UIContext uiContext = mapper.fromJSON(uiContextS, BearScriptRunner.UIContext.class);

            final BearProject project = newProject(uiContext);

            boolean runInSingleShell = !"shell".equals(uiContext.shell) && !"status".equals(uiContext.shell);

            global.putConst(bear.internalInteractiveRun, true);

            if(runInSingleShell){
                //better to call saveMap
                global.putConst(bear.activeHosts, singletonList(uiContext.shell));
                global.putConst(bear.activeRoles, Collections.emptyList());
            }

            GlobalTaskRunner runner = project.run(singletonList(new NamedCallable>(firstLine, new TaskCallable>() {
                @Override
                public TaskResult call(SessionContext $, Task> task) throws Exception {
                    Plugin shellPlugin = project.findShell(uiContext.plugin).get();

                    Task> interpretedTask = shellPlugin.getShell().interpret(command, $, task, task.getDefinition());
                    return $.runner.runSession(interpretedTask);
                }
            })));

            if(runInSingleShell){
                //not safe when quickly fails, better to restore the map
                runner.whenAllFinished(new ComputingGrid.WhenAllFinished() {
                    @Override
                    public void run(int failedParties, int okParties) {
                        global.removeConst(bear.activeHosts);
                        global.removeConst(bear.activeRoles);
                    }
                });
            }

            return sendHostsEtc(runner);
        }

        private void switchToPlugin(Class aClass) {
            this.currentShellPlugin = global.plugin(aClass);
        }

        public String completeCode(String script, int caretPos) {
            try {
                Replacements replacements = currentInterpreter().completeCode(script, caretPos);

                StringWriter writer = new StringWriter(1024);
                JsonGenerator g = mapper.getMapper().getFactory().createGenerator(writer);

                g.writeStartArray();

                for (Replacement replacement : replacements.getReplacements()) {
                    g.writeStartObject();
                    g.writeStringField("caption", replacement.name);
                    g.writeStringField("meta", replacement.type);
                    g.writeStringField("snippet", replacement.snippet);
                    g.writeEndObject();
                }

                g.writeEndArray();

                g.close();

                return writer.toString();
            } catch (IOException e) {
                throw Exceptions.runtime(e);
            }
        }
    }

    public ProjectInfosResponse getProjectInfos(){
        List> list = compileManager.findProjects();

        List infos = new ArrayList();

        for (CompiledEntry compiledEntry : list) {
            infos.add(new ProjectInfo(compiledEntry.aClass, compiledEntry.file.getAbsolutePath(), global));
        }

        Class prjClass;

        if(global.isSet(bear.activeProject)){
            prjClass = global.var(bear.activeProject).getClass();

            selectProject(prjClass.getAnnotation(Project.class).shortName());
        } else {
            File currentProjectFile = new File(bearFX.bearProperties.getProperty("bear-fx.project"));

            Optional> aClass = compileManager.findClass(currentProjectFile);

            prjClass = (Class) aClass.get().aClass;
        }

        return new ProjectInfosResponse(infos)
            .setSelectedProject(prjClass.getSimpleName());
    }

    //todo refactor to properties management?
    void selectProject(String shortName){
        for (CompiledEntry entry : compileManager.findProjects()) {
            if(entry.aClass.getAnnotation(Project.class).shortName().equals(shortName)){
                try {
                    bearFX.bearProperties.setProperty("bear-fx.project", entry.file.getAbsolutePath());
                    bearFX.bearProperties.store(new FileWriter(BearFX.BEAR_FX_PROPERTIES), "");
                    return;
                } catch (IOException e) {
                    throw Exceptions.runtime(e);
                }
            }
        }

        throw new IllegalArgumentException("didn't find project: " + shortName);
    }

    public class ProjectInfo{
        public String shortName;
        public String name;
        public List methods;
        public String path;
        public String defaultMethod;
        public List shells;

        public ProjectInfo() {
        }

        public ProjectInfo(Class project, String path, GlobalContext global) {
            Project projectAnnotation = project.getAnnotation(Project.class);

            shortName = projectAnnotation.shortName();
            name = project.getSimpleName();
            defaultMethod = projectAnnotation.method();
            methods = new ArrayList();
            shells = new ArrayList();
            this.path = path;

            Set temp = new LinkedHashSet();

//            BearProject prj = newProject(new File(path));

//            prj.configureWithAnnotations(true);

            for (MethodDesc desc : OpenBean.methods(project)) {
                if(desc.getMethod().isAnnotationPresent(bear.annotations.Method.class)){
                    temp.add(desc.getName());
                }
            }
            for (MethodDesc methodDesc : OpenBean.methodsReturning(project, GlobalTaskRunner.class)) {
                if(methodDesc.getMethod().getParameterTypes().length == 0){
                    temp.add(methodDesc.getName());
                }
            }


            for (Method method : project.getDeclaredMethods()) {
                if(Modifier.isPublic(method.getModifiers())
                    && method.getReturnType().equals(void.class)
                    && method.getParameterTypes().length == 0
                    ){
                    temp.add(method.getName());
                }
            }

            for (String s : temp) {
                if(s.contains("$1") || s.contains("$2") || s.contains("__$")) continue;

                methods.add(s);
            }

//            for (Plugin plugin : prj.getAllShellPlugins(global, project)) {
//                shells.add(plugin.cmdAnnotation());
//            }

//            System.out.println(this);
        }

        public ProjectInfo setPath(String path) {
            this.path = path;
            return this;
        }
    }

    public static class ProjectInfosResponse {
        public String selectedProject;
        public String selectedMethod;

        public List infos;

        public ProjectInfosResponse() {
        }

        public ProjectInfosResponse(List infos) {
            this.infos = infos;
        }

        public ProjectInfosResponse setSelectedProject(String selectedProject) {
            this.selectedProject = selectedProject;

            for (ProjectInfo info : infos) {
                if(info.name.equals(selectedProject)){
                    selectedMethod = info.defaultMethod;
                    break;
                }
            }

            return this;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy