/* 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);
}
}
}