シナリオ:Reader 用の拡張による PDF プレビュー

Adobe® LiveCycle® Reader Extensions モジュールを使用するように Correspondence Management Solution を設定できます。これにより、レンダリング前の、保存、印刷および共有といったPDF ドキュメントの処理が簡単になります。Reader Extensions の設定は、クライアントマシンに Adobe® Acrobat® がインストールされている場合は必要ありません。

実装の概要

このユーザーストーリーの実装には、コード変更およびソリューションの再構築と再デプロイが含まれます。開始する前に、開発環境の設定の章で説明した手順を実行したことを確認してください。その後、ユーザーストーリーを実装する前に以下の手順を実施します。

以下の Document Services クライアント JAR を Solution Template の Services プロジェクトのクラスパスに追加します。
  • adobe-reader-extensions-client.jar

  • adobe-livecycle-client.jar

  • adobe-usermanager-client.jar

これらのクライアント JAR をクラスパスに追加するには:
  1. これらを、CorrespondenceManagementSolutionTemplate フォルダーの下の DS_SDK という名前のフォルダーにコピーします。

  2. Eclipse 環境で、Services プロジェクトを右クリックし、ビルドパス/ビルドパスの構成をクリックします。

  3. プロパティポップアップウィンドウで、「外部 JAR の追加...」をクリックします。

  4. DS_SDK フォルダーを参照し、3 つの JAR すべてを選択して「開く」をクリックします。

  5. 3 つのクライアント JAR がビルドパスに追加されたことを確認してください。「OK」をクリックし、変更を保存します。

次に、PDF の読み手の書き直し用 DocumentRenderHandler インターフェィスのカスタム実装を提供します。

  1. PDF ドキュメントの拡張を支援する DocumentRenderHandler インターフェイスのカスタム実装を指定します。コードスニペットの例を以下に示します。
    package com.adobe.icc; 
    import java.io.InputStream; 
    import java.util.HashMap; 
    import java.util.Map; 
    import org.slf4j.Logger; 
    import org.slf4j.LoggerFactory; 
    import com.adobe.icc.ddg.api.DocumentRenderHandler; 
    import com.adobe.idp.Document; 
    import com.adobe.idp.dsc.clientsdk.ServiceClientFactory; 
    import com.adobe.livecycle.readerextensions.client.ReaderExtensionsOptionSpec; 
    import com.adobe.livecycle.readerextensions.client.ReaderExtensionsServiceClient; 
    import com.adobe.livecycle.readerextensions.client.UsageRights; 
    /** 
     * Register document processing handler for Reader extending PDFs. 
     */ 
    public class ReaderExtendDocumentHandler implements DocumentRenderHandler { 
        protected final Logger logger = LoggerFactory.getLogger(getClass()); 
        private ServiceClientFactory serviceClientFactory; 
        public ServiceClientFactory getServiceClientFactory() { 
            return serviceClientFactory; 
        } 
        public void setServiceClientFactory( 
                ServiceClientFactory serviceClientFactory) { 
            this.serviceClientFactory = serviceClientFactory; 
        } 
        @Override 
        public int getHandlerType() { 
        return INTERACTIVE_DOCUMENT_HANDLER; 
        } 
        @Override 
        public Map<String, byte[]> preProcessDocument(byte[] xdp, byte[] xml) { 
            Map<String, byte[]> result = new HashMap<String, byte[]>(); 
            result.put(XDP_KEY, xdp); 
            result.put(XML_KEY, xml); 
            // doing nothing here - just return what we are given 
            return result; 
        } 
        @Override 
        public byte[] postProcessDocument(byte[] inputDoc) { 
            logger.info("[CUSTOMIZATION] RE document..."); 
            try { 
                return readerExtendDocument(inputDoc); 
            } catch (Exception e) { 
                logger.error("Failed to RE document : " + e.getMessage()); 
                e.printStackTrace(); 
            } 
            return inputDoc; 
        } 
        private byte[] readerExtendDocument(byte[] doc) throws Exception { 
            Document inputPDF = new Document(doc); 
            // Create a UsageRight object and specify specific usage rights 
            UsageRights useRight = new UsageRights(); 
            useRight.setEnabledDynamicFormFields(true); 
            useRight.setEnabledComments(true); 
            useRight.setEnabledFormFillIn(true); 
            useRight.setEnabledDigitalSignatures(true); 
            useRight.setEnabledFormDataImportExport(true); 
            // Create a ReaderExtensionsOptions object 
            ReaderExtensionsOptionSpec reOptions = new ReaderExtensionsOptionSpec(); 
            // Set the usage rights 
            reOptions.setUsageRights(useRight); 
            reOptions.setMessage("This is a Rights-Enabled PDF Document"); 
            ReaderExtensionsServiceClient readerExtensionClient = new ReaderExtensionsServiceClient( 
                    serviceClientFactory); 
            logger.info("Performing RE now..."); 
            // Apply usage rights to a PDF document 
            Document rightsEnabledPDF = readerExtensionClient.applyUsageRights( 
                    inputPDF, "PRODUCTION", null, reOptions); 
            InputStream is = rightsEnabledPDF.getInputStream(); 
            long length = is.available(); 
            byte[] bytes = new byte[(int) length]; 
            is.read(bytes); 
            logger.info("RE done. Returning bytes..."); 
            return bytes; 
        } 
    }
    以下の API を DocumentRenderHandler インターフェイス用に実装する必要があります。
    Map<String, byte[]> preProcessDocument(byte[] xdpBytes, byte[] xmlBytes)
    ドキュメントのレンダリングに使用される XDP データと XML データを使用できるようにする前処理 API です。このユーザーストーリーでは何もしません。

    byte[] postProcessDocument(byte[])
    ドキュメントの後処理を決定する IRenderService から呼び出される API です。この API はカスタム実装で使用します。

    int getHandlerType()
    処理されるドキュメントのタイプを決定する API です(インタラクティブまたは非インタラクティブ)。

    注意: 以上のクラスは、Services プロジェクトの com.adobe.icc パッケージにあります。
  2. 以下の Spring の初期化 Bean を定義することで、カスタム実装を IRenderService に登録します。
    package com.adobe.icc.bootstrap; 
    import java.util.ArrayList; 
    import java.util.List; 
    import org.slf4j.Logger; 
    import org.slf4j.LoggerFactory; 
    import org.springframework.beans.factory.InitializingBean; 
    import org.springframework.beans.factory.annotation.Autowired; 
    import com.adobe.icc.ReaderExtendDocumentHandler; 
    import com.adobe.icc.ddg.api.DocumentRenderHandler; 
    import com.adobe.icc.render.IRenderService; 
    /** 
     * Register document processing handlers. 
     */ 
    public class DocumentHandlerRegistration implements InitializingBean { 
        protected final Logger logger = LoggerFactory.getLogger(getClass()); 
        @Autowired 
        IRenderService renderService; // catch hold of the RenderService reference 
        @Autowired 
        ReaderExtendDocumentHandler readerExtendDocumentHandler; // your handler's instance 
         
        public void afterPropertiesSet() throws Exception 
        { 
            List<DocumentRenderHandler> handlers = new ArrayList<DocumentRenderHandler>(); 
            handlers.add(readerExtendDocumentHandler); // we have only one handler at this time, so add this to the list 
             
            renderService.setRenderHandlers(handlers); // register handlers 
        } 
    }
    注意: 以上のクラスは、Services プロジェクトの com.adobe.icc.bootstrap パッケージにあります。
  3. CorrespondenceManagementSolutionTemplate\Services\resources\META-INF\spring\cm\adobe-cm-spring-config.xml にある adobe-cm-spring-config.xml ファイルで、カスタム実装に適した Bean を定義します。Bean 定義の例を以下に示します。
    <?xml version="1.0" encoding="UTF-8"?> 
    <beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:flex="http://www.springframework.org/schema/flex" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:lang="http://www.springframework.org/schema/lang" 
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 
        xmlns:context="http://www.springframework.org/schema/context" 
        xmlns:sec="http://www.springframework.org/schema/security" 
        xsi:schemaLocation=" 
            http://www.springframework.org/schema/flex http://www.springframework.org/schema/flex/spring-flex-1.0.xsd 
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
            http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd 
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd 
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd 
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 
            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd" 
            default-init-method="init"> 
           //IMPORTANT: If the following higlighted lines are not defined in the adobe-cm-spring-config.xml, you need to include them 
        <bean id="serviceClientFactory" 
            factory-bean="serviceClientFactoryProvider" factory-method="getDefaultServiceClientFactory" scope="prototype"> 
        </bean> 
        <bean id="lc.cm.readerExtendHandler" class="com.adobe.icc.ReaderExtendDocumentHandler"> 
            <property name="serviceClientFactory" ref="serviceClientFactory" /> 
        </bean> 
         
        <bean id="lc.cm.documentRegistration" class="com.adobe.icc.bootstrap.DocumentHandlerRegistration" />  
        <!-- ___________________ BootStraper beans _____________________ --> 
         
        <bean id="lc.cm.assetDefinitionsDeployer" class="com.adobe.icc.bootstrap.AssetDefinitionsDeployer"> 
            <property name="assetDefinitions"> 
                <list> 
                    <value>/apps/solutions/cm/assetDefinitions/ConditionalDataModule.fml</value> 
                    <value>/apps/solutions/cm/assetDefinitions/ImageModule.fml</value> 
                    <value>/apps/solutions/cm/assetDefinitions/Letter.fml</value> 
                    <value>/apps/solutions/cm/assetDefinitions/Layout.fml</value> 
                    <value>/apps/solutions/cm/assetDefinitions/ListDataModule.fml</value> 
                    <value>/apps/solutions/cm/assetDefinitions/TextModule.fml</value> 
                    <value>/apps/solutions/cm/assetDefinitions/DataDictionary.fml</value> 
                    <value>/apps/solutions/cm/assetDefinitions/Category.fml</value> 
                    <value>/apps/solutions/cm/assetDefinitions/DataModule.fml</value> 
                    <value>/apps/solutions/cm/assetDefinitions/FragmentLayout.fml</value> 
                    <value>/apps/solutions/cm/assetDefinitions/Asset.fml</value> 
                </list> 
            </property> 
            <property name="defaultCharacterEncoding" value="${defaultCharacterEncoding}"/> 
        </bean> 
         
         
    </beans>
    注意: 上記の強調表示されたテキストが adobe-cm-spring-config.xml ファイルにあることを確認します。なければ、このテキストをファイルに含める必要があります。
    IRenderService は ACM 構築ブロックによって公開されます。そのため、CorrespondenceManagementSolutionTemplate\Services\resources\META-INF\spring\osgi-context.xml にある osgi-context.xml で参照を追加することによって、CM ソリューションバンドル内で読み込みます。Bean は以下の変更を反映します。
    <beans xmlns="http://www.springframework.org/schema/beans" 
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
           xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0" 
           xmlns:context="http://www.springframework.org/schema/context" 
           xmlns:osgix="http://www.springframework.org/schema/osgi-compendium" 
           xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd 
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
            http://www.springframework.org/schema/osgi-compendium http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd"> 
    //IMPORTANT: If the following higlighted line is not defined in the adobe-cm-spring-config.xml, you need to include it 
        <import resource="cm/adobe-cm-spring-config.xml"/> 
        <bp:blueprint> 
            <!-- <bp:service interface="com.adobe.icc.ddg.api.LetterRenderService" ranking="10" ref="customRenderService"> 
                   <bp:service-properties> 
                           <entry key="connectors.httpinvoker" value="true" /> 
                           <entry key="connectors.httpinvoker.alias" value="/lc.icc.renderlib.letterRenderService" /> 
                    </bp:service-properties> 
            </bp:service> --> 
             
            <bp:reference id="osgi.resourceResolverFactory" interface="org.apache.sling.api.resource.ResourceResolverFactory"/> 
            <bp:reference interface="org.apache.sling.settings.SlingSettingsService"/> 
             
            <bp:reference interface="com.adobe.livecycle.content.config.ApplicationManager" /> 
            
            <bp:reference id="serviceClientFactoryProvider" interface="com.adobe.livecycle.dsc.clientsdk.ServiceClientFactoryProvider" /> 
            
            <!-- <bp:reference interface="com.adobe.idp.applicationmanager.service.ApplicationManager" /> --> 
             
    //IMPORTANT: If the following higlighted line is not defined in the adobe-cm-spring-config.xml, you need to include it 
            <bp:reference interface="com.adobe.icc.render.IRenderService" /> 
            <bp:reference interface="com.adobe.dct.service.DataDictionaryUtilService" /> 
            <bp:reference interface="com.adobe.dct.service.DataDictionaryRegistryService" /> 
            <bp:reference interface="com.adobe.livecycle.content.activate.ActivateBootstrapper" /> 
            <bp:reference id="lc.content.remote.fileService" interface="com.adobe.livecycle.content.repository.FileService" /> 
                     
        </bp:blueprint> 
        <osgix:cm-properties id="cmProps" persistent-id="com.adobe.livecycle.cm"> 
            <prop key="tmpfolder">C:/temp</prop> 
            <prop key="xmlfile.name">/WEB-INF/classes/ExampleData.xml</prop> 
            <prop key="letterfile.name">/WEB-INF/classes/InsuranceCorrespondance.xml</prop> 
            <prop key="icc.letter.id.name">cmLetterName=</prop> 
            <prop key="icc.user.testdata.name">cmLetterState=1&amp;cmUseTestData=1</prop> 
            <prop key="icc.data.url">cmDataUrl=assets/</prop> 
            <prop key="icc.preview.name">cmPreview=0</prop> 
            <prop key="defaultCharacterEncoding">UTF-8</prop> 
        </osgix:cm-properties> 
        <context:property-placeholder properties-ref="cmProps" /> 
        
        <!-- IMPORTANT: This tag is responsible for enabling annotations like autowiring etc --> 
    //IMPORTANT: If the following higlighted lines are not defined in the adobe-cm-spring-config.xml, you need to include them 
        <context:annotation-config/> 
        <bean id="serviceClientFactory" 
                factory-bean="serviceClientFactoryProvider" factory-method="getDefaultServiceClientFactory"> 
        </bean>  
         
    </beans>
    注意: 上記の強調表示されたテキストが osgi-context.xml ファイルにあることを確認します。なければ、このテキストをファイルに含める必要があります。
  4. LiveCycle SDK(com.adobe.idp および com.adobe.idp.dsc)にある Services/API のパッケージを CorrespondenceManagementSolutionTemplate\Services\bnd\cmsa.bnd にある Correspondence Management バンドルの BND 設定ファイル(cmsa.bnd)に読み込みます。BND ファイルのコードスニペットの例を以下に示します。
    version=1.0.0 
    Export-Package: com.adobe.icc;com.adobe.icc.bootstrap;version=${version} 
    //IMPORTANT: If the following higlighted line is not defined in the adobe-cm-spring-config.xml, you need to include it 
    Import-Package: com.adobe.idp,com.adobe.idp.dsc,com.adobe.livecycle.readerextensions.client.* 
    Bundle-Version: ${version} 
    Bundle-Description: Adobe Correspondence Management Solution Bundle 
    Bundle-SymbolicName: com.adobe.livecycle.cm 
    X-Spring-Context: META-INF/spring/cm 
    Spring-Context: META-INF/spring/osgi-context.xml
    注意: 上記の強調表示されたテキストが BND コンフィギュレーションファイルにあることを確認します。なければ、このテキストをファイルに含める必要があります。
  5. 以下の手順を実行して、CorrespondenceManagementSolutionTemplate\Services\build.xml にある Services プロジェクトの build.xml ファイルに必要な変更を加えます。
    • 以下のファイルセットエントリを追加することによって、構築クラスパスにクライアント JAR を追加します。
      ... 
               <fileset dir="../DS_SDK"> 
              <include name="*.jar"/> 
           </fileset> 
      ...
    • バンドル内のクライアント JAR 内にクラスを埋め込みます。

    build.xml ファイルは、上記の変更を反映します。
    <?xml version="1.0" encoding="UTF-8"?> 
    <!-- 
    /* 
     * ADOBE SYSTEMS INCORPORATED 
     * Copyright 2010 Adobe Systems Incorporated 
     * All Rights Reserved. 
     * 
     * NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the 
     * terms of the Adobe license agreement accompanying it.  If you have received this file from a 
     * source other than Adobe, then your use, modification, or distribution of it requires the prior 
     * written permission of Adobe. 
     */ 
    --> 
    <project name="solution-template-build" default="build-bundle" basedir="."> 
         
        <property file="../build/build.properties"/> 
        <property file="build.properties"/> 
         
        <target name="compile" description="Compile and copy the source" depends="clean"> 
            <echo>Compile classes ...</echo> 
            <path id="build.class.path"> 
                <fileset dir="../"> 
                    <include name="*.jar"/> 
                </fileset> 
                <fileset dir="../DS_SDK"> 
                    <include name="*.jar"/> 
                </fileset> 
                <fileset dir="${tp.lib.dir}"> 
                    <include name="*.jar"/> 
                </fileset> 
                <fileset dir="${[SDK]}/riaservices/assetcomposer/10.0.0.0/java"> 
                    <include name="*.jar"/> 
                </fileset> 
                <fileset dir="${[SDK]}/riaservices/datadictionary/10.0.0.0/java"> 
                    <include name="*.jar"/> 
                </fileset> 
                <fileset dir="${[SDK]}/riaservices/riacore/10.0.0.0/java"> 
                    <include name="*.jar"/> 
                </fileset> 
            </path> 
            <mkdir dir="dist/classes"/> 
            <javac destdir="dist/classes" srcdir="./src" classpathref="build.class.path" debug="true" verbose="false"/> 
            <jar destfile="dist/cmsa.jar"> 
                <fileset dir="dist/classes"> 
                    <include name="**/*"/> 
                </fileset> 
                <fileset dir="./resources"> 
                    <include name="**/*"/> 
                </fileset> 
            </jar> 
        </target> 
         
        <target name="clean"> 
            <echo>Cleanup..</echo> 
            <delete dir="dist"/> 
        </target> 
         
        <target name="build-bundle" depends="compile"> 
           <taskdef resource="aQute/bnd/ant/taskdef.properties" classpath="${tp.lib.dir}/biz.aQute.bnd.jar"/> 
           <bndwrap definitions="bnd" output="dist" jars="dist/cmsa.jar">  
            </bndwrap> 
            <zip destfile="dist/cmsa_withRE.bar"> 
                <zipgroupfileset dir="../" 
                    includes="Services/dist/cmsa.bar,DS_SDK/adobe-reader-extensions-client.jar"/> 
            </zip> 
            <move file="dist/cmsa_withRE.bar" overwrite="true" tofile="dist/cmsa.jar"/> 
        </target> 
    </project>
  6. ソリューションテンプレートを構築してデプロイし、Correspondence Management 用の Reader Extensions API のカスタム実装を完了します。詳しくは、Solution Template の構築とデプロイを参照してください。

注意: このソリューションを構築し、デプロイする前に、ReaderExtentionsServices を dscserviceWhiteList に追加する必要があります。詳しくは、レターと後処理の関連付けを参照してください。