Skip to Content
Technical Articles
Author's profile photo Shawn Penner

How to Remove all Orphaned Files from the Input and Output FRS


This sample will delete files from your Input and Output FRS.  It is strongly recommended that you make a backup of your FRS before running it.

Also – you MUST run this sample with an administrator user.   It detects orphaned objects by querying for them.  If the user you run it with is not the administrator – they it may not have rights to see the object and it will delete the associated file.

EXTRA NOTE: Due to how objects in the recycle bin are handled by Enterprise, this sample will not detect recycled objects as valid and will delete the associated files.  It is strongly recommended that you empty the recycle bin before running the sample.


How It Works

This sample recursively loops through all directories in the Input and Output FRS.  When it finds a file, it assumes that the name of the folder it is contained in is the SI_ID of the associated object.  It then queries the Enterprise server for any object with the same SI_ID.  If one does not exist, it then deletes all files in the folder and flags the folder for deletion.

This code is designed to work with BI 4.1 and BI 4.2


How to Use It

  1. Copy the code pasted at the bottom of this blog into a jsp page and copy that jsp page into the folder C:\Program Files (x86)\SAP BusinessObjects\tomcat\webapps\AdminTools
  2. Edit the code and change the values in the following section:
    Boolean Run_In_Test_Mode = true; If set to true, it will just list the files it would have deleted, but won’t actually delete them.
    If set to false, it will list the files and actually delete it.  By default this is set to true.

    Note: true and false are Case Sensitive.  You must use the values of “true” or “false”.  Do not use “True” or “False”

    String pathToInputFRS = “C:\\Program Files (x86)\\SAP BusinessObjects\\SAP BusinessObjects Enterprise XI 4.0\\FileStore\\Input”;
    String pathToOutputFRS = “C:\\Program Files (x86)\\SAP BusinessObjects\\SAP BusinessObjects Enterprise XI 4.0\\FileStore\\Output”;

    This is the path to the FRS folders.  Because this is java, all slashes must be double slashes and there should not be a slash at the end of the file path.

    String fileToLogTo = “C:\\Program Files (x86)\\SAP BusinessObjects\\tomcat\\webapps\\AdminTools\\TestOutput.txt”;

    This is the path and filename of the logging file it will create.  If the file already exists, it will append the new logs to the end.  It will not over-write the log file.

    // User Credentials
    String username = “Administrator”;
    String password = “Password1”;
    String cmsname = “localhost”;
    String authType = “secEnterprise”;

    The logon credentials for the Enterprise server.  You MUST use the Administrator user for this.  The script requires the ability to verify if an object exists.  If the account does not have the rights to see the object, it will assume it does not exist and delete it.

  3. Open up a browser and go to http://myserver:8080/AdminTools/scanFRS.jsp


The Code

<%@ page import = "com.crystaldecisions.sdk.exception.SDKException,

// ------------------------------
// How to use:
// Copy this jsp page into the folder C:\Program Files (x86)\SAP BusinessObjects\tomcat\webapps\AdminTools
// Modify the User Credentials Section to appropriate logon credentials for your system
// change fileToLogTo to whatever desired path you want the log file to be written to.  The default is in the AdminTools folder referenced above
// Change pathToInputFRS and pathToOutputFRS to the location of your Input and Output FRS
// If you set Run_In_Test_Mode to true this sample will run in Demo mode and will not delete files
// If you set Run_In_Test_Mode to false this sample will run in delete mode and will delete files
// Run this by opening a new browser and going to http://myServer:8080/AdminTools/scanFRS.jsp
// ------------------------------

Boolean Run_In_Test_Mode = true;    // true = demo mode  false = delete mode
String pathToInputFRS = "C:\\Program Files (x86)\\SAP BusinessObjects\\SAP BusinessObjects Enterprise XI 4.0\\FileStore\\Input";
String pathToOutputFRS = "C:\\Program Files (x86)\\SAP BusinessObjects\\SAP BusinessObjects Enterprise XI 4.0\\FileStore\\Output";
String fileToLogTo = "C:\\Program Files (x86)\\SAP BusinessObjects\\tomcat\\webapps\\AdminTools\\TestOutput.txt";

// User Credentials
String username = "Administrator";
String password = "Password1";
String cmsname  = "localhost";
String authType = "secEnterprise";

IEnterpriseSession enterpriseSession  = null;
IInfoStore boInfoStore;
enterpriseSession = CrystalEnterprise.getSessionMgr().logon(username, password, cmsname, authType);
boInfoStore = (IInfoStore)enterpriseSession.getService("", "InfoStore");

out.println("Starting </BR>");
writeToLog("Starting Sample", fileToLogTo);

// The logic used is:
// - Is there a file?  If not, is there a sub-folder.
// - If there is a sub-folder - then go into it
// - If there is a file - then look at the last folder name - that will be the SI_ID
// - Check if an object with that SI_ID exists.  If it does - all is well - if not - flag for deletion
// - The deletion will go up folder by folder until one of three conditions occur.  
// - 1. A file exists in the folder.
// - 2. More than 1 sub-folder
// - 3. The name of the current folder is either Input, or Output

Boolean isDoneInput = CheckAndDelete(Run_In_Test_Mode, boInfoStore, fileToLogTo, pathToInputFRS, "Input");
Boolean isDoneOutput = CheckAndDelete(Run_In_Test_Mode, boInfoStore, fileToLogTo, pathToOutputFRS, "Output");

writeToLog("Finished Sample </BR>", fileToLogTo);
out.println("Job Completed");

// Helper Methods
public void writeToLog(String msg, String logFilePath) {
	try {
		// Set up Logging File
		FileOutputStream FSout;
		PrintStream pStream; // declare a print stream object
		FSout = new FileOutputStream(logFilePath, true);  // Append
		pStream = new PrintStream(FSout); 
	} catch (IOException e) {
		//error writing to log

public Boolean CheckAndDelete(Boolean doDelete, IInfoStore boInfoStore, String fileToLogTo, String currentFolderPath, String currentFolderName) {

// Loop through all the files / subdirectories in the current directory
int subDirCount = 0;
Boolean isOrphan = false;
Boolean checkFiles = false;

try {

	File currentDir = new File(currentFolderPath);
	File[] listFiles = currentDir.listFiles();
	for (File file : listFiles) 
		// Is this a sub-directory
		if (file.isDirectory()) 
			// Do the recursive check into the directory.  If it returns true, then the sub-folder is now clear and can be deleted.
			if (CheckAndDelete(doDelete, boInfoStore, fileToLogTo, file.getCanonicalPath(), file.getName()) == true) {
				// Are we in demo mode
				if (doDelete == false) {
			} else {
				// Have we already checked the files for this directory.
				if (checkFiles == false) {
					// Since there are files - that means this is an infoobject and we need to check it.
					// The current directory name is the SI_ID of the infoobject, so query for that.
					IInfoObjects boInfoObjects = (IInfoObjects)boInfoStore.query("Select * from CI_INFOOBJECTS, CI_APPOBJECTS, CI_SYSTEMOBJECTS where SI_ID = " + currentFolderName);
					// Did we get a result
					if (boInfoObjects.size() == 0) {
						isOrphan = true;
					// We have already checked this object - no need to check it again.
					checkFiles = true;
				// If we verified that this is an orphan - delete the file
				if (isOrphan == true) {
					writeToLog("Deleting file " + file.getCanonicalPath() + " from Orphaned Infoobject with SI_ID " + currentFolderName, fileToLogTo);
					// Are we in demo mode
					if (doDelete == false) {
	} catch (IOException e) {
	} catch (SDKException ex) {
return (isOrphan);

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Scott Frisby
      Scott Frisby

      Somehow some of our FileStores got way out of hand. I reduced one from 79 GB to 12 GB with this script. Thank you so much!