001/* 002 * Copyright 2025 devteam@scivicslab.com 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, 011 * software distributed under the License is distributed on an 012 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the 014 * specific language governing permissions and limitations 015 * under the License. 016 */ 017 018package com.scivicslab.actoriac.cli; 019 020import java.io.File; 021import java.io.IOException; 022import java.net.HttpURLConnection; 023import java.net.URL; 024import java.util.concurrent.Callable; 025 026import picocli.CommandLine; 027import picocli.CommandLine.Command; 028import picocli.CommandLine.Option; 029 030/** 031 * CLI tool for clearing (deleting) the H2 log database files. 032 * 033 * <p>This command safely deletes the database files after checking 034 * that the log server is not running.</p> 035 * 036 * <p>Usage examples:</p> 037 * <pre> 038 * # Clear the default database 039 * java -jar actor-IaC.jar db-clear --db logs 040 * 041 * # Force clear without checking log server 042 * java -jar actor-IaC.jar db-clear --db logs --force 043 * </pre> 044 * 045 * @author devteam@scivicslab.com 046 * @since 2.12.0 047 */ 048@Command( 049 name = "db-clear", 050 mixinStandardHelpOptions = true, 051 versionProvider = VersionProvider.class, 052 description = "Clear (delete) the H2 log database files." 053) 054public class DbClearCLI implements Callable<Integer> { 055 056 @Option( 057 names = {"--db"}, 058 description = "H2 database path (without .mv.db extension)", 059 required = true 060 ) 061 private File dbPath; 062 063 @Option( 064 names = {"--http-port"}, 065 description = "HTTP port to check for running log server", 066 defaultValue = "29091" 067 ) 068 private int httpPort; 069 070 @Option( 071 names = {"-f", "--force"}, 072 description = "Force clear without checking if log server is running" 073 ) 074 private boolean force; 075 076 /** 077 * Main entry point for the db-clear CLI. 078 * 079 * @param args command line arguments 080 */ 081 public static void main(String[] args) { 082 int exitCode = new CommandLine(new DbClearCLI()).execute(args); 083 System.exit(exitCode); 084 } 085 086 @Override 087 public Integer call() { 088 // Check if log server is running 089 if (!force && isLogServerRunning()) { 090 System.err.println("Error: Log server is running on HTTP port " + httpPort); 091 System.err.println("Please stop the log server first, or use --force to skip this check."); 092 return 1; 093 } 094 095 File mvDb = new File(dbPath.getAbsolutePath() + ".mv.db"); 096 File traceDb = new File(dbPath.getAbsolutePath() + ".trace.db"); 097 098 boolean anyDeleted = false; 099 100 if (mvDb.exists()) { 101 if (mvDb.delete()) { 102 System.out.println("Deleted: " + mvDb.getAbsolutePath()); 103 anyDeleted = true; 104 } else { 105 System.err.println("Failed to delete: " + mvDb.getAbsolutePath()); 106 return 1; 107 } 108 } 109 110 if (traceDb.exists()) { 111 if (traceDb.delete()) { 112 System.out.println("Deleted: " + traceDb.getAbsolutePath()); 113 anyDeleted = true; 114 } else { 115 System.err.println("Failed to delete: " + traceDb.getAbsolutePath()); 116 return 1; 117 } 118 } 119 120 if (!anyDeleted) { 121 System.out.println("No database files found at: " + dbPath.getAbsolutePath()); 122 } else { 123 System.out.println("Database cleared successfully."); 124 } 125 126 return 0; 127 } 128 129 /** 130 * Checks if the log server is running by attempting to connect to the HTTP info endpoint. 131 * 132 * @return true if log server is running 133 */ 134 private boolean isLogServerRunning() { 135 try { 136 URL url = new URL("http://localhost:" + httpPort + "/info"); 137 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 138 conn.setRequestMethod("GET"); 139 conn.setConnectTimeout(1000); 140 conn.setReadTimeout(1000); 141 int responseCode = conn.getResponseCode(); 142 conn.disconnect(); 143 return responseCode == 200; 144 } catch (IOException e) { 145 // Connection failed, server is not running 146 return false; 147 } 148 } 149}