/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.activemq.artemis.cli.commands.tools;

import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;

import org.apache.activemq.artemis.cli.CLIException;
import org.apache.activemq.artemis.cli.commands.Action;
import org.apache.activemq.artemis.cli.commands.ActionContext;

public abstract class LockAbstract extends DataAbstract implements Action {

   // There should be one lock per VM
   // These will be locked as long as the VM is running
   private static RandomAccessFile serverLockFile = null;
   private static FileLock serverLockLock = null;

   protected File getLockPlace() throws Exception {
      String brokerInstance = getBrokerInstance();
      if (brokerInstance != null) {
         return new File(new File(brokerInstance), "lock");
      } else {
         return null;
      }
   }

   public static void unlock() {
      try {
         if (serverLockFile != null) {
            serverLockFile.close();
            serverLockFile = null;
         }

         if (serverLockLock != null) {
            serverLockLock.close();
            serverLockLock = null;
         }
      } catch (Exception ignored) {
      }
   }

   @Override
   public Object execute(ActionContext context) throws Exception {
      super.execute(context);

      if (getBrokerInstance() == null) {
         System.err.println("Warning: You are running a data tool outside of any broker instance. Modifying data on a running server might break the server's data");
         System.err.println();
      } else {
         lockCLI(getLockPlace());
      }

      return null;
   }

   protected void lockCLI(File lockPlace) throws Exception {
      if (lockPlace != null) {
         lockPlace.mkdirs();
         if (serverLockFile == null) {
            File fileLock = new File(lockPlace, "cli.lock");
            serverLockFile = new RandomAccessFile(fileLock, "rw");
         }
         try {
            FileLock lock = serverLockFile.getChannel().tryLock();
            if (lock == null) {
               throw new CLIException("Error: There is another process using the server at " + lockPlace + ". Cannot start the process!");
            }
            serverLockLock = lock;
         } catch (OverlappingFileLockException e) {
            throw new CLIException("Error: There is another process using the server at " + lockPlace + ". Cannot start the process!");
         }
      }
   }

}
