content: /* The contents of this file are subject to the terms
   * of the Common Development and Distribution License
   * (the License). You may not use this file except in
   * compliance with the License.
   *
   * You can obtain a copy of the License at
   * http://www.sun.com/cddl/cddl.html or
   * install_dir/legal/LICENSE
   * See the License for the specific language governing
   * permission and limitations under the License.
   *
   * When distributing Covered Code, include this CDDL
   * Header Notice in each file and include the License file
   * at install_dir/legal/LICENSE.
   * If applicable, add the following below the CDDL Header,
   * with the fields enclosed by brackets [] replaced by
   * your own identifying information:
   * "Portions Copyrighted [year] [name of copyright owner]"
   *
   * $Id$
   *
   * Copyright 2005-2009 Sun Microsystems Inc. All Rights Reserved
   */
  package com.sun.faban.harness.agent;
  
  import com.sun.faban.harness.common.Config;
  import com.sun.faban.harness.util.FileHelper;
  import com.sun.faban.common.FileTransfer;
  import com.sun.faban.common.Utilities;
  
  import java.io.*;
  import java.net.InetAddress;
  import java.rmi.Naming;
  import java.rmi.RMISecurityManager;
  import java.rmi.RemoteException;
  import java.rmi.server.UnicastRemoteObject;
  import java.util.logging.Logger;
  import java.util.Properties;
  
  
  /**
   * This is the class that reads/writes files for remote objects.
   *
   * @author Ramesh Ramachandran
   * @see com.sun.faban.harness.agent.FileAgent
   */
  public class FileAgentImpl extends UnicastRemoteObject
          implements FileAgent {
  
      private Logger logger;
  
      /**
       * Constructs the file agent.
       * @throws RemoteException A communications error occurred.
       */
      public FileAgentImpl() throws RemoteException {
          super();
          logger = Logger.getLogger(this.getClass().getName());
      }
  
      /**
       *
       * This method creates a new FileServiceImpl object and returns a 
       * reference to its interface, FileService. The caller can then use it
       * to read or write from/to the file.
       *
       * @param file - The pathname for the file.
       * @param mode - specifies whether the file is opened for reading or
       *                   for writing. The mode is specified by the FileAgent
       *                   interface class variables - READ, WRITE, APPEND.
       * @return FileService - reference to the FileService interface.
       * @throws RemoteException A communications error occurred.
       * @throws FileServiceException Error opening file
       */
      public FileService open(String file, int mode)
              throws RemoteException, FileServiceException {
          return(new FileServiceImpl(Utilities.convertPath(file), mode));
      }
  
      /**
       *
       * Read the contents of a file. It maybe called by the benchmark specific 
       * code or the RunQ to copy files.
       * @param file - The pathname for the file
       * @return String - Contents of the file as a String object
       * @throws IOException An I/O error occurred
       */
      public String readWholeFile(String file) throws IOException {
  
          BufferedReader br;
          char[] buf = new char[65535];
          StringBuffer strBuf = new StringBuffer();
          int cnt;
  
          logger.fine("FileAgentImpl:readWholefile() reading " + file);
          try {
              br = new BufferedReader(new FileReader(file));
  
              while (true) {
                  cnt = br.read(buf, 0, 65535);
                  if (cnt == -1)
                      break;
                  if (cnt > 0) {
                      strBuf.append(buf, 0, cnt);
                  }
              }
          }
          catch (FileNotFoundException e1)
          {
              FileNotFoundException e2 =
                      new FileNotFoundException("FileAgentImpl:readWholeFile " +
                      e1.getMessage());
              throw e2;
          }
          catch (IOException e1)
          {
              IOException e2 = new IOException("FileAgentImpl:readWholeFile " +
                      e1.getMessage());
              throw e2;
          }
          String s = strBuf.toString();
          return s;
      }
  
  
      /**
       * Gets a property from a given file.
       * @param configFile The config file name
       * @param propName The property key name
       * @return The property value
       * @throws IOException If there is an error accessing the config file
       */
      public String getProperty(String configFile, String propName) 
              throws IOException {
          Properties p = new Properties();
          FileInputStream cfgStream = new FileInputStream(configFile);
          p.load(cfgStream);
          cfgStream.close();
          return p.getProperty(propName);
      }
  
  
      /**
       *
       * Write contents to a file. It maybe called by the benchmark specific 
       * code or the RunQ to copy files.
       *
       * @param fileName - The pathname for the file.
       * @param contents - Contents of the file as a String object.
       * @return boolean - true if successful, false if not.
       */
      public boolean writeWholeFile(String fileName, String contents) {
  
          PrintWriter pr = null;
          try {
              pr = new PrintWriter(new FileWriter(Config.TMP_DIR + "fa.log"));
          }
          catch (IOException ie) {
              return false;
          }
          try {
              pr.println("In writeWholeFile");
              pr.flush();
              pr.println("filename = " + fileName);
              pr.flush();
              pr.println("\ncontents = \n" + contents);
              pr.flush();
              logger.fine("FileAgentImpl:writeWholeFile() writing " + fileName);
              PrintWriter out = null;
  
              try {
                  out = new PrintWriter(new FileWriter(fileName));
                  pr.println("dasdasd\n");
                  pr.flush();
                  if (out == null) {
                      return false;
                  }
                  out.println(contents);
                  out.flush();
              }  catch (IOException ioe) {}
  
              return (!out.checkError());
          }
          catch (NullPointerException npe) {
              return false;
          }
      }
  
      /**
       *
       * Removes a file.
       *
       * @param fileName - The pathname for the file.
       * @return boolean - true if successful,
       *                   false if not successful or file does not exist.
       */
      public boolean removeFile(String fileName) {
          fileName = Utilities.convertPath(fileName);
          File file = new File(fileName);
  
          if (file.exists()) {
              return file.delete();
          }
          return false;
      }
  
      /**
       * Truncates a file to zero-length.
       *
       * @param fileName The pathname for the file
       * @return Whether truncation succeeded
       */
      public boolean truncateFile(String fileName) {
          fileName = Utilities.convertPath(fileName);
          File file = new File(fileName);
          boolean retVal = false;
  
          if (file.exists()) {
              try {
                  RandomAccessFile raf = new RandomAccessFile(file, "rw");
                  raf.setLength(0);
                  raf.close();
                  retVal = true;
              } catch (IOException e) {
                  // Do nothing, returns false
              }
          }
          return retVal;
      }
  
      /**
       * Remove files from a directory matched by the filter.
       * @param dirName The directory path name
       * @param filter The filter
       * @return True if files are successfully removed. False otherwise
       */
      public boolean removeFiles(String dirName, 
                                 com.sun.faban.harness.FileFilter filter) {
          dirName = Utilities.convertPath(dirName);
          return FileHelper.delete(new File(dirName), filter);
      }
  
      /**
       * Checks whether the given remote file exists.
       *
       * @param fileName The file name to test.
       * @return true if exists, false otherwise.
       */
      public boolean doesFileExist(String fileName) {
          fileName = Utilities.convertPath(fileName);
          File file = new File(fileName);
          return file.exists();
      }
  
      /**
       * Checks whether the given remote file exists and is a normal file.
       *
       * @param fileName The file name to test.
       * @return true if file is a normal file, false otherwise.
       */
      public boolean isFile(String fileName) {
          fileName = Utilities.convertPath(fileName);
          File file = new File(fileName);
          return file.isFile();
      }
  
      /**
       * Checks whether the given remote file exists and is a directory.
       *
       * @param fileName The file name to test.
       * @return true if file is a directory, false otherwise.
       */
      public boolean isDirectory(String fileName) {
          fileName = Utilities.convertPath(fileName);
          File file = new File(fileName);
          return file.isDirectory();
      }
  
      /**
       * Pushes a file, as encapsulated in the FileTransfer, from a the master
       * to this agent. The serialization of the FileTransfer causes the file
       * to be copied from src to dest over the wire.
       *
       * @param transfer The file transfer description
       * @return The number of bytes transferred
       * @throws java.rmi.RemoteException If there is an error in the transfer
       */
      public long push(FileTransfer transfer) throws RemoteException {
          // This is all we need to do. The copy itself happens in
          // FileTransfer.writeObject and FileTransfer.readObject.
          // This is the most memory-efficient way to transfer large
          // files over RMI.
          logger.fine("Received " + transfer.getSource() + "->" +
                      transfer.getDest() + ", " +
                      transfer.getTransferSize() + " out of " +
                      transfer.getSize() + " bytes");
          return transfer.getSize();
      }
  
      /**
       * Gets a file from the local system to the master. The serialization of
       * the FileTransfer itself causes the file to be copied to the master.
       *
       * @param srcFile  The source file on the host the agent is running on
       * @param destFile The destination file on the master
       * @return The FileTransfer causing this transfer
       * @throws RemoteException If there is an error reading or transferring
       */
      public FileTransfer get(String srcFile, String destFile)
              throws IOException {
          // Copying happens in FileTransfer.writeObject and
          // FileTransfer.readObject. This is the most memory-efficient way
          // to transfer large files over RMI.
          srcFile = Utilities.convertPath(srcFile);
          FileTransfer t = new FileTransfer(srcFile, destFile);
          logger.fine("Transferring " + t.getSource() + "->" + t.getDest() +
                      " size " + t.getTransferSize() + " bytes.");
          return t;
      }
  
      // Registration for RMI serving - used only for stand-alone testing.
  
      /**
       * Starts a standalong file agent.
       * @param argv Command line arguments, not used
       */
      public static void main(String [] argv) {
  
          //		LocateRegistry.createRegistry();
          System.setSecurityManager (new RMISecurityManager());
  
          try {
              FileAgentImpl log = new FileAgentImpl();
              System.out.println("FileAgentImpl object created");
              String host = (InetAddress.getLocalHost()).getHostName();
              String s = "//" + host  + "/FileAgent";
              System.out.println("Calling rebind on " + s);
              Naming.rebind(s , log);
              System.out.println("FileAgent started on machine " + host);
          } catch(Exception e) {
              e.printStackTrace();
              System.exit(-1);
          }
      }
  }
  