Hi,

I would like to expose you a simple example of interaction with the IRM server in order to encrypt and apply the IRM security on CONTENT files of a document. The IRM configuration is out of scope of this article.
 
 
IRM
Briefly, EMC Documentum Information Rights Management (IRM): Unauthorized access prevention to secured content, enabling organizations to maintain control of information rights beyond the firewall.

  • current version 5.1 SP2,
     
  • IRM solution needs a distinct server with specific installation (1 DB, DFS Web service, load balancer, 2 instances IRM,…).
     
  • To view and interact with IRM, there are several local clients like IRM Client For PDF, IRM Client For Microsoft Office. These clients interact with IRM server when a document is IRMised and with locale tools like WORD, EXCEL, PDF READER..etc.
     
  • To administrate manage the IRM server, there is IRM Adminstration Client tool.
     
  • In DCTM side, in Content server, there are some objects configured for IRM. These elements are also accessible in DA under the node:
    [DOCBASE node]
    |- Rights Management
    |- IRM Profiles
    |- IRM Servers

    select * from irm_profile;
    080xxxxxa0	IRMDEV
    080xxxxx30	IRMConnector
    select * from irm_server; 
    080xxxxxa5	MYIRMSERVER
    select * from irm_expiration;
  • The IRM profile precise only the server to use for IRMisation.
     
  • The security is managed on document via ACL and IRM permission available when a document is IRMised. So, in ACL, it is possible to manage the IRM permission in the [-] Grant IRM Permissions section:
    o Print (irm_print) : Allow users to print content
    o Copy (irm_copy) : Allow users to copy content
    o Take Offline (irm_offline) : Allow access to content when disconnected
    o View Activity (irm_activity) : Allow users to view IRM activity log
    o [LIST_WATERMARK] (irm_wmXXXXXXX) : Watermark to display on protected document. EX: default, watermark_dev, XXXXX => irm_wmdefault, irm_wmwatermark_dev, irm_wmXXXXX
     
  • The IRM permissions are set via an ApplicationPermit entry in the ACL in the “r_application_permit”, “r_permit_type = 2” fields. Reminder:
    o ApplicationPermit (2): An ApplicationPermit entry identifies a user or group and a user-defined permission level granted to that user or group.
    o Application permits are interpreted only by user applications. Content Server does not enforce application permits.

    It is possible to set an IRM Permission (any myacl.r_application_permit like ‘%irm_%’) in a document not-IRMised (NOT any mydoc.r_aspect_name = ‘irm_document_aspect’). However, the IRM permissions apply only if the document is IRMised. For example:
    o Ex 1 : document IRMISED WITH irm_print ==> PRINT POSSIBLE
    o Ex 2 : document IRMISED WITHOUT irm_print ==> PRINT NOT POSSIBLE
    o Ex 3 : document NOT IRMISED WITH irm_print ==> PRINT POSSIBLE
    o Ex 4 : document NOT IRMISED WITHOUT irm_print ==> PRINT POSSIBLE because the document is not IRMISED

    Here, an example of ACL modification:

    ################ Transaction for 45xxxxxxxxxx104
    begintran,c
    #
    retrieve,c,dm_acl where r_object_id='45xxxxxxxxxx104'
    grant,c,l,group_printing,ApplicationPermit,,irm_actions:irm_print;irm_wmdefault
    save,c,l
    #
    commit,c
    

    …results of ACL PST using the IRM Permissions (via r_application_permit):

      r_object_id                : 45xxxxxxxxxx104
      object_name                : MY_PST
      description                : My Acl for documents
      acl_class                  : 1
      r_accessor_name
            [ 0]: dm_world
            [ 1]: dm_owner
            [ 2]: %Responsible
            [ 3]: admins
            [ 4]: %Responsible
            [ 5]: user - irm_print
            [ 6]: user - irm_activity
            [ 7]: user - irm_watermark - default
            [ 8]: technical users
            [ 9]: all
            [10]: %Manager
            [11]: %Manager
    	...
            [27]: %ReaderRestrictAccess
    	...
            [37]: group_printing
    
      r_accessor_permit
            [ 0]: 1
            [ 1]: 7
            [ 2]: 4
            [ 3]: 4
            [ 4]: 0
            [ 5]: 0
            [ 6]: 0
            [ 7]: 0
            [ 8]: 0
            [ 9]: 0
            [10]: 4
            [11]: 0
    	...
            [27]: 5
    	...
            [37]: 0
    
      r_accessor_xpermit
            [ 0]: 3
            [ 1]: 131073
            [ 2]: 3
            [ 3]: 3
            [ 4]: 0
            [ 5]: 0
            [ 6]: 0
            [ 7]: 0
            [ 8]: 0
            [ 9]: 0
            [10]: 3
            [11]: 0
    	...
            [27]: 0
    	...
            [37]: 0
    
      r_permit_type
            [ 0]: 0	=> AccessPermit (0)
            [ 1]: 0	=> AccessPermit (0)
            [ 2]: 0	=> AccessPermit (0)
            [ 3]: 0	=> AccessPermit (0)
            [ 4]: 2	=> ApplicationPermit (2)	=> See r_application_permit
            [ 5]: 2	=> ApplicationPermit (2)	=> See r_application_permit
            [ 6]: 2	=> ApplicationPermit (2)	=> See r_application_permit
            [ 7]: 2	=> ApplicationPermit (2)	=> See r_application_permit
            [ 8]: 7	=> RequiredGroupSet (7)
            [ 9]: 7	=> RequiredGroupSet (7)
            [10]: 0	=> AccessPermit (0)
            [11]: 2	=> ApplicationPermit (2)	=> See r_application_permit
    	...
            [27]: 3	=> AccessRestriction (3)
    	...
            [37]: 2	=> ApplicationPermit (2)	=> See r_application_permit
    
      r_application_permit
            [ 0]: 
            [ 1]: 
            [ 2]: 
            [ 3]: 
            [ 4]: irm_actions:irm_wmdefault
            [ 5]: irm_actions:irm_print
            [ 6]: irm_actions:irm_activity
            [ 7]: irm_actions:irm_wmdefault
            [ 8]: 
            [ 9]: 
            [10]: 
            [11]: irm_actions:irm_wmdefault
    	...
            [27]: 
    	...
    	[37]: irm_actions:irm_print
    

     

  • The security is also managed on IRM server document for example, it is possible to restrict all documents to nobody can print document. This security overwrites the document security.
     
  • An user who has the READ (or WRITE) basic permission in DCTM, will have the same READ (or WRITE) permission in IRM.
     
  • The R_MODIFIER and R_MODIFY_DATE are overridden:
    BEFORE IRMisation of CONTENT : i_vstamp=14 - r_modify_date=08/06/2015 11:28:31
    AFTER IRMisation of CONTENT : i_vstamp=15 - r_modify_date=01/12/2016 11:40:58
    
  • When a document has been secured via IRM, the irm_document_aspect is attached to this document,
     
  • When a document has been secured via IRM, a new format is associated irm-***** to this document => see the dm_format table:
    select * from dm_format where LOWER(name) like 'irm-%';
    irm-excel12book	IRM-protected MS Excel 2007
    irm-excel8book	IRM-protected MS Excel 8.0-2003 (Windows)
    irm-msw12	IRM-protected MS Word 2007
    irm-msw8	IRM-protected MS Word 8.0-2003 (Windows)
    irm-pdf	IRM-protected Acrobat PDF
    irm-ppt12	IRM-protected MS PowerPoint 2007
    irm-ppt8	IRM-protected MS PowerPoint 8.0-2003 (Windows)
    irm-excel14book	IRM-protected MS Excel 2010
    irm-msw14	IRM-protected MS Word 2010
    irm-ppt14	IRM-protected MS PowerPoint 2010
    
  • The apply of IRM security is done via a SBO service provided by IRM com.documentum.services.irm.IIRMService:
    IDfService irmService = DfClient.getLocalClientEx().newService("com.documentum.services.irm.IIRMService", sessMgr);
    Method method = irmService.getClass().getMethod("setObjectIRMProfile", IDfSession.class, IDfSysObject.class, IDfId.class);
    method.invoke(irmService, targetObject.getObjectSession(), 
    
  • A new dmr_content object is created for the secured content.
     
  • A new dmr_content object can not overwrite directly the previous content.
     
  • The previous dmr_content object (no-secured) is not removed and exists still in the docbase. It becomes unused and unreferenced in dm_document. The execution of standard cleaner “dm_DMClean” “dm_DMFilescan” jobs could remove the object and the file on filestore, howver, these jobs could not remove files from CENTERA.

 
 
LOCAL CONFIG
When, you use IRM on your local development machine, the following actions are necessary:

  • Adding of “emcdctmirm.jar” in the classpath of local project. Otherwise, you obtain the following error:
    29281 [main] ERROR com.documentum.services.irm.impl.irmserver.BaseIRMProxy  - java.lang.ClassNotFoundException: com.emcirm.edsdecrypt.CAPIEDS
     29286 [main] ERROR com.documentum.services.irm.impl.irmserver.PolicyServerConnectionPool  - java.lang.ClassNotFoundException: com.authentica.pvsapi.PVSAPI
     com.documentum.services.irm.impl.irmserver.PolicyServerProxy$PolicyServerException: java.lang.ClassNotFoundException: com.authentica.pvsapi.PVSAPI
  • Adding of a parameter in “VM arguments” of executed class corresponding to the IRM DLL local folders :
    -Djava.library.path="D:\Documentum\DEV\irm;D:\Documentum\DEV\irm\Common"
  • Adding of parameters in “dfc.properties” file:
    dfc.data.dir=C:/Documentum/DEV
  • Creation of new file in classpath for “dctmirm.properties”:
    irm.dir=D\:/Documentum/DEV/irm
    irm.index.enable=false
    irm.connectPool.size=5
    irm.protect.deleteOriginal=true
    irm.log.performance.enable=false
    
  • Installation of IRM Clients:
    C:\Program Files (x86)\EMC IRM:
     * Common
     * IRM Client for Microsoft Office
     * IRM Client For PDF
     * IRM Common
  • If the following error occurs, check the JRE used by your project:
    16:48:29,796 ERROR [main] com.documentum.services.irm.impl.irmserver.BaseIRMProxy - java.lang.UnsatisfiedLinkError: C:\Documentum\DEV\irm\libemcirm_mem.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
    16:48:29,812 ERROR [main] com.documentum.services.irm.impl.irmserver.PolicyServerConnectionPool - java.lang.UnsatisfiedLinkError: com.authentica.pvsapi.PVSConnHandle.nPVSConnHandle()V
    com.documentum.services.irm.impl.irmserver.PolicyServerProxy$PolicyServerException: java.lang.UnsatisfiedLinkError: com.authentica.pvsapi.PVSConnHandle.nPVSConnHandle()V
    	at com.documentum.services.irm.impl.irmserver.PolicyServerProxy$PolicyServerException.throwException(PolicyServerProxy.java:50)
    	at com.documentum.services.irm.impl.irmserver.PolicyServerProxy.newObject(PolicyServerProxy.java:89)
    
  • IRM uses a token in the Registry, so its clients must be update these informations in the CLIENT Registry database with a valid ticket, in case the document is IRM-protected :
    	HKEY_CURRENT_USER
    		+ SOFTWARE
    			+ AUTHENTICA
    				+ RegistrySandbox
    					- DCTMDomainName = mydomain
    					- DCTMLoginToken = DM_TICKET=T0...zMkdnPQo=
    					- DCTMUserName = myuser1
    

 
 
REMOVING IRM

  • The user used to unIRMisation must be in the group irm_decrypt. The users in this group can decrypt the IRMised documents accessible to them.:
    select * from dm_group where group_name = 'irm_decrypt';
    
    select i_all_users_names from dm_group where group_name = 'irm_decrypt';
    # useradm
    # myuser1
    
  • There are several levels of security. The IRM decryption classes are in a signed JAR whose signature is known to the DCTM IRM server. To work around this security, the “home” classes use JAVA introspection. The Java JVM must allow the display of PRIVATE fields that are passed in PUBLIC for power.

 

EXAMPLE : DOC sur FILESTORE = 090xxxxxxx3c

----------------
BEFORE : 
----------------

------ dm_document or sub-type
o a_storage_type             : filestore_01
o r_aspect_name           [0]: my_aspect_java
o r_content_size             : 9401
o r_full_content_size        : 9401
o a_content_type             : excel12book
o i_contents_id              : 060xxxxxxxxxxxxxxc
o i_vstamp                   : 14
o r_modify_date              : 08/06/2014 11:28:31
o r_modifier                 : user1

------ dmr_content or sub-type
o r_object_id                : 060xxxxxxxxxxxxxxc
o content_size               : 9401
o full_format                : excel12book
o format                     : 27xxxxxxxxxxxxx4
o full_content_size          : 9401
o i_format                [0]: 27xxxxxxxxxxxxx4
o i_full_format           [0]: excel12book
o i_vstamp                   : 1

API> getpath,c,090xxxxxxx3c
\\MYFILESERVER\data\MY_DOCBASE_DEV\content_storage_01\000XXXX5\80\02\ef\18.xls

DQL>execute get_path for '060xxxxxxxxxxxxxxc';
\\MYFILESERVER\data\MY_DOCBASE_DEV\content_storage_01\000XXXX5\80\02\ef\18.xls
----------------
AFTER: 
----------------
------ dm_document or sub-type
o a_storage_type             : filestore_01
o r_aspect_name           [0]: my_aspect_java [1]: irm_document_aspect
o r_content_size             : 14848
o r_full_content_size        : 14848
o a_content_type             : irm-excel12book
o i_contents_id              : 06xxxxxxxxxxxxxx1a
o i_vstamp                   : 15
o r_modify_date              : 01/12/2015 11:40:58
o r_modifier                 : user2
  
------ dmr_content or sub-type
o r_object_id                : 06xxxxxxxxxxxxxx1a
o content_size               : 14848
o full_format                : irm-excel12book
o format                     : 270xxxxxxxxxxxx329
o full_content_size          : 14848
o i_format                [0]: 270xxxxxxxxxxxx329
o i_full_format           [0]: irm-excel12book
o i_vstamp                   : 0

API> getpath,c,090xxxxxxx3c
\\MYFILESERVER\data\MY_DOCBASE_DEV\content_storage_01\000XXXX5\80\2a\f3\34.xls

DQL>execute get_path for '06xxxxxxxxxxxxxx1a';
\\MYFILESERVER\data\MY_DOCBASE_DEV\content_storage_01\000XXXX5\80\2a\f3\34.xls

 
Concerning the PREVIOUS dm_content (no-secured):

  • The previous dmr_content object exists still in the docbase:
    SELECT * from dmr_content where r_object_id = '060xxxxxxxxxxxxxxc';
    060xxxxxxxxxxxxxxc	0	0	6dxxxxxxxxxx28	1	0	9401	excel12book
  • The previous dmr_content becomes unused and unreferenced in dm_document:
    SELECT * from dm_sysobject where i_contents_id = '060xxxxxxxxxxxxxxc';
  • EXECUTION of “dm_DMClean” job with parameter “-clean_content TRUE”. Its logs contains:
    Content object 060xxxxxxxxxxxxxxc has parent count of zero.
    apply,c,060xxxxxxxxxxxxxxc,DESTROY_CONTENT
    getmessage,c
    close,c,q0
    ...
    28.626 0.234 N/A [main] com.documentum.dmcl.impl.DmclApiNativeAdapter@727e8a11.get("apply,c,060xxxxxxxxxxxxxxc,DESTROY_CONTENT") ==> "q0" 
    28.860 0.000 N/A [main] com.documentum.dmcl.impl.DmclApiNativeAdapter@727e8a11.exec("close,c,q0") ==> true 
    
  • The previous dmr_content object has been removed from the docbase.
     
  • The file “\\MYFILESERVER\data\MY_DOCBASE_DEV\content_storage_01\000XXXX5\80\02\ef\18.xls” has been deleted from filestore.
     
  • Importante Note: the content file on Storage has also been deleted by the use of “-clean_content TRUE” parameter otherwise it is necessary to execute the job “dm_DMFilescan”.
    The DESTROY_CONTENT administration method is used and removes a content object from the Docbase if the object has no parent_id values. It also removes the content file associated with the content object from its storage area. This administrative function is used by the dmclean utility to clean up storage areas. (Do not use this for archiving; use PURGE_CONTENT instead : PURGE_CONTENT).

    SELECT * from dmr_content where r_object_id = '060xxxxxxxxxxxxxxc';
    
    DQL> execute get_path for '060xxxxxxxxxxxxxxc'
      [DM_CONTENT_E_SECUREWRITE_POPEN]error:  "Error executing the Secure Writer: 060xxxxxxxxxxxxxxc. The popen() operation failed with status (s)."
      [DM_OBJ_MGR_E_FETCH_FAIL]error:  "attempt to fetch object with handle 060xxxxxxxxxxxxxxc failed"
    

 
 
SOURCE CODE APPY IRM
Finally, here the source code test class for applying IRM security:

import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;

import org.apache.commons.lang.exception.ExceptionUtils;

import com.documentum.fc.client.DfClient;
import com.documentum.fc.client.DfQuery;
import com.documentum.fc.client.IDfClient;
import com.documentum.fc.client.IDfCollection;
import com.documentum.fc.client.IDfDocument;
import com.documentum.fc.client.IDfQuery;
import com.documentum.fc.client.IDfService;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSessionManager;
import com.documentum.fc.client.IDfSysObject;
import com.documentum.fc.client.aspect.IDfAspects;
import com.documentum.fc.commands.admin.DfAdminCommand;
import com.documentum.fc.commands.admin.IDfApplyExecSQL;
import com.documentum.fc.common.DfException;
import com.documentum.fc.common.DfId;
import com.documentum.fc.common.DfLoginInfo;
import com.documentum.fc.common.IDfId;
import com.documentum.fc.common.IDfLoginInfo;
import com.documentum.fc.common.IDfTime;
import com.documentum.fc.common.IDfValue;

public class DfcApiApplyIRMSecurityTest {
	IDfSession idfSession = null;
	IDfSessionManager sessMgr = null;

	/**
	 * Constructor
	 */
	public DfcApiApplyIRMSecurityTest(String user, String passwd, String docbase) throws Exception {
		getDfSession(user, passwd, docbase);
	}

	/**
	 * MAIN METHOD
	 */
	public static void main(String[] args) throws Exception {
		long startTime = 0;
		long stopTime = 0;
		
		String user = "useradm";
		String passwd = "passwordOfuseradm";
		String docbase = "MY_DOCBASE_DEV";
		String objectId = "090xxxxxxx2f2";
		String irmProfileName = "IRMConnectorProfile";
		
		DfcApiApplyIRMSecurityTest me = new DfcApiApplyIRMSecurityTest(user, passwd, docbase);
		
		boolean isTransactionalSession = false;
		boolean noErrorWithCurrentDocument = false;
		try {
			if (!me.idfSession.isTransactionActive()) {
				me.idfSession.beginTrans();
				isTransactionalSession = true;
			}

			startTime = System.currentTimeMillis();

			// Examples : irm-excel12book
			List<String> irmFormats = me.getIRMFormats();

			IDfDocument doc = null;
			{
				doc = (IDfDocument)me.idfSession.getObject(new DfId(objectId));
				System.out.println("BEFORE IRMisation of CONTENT : i_vstamp="+doc.getInt("i_vstamp") + " - r_modify_date="+doc.getTime("r_modify_date"));
			}
			
			if(doc instanceof IDfAspects) {
				if(doc.findString("r_aspect_name", "irm_document_aspect")>=0){ // OR IDfList aspectsAttached = ((IDfAspects) doc).getAspects();
					throw new RuntimeException(MessageFormat.format("The document ({0}) has already been IRMised (associated to the \"{1}\" ASPECT)", objectId, "irm_document_aspect"));
				}
			}
			
			IDfTime previousModifyDateTime = doc.getTime("r_modify_date");
			String previousModifier = doc.getString("r_modifier");
			String aContentType = doc.getString("a_content_type"); // excel12book

			boolean isIRMableContentType = false;
			for (Iterator<String> iterator = irmFormats.iterator(); iterator.hasNext() && isIRMableContentType==false;) {
				String currIRMFormat = iterator.next();
				isIRMableContentType = currIRMFormat.equalsIgnoreCase("irm-"+aContentType);
			}//end-for

			if(isIRMableContentType==false){
				throw new RuntimeException("The content type of object ("+aContentType+") is not compliant with IRM!");
			}
			
						
			me.applyIRMSecurity(objectId, irmProfileName);	

			
			{
				doc = (IDfDocument)me.idfSession.getObject(new DfId(objectId));
				System.out.println("AFTER IRMisation of CONTENT : i_vstamp="+doc.getInt("i_vstamp")  + " - r_modify_date="+doc.getTime("r_modify_date"));
			}

			// Setting of the previous value for r_modify_date AND r_modifier because the attachment of aspect needs a SAVE action on document.
			// So, Content server overrides r_modifer and r_modify_date informations. 
			setPreviousValuesOfLastModifAttributesBySQL(objectId, me.idfSession, previousModifyDateTime, previousModifier);

			stopTime = System.currentTimeMillis();
			
			noErrorWithCurrentDocument = true;
			
		} catch(Throwable th) {
			Throwable rootCause = ExceptionUtils.getRootCause(th);
			if(rootCause!=null){
				rootCause.printStackTrace();
			}else{
				th.printStackTrace();
			}
			
		} finally {
			if(me!=null){
				if (isTransactionalSession && me.idfSession!=null) {
					if (noErrorWithCurrentDocument) {
						me.idfSession.commitTrans();
					} else {
						me.idfSession.abortTrans();
					}
				}

				// to release a docbase session
				me.releaseSession();
				
				long elapsedTime = stopTime - startTime;
				System.out.println(MessageFormat.format("Execute() total execution time : {0} ms ", elapsedTime));
			}
			
		}
	}

	
	private IDfSession getDfSession(String userName, String password, String docbaseName) throws Exception {
		IDfLoginInfo login = new DfLoginInfo();
		login.setUser(userName);
		login.setPassword(password);
		IDfClient client = DfClient.getLocalClient(); // new DfClient();
		sessMgr = client.newSessionManager();
		sessMgr.setIdentity(docbaseName, login);
		idfSession = sessMgr.getSession(docbaseName);

		if (idfSession != null){
			System.out.println("Session created successfully");
		}

		return idfSession;
	}
	
	
	private void releaseSession() throws Exception {
		sessMgr.release(idfSession);
	}

	private List<String> getIRMFormats() throws DfException {
		IDfCollection col = null;
		List<String> result = new ArrayList<String>();
		try {
			IDfQuery query = new DfQuery();
			query.setDQL("select r_object_id, name, dos_extension, mime_type from dm_format where LOWER(name) like 'irm-%'");
			col = query.execute(idfSession, IDfQuery.DF_EXEC_QUERY);
			if(col != null) {
				while(col.next()){
					// ---- dm_format
					// 27xxxxx123		irm-excel12book		xlsx	application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
					// 27xxxxxxxx456		irm-excel8book		xls		application/vnd.ms-excel
					result.add(col.getString("name"));
				}//end-while
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (col!=null) {
				col.close();
			}
		}
		return result;
	}
	
	private void applyIRMSecurity(String targetObjectId, String irmProfileName) throws Throwable {
		IDfSysObject sysObjectIRMProfile = (IDfSysObject) idfSession.getObjectByQualification("irm_profile WHERE object_name = '"+irmProfileName+"'");
		if(sysObjectIRMProfile != null) {
			DfId irmProfileId = new DfId(sysObjectIRMProfile.getString("r_object_id"));
			if(irmProfileId!=null && !irmProfileId.isNull()) {
				IDfSysObject targetObject = (IDfSysObject)idfSession.getObject(new DfId(targetObjectId));
				if(targetObject instanceof IDfAspects) {
					if(targetObject.findString("r_aspect_name", "irm_document_aspect")<0){ // OR IDfList aspectsAttached = ((IDfAspects) doc).getAspects();
						IDfService irmService = DfClient.getLocalClientEx().newService("com.documentum.services.irm.IIRMService", sessMgr);
						Method method = irmService.getClass().getMethod("setObjectIRMProfile", IDfSession.class, IDfSysObject.class, IDfId.class);
						method.invoke(irmService, targetObject.getObjectSession(), targetObject, irmProfileId);
					}else{
						String tmpStr = MessageFormat.format("The document \"{0}\" is already protected by IRM (presence of ASPECT 'irm_document_aspect')", targetObjectId);
						System.out.println(tmpStr);	
					}
				}
			}
		}
	}
	
	
	private static void setPreviousValuesOfLastModifAttributesBySQL(String currObjectId, IDfSession session, IDfTime previousModifyDateTime, String previousModifier) throws Throwable{
		StringBuilder sql = new StringBuilder();
		sql.append("UPDATE ").append(session.getDocbaseOwnerName()).append(".DM_SYSOBJECT_S");
		sql.append(" SET ");
		sql.append(" R_MODIFIER = '").append(previousModifier).append("',");
		DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
		dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
		sql.append(" R_MODIFY_DATE = to_date('").append(dateFormat.format(previousModifyDateTime.getDate())).append("', 'DD-MM-YYYY HH24:MI:SS')");
		sql.append(" WHERE R_OBJECT_ID = '").append(currObjectId).append("'");
		IDfApplyExecSQL dfApplyExecSQL = (IDfApplyExecSQL) DfAdminCommand.getCommand(DfAdminCommand.APPLY_EXEC_SQL);
		dfApplyExecSQL.setQuery(sql.toString());
		IDfCollection coll = dfApplyExecSQL.execute(session);
		try {
			if (coll.next()) {
				IDfValue dfValue = coll.getValueAt(0);
				if (!dfValue.asBoolean()) {
					throw new RuntimeException("Error in updating of R_MODIFIER and R_MODIFY_DATE fields.");
				}
			} else {
				throw new RuntimeException("Error in updating of R_MODIFIER and R_MODIFY_DATE fields.");
			}
		} finally {
			if(coll!=null){
				coll.close();
			}
		}
	}
	
}

 
 
IRMServiceUtils : Useful class

package com.huo.test.ecm.test2;

import java.lang.reflect.Method;
import java.util.Collection;

import com.documentum.fc.client.DfClient;
import com.documentum.fc.client.DfServiceException;
import com.documentum.fc.client.IDfFormat;
import com.documentum.fc.client.IDfService;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSessionManager;
import com.documentum.fc.client.IDfSysObject;
import com.documentum.fc.common.DfException;

public class IRMServiceUtils {
	private final IDfSessionManager dfSessionManager;

	private IRMServiceUtils(IDfSessionManager dfSessionManager) {
		if (dfSessionManager == null) {
			throw new IllegalArgumentException("IDfSessionManager argument cannot be null");
		}
		this.dfSessionManager = dfSessionManager;
	}
	
	public static IRMServiceUtils getFactory(IDfSessionManager dfSessionManager) throws DfServiceException {
		return new IRMServiceUtils(dfSessionManager);
	}

	private static IDfService getIRMService(IDfSessionManager dfSessionManager) throws DfServiceException {
		return DfClient.getLocalClientEx().newService("com.documentum.services.irm.IIRMService", dfSessionManager);
	}

	public java.util.Collection<?> getIRMActivity(IDfSession session, com.documentum.fc.common.IDfId docId) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("getIRMActivity", IDfSession.class, com.documentum.fc.common.IDfId.class);
			return (Collection<?>) method.invoke(irmService, session, docId);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}

	public com.documentum.fc.common.IDfId getObjectIRMProfile(IDfSession session, IDfSysObject obj) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("getObjectIRMProfile", IDfSession.class, IDfSysObject.class);
			return (com.documentum.fc.common.IDfId) method.invoke(irmService, session, obj);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}

	public com.documentum.fc.common.IDfId getObjectIRMProfile(IDfSession session, com.documentum.fc.common.IDfId objId) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("getObjectIRMProfile", IDfSession.class, com.documentum.fc.common.IDfId.class);
			return (com.documentum.fc.common.IDfId) method.invoke(irmService, session, objId);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}

	public boolean hasIRMAction(IDfSysObject obj, int action) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("hasIRMAction", IDfSysObject.class, Integer.TYPE);
			return (Boolean) method.invoke(irmService, obj, action);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}

	public boolean hasProtectedContent(IDfSysObject doc) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("hasProtectedContent", IDfSysObject.class);
			return (Boolean) method.invoke(irmService, doc);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}

	public boolean isProtectedFormat(IDfFormat format) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("isProtectedFormat", IDfFormat.class);
			return (Boolean) method.invoke(irmService, format);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}

	public boolean isProtectedFormat(java.lang.String formatName) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("isProtectedFormat", java.lang.String.class);
			return (Boolean) method.invoke(irmService, formatName);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}

	public boolean isSupportedFormat(IDfSession session, java.lang.String formatName) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("isSupportedFormat", IDfSession.class, java.lang.String.class);
			return (Boolean) method.invoke(irmService, session, formatName);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}

	public void protectDocument(IDfSysObject doc, java.lang.String formatName, IDfSysObject profile) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("protectDocument", IDfSysObject.class, java.lang.String.class, IDfSysObject.class);
			method.invoke(irmService, doc, formatName, profile);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}

	public void removeObjectIRMProfile(IDfSession session, com.documentum.fc.common.IDfId objId) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("removeObjectIRMProfile", IDfSession.class, com.documentum.fc.common.IDfId.class);
			method.invoke(irmService, session, objId);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}

	public void setObjectIRMProfile(IDfSession session, IDfSysObject obj, com.documentum.fc.common.IDfId profileId) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("setObjectIRMProfile", IDfSession.class, IDfSysObject.class, com.documentum.fc.common.IDfId.class);
			method.invoke(irmService, session, obj, profileId);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}

	public void setObjectIRMProfile(IDfSession session, com.documentum.fc.common.IDfId objId, com.documentum.fc.common.IDfId profileId) throws DfException {
		try {
			IDfService irmService = getIRMService(dfSessionManager);
			Method method = irmService.getClass().getMethod("setObjectIRMProfile", IDfSession.class, com.documentum.fc.common.IDfId.class, com.documentum.fc.common.IDfId.class);
			method.invoke(irmService, session, objId, profileId);
		} catch (Throwable e) {
			throw new DfException(e);
		}
	}
}

 
 
SOURCE CODE REMOVE IRM

package com.huo.test.ecm.test2;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

import org.apache.commons.lang.exception.ExceptionUtils;

import com.documentum.com.DfClientX;
import com.documentum.com.IDfClientX;
import com.documentum.fc.client.DfClient;
import com.documentum.fc.client.IDfClient;
import com.documentum.fc.client.IDfCollection;
import com.documentum.fc.client.IDfDocument;
import com.documentum.fc.client.IDfService;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSessionManager;
import com.documentum.fc.client.IDfSysObject;
import com.documentum.fc.client.aspect.IDfAspects;
import com.documentum.fc.commands.admin.DfAdminCommand;
import com.documentum.fc.commands.admin.IDfApplyExecSQL;
import com.documentum.fc.common.DfException;
import com.documentum.fc.common.DfId;
import com.documentum.fc.common.DfLoginInfo;
import com.documentum.fc.common.IDfId;
import com.documentum.fc.common.IDfLoginInfo;
import com.documentum.fc.common.IDfTime;
import com.documentum.fc.common.IDfValue;

public class DfcApiRemoveIRMSecurityTest {
	IDfSession idfSession = null;
	IDfSessionManager sessMgr = null;

	/**
	 * Constructor
	 */
	public DfcApiRemoveIRMSecurityTest(String user, String passwd, String docbase) throws Exception {
		getDfSession(user, passwd, docbase);
	}

	//------------------------------------------------------------------------------------------------------------ MAIN METHOD
	/**
	 * MAIN METHOD
	 */
	public static void main(String[] args) throws Exception {
		long startTime = 0;
		long stopTime = 0;
		
		String user = "useradm";
		String passwd = "passwordOfuseradm";
		String docbase = "MY_DOCBASE_DEV";
		String objectId = "090XXXXXXXXXa97";

		DfcApiRemoveIRMSecurityTest me = new DfcApiRemoveIRMSecurityTest(user, passwd, docbase);
		
		boolean isTransactionalSession = false;
		boolean noErrorWithCurrentDocument = false;
		try {
			if (!me.idfSession.isTransactionActive()) {
				me.idfSession.beginTrans();
				isTransactionalSession = true;
			}

			startTime = System.currentTimeMillis();

			IDfDocument doc = null;
			DfId dfId = new DfId(objectId);
			{
				doc = (IDfDocument)me.idfSession.getObject(dfId);
				System.out.println("BEFORE unIRMisation of CONTENT : i_vstamp="+doc.getInt("i_vstamp") + " - r_modify_date="+doc.getTime("r_modify_date"));
			}
			
			if(doc instanceof IDfAspects) {
				if(doc.findString("r_aspect_name", "irm_document_aspect")<0){ // OR IDfList aspectsAttached = ((IDfAspects) doc).getAspects();
					throw new RuntimeException(MessageFormat.format("The document ({0}) must be IRMised (associated to the \"{1}\" ASPECT)", objectId, "irm_document_aspect"));
				}
			}
			
			IDfTime previousModifyDateTime = doc.getTime("r_modify_date");
			String previousModifier = doc.getString("r_modifier");
			String aContentType = doc.getString("a_content_type"); // excel12book
			if(aContentType.toLowerCase().startsWith("irm-")==false){
				throw new RuntimeException("The content type of object ("+aContentType+") must be IRMised!");
			}
			
			me.removeIRMSecurityMethod1(dfId);	

			String sourceFile = "C:\\....\\mydoc_crypted.xlsx";
			String outputFile = "C:\\...\\mydoc_decrypted.xlsx";
			me.removeIRMSecurityMethod2(sourceFile, outputFile);
				
			{
				doc = (IDfDocument)me.idfSession.getObject(new DfId(objectId));
				System.out.println("AFTER unIRMisation of CONTENT : i_vstamp="+doc.getInt("i_vstamp")  + " - r_modify_date="+doc.getTime("r_modify_date"));
			}

			// Setting of the previous value for r_modify_date AND r_modifier because the attachment of aspect needs a SAVE action on document.
			// So, Content server overrides r_modifer and r_modify_date informations. 
			setPreviousValuesOfLastModifAttributesBySQL(objectId, me.idfSession, previousModifyDateTime, previousModifier);

			stopTime = System.currentTimeMillis();
			
			noErrorWithCurrentDocument = true;
			
		} catch(Throwable th) {
			Throwable rootCause = ExceptionUtils.getRootCause(th);
			if(rootCause!=null){
				rootCause.printStackTrace();
			}else{
				th.printStackTrace();
			}
			
		} finally {
			if(me!=null){
				if (isTransactionalSession && me.idfSession!=null) {
					if (noErrorWithCurrentDocument) {
						me.idfSession.commitTrans();
					} else {
						me.idfSession.abortTrans();
					}
				}

				// to release a docbase session
				me.releaseSession();
				
				long elapsedTime = stopTime - startTime;
				System.out.println(MessageFormat.format("Execute() total execution time : {0} ms ", elapsedTime));
			}
			
		}
	}

	
	//------------------------------------------------------------------------------------------------------------ PRIVATE METHODS
	private IDfSession getDfSession(String userName, String password, String docbaseName) throws Exception {
		IDfLoginInfo login = new DfLoginInfo();
		login.setUser(userName);
		login.setPassword(password);
		IDfClient client = DfClient.getLocalClient(); // new DfClient();
		sessMgr = client.newSessionManager();
		sessMgr.setIdentity(docbaseName, login);
		idfSession = sessMgr.getSession(docbaseName);

		if (idfSession != null){
			System.out.println("Session created successfully");
		}

		return idfSession;
	}
	
	
	private void releaseSession() throws Exception {
		sessMgr.release(idfSession);
	}

	private void removeIRMSecurityMethod1(IDfId dfId) throws Throwable {
		IDfSysObject dfSysObject = (IDfSysObject) idfSession.getObject(dfId);
		File file = File.createTempFile(dfId.getId(), "." + dfSysObject.getFormat().getDOSExtension());
		IDfService dfService = DfClient.getLocalClientEx().newService("com.documentum.services.irm.IIRMService", sessMgr);
		try {
			Method method = dfService.getClass().getMethod("DecryptIRMDocument", IDfSession.class, IDfId.class, String.class);
			((Boolean) method.invoke(dfService, idfSession, dfId, "C:\\temp\\test.xlsx")).booleanValue();
		} catch (Exception e) {
			throw new DfException(MessageFormat.format("IRMService.decryptIRMDocument({0}, {1}, {2})", idfSession, dfId, file.getCanonicalPath()), e);
		}
	}
	
	private void removeIRMSecurityMethod2(String sourceFile, String outputFile) throws Throwable {
		IDfClientX clientx = new DfClientX();
		IDfClient client = clientx.getLocalClient();
		IDfSessionManager dfSessionManager = client.newSessionManager();
		IDfService dfService = client.newService("com.documentum.services.irm.IIRMService", dfSessionManager);
		final Class<?> iRMDecryptorProxyClass = Class.forName("com.documentum.services.irm.impl.irmserver.IRMDecryptorProxy", true, dfService.getClass().getClassLoader());
		String s_appCert = getValue(dfService.getClass(), "s_appCert");
		String s_issCert = getValue(dfService.getClass(), "s_issCert");
		String s_key = getValue(dfService.getClass(), "s_key");
		String s_appName = getValue(dfService.getClass(), "s_appName");
		String s_appVersion = getValue(dfService.getClass(), "s_appVersion");
		final String decryptUser = "\\\\MYDOMAIN\\useradm";
		final String decryptPassword = "passwordOfuseradm";
		
		Object decryptor = iRMDecryptorProxyClass.getMethod("newEDSDecryptor").invoke(null);
		Method method = iRMDecryptorProxyClass.getMethod("EDSDecryptDocumentForIndexing", Object.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class);
		Boolean bRet = (Boolean) method.invoke(null, decryptor, sourceFile, outputFile, s_appCert, s_issCert, s_key, s_appName, s_appVersion, decryptUser, decryptPassword);
		if(bRet!=null && bRet.booleanValue()){
			
		}
	}
	
	private static String getValue(Class<? extends IDfService> clazz, String fieldName) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		Field field = clazz.getDeclaredField(fieldName);
		field.setAccessible(true);
		return (String) field.get(null);
	}
	
	private static void setPreviousValuesOfLastModifAttributesBySQL(String currObjectId, IDfSession session, IDfTime previousModifyDateTime, String previousModifier) throws Throwable{
		StringBuilder sql = new StringBuilder();
		sql.append("UPDATE ").append(session.getDocbaseOwnerName()).append(".DM_SYSOBJECT_S");
		sql.append(" SET ");
		sql.append(" R_MODIFIER = '").append(previousModifier).append("',");
		DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
		dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
		sql.append(" R_MODIFY_DATE = to_date('").append(dateFormat.format(previousModifyDateTime.getDate())).append("', 'DD-MM-YYYY HH24:MI:SS')");
		sql.append(" WHERE R_OBJECT_ID = '").append(currObjectId).append("'");
		IDfApplyExecSQL dfApplyExecSQL = (IDfApplyExecSQL) DfAdminCommand.getCommand(DfAdminCommand.APPLY_EXEC_SQL);
		dfApplyExecSQL.setQuery(sql.toString());
		IDfCollection coll = dfApplyExecSQL.execute(session);
		try {
			if (coll.next()) {
				IDfValue dfValue = coll.getValueAt(0);
				if (!dfValue.asBoolean()) {
					throw new RuntimeException("Error in updating of R_MODIFIER and R_MODIFY_DATE fields.");
				}
			} else {
				throw new RuntimeException("Error in updating of R_MODIFIER and R_MODIFY_DATE fields.");
			}
		} finally {
			if(coll!=null){
				coll.close();
			}
		}
	}
	
}

 
 

More informations:

 

That’s all!!

Huseyin OZVEREN