![Symbian Developer Library](../../../../a_stock/images/mainheading.gif)
![]() |
![]() |
|
The Supplier API allows agents to publicise the MIME types they are interested in. When files arrive on the device, message handling applications can check these MIME types and import the file into CAF. The agent transforms the file into a different format for use within the device.
In most cases this won't be necessary, since the files will arrive in the same format that they will be used in. However, some agents require the device to protect (encrypt) the content at the moment it arrives; the Supplier API fulfills that role.
The classes used in the supply operation are:
ContentAccess::CSupplier
and instances of
ContentAccess::CImportFile
.
The ContentAccess::CSupplier
is designed to allow
several unrelated files to be imported into CAF. It uses its
ContentAccess::CAgentResolver
member to determine which CA
agent should be used to import each file. The
CAgentResolver
builds a list of all agents when it is
created and updates the list if new agents are installed.
A typical import session will start with the creation of a
CSupplier
, for example:
// Create Supplier
CSupplier *mySupplier = CSupplier::NewL();
Most applications will have a preference for the directory where output
files are to be stored. Usually the first thing to do with the new
CSupplier
instance is to set the output path.
// Set output path for DRM protected content
_LIT(KPath,"C:\\myOutputFiles");
mySupplier->SetOutputDirectoryL(KPath());
It is not necessary to set the output path if the application provides output file handles to the agent.
Before importing a file into the content access framework, an
application should check that the MIME type of the file is supported. Each
agent publishes a list of the MIME types it supports. The list is configured in
the agent's resource file and can be checked using
ContentAccess::CSupplier::IsImportSupported()
.
if(!mySupplier->IsImportSupported(myMimeType))
{
return;
}
CMetaDataList
object
The CMetaDataList
object is used to store any
information associated with the import file that may be useful for the agent.
These values will be passed to the agent.
For example OMA DRM 1.0 files sometimes arrive with the HTTP header
X-Oma-Drm-Separate-Delivery
. This informs the agent how long
before rights are expected for the content. If the rights were expected in 12
seconds it would be something like the following:
// Create meta-data array
CMetaDataArray *metaDataArray = new (ELeave) CMetaDataArray();
CleanupStack::PushL(metaDataArray);
// Add any useful information we can think of....
metaDataArray->AddL(_L("Content Type"),_L("application/vnd.oma.drm.dm"));
metaDataArray->AddL(_L("X-Oma-Drm-Separate-Delivery"),_L("12"));
The file is 'written' to CAF using a
ContentAccess::CImportFile
object.
ContentAccess::CSupplier::ImportFileL()
creates an
CImportFile
object for importing a file.
The parameters supplied indicate whether the agent will create the output files or whether the application using CAF will generate output files for the agent on demand.
// Create the import object, passing in the metaDataArray created earlier
// The application will supply the output files
CImportFile *import = mySupplier->ImportFileL(sourceMimeType, *metaDataArray);
The application should now transfer the file to CAF using the
CImportFile
object. Only one file can be transferred by each
instance although several output files may be produced. Applications should
create new CImportFile
objects in order to import more files.
If the application wants the agent to generate the output files, it
should supply a suggested file name in the call to
CSupplier::ImportFileL()
. Even if this parameter is a zero
length descriptor, it still indicates that the agent is responsible for
generating output files.
Agents will create the output files in a directory nominated by the
application when it called
CSupplier::SetOutputDirectoryL()
or they may decide to
store the output files in their private directory.
Applications should check at the end of the import to find out how many output files were created and where they are stored.
If no suggested file name is passed to the agent, the application will provide output files for the agent to use. This mechanism allows applications to open files in their own private directory and ask the CAF agent to store the output in those files.
The way it works is the same as in any other import operation, the
difference is that the call to CImportFile::WriteData()
or
CImportFile::WriteDataComplete()
may return an error code
of KErrCANewFileHandleRequired
.
This error code indicates that the agent needs a new output file handle
in order to continue. The application should open a new output file with write
access and call CImportFile::ContinueWithNewOutputFile()
to supply the new handle to the agent. It is possible that further handles may
be needed. If so, CImportFile::ContinueWithNewOutputFile()
will return KErrCANewFileHandleRequired
and the application should
repeat the procedure with another file.
The agent must cache its state before returning
KErrCANewFileHandleRequired
. The application must not
resend the same WriteData()
or WriteDataComplete()
command.
At the end of the import operation the output files will still be listed regardless of whether they were supplied by the application or the agent.
ContentAccess::CImportFile
is the class used to
write the file data to CAF. It is created by
ContentAccess::CSupplier
and can only be used to import a
single file.
An application should call WriteData()
to transfer a field
in 'chunks' to the Content Access Framework. Usually this would be something
like the following:
ImportFile *import;
TFileName fileName;
TPath outputfileName;
TBuf8 data <128>
_LIT(KDirectoryPath, "C:\\private\\12345678\\");
...
while(!endofsource)
{
source.read(data);
err = import->WriteData(data);
// When application supplies file handles it must always check to see if
// the agent needs a new file handle
while(err == KErrCANewFileHandleRequired)
{
RFile newFile;
import->GetSuggestedOutputFileName(fileName);
outputFileName.Copy(KDirectoryPath);
outputFileName.Append(fileName);
newFile.Open(outputFileName, EFileWrite);
err = import->ContinueWithNewOutputFile(newFile, outputFileName);
// It is possible that the agent needs yet another file handle
newFile.Close(); // agent makes a copy so we don't need to keep our file handle
}
}
When all the data is written, the application should call
ContentAccess::CImportFile::WriteDataComplete()
, which
will let the agent know that all the data has been transferred and allow it to
perform any final processing.
err = import->WriteDataComplete();
// When the application supplies file handles it must always check to see if
// the agent needs a new file handle
while(err == KErrCANewFileHandleRequired)
{
RFile newFile;
import->GetSuggestedOutputFileName(fileName);
outputFileName.Copy(KDirectoryPath);
outputFileName.Append(fileName);
newFile.Open(outputFileName, EFileWrite);
err = import->ContinueWithNewOutputFile(newFile, outputFileName);
// It is possible that the agent needs yet another file handle
newFile.Close(); // agent makes a copy so we don't need to keep our file handle
}
// Finished
At this stage all the agent's work is done and the
CImportFile
object can be deleted.
When the import is finished, the application may wish to check if any
output files have been produced. The list of output files is accessed using
ContentAccess::CImportFile::OutputFileL()
.
// loop over all the output files produced
for(TInt i =0; i < import->OutputFileCountL(); i++)
{
// Can now retrieve filename, type of file (receipt or content) and MIME type for the file produced
TPtr filename = import->OutputFileL(i).FileName();
TOutputType type = import->OutputFileL(i).OutputType();
TPtr8 mimetype = import->OutputFileL(i).MimeType();
}
The output files can be either content files or receipts for DRM rights. It is possible that no output files will be generated and the file will be "absorbed" into the agent.
Also, it is important to remember that the MIME type and most likely the file extension of the output files are almost certainly different to the MIME type and file extension of the imported file.