lib 1400521 // FlatLAF set flag PingV3. set flag NotifyingPrintLog. set flag SymbolAsString. // Do the JavaX init svoid standaloneInit { __javax = x30.class; x30.__javax = x30.class; // for hotwire x30_pkg.x30_util.__setJavaX(x30.class); x30.cleanKillMsg = ""; callOnLoadMethods(mc()); } concept PrintLogModule > DynPrintLog { start { setModuleName("Log"); } S getPrintLog() { ret printLog(); } bool useErrorHandling() { false; } } concept Stem extends ConceptWithChangeListeners is AutoCloseable { transient GazelleHost host; transient LoadedDB db; DynModule module; settableWithVar Rect frameRect; bool minimized, maximized, alwaysOnTop, minimizeToTray; transient JFrame window; transient JButton btnMax; transient JLabel titleComponent; transient gettable JButton compileButton; //transient bool autoUpdateDisabled; transient bool started; *() {} *(LoadedDB *db) { host = db.host; } *(LoadedDB db, DynModule *module) { this(db); } transient Component selfVis; // how the module visualized itself // Not sure why we use LazyVar here instead of simplyCached transient LazyVar scpMainWindowContents = new(-> scp()); SingleComponentPanel scpMainWindowContents() { ret scpMainWindowContents!; } transient LazyVar scpMainWindowWithTitle = new(-> scp()); SingleComponentPanel scpMainWindowWithTitle() { ret scpMainWindowWithTitle!; } transient LazyVar scpFrameIcon = new(-> scp()); SingleComponentPanel scpFrameIcon() { ret scpFrameIcon!; } Rect grabFrameRect() { ret toRect(getBounds(window)); } void saveFrameRect { frameRect(grabFrameRect()); } void restoreFrameRect { if (frameRect != null) setBounds(window, frameRect); } void setAlwaysOnTop(bool alwaysOnTop) { this.alwaysOnTop = alwaysOnTop; change(); alwaysOnTop(window, alwaysOnTop); } void setMinimizeToTray(bool minimizeToTray) { cset(this, +minimizeToTray); } void setWindow(JFrame window) { this.window = window; restoreFrameRect(); //onWindowClosing(window, -> host.cleanExit()); onBoundsChange(window, r saveFrameRect); if (host.restrictWindowsToScreenSize) restrictWindowToScreenSize(window); alwaysOnTop(window, alwaysOnTop); } void activateWindow { print("activateWindow: " + window); if (window != null) activateFrame_v3(window); else startAndShow(false); } bool isMain() { ret this == db.mainStem; } void minimize { cset(this, minimized := true); if (!minimizeToTray || host.trayIcon == null || !isMain()) minimizeWindow(window); else hideWindow(window); } void deleteMe { temp tempPrintAlsoToSystemOut(); print("deleteMe " + isMain()); if (isMain()) host.closeDatabase(db); else delete(); } close { disposeWindow(window); cleanUp(module); } void delete :: before { close(); } void grabWindowState { setField(maximized := !isExtendedStateNormal(window)); } void updateBtnMax { if (!isShowing(btnMax)) ret; grabWindowState(); setText(btnMax, maximized ? "NORM" : "MAX"); } JComponent makeWindowBorderAndTitle(JComponent contents, S title) { //ret jCenteredSection_fontSizePlus(10, title, vis); var icons = jline(); if (host.allowFrameMaximization) { icons.add(btnMax = jbutton("", rThread { maximizeOrRestoreFrame(window); updateBtnMax(); })); onFirstShowing(btnMax, r updateBtnMax); } icons.add(toolTip("Minimize this window", jbutton("MIN", r minimize))); icons.add(toolTip("Close this window", jimageButtonScaledToWidth(16, #1103067, rThread deleteMe))); //setHorizontalMarginForAllButtons(icons, 4); icons.add(new JPopDownButton(menu -> fillJPopupMenu(menu, flattenToList( // always on top jCheckBoxMenuItem/*_dyn*/("Always on top", /*->*/ alwaysOnTop, alwaysOnTop -> setAlwaysOnTop(alwaysOnTop)), // quit, restart + update "---", "Exit Gazelle", rThread { host.cleanExit() }, "Restart", rThread { host.restart() }, "Re-open project", rThread { host.reopenDB(db) }, "Hide project", rThread { db.hide() }, "Update Gazelle", rThread { host.upgradeGazelle() }, !isMain() ? null : jCheckBoxMenuItem/*_dyn*/("Auto-Update", /*->*/ print(autoUpdate := db.g22utils.autoUpdateEnabled()), b -> { // save flag db.g22utils.setAutoUpdate(b); // if user just turned on auto-update, do the update if (b) thread { host.upgradeGazelle(); } }), // debugging + screenshooting gazelle "---", !isMain() ? null : ll( "Screenshoot this window", rThread shootWindow, "Dump threads", rThread { showText("User threads", renderUserThreadsWithStackTraces()); }, "Log", !isMain() ? null : r { db.showPrintLog() }, "Copy log to clipboard", !isMain() ? null : rThread { copyToClipboard(printLog()); infoBox("Copied log to clipboard"); }, "10 Second Profiler", rThread runTenSecondProfiler, ), ccallOpt(module, "popDownItems") )))); JComponent actualTitle = titleComponent = fontSizePlus(7, jCenteredLabel(title)); installWindowDragger(actualTitle); if (/*isMain() &&*/ host.devMode()) actualTitle = centerAndEastWithMargin(actualTitle, jline( compileButton = makeCompileButton(), installWindowDragger(lblComputerAndUserCount()), )); updateFrameIcon(); var spacer = gazelle_wavySpacer(color1(), color2()); var titleBarMain = setOpaqueBackground(color1(), jtransparent_recursive(westCenterAndEastWithMargin( scpFrameIcon(), actualTitle, setOpaqueBackground(color2(), spacer))); installWindowDragger(spacer); var titleBar = setBackground(color2(), centerAndEast( titleBarMain, icons)); var border = // createBevelBorder(); BorderFactory.createLineBorder(color1(), host.borderSize); var outerPanel = withBorder(border, northAndCenter(titleBar, contents)); installWindowResizeDraggerOnBorder(outerPanel); ret markVisualizer(this, outerPanel); } swappable S frameIconID() { ret host.trayIconImageID; } swappable int frameIconHeight() { ret 24; } selfType frameIconID(S iconID) { frameIconID = -> iconID; updateFrameIcon(); this; } swappable JComponent makeFrameIcon() { ret jImage_scaledToHeight(frameIconHeight(), frameIconID()); } void updateFrameIcon { scpFrameIcon().set(makeFrameIcon()); } swappable Color color1() { ret host.color1; } swappable Color color2() { ret host.color2; } JLabel lblComputerAndUserCount() { JLabel label = jlabel(); Runnable update = -> { Int computerCount = host.computerCount(); Int userCount = host.lvGazelleUserCount()!; setText(label, (computerCount == null ? "" : n2(computerCount)) + appendSquareBracketed( userCount == null ? "" : n2(userCount))); }; bindChangeListenerToComponent(label, host.lvComputerCount(), update); bindChangeListenerToComponent(label, host.lvGazelleUserCount(), update); ret label; } JButton makeCompileButton() { var gears = resizeImageIcon(imageIcon(#1103061), 16); var btn = jimageButtonScaledToWidth(16, #1101268, "Compile & update", rThread { host.compile() }); //enableComponentAccordingToVar(host.compileButtonEnabled, btn); componentPopupMenuItems(btn, "Compile all", rThread { host.compileAll() }, "Compile main library", rThread { host.compileUtilsAndRepackage() }, "Repackage", rThread { host.repackage() }, ); ret btn; } JComponent wrapVis(JComponent vis) { //ret jMinSize0(vis); ret vis; } void startAndShow(bool hidden default false) { if (module._host != this) { module._host = this; setOpt_raw(module, +threadPool); // only if the field exists setOpt_raw(module, concepts := db.concepts); setOpt_raw(module, g22utils := db.g22utils); copyLocalLog(module, mc()); } var vis, title = unpair startAndVisualize(); if (!hidden) { printWithMS("Show frame"); JFrame frame = makeUndecoratedFrame(title, wrapVis(vis)); setFrameIcon(frame, host.trayIconImageID); setWindow(frame); frame.addPropertyChangeListener("title", evt -> setText(titleComponent, frame.getTitle())); if (minimized) minimize(); onWindowDeiconified(frame, -> cset(this, minimized := false)); showWindow(window); if (maximized && host.allowFrameMaximization) maximizeFrame(window); } } Pair startAndVisualize() { JComponent vis = null; { printWithMS("Starting " + module); try { if (!started) { set started; temp module.enter(); module.start(); } printWithMS("Visualize"); vis = swing(-> { temp module.enter(); ret module.visualize(); }); } on fail e { waitForFrameClose(showErrorFrame(e)); } } selfVis = vis; var scp1 = scpMainWindowContents(); scp1.set(vis); S title = createTitleText(); var vis2 = makeWindowBorderAndTitle(scp1, title); var scp2 = scpMainWindowWithTitle(); scp2.set(vis2); ret pair(scp2, title); } S createTitleText() { S moduleName = takeFirst_unnull(800, module.moduleName()); if (isMain()) // OLD: ret host.windowTitle + appendWithColon(moduleName); ret joinNemptiesWithVBar(moduleName, host.windowTitle); else ret moduleName; } void revisualize { if (window == null) ret; pcall { module.unvisualize(); } var vis, title = unpair startAndVisualize(); setFrameContents(window, wrapVis(vis)); } void shootWindow { var img = renderComponentToImage(window); copyImageToClipboard(img); File imgFile = saveInImageDirectoryWithCounter(gazelle22_imagesSubDirName() + "/Gazelle", img); pcallOpt(module, "addToGallery", imgFile); } // Breaking change 2022 Dec 10 (is this even used?) // old: Component vis() { ret getFrameContents(window); } Component vis() { ret scpMainWindowContents()!; } S tenSecondProfilerScript = [[ temp profiler <- new AllThreadsProfiler infoBox "Profiling..." profiler start sleepSeconds 10 showText "10 Second Profile" < profiler renderFullResults false ]]; File byteCodePath() { ret assertNotNull(getBytecodePathForClass(this)); } ClassNameResolver classNameResolver() { ret new ClassNameResolver().byteCodePath(byteCodePath()).init(); } GazelleV_LeftArrowScriptParser leftArrowParser() { new GazelleV_LeftArrowScriptParser parser; parser.classNameResolver(classNameResolver()); parser.allowTheWorld(mc(), utils.class); ret parser; } void runTenSecondProfiler { leftArrow(leftArrowParser(), tenSecondProfilerScript); } } // end of Stem sclass LoadedDB is AutoCloseable, IG22LoadedDB { GazelleHost host; gettable Concepts concepts; gettable new G22Utils g22utils; Stem mainStem; gettable bool hidden; *(GazelleHost *host, Concepts *concepts, bool *hidden) { g22utils.concepts(concepts); g22utils.masterStuff(host); } S name() { ret fileName(conceptsDir(concepts)); } void start { concepts.grabThroughSocket(false); concepts.makeStructureData = -> { structure_Data data = concepts.makeStructureData_base(); data.realShortName = name -> { S n = dropPrefixOrNull("userCode.", name); if (n != null) ret takeFirst(n, indexOf(n, '_')); ret data.realShortName_base(name); }; data.mcDollar = mcDollar(); ret data; }; var lock = concepts.fileLock(); try { lock.contentsForLockFile("Locked by computer " + computerID() + "\n"); lock.lockOrFail(); } catch print e { if (cic(str(e), "Couldn't aquire lock")) { if (!lock.hasExpectedContents()) { infoBox("Overriding project lock (" + lock.actualContents() + ")"); lock.forceLock(); } else { S msg = "This project is already opened in another process"; infoBox(msg, 10.0); sleepSeconds(1); fail(msg); } } else throw rethrow(e); } concepts.fileLock().deleteOnExit(); thinAProgramsBackups(concepts.conceptsDir(), true); //concepts.persist(); concepts.loadConcepts(); // Check that we are not loading with an old program version var projectInfo = optimizedUniq(concepts, G22ProjectInfo); S compilationDate = compilationDateFromClassPath(this); print("Compilation date in project: " + projectInfo.compilationDate); if (nempty(projectInfo.compilationDate) && lessThan(compilationDate, projectInfo.compilationDate)) { messageBoxAndFail("Trying to open project with old Gazelle version - please update Gazelle first (" + compilationDate + " vs " + projectInfo.compilationDate + ")"); } if (cset(projectInfo, +compilationDate) != 0) print("Bumped compilation date in project to " + compilationDate); concepts.autoSaveConcepts(); //db_setMainConcepts(concepts); //print("Concepts loaded: " + map className(allConcepts(concepts)); var stems = stems(); print("Stems in DB: " + l(stems)); mainStem = first(stems); if (mainStem == null) { print("Starting new module"); var module = host.makeModule(); mainStem = registerConcept(concepts, new Stem(this, module)); print("Stems in DB: " + l(stems())); } for (stem : stems()) { stem.db = this; stem.host = host; stem.startAndShow(hidden); } print("Stems in DB: " + l(stems())); } L stems() { ret list Stem(concepts); } Q systemQ() { ret host.systemQ; } Stem findPrintLog() { ret firstThat(list(concepts, Stem), stem -> stem.module instanceof PrintLogModule); } void showPrintLog { systemQ().add(-> { var logModule = findPrintLog(); if (logModule != null) logModule.activateWindow(); else registerConcept(concepts, new Stem(this, new PrintLogModule)).startAndShow(); }); } void hidePrintLog { systemQ().add(-> deleteConcept(findPrintLog())); } void activate { print("Activating DB: " + conceptsFile(concepts)); if (hidden) { hidden = false; host.loadedDBsChange(); } mainStem?.activateWindow(); } void hide { hideWindow(mainWindow()); if (!hidden) { hidden = true; host.loadedDBsChange(); } } public JFrame mainWindow() { ret mainStem?.window; } close { print("Cleaning up " + concepts); print("Stems in DB: " + l(stems())); for (Concept c : allConcepts(concepts)) cleanUp(c); print("Releasing DB (" + n2(list(concepts, Stem), "stem") + ")"); dispose concepts; host.loadedDBs.remove(this); host.loadedDBsChange(); print("Remaining DBs: " + l(host.loadedDBs)); } toString { ret name(); } DynModule module() { ret mainStem?.module; } public G22ProjectActions projectActions() { ret (G22ProjectActions) module(); } } // end of LoadedDB // This replaces the Stefan's OS main class. It is not persisted // and there is only one instance. transient sclass GazelleHost is G22MasterStuff { Set loadedDBs = syncLinkedHashSet(); event loadedDBsChange; event newClassesDefined; transient S repackageURL = "https://botcompany.de/jar/1033860?withX30=1&withLibs=1&noSrc=1&mainClassForManifest=Starter&repackage=1"; // Title of this Gazelle instance transient S windowTitle = "Gazelle 22"; transient S trayIconImageID = #1103047; transient int borderSize = 5; transient Color color1 = awtColor("ADD8E6"); transient Color color2 = awtColor("EEEEEE"); transient Color color3 = awtColor("A3C0AA"); transient IF0 moduleMaker; transient ThreadPool threadPool; transient File dbMotherDir; transient TrayIcon trayIcon; transient TrayIconLastPosition trayIconLastPosition; transient S[] args; transient Set argsSet; transient bool incrementalDownloads = true; transient volatile bool shuttingDown; transient bool restrictWindowsToScreenSize /*= true*/; // This caused problems, disabled for now transient bool allowFrameMaximization; transient G22Utils g22utils; transient StefansOS_ConnectToServer serverConnector; transient ComputerCountListener computerCount; transient GazellePresenceListener gazellePresenceListener; transient gettable Q systemQ = startQ("System Q"); transient AutoCloseable pimpedPopups; // Let's use one of these centrally because it blocks a thread // and does next to nothing most of the time. gettable new RunnablesReferenceQueue runnablesReferenceQueue; transient gettable ILASClassLoader lasClassLoader = //new LASClassLoader(getClass()); new LASMultiClassLoader(mc()).runnablesReferenceQueue(assertNotNull(runnablesReferenceQueue)); //transient BoolVarWithNotify compileButtonEnabled = new(true); gettable EphemeralObjectIDs ephemeralObjectIDs = new() .runnablesReferenceQueue(assertNotNull(runnablesReferenceQueue)); transient bool autoExitDisabled; event fillingTrayIconMenu(PopupMenu menu); // add fields here *(ThreadPool *threadPool, IF0 *moduleMaker) { g22utils = new G22Utils().masterStuff(this); onLoadedDBsChange(-> { if (shuttingDown) ret; var dbs = getLoadedDBs(); if (nempty(dbs)) g22utils.setOpenDBs(dbs); updateTrayIconMenu(); }); } // Reminder: We are in GazelleHost A inSystemQ(IF0 f) { ret evalInQ(systemQ(), f); } JFrame mainWindow() { ret firstNonNull(loadedDBs(), db -> db.mainWindow()); } void trayIconLeftClick { first(loadedDBs()).activate(); } void makeTrayIcon { pcall-short { trayIcon_imageAutoSize = false; trayIcon = installTrayIcon(trayIconImageID, windowTitle, r trayIconLeftClick, /*"Show " + windowTitle, r trayIconLeftClick, "Exit " + windowTitle, r cleanExit*/ ); updateTrayIconMenu(); trayIconLastPosition = new TrayIconLastPosition(trayIcon); } } void updateTrayIconMenu { rstUpdateTrayIconMenu.trigger(); } transient ReliableSingleThread rstUpdateTrayIconMenu = rstWithPostDelay(1000, l0 updateTrayIconMenuImpl); void updateTrayIconMenuImpl { if (trayIcon == null) ret; new PopupMenu menu; var projects = openProjects(); printVars("updateTrayIconMenuImpl", +projects); for (IG22LoadedDB otherDB : projects) { S name = otherDB.g22utils().projectName(); S status = otherDB.hidden() ? "Hidden" : ""; addMenuItem(menu, name + appendSquareBracketed(status), rThread { otherDB.activate() }); } fillingTrayIconMenu(menu); addMenuItem(menu, "Exit " + windowTitle, rThread cleanExit); trayIcon.setPopupMenu(menu); } void run(S[] args) { try { this.args = args; run2(args); } catch print e { //messageBox(e); hideTrayIcon(trayIcon); onWindowClosing(-> systemExit(1), getWindow( showText_fast_noWrap("Gazelle Error", renderStackTrace(e)))); } } void run2(S[] args) { argsSet = asSet(args); S s = first(args); bool isDirectory = isDirectory(s); if (isDirectory) dbMotherDir = canonicalFile(s); printVars(args := asList(args), +s, +isDirectory, +dbMotherDir); print("Using mother directory: " + databasesMotherDir()); windowTitle = or2(loadTextFile(newFile(dbMotherDir, "Gazelle Name")), windowTitle); if (!argsSet.contains("noflatlaf")) com.formdev.flatlaf.FlatLightLaf.setup(); if (contains(args, "profile")) profileToConsole(() -> actualMain(args)); else actualMain(args); if (argsSet.contains("brexit")) System.exit(0); } void actualMain(S... args) { vm_generalMap_put(stefansOS := this); System.out.println(hmsWithColonsAndMS() + ": Init"); //x30.coreInit(); // Ready to roll printJavaVersion(); //tempAddGlobalCtrlKeyListener(b -> print("Ctrl key: " + b)); if (contains(argsSet, "profile")) doEvery(1.0, r printRunningThreads); if (containsOneOf(argsSet, "upgrade", "update")) ret with upgradeGazelle(); makeTrayIcon(); initAutoUpdate(); if (devMode()) { print("Pimping popup menus"); PopupMenuMaker.fix(); pimpedPopups = tempGlobalPopupMenu((c, menu) -> { printVars("pimpedPopups", c := className(c)); // Skip linux tray icon popups if (contains(className(c), "XTrayIcon")) ret; // This is for popup menus displayed via setComponentPopupMenu // which are re-used instances if (any(getMenuItems(menu), menuItem -> cicOneOf(menuItem.getText(), "Component: ", "src: "))) ret; O src = componentMetaSrc(c); menu.add(commaCombine( classNameAndEphString(c), src == null ?: "src: " + classNameAndEphString(src))); }); } // Start DB LS dbNames = g22utils.dbsToOpen(); for (S dbName : dbNames) { S name2 = dropPrefix("*", dbName); openDB(name2, !eq(dbName, name2)); } exitIfAllDBsClosed(); printWithMS("Dudadoneski"); } public bool projectExists(S dbName) { File conceptsFile = newFile(newFile(databasesMotherDir(), dbName), conceptsFileName()); ret isFile(conceptsFile); } LoadedDB openDB(S dbName, bool hidden default false) { File conceptsFile = newFile(newFile(databasesMotherDir(), dbName), conceptsFileName()); ret openDB(conceptsFile, hidden); } public IG22LoadedDB getLoadedDB(Concepts concepts) { ret firstThat(cloneList(loadedDBs), db -> db.concepts == concepts); } IG22LoadedDB getLoadedDBForConceptDir(File dir) { ret findLoadedDBForConceptsDir(dir); } LoadedDB findLoadedDBForConceptsDir(File conceptsDir) { ret firstThat(cloneList(loadedDBs), db -> sameFile( conceptsDir(db.concepts), conceptsDir)); } LoadedDB findLoadedDBForConceptsFile(File conceptsFile) { ret firstThat(cloneList(loadedDBs), db -> sameFile( conceptsFile(db.concepts), conceptsFile)); } public IG22LoadedDB reopenDB(IG22LoadedDB db) { ret reopenDB((LoadedDB) db); } LoadedDB reopenDB(LoadedDB db) { File conceptsFile = db.concepts.conceptsFile(); try { autoExitDisabled = true; closeDatabase(db); ret openDB(conceptsFile); } finally { autoExitDisabled = false; } } LoadedDB openDB(File conceptsFile, bool hidden default false) { ret inSystemQ(-> { var loadedDB = findLoadedDBForConceptsFile(conceptsFile); if (loadedDB != null) { if (!hidden) loadedDB.activate(); ret loadedDB; } temp tempInfoBoxNoHide("Opening Gazelle project " + quote(fileName(dirOfFile(conceptsFile)))); // profile project opening //temp tempProfileSingleThreadToConsole(); print("Loading new DB: " + f2s(conceptsFile)); g22utils.addToRecentDBNames(parentName(conceptsFile), hidden); Concepts concepts = newConceptsWithClassFinder(conceptsFile, makeClassFinder()); concepts.onSaveError(l1 infoBox); // to clean-up resources in project variables concepts.closeConceptsOnExit(true); var db = new LoadedDB(this, concepts, hidden); loadedDBs.add(db); try { db.start(); loadedDBsChange(); } catch print e { loadedDBs.remove(db); _close(db); } ret db; }); } public Cl openConceptDirs() { ret cloneMap(loadedDBs, _db -> conceptsDir(_db.concepts)); } O resolveModule(O moduleOrStem) { ret moduleOrStem cast Stem ? moduleOrStem.module : moduleOrStem; } void cleanExit { set shuttingDown; print("Closing " + n2(loadedDBs, "database")); closeAndClear(loadedDBs); System.exit(0); } File myJar() { ret getBytecodePathForClass(this); } AutoCloseable tempDisableCompileButtons() { ret tempDisableButtons(compileButtons()); } swappable void upgradeGazelleForeplay { infoBox("Updating Gazelle in 10..."); sleepSeconds(10); upgradeGazelle(); } void upgradeGazelle { try { temp tempPrintAlsoToSystemOut(); // Show an infoBox to make sure the code for infoBox is loaded temp tempInfoBox("Updating Gazelle..."); //temp tempSetBoolVar(compileButtonEnabled, false); temp tempDisableCompileButtons(); //for (f : allJFrames()) setFrameTitle(f, "Updating..."); File myJar = myJar(); print(+myJar); S existingFilesComp = !incrementalDownloads ? null : existingFilesInfo(); S date = ymdMinusHMS(); File f = javaxCodeDir("Downloaded Updates/" + "gazelle-" + date + ".jar"); temp progress = tempProgressBar_addToWindowIfPossible(mainWindow(), "Updating Gazelle"); progress.setText("Downloading Update..."); time "Downloading zip" { postBinaryPageToFile(downloadURL(), f, +existingFilesComp); } printFileInfo(f); if (!isNonEmptySingleZip_byMagicHeader(f)) ret with infoBox("Bad file downloaded... :("); bool replaced; if (isFile(myJar)) { // load all my classes to be sure (TODO: could do this in parallel to downloading) //print("Loaded " + nClasses(loadAllClassesInByteCodePath(myJar))); progress.setText("Replacing with new version: " + renderFileInfo(myJar)); File myJarSaved = fileInSubDir("old-code", appendToBaseName(myJar, ".bak." + date)); File myJarNew = appendToFileName(myJar, ".new"); Set toKeep = asSet(tlft(loadTextFileFromZip(f, "to-keep"))); if (nempty(toKeep)) { int toUpdate = countFilesInZip(f)-1; //progress.setText("Keeping " + nFiles(toKeep)); progress.setText("Updating " + nFiles(toUpdate)); // Do we have anything to updatE? int have = countFilesInZip(myJar); if (l(toKeep) == have && countFilesInZip(f) == 1) { infoBox("Nothing to update - Gazelle is up to date!"); deleteFile(myJarNew); deleteFile(myJarSaved); ret; } temp Zip4j_MergeZipFilesWithFilter merger = new(myJarNew); merger.addZipFile(myJar, name -> contains(toKeep, name)); merger.addZipFile(f, name -> !eq(name, "to-keep")); merger.finish(); } else myJarNew = f; if (isWindows()) { copyFileVerbose(myJar, myJarSaved); copyFileVerbose(myJarNew, myJar); deleteFileVerbose_assertSuccess(myJarNew); } else { renameFileVerbose_assertSuccess(myJar, myJarSaved); renameFileVerbose_assertSuccess(myJarNew, myJar); } printFileInfo(myJar); set replaced; } progress.setText("Done"); if (replaced) infoBox("Installed update, replaced " + f2s(myJar) + " - now starting"); else infoBox("Updated but could not replace originally downloaded jar"); restart(replaced ? myJar : f); } on fail e { printStackTrace(e); } } void restart(File jar default myJar()) { temp tempPrintAlsoToSystemOut(); S javaCmd = or2(currentProcessCommand(), "java"); S cmd = platformQuoteArgs(flattenToList( javaCmd, "-jar", jar, args)); print(cmd); nohup(cmd); cleanExit(); } DynModule makeModule() { ret callF(moduleMaker); } void reloadModuleInBackground(Stem mod) { restart(); } void initAutoUpdate { print("Making server connection for updates."); serverConnector = snippetUpdateConnector(/*verbose := true*/); //serverConnector.verbose = true; vmBus_onMessage snippetUpdate(voidfunc(L l) { S uri = getString(l, 1); new Matches m; if (swic(uri, "/transpileOK/", m)) { if (sameSnippetID(programID(), firstIntAsString(m.rest()))) { if (g22utils.autoUpdateEnabled() /*&& autoUpdateDisabled*/) { upgradeGazelleForeplay(); } //infoBox("Gazelle can be updated!"); } } else if (swic(uri, "/edit/", m)) { S snippetID = fsI(firstIntAsString(m.rest()); if (contains(stdFunctionListSnippetIDs(), snippetID)) stdFunctions_clearCache(); if (contains(standardClassesSnippetIDs(), snippetID)) standardClassesMap_clearCache(); } }); pcall { computerCount = new ComputerCountListener(serverConnector); computerCount.init(); } pcall { gazellePresenceListener = GazellePresenceListener(serverConnector); gazellePresenceListener.init(); } } S downloadURL() { ret "https://botcompany.de/jar/" + psI(programID()) + "?withLibs=1&withX30=1" + "&mainClassForManifest=Starter" + (!downloadJarWithSrc() ? "&noSrc=1" : "") + (downloadUncompressedJAR() ? "&uncompressed=1" : ""); } bool downloadJarWithSrc() { true; } bool downloadUncompressedJAR() { false; } // called by DynModule void revisualizeModule(Stem stem) { stem.revisualize(); } Int computerCount() { ret computerCount == null ? (Int) 0 : computerCount!; } LiveValue lvComputerCount() { ret computerCount?.liveValue(); } public IGetterWithNotify lvGazelleUserCount() { ret gazellePresenceListener?.userCount; } L compileButtons() { ret mapNonNulls(allStems(), s -> s.compileButton()); } L allStems() { ret concatLists(cloneMap(loadedDBs, db -> list(db.concepts, Stem))); } // compile main program void compile { compile(programID, null); } void resetNeedLatest { editSnippet(#1035306, "need latest ."); } void compileAll { resetNeedLatest(); compile(utilsSnippetID(), l0 compile); } void compileUtilsAndRepackage { compile(utilsSnippetID(), l0 repackage); } void compile(S snippetID, Runnable onSuccess) { print("Compiling " + snippetID); var gears = resizeImageIcon(imageIcon(#1103061), 16); temp tempDisableCompileButtons(); temp tempSetButtonImages(compileButtons(), gears); thread { existingFilesInfo(); } // precompute var tr = TranspileWithErrorWindow().snippetID(snippetID); /*tr.transpileAction(-> new TranspileForServer_v2(snippetID).run());*/ tr.transpileAction(-> { var p = transpileOnNewServer(snippetID, "medium"); if (!p.a) fail(p.b); }); tr.onSuccess(onSuccess); tr.run(); print("Done transpilation of " + snippetID); } void repackage { File f = javaxCachesDir("Gazelle-22/repackaged.jar"); deleteFile(f); loadBinaryPageToFile(appendParamsToURL(repackageURL, uniq := randomID()), f); if (isJAR(f)) infoBox("Repackaged."); else messageBox("Oh shit"); } public void closeDatabase(LoadedDB db) { db.close(); exitIfAllDBsClosed(); } void exitIfAllDBsClosed { if (!autoExitDisabled && empty(loadedDBs)) cleanExit(); } Cl getLoadedDBs aka loadedDBs() { ret cloneList(loadedDBs); } public void closeDatabase(File conceptsDir) { for (db : cloneList(loadedDBs)) if (sameFile(conceptsDir, conceptsDir(db.concepts))) db.close(); } public void switchToDatabase(File conceptsDir) { if (conceptsDir == null) ret; // open/activate the desired database first var db = openDatabase(conceptsDir); if (db == null) ret; // probably impossible but whatever closeAllDBsExcept(db); } void closeAllDBsExcept(LoadedDB db) { closeAll(listMinus(loadedDBs, db)); } public LoadedDB openDatabase(File conceptsDir, bool hidden default false) { temp tempPrintAlsoToSystemOut(); File conceptsFile = newFile(conceptsDir, conceptsFileName()); if (!fileExists(conceptsFile)) fail(infoBox("Database not found: " + conceptsFile)); var db = openDB(conceptsFile, hidden); print("Database opening complete"); ret db; } Map classMigrations() { ret litmap( G22RecognizerScript := G22Analyzer, GalleryImage := G22GalleryImage); } public IF1 makeClassFinder() { IF1 defaultClassFinder = toIF1(_defaultClassFinder()); var migrations = classMigrations(); IF1 classFinder = name -> { // class migration S shortName = dropPrefixOrNull("main$", name); if (shortName != null) { Class c = migrations.get(shortName); if (c != null) { S newName = className(c); print("Migrating legacy class " + name + " to " + newName); name = newName; } } ret defaultClassFinder.get(name); }; // Test classFinder sanity assertEquals(callF(classFinder, "main$Stem"), Stem.class); ret classFinder; } transient cached S existingFilesInfo() { L fingerprints = zipFileToJSONFingerprint_md5(myJar()); S s = base64encode(gzipString(jsonEncode(fingerprints))); print(existingFilesInfo := nBytes(l(s))); ret s; } bool devMode() { ret g22_devMode(); } // remember ephemeral object, return script code to get it back S ephString(O o) { ret o == null ? "" : "eph " + ephemeralObjectIDs.remember(o); } S classNameAndEphString(O o) { ret o == null ?: spaceCombine(ephString(o), className(o)); } public File databasesMotherDir() { if (dbMotherDir == null) dbMotherDir = javaxDataDir("Gazelle-22"); ret dbMotherDir; } } // end of GazelleHost [G22MasterStuff]