Create random files with random content with Java

I was playing with DAOS in Domino 12 recently and needed a way to create thousands of test files with a given file size and random content.

I did not want to use existing files with real data for my tests. There are several programs available for Linux and Windows. Google for it. But as a developer, I should be able to create my one tool.

Here is some sample Java code that uses java.util.Random to create filnames and content in an easy way.

package de.eknori;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;

public class DummyFileCreator {
	static int filesize = 129 * 1024;
	static int count = 9500;

	static File dir = new File("c:\\temp\\dummy\\");
	static String ext = ".txt";

	public static void main(String[] args) {
		byte[] bytes = new byte[filesize];
		BufferedOutputStream bos = null;
		FileOutputStream fos = null;

		try {
			for (int i = 0; i < count; i++) {
				Random rand = new Random();

				String name = String.format("%s%s", System.currentTimeMillis(), rand.nextInt(100000) + ext);
				File file = new File(dir, name);

				fos = new FileOutputStream(file);
				bos = new BufferedOutputStream(fos);

				rand.nextBytes(bytes);
				bos.write(bytes);

				bos.flush();
				bos.close();
				fos.flush();
				fos.close();
			}

		} catch (FileNotFoundException fnfe) {
			System.out.println("File not found" + fnfe);
		} catch (IOException ioe) {
			System.out.println("Error while writing to file" + ioe);
		} finally {
			try {
				if (bos != null) {
					bos.flush();
					bos.close();
				}
				if (fos != null) {
					fos.flush();
					fos.close();
				}
			} catch (Exception e) {
				System.out.println("Error while closing streams" + e);
			}
		}
	}

}

The code is self-explanatory. Adjust the variables to your own needs, and you are ready to go


Gradle – Execution failed for task ‘clean’. Unable to delete file

I am using Gradle to build my Java projects. This works well on a Mac, but the build process fails on a Windows machine, when the task clean is going to be executed.

Task :clean FAILED
FAILURE: Build failed with an exception.
What went wrong:
Execution failed for task ':clean'.
Unable to delete file: C:\0.GIT\travelerrules-dots\de.midpoints.travelerrules.dots\build\unpuzzle_temp\maven-ant-tasks-2.1.4-SNAPSHOT

The jar file is build when I omit the clean task, but I always wanted the build process to to all the build steps on Windows and on the Mac. I never found a good solution, and also upgrading Gradle did not solve the problem.

Today, I found at least a workaround. Run the following command from the Windows command prompt.

TASKKILL /F /IM java.exe

now you can use

gradle cleanEclipse eclipse clean build

without any issues.


DAOS – JAR files in Java agents.

Martin Vogel from sirius-net GmbH informed me in an email about a possible problem with DAOS and Java agents.

If DAOS is activated on a database, in addition to the attachments from data documents, the jar files contained in a Java agent are also transferred to the DAOS repository if they exceed the set size.

I have been able to reproduce the problem with Domino V11.
I started with a freshly installed server, activated DAOS on the server

and enabled the database for DAOS.

load compact -c -DAOS ON barcode.nsf
[0B1C:0004-2C3C] 23.01.2020 18:26:48   Informational, DAOS has been enabled for database barcode.nsf.
[0B1C:0004-2C3C] 23.01.2020 18:26:48   Compacting barcode.nsf (barcode),  -c -DAOS ON barcode.nsf
[0B1C:0004-2C3C] 23.01.2020 18:26:48   Recovery Manager: Assigning new DBIID for C:\Domino\Data\barcode.nsf (need new backup for media recovery).
[0B1C:0004-2C3C] Clearing DBIID 5B9C3856 for DB C:\Domino\Data\barcode.ORIG
[0B1C:0004-2C3C] 23.01.2020 18:26:49   Compacted  barcode.nsf, 5K bytes recovered (<1%),  -c -DAOS ON barcode.nsf
[0B1C:0002-2F14] 23.01.2020 18:26:50   Database compactor process shutdown 

Result: Both archive files contained in the agent were transferred to the DAOS repository as NLO.

The agent continues to run without any issue.


AutoPopulateGroup – Scheduled Agent

In yesterdays post about how to automatically populate a group document, I published code to do the job in the foreground only. One of my blog readers complained about this. Maybe I was to naive to think that even an unexperienced java developer like me could modify the given code to run on a scheduled basis on the server.

Well, here is the code for an scheduled agent.

import lotus.domino.*;
import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;
import java.util.Vector; 

public class LDAPSearchWithFilter extends AgentBase { 

	private static String fldMembers = "Members";

    	public void NotesMain() { 

    	try {
        	Database _db;
        	Document _doc;
        	Session session = getSession();
        	AgentContext agentContext = session.getAgentContext();
        	_db = agentContext.getCurrentDatabase(); 

        	Agent ag1 = agentContext.getCurrentAgent(); 

        	String ldapCF = "com.sun.jndi.ldap.LdapCtxFactory";
        	String ldapURL = "ldap://localhost:389/";
        	String ldapBaseDN = "";
        	String ldapUserID = "";
        	String ldapPassword = ""; 

        	Hashtable env = new Hashtable(4);
        	env.put(Context.INITIAL_CONTEXT_FACTORY, ldapCF);
        	env.put(Context.PROVIDER_URL, ldapURL + ldapBaseDN);
        	env.put(Context.SECURITY_PRINCIPAL, ldapUserID);
        	env.put(Context.SECURITY_CREDENTIALS, ldapPassword); 

      	DocumentCollection _dc = _db.getAllDocuments();
      	Document doc = _dc.getFirstDocument();

      	while (doc != null) {
        	String searchCriteria = doc.getItemValueString("SelectionCriteria");
        	DirContext ctx = new InitialDirContext(env);
        	SearchControls ctls = new SearchControls();
		NamingEnumeration answer = ctx.search("", searchCriteria, ctls);
		PopulateGroup (answer, doc);
     		ctx.close();
        	doc = _dc.getNextDocument();
		} // end of while
	  } // end of try
		catch (Exception e) {
    		e.printStackTrace(); }
	} // end of Main 

	public static void PopulateGroup(NamingEnumeration col, Document doc) { 

    	try {
    	Item item = doc.getFirstItem(fldMembers);
    	Vector v = new Vector();
    	String result;
	if (col.hasMore()) {
        	while (col.hasMore()) {
            	  SearchResult sr = (SearchResult)col.next();
            	  result = (String)sr.getName();
                  v.addElement(result.replace(',','/'));
           	} // end of while
		  doc.replaceItemValue(fldMembers, v);
    		  doc.save(true);
		} // end of if
    	} // end of try
	catch (NamingException e) {
    		e.printStackTrace(); }
	catch (Exception e) {
    		e.printStackTrace(); }
	} // end of PopulateGroup
} // end of class

AutoPopulateGroup (If You Do Not Run Domino 8.5)

A few days ago, I wrote about a new feature of Domino 8.5 to automatically populate groups via a LDAP selectioncriteria. This is a great feature and I have successfully tested it on my sandbox server.
Since we run Domino 8.0.1 on our productive servers, we cannot use this very useful feature. …

But, with a few lines of JAVA and Lotusscript code, you can build your own solution to auto populate groups. Here is what I came out with.

I’ve created a subform with two fields and a button.

  • HiddenMembers, Text, hidden
  • SelectionCriteria, Text, editable

The “Populate Group” button contains the following code

'/* Declaration
Const fldMEMBERS = "Members"
Const fldHIDDEN = "HiddenMembers"
Const agntDOLDAP = "AutoPopulateGroup"

Sub Click(Source As Button)
	Dim s As New NotesSession
	Dim ws As New NotesUIWorkspace
	Dim db As NotesDatabase
	Dim agent As NotesAgent
	Dim doc As NotesDocument
	Dim uidoc As NotesUIDocument
	Dim searchResultItem As NotesItem
	Dim paramid As String 

	Set db = s.CurrentDatabase
	Set uidoc = ws.CurrentDocument
	Set doc = uidoc.Document
	Set agent = db.GetAgent(agntDOLDAP)
	Call doc.save(True, False)
	paramid = doc.NoteID
	Call agent.RunOnServer(paramid)
	Delete doc
	Set doc = db.GetDocumentByID(paramid) 

	Set searchResultItem = doc.getFirstItem(fldHIDDEN)
	Call uidoc.FieldSettext( fldMEMBERS,  "")
	Forall values In searchResultItem.Values
		Call uidoc.FieldAppendText(fldMEMBERS,  values)
		Call uidoc.FieldAppendText(fldMEMBERS, Chr(10))
	End Forall
	Call uidoc.Refresh
	doc.Remove(True)
End Sub

Like in Domino 8.5 you’ll have to run LDAP on your server. To access LDAP and do a search according to the SelectionCriteria, you need an agent with the following piece of Java code.

import lotus.domino.*;
import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;
import java.util.Vector; 

public class LDAPSearchWithFilter extends AgentBase { 

	private static String fldTmpMembers = "HiddenMembers";

    	public void NotesMain() { 

    	try {
        Database _db;
        Document _doc;
        Session session = getSession();
        AgentContext agentContext = session.getAgentContext();
        _db = agentContext.getCurrentDatabase(); 

        Agent ag1 = agentContext.getCurrentAgent();
        String paramid = ag1.getParameterDocID();
        Document doc = _db.getDocumentByID(paramid); 

        String searchCriteria = doc.getItemValueString("SelectionCriteria"); 

        String ldapCF = "com.sun.jndi.ldap.LdapCtxFactory";
        String ldapURL = "ldap://localhost:389/";
        String ldapBaseDN = "";
        String ldapUserID = "";
        String ldapPassword = ""; 

        Hashtable env = new Hashtable(4);
        env.put(Context.INITIAL_CONTEXT_FACTORY, ldapCF);
        env.put(Context.PROVIDER_URL, ldapURL + ldapBaseDN);
        env.put(Context.SECURITY_PRINCIPAL, ldapUserID);
        env.put(Context.SECURITY_CREDENTIALS, ldapPassword); 

    try {
       	DirContext ctx = new InitialDirContext(env);
        	SearchControls ctls = new SearchControls();
		NamingEnumeration answer = ctx.search("", searchCriteria, ctls);
		PopulateGroup (answer, doc);
        	ctx.close(); 

	    		} catch(NamingException e) {
     	   		e.printStackTrace();
    		} 

	    } catch (Exception e) {
    		e.printStackTrace();
    }
} // end of Main 

public static void PopulateGroup(NamingEnumeration col, Document doc) { 

    try {
    Item item = doc.getFirstItem(fldTmpMembers);
    Vector v = new Vector();
    String result;    

	if (col.hasMore()) { 

        		while (col.hasMore()) {
            		SearchResult sr = (SearchResult)col.next();
            		result = (String)sr.getName();
                	v.addElement(result.replace(',','/'));
           	} // end of while

			doc.replaceItemValue(fldTmpMembers, v);
    			doc.save(true);
		}
    }
	catch (NamingException e) {
    		e.printStackTrace();
    		} catch (Exception e) {
    			e.printStackTrace();
    			}
	} // end of PopulateGroup
} // end of class

Set the agent’s runtime security to “2”, to allow restricted operations. When you have all code in place, you can test the function by typing a selection criteria and clicking the button.

The members field in your form should now show all persons that have “serv01” as their mailserver.

Download sample database