Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Enhancing document security with FileNet Web Application Toolkit

Bharath N S (bnadampa@in.ibm.com), Senior Staff Software Engineer, IBM  
Photo of Bharath Nadampalli
Bharath N.S. works as a Senior Staff Software Engineer at IBM India Software labs, with over ten years of experience in software development experience based on Microsoft technologies, and more recently, on Java and J2EE technologies. Bharath's hobbies include image processing and exploring new technologies.
Nandish S. Kori (nandkori@in.ibm.com), Software Engineer, IBM
Nandish Kori
Nandish S Kori works as a Software Engineer at IBM India Software lab on the FileNet team. He has 4 years of software development experience based on Java and C. His hobbies include playing any game and exploring new things.

Summary:  This article examines a scenario for encoding and decoding a document to enhance security using the FileNet Web Application Toolkit to customize IBM® FileNet® P8 Workplace. It also includes a look at the toolkit architecture in the context of saving a document.

Date:  17 Feb 2011
Level:  Intermediate

Activity:  4815 views
Comments:  

Introduction

In a typical content management or process management system, documents are routed from one user to the next with no guarantee that the contents of the document are secure. After it has been downloaded or checked out, a document might be used maliciously. So let us say we encrypt the document as it comes from the content repository, for example FileNet Content Engine (CE). The document cannot be openly viewed, even if it is tranferred maliciously. It will be viewable only by users who can decrypt it with the help of a policy server.

A typical use case for a digital rights management (DRM) scenerio is shown in Figure 1:


Figure 1. Typical digital rights management scenario
Diagram shows flow from user request to decoding the  document, to repository, to encoding, to user request, to user role database, to decoding the document, and then back to user request

The scenario includes the following steps:

  1. First you (the user) request to check in a protected document(Base64 encoding and decoding is used in this example).
  2. The document, which needs to be sent to a repository (in this case FileNet Content Engine), must be decoded to enable text search.
  3. When you attempt to check-out or download the file, the system encrypts the document, then sends it to you.
  4. You then contact the policy server provided by a DRM solution provider with the checked-out, encrypted file. After you authenticate at the policy server, the file is decrypted and you can view or modify it as desired.

You will need to customize FileNet P8 in order to accomplish steps 2 and 3.

The solution uses FileNet Web Application Toolkit (WAT), an extensible framework for building web applications that was used to create the FileNet P8 Workplace.


Prerequisites

To implement this solution, you should have some knowledge of the different components of the IBM FileNet P8 platform,including Application Engine (AE), Content Engine (CE) and Process Engine (PE). The code accompanying this article has been tested on FileNet P8 4.5.1 and IBM WebSphere Application Server - ND, 6.1.0.25. In addition, you should have familiarity with Eclipse and Java.


Next steps

How do you achieve the customizations shown in Figure 1? This will depend on which method was used to get the document into the FileNet CE repository:

  • Using FileNet P8 Workplace (Application Engine)
  • Using FileNet Enterprise Manager (FEM)
  • Using a custom application

In the next part of the article, you'll see how to customize the FileNet P8 Workplace so that you can do the following operations:

  • Decrypt an encrypted file while adding through FileNet P8 Workplace (WAT).
  • Encrypt a file while viewing or checking out the file using FileNet P8 Workplace (WAT).

Solving the business case

In the real world there are many third-party vendors who offer DRM solutions. Most of them use an architecture similar to the one you saw in Figure 1.

For the sake of simplicity, we used Base64 in our example to encode and decode a document. In this article, we are considering simple Text files (*.txt). In an actual content management environment, there are be many ways in which document protection can be achieved, for all kinds of documents.

We are using Apache Base64 conversion library commons-codec-1.4.jar (org.apache.commons.codec.binary.Base64)

Document check-in

Document check-in in FileNet P8 Workplace happens through WcmUploadInputStream servlet. This is part of the p8ToolKit.jar, found at the Websphere Application Server machine where the workplace is deployed, in the following path:
<WAS node Cell path>\ Workplace.ear\app_engine.war\WEB-INF\lib\

You will find the WcmUploadInputStream.java file at this path:
<WAS node Cell path>\Workplace.ear\app_engine.war\AESource

It is part of the com.filenet.wcm.toolkit.server.util package.

WcmUploadInputStream class has a static method getInstance which is overloaded twice:

  • The first overload takes HttpServletRequest and the form name as second and third parameters respectively.
  • The second overload, shown below, takes the WcmMimeFormParser and HttpServletRequest as second and third parameters respectively.

WcmDataStore is the common parameter for both of the overloaded functions. This parameter holds the user session-specific data store.

As the code examples below illustrate the following steps:

  • A static function DecodeFile is added to WcmUploadInputStream.java. This function takes a reference to file object and the filepath where the inputstream has been cached.
  • The DecodeFile is called in getInstance.

Listing 1. Document check-in

public static WcmUploadInputStream getInstance(WcmDataStore ds,
	WcmMimeFormParser mfp,HttpServletRequest req)throws IOException,Exception
    {
	WcmUploadInputStream uis   = null;
        if ( !mfp.isEOD() )
        {
            String fname = mfp.getSectionParameter(WcmMimeFormParser.INPUT_FILENAME);
            if ( fname != null )
            {
                File theFile = null;
                try
                {
		theFile = UploadDownloadFileUtil.initUploadCacheFile(req.getLocale(),
			req.getSession().getServletContext(),null,null);
                }
                catch (WcmException e)
                {
                	//System.out.println("Hello #2_3");
                    throw new IOException(wsCacheFileError.toString(req.getLocale()));
                }
		System.out.println("File name is : " + fname);
		System.out.println("File name is : " + theFile.getPath());

		FileOutputStream  fos     = new FileOutputStream(theFile);
		mfp.writeSectionContent(fos);
		fos.close();
		// Start of decoding
                 File theFile1 = DecodeFile (theFile,fname,req.getLocale());
                 //End of decoding

                uis = new WcmUploadInputStream(
                    new FileInputStream(theFile1),
                    theFile1,
                    mfp.getSectionContentLength(),
                    mfp.getSectionParameter(WcmMimeFormParser.MIME_TYPE),
                    //fname,
                    theFile1.getPath(),
                    theFile1.getPath(),
                    true, true, req.getSession().getServletContext());
            }
        }

        return(uis);
    }
*******************************************************************************

public static File DecodeFile(File theFile,String fileName2,Locale locale) 
throws Exception
  {
	  String fname = theFile.getPath();
	  FileInputStream fis1 = new FileInputStream(fname); 
	  String fileName2_1= fileName2.substring(fname2+1,  fileName2.length()); 
	  fileName2 = "C:\\TEMP\\"+fileName2_1;
	  File theFile1 =  new File(fileName2);
	  FileOutputStream fos1 = new FileOutputStream (theFile1);
	  int off1 =0;
	  int bytes_read1;
	  byte [] buffer1 = new byte[4096];
	  while ((bytes_read1 = fis1.read(buffer1))!= -1)
	  {
	 	//byte[] decoded = Base64.decodeBase64(buffer1);
		byte[] encoded = WcmEncodingUtil.encodeBase64(locale,nextBytes);
		fos1.write(decoded, off1, decoded.length);	
	}
	fos1.close();
	fis1.close();
	System.out.println("filename2 : "+fileName2);
	return theFile1;
  }

Once the code changes are made, it is time to deploy the code into the workplace following these steps:

  1. Compile the Java file.
  2. Deploy the .jar file (in this case p8Toolkit.jar) to the folder where Workplace is deployed

Once the WcmGetContentServlet.java is compiled, it creates two class files. Copy them to the appropriate folders and then update the p8toolkit.jar file with both the class files, using these commands:

  1. Copying the class file to the appropriate folder:
    copy /Y WcmGetContentServlet.class .\com\filenet\wcm\toolkit\server\servlet\
  2. Updating the jar with the new class file:
    jar -uvf p8toolkit.jar com\filenet\wcm\toolkit\server\servlet\WcmUploadInputStream.class
  3. Deploying the jar file back into the application:
    copy /Y p8toolkit.jar "C:\Program Files\IBM\WebSphere\AppServer\profiles\AppSrv01\installedApps\idmdev18bNode01Cell\Workplace.ear\app_engine.war\WEB-INF\lib\

Note that all these operations are performed in the AESource directory:
< WAS node Cell path>\Workplace.ear\app_engine.war\AESource

Document open and check-out

Open and check-out in FileNet P8 Workplace occurs with the WcmGetServlet.java file, part of the com.filenet.wcm.toolkit.server.servlet package. This is the layer where you manipulate the filestream before sending it the user.

The function in question is streamContentToBrowser. This particular function makes a call to a function called transferHeaders. The response object is sent to this function as shown in the code snippet below.

The transferHeaders function uses this request object and sets the contentLength of the response object. Our implementation uses Base64 encoding, which increases the size of the encoded file. So we get the stream encoded, and also calculate the encoded stream length, which is used in the transferHeaders function call.

The encoded stream is sent along the previous normal path. That is, we use it the tranferContent function call, which writes it to the response stream

So that is the end of document open / check-out.


Listing 2. Document open/check-out

private void streamContentToBrowser(Document doc) throws IOException
  {

      TransportInputStream inStream = doc.getContentElement(iElement);

      response.setHeader("ResultXml", "<?xml version=\"1.0\"?><response>
	  <errorcode>0</errorcode><description>" +
                "Success</description></response>");

	String filename = inStream.getFilename();
      contentLength = (int) inStream.getContentSize();
      sMimeType = inStream.getMimeType();

  if (sMimeType != null && sMimeType.equalsIgnoreCase(MimeTypes.FILENET_PUBLISHTEMPLATE))
                sMimeType = "text/xml";

      if (contentLength <0 && getEnableFiletracking(dataStore, 
	  WcmStringResources.getClientLocale(request)))
      {
        contentLength= getContentLength(inStream);
        nStream = doc.getContentElement(iElement);
	  }
      ServletOutputStream outStream = response.getOutputStream();
		

	  // Start of encoding
                 ByteArrayOutputStream outStream_Encoded = EncodeFile (inStream);
                 //End of encoding
 ByteArrayInputStream inS_en = new ByteArrayInputStream(outStream_Encoded.toByteArray());
      contentLength=  encodedContentLength;
      transferHeaders(filename, contentLength, sMimeType, response);

      //transferContent(inStream, outStream);
      transferContent(inS_en, outStream);
      outStream.close();
      inStream.close();
      inS_en.close();
 }
public static ByteArrayOutputStream EncodeFile(TransportInputStream inStream) 
		throws Exception
  {
	  InputStream istream = inStream;
      int nBytesRead = 0;
      encodedContentLength=0;
      ByteArrayOutputStream outStream_Encoded= new ByteArrayOutputStream();
      OutputStream outFile = new FileOutputStream ("C:\\File_instream.txt");
      for (byte[] nextBytes = new byte[8192]; nBytesRead != -1; 
	  nBytesRead = inStream.read(nextBytes))
      {
		if(nBytesRead>0)
		{
			//byte[] encoded = Base64.encodeBase64(nextBytes);
			byte[] encoded = WcmEncodingUtil.encodeBase64(nextBytes);
			encodedContentLength=encodedContentLength+encoded.length;
			outStream_Encoded.write(encoded, 0, encoded.length);
			//WriteToLog(encoded);
			outFile.write(encoded, 0, encoded.length);
		}
      }
      outFile.close();
	return outStream_Encoded;
  }

Our solution leveraged the org.apache.commons.codec.binary.Base64 package for Base64 encoding and decoding. Refer to the Resources section for more information on the package. Alternatively you could use the WcmEncodingUtil class which has methods such as WcmEncodingUtil.encodeBase64 and WcmEncodingUtil.decodeBase64. This class can be used for the same purpose.


Understanding the underlying architecture

Some aspects of how the FileNet Web Application Toolkit works played an important part in solving this problem, spcifically the call sequence with respect to the save document function.

Figure 2 illustrates the model-view-controller (MVC) pattern used in WAT. For more information, see the FileNet documentation.


Figure 2. Sequence diagram
Sequence diagram

The modules belonging to each part are as follows:

  • Model:
    • WcmSaveOperation is part of the com.filenet.wcm.apps.server.ui.operation package. This will call the appropriate data provider to do any operation on CE or PE. This class also implements the events that are called by the controller. In this case it implements the onSave event. (Also this derives ultimately from a base class called WcmUiModule)
    • WcmAuthoringDataProvider is part of the com.filenet.wcm.toolkit.server.dp package. The primary job of a data provider is to use to the CE and PE apis. In this implementation, the authoring data provider talks to CE to retrieve, add, or replace documents in CE.
  • View:
    • WcmSaveContent.jsp is found at "app_engine.war\UI-INF\jsp\ui\operations" folder in websphere's workplace deployment folder. It renders the HTML output the client. The HTML content is built in the model phase. This page is called from the model phase via a redirect.
  • Controller:
    • WcmSaveContent.jsp is found at "app_engine.war\operations" folder in WebSphere's workplace deployment folder. This page configures the controller. During the configuration, events that needs to be called in the model are recovered from the request object.
    • The controller registers the modules in the model phase. During the registration it calls the Initialize method on each of the modules. In this example it will be WcmSaveOperation and WcmAuthoringDataProvider.
    • Once the initialization operations on the modules are complete, the controller calls the handleEvent which triggers the events. In this case it is the onSave event on WcmSaveOperation object.

Conclusion

This article was aimed at solving a potential security issue in a document management scenario, and also explored a piece of the Web Application Toolkit architecture. There could be scenarios where you don't want to encode and decode some of the documents in your workflow. This is an implementation detail that you can figure out how to implement when you go through WcmUploadInputStream.

Note that the article explains only a partial overview sequence of save document. There are many other modules that are involved, such as WcmUploadInputStream which we have used to implement the business case. The information in this article provided a beginning as you start to explore this topic, and a base for further exploration.


Acknowledgement

Thanks to Phong Chu, Technical Instructor Specialist, ECM Education Services, for reviewing this article and providing valuable comments.


Resources

About the authors

Photo of Bharath Nadampalli

Bharath N.S. works as a Senior Staff Software Engineer at IBM India Software labs, with over ten years of experience in software development experience based on Microsoft technologies, and more recently, on Java and J2EE technologies. Bharath's hobbies include image processing and exploring new technologies.

Nandish Kori

Nandish S Kori works as a Software Engineer at IBM India Software lab on the FileNet team. He has 4 years of software development experience based on Java and C. His hobbies include playing any game and exploring new things.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Information Management
ArticleID=627297
ArticleTitle=Enhancing document security with FileNet Web Application Toolkit
publish-date=02172011
author1-email=bnadampa@in.ibm.com
author1-email-cc=
author2-email=nandkori@in.ibm.com
author2-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers