]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.export.core/src/org/simantics/export/core/pdf/ExportPdfFormat.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.export.core / src / org / simantics / export / core / pdf / ExportPdfFormat.java
index 1f2667dab01c88f2358969f1a273ce59d992d11b..9711fbccf06e02ca60b01f837ed7e0f0b757a2d7 100644 (file)
-package org.simantics.export.core.pdf;\r
-\r
-import java.io.File;\r
-import java.io.FileNotFoundException;\r
-import java.io.FileOutputStream;\r
-import java.io.IOException;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-import java.util.StringTokenizer;\r
-import java.util.concurrent.atomic.AtomicBoolean;\r
-import java.util.regex.Pattern;\r
-\r
-import org.eclipse.core.runtime.IProduct;\r
-import org.eclipse.core.runtime.Platform;\r
-import org.eclipse.core.runtime.preferences.DefaultScope;\r
-import org.eclipse.core.runtime.preferences.InstanceScope;\r
-import org.osgi.service.prefs.Preferences;\r
-import org.simantics.databoard.Accessors;\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.Datatypes;\r
-import org.simantics.databoard.accessor.RecordAccessor;\r
-import org.simantics.databoard.accessor.UnionAccessor;\r
-import org.simantics.databoard.accessor.error.AccessorConstructionException;\r
-import org.simantics.databoard.accessor.error.AccessorException;\r
-import org.simantics.databoard.accessor.error.ReferenceException;\r
-import org.simantics.databoard.accessor.reference.ChildReference;\r
-import org.simantics.databoard.accessor.reference.LabelReference;\r
-import org.simantics.databoard.binding.mutable.Variant;\r
-import org.simantics.databoard.forms.DataboardForm;\r
-import org.simantics.databoard.type.DoubleType;\r
-import org.simantics.databoard.type.RecordType;\r
-import org.simantics.databoard.type.StringType;\r
-import org.simantics.databoard.type.UnionType;\r
-import org.simantics.export.core.ExportContext;\r
-import org.simantics.export.core.error.ExportException;\r
-import org.simantics.export.core.intf.FormatClass;\r
-import org.simantics.export.core.manager.Content;\r
-import org.simantics.export.core.util.ExporterUtils;\r
-import org.simantics.utils.page.MarginUtils;\r
-import org.simantics.utils.page.MarginUtils.Margin;\r
-import org.simantics.utils.page.MarginUtils.Margins;\r
-import org.simantics.utils.page.PageDesc;\r
-import org.simantics.utils.page.PageOrientation;\r
-\r
-import com.lowagie.text.Document;\r
-import com.lowagie.text.DocumentException;\r
-import com.lowagie.text.FontFactory;\r
-import com.lowagie.text.Rectangle;\r
-import com.lowagie.text.pdf.DefaultFontMapper;\r
-import com.lowagie.text.pdf.PdfBoolean;\r
-import com.lowagie.text.pdf.PdfCopy;\r
-import com.lowagie.text.pdf.PdfName;\r
-import com.lowagie.text.pdf.PdfWriter;\r
-\r
-/**\r
- * Represents the actions to Pdf File format in Export Core.\r
- *\r
- * @author toni.kalajainen@semantum.fi\r
- */\r
-public class ExportPdfFormat implements FormatClass {\r
-\r
-       public static final Pattern PATTERN_PDF = Pattern.compile(".*\\.pdf$", Pattern.CASE_INSENSITIVE);\r
-       \r
-       // Options references\r
-       public static String S_PDF = "Portable Document Format (PDF)";\r
-       public static ChildReference P_PDF_TITLE = ChildReference.parsePath(S_PDF+"/Title");\r
-       public static ChildReference P_PDF_AUTHOR = ChildReference.parsePath(S_PDF+"/Author");\r
-       public static ChildReference P_PDF_SUBJECT = ChildReference.parsePath(S_PDF+"/Subject");\r
-       public static ChildReference P_PDF_KEYWORDS = ChildReference.parsePath(S_PDF+"/Keywords");\r
-       public static ChildReference P_PDF_COMPRESSION = ChildReference.parsePath(S_PDF+"/Compression");\r
-       \r
-       public static String S_SIGN = "Digital Signature";\r
-       public static LabelReference P_SIGN = new LabelReference( S_SIGN );\r
-       public static ChildReference P_SIGN_KEYSTORE = ChildReference.concatenate(P_SIGN, new LabelReference("Keystore") );     \r
-       public static ChildReference P_SIGN_KEYSTOREPASSWORD = ChildReference.concatenate(P_SIGN, new LabelReference("Keystore Password"));\r
-       public static ChildReference P_SIGN_PRIVATEKEYPASSWORD = ChildReference.concatenate(P_SIGN, new LabelReference("Private Key Password"));\r
-       public static ChildReference P_SIGN_LOCATION = ChildReference.concatenate(P_SIGN, new LabelReference("Sign Location")); \r
-       public static ChildReference P_SIGN_REASON = ChildReference.concatenate(P_SIGN, new LabelReference("Sign Reason"));     \r
-\r
-       public static String S_PAGE = "Page Settings";\r
-       public static ChildReference P_PAGE = new LabelReference( S_PAGE );\r
-       public static ChildReference P_PAGE_PAPERSIZE = ChildReference.concatenate(P_PAGE, new LabelReference("Size"));\r
-       public static ChildReference P_PAGE_ORIENTATION = ChildReference.concatenate(P_PAGE, new LabelReference("Orientation"));\r
-       public static ChildReference P_PAGE_MARGIN_LEFT = ChildReference.concatenate(P_PAGE, new LabelReference("Margin Left"));\r
-       public static ChildReference P_PAGE_MARGIN_RIGHT = ChildReference.concatenate(P_PAGE, new LabelReference("Margin Right"));\r
-       public static ChildReference P_PAGE_MARGIN_TOP = ChildReference.concatenate(P_PAGE, new LabelReference("Margin Top"));\r
-       public static ChildReference P_PAGE_MARGIN_BOTTOM = ChildReference.concatenate(P_PAGE, new LabelReference("Margin Bottom"));\r
-       \r
-       // Preference page IDs\r
-    public static String PAGE_PLUGIN_ID = "org.simantics.modeling.ui";\r
-       \r
-    public static String P_DEFAULT_PAGE_SIZE        = "page.default.size";\r
-    \r
-    private static final AtomicBoolean fontFactoryInitialized = new AtomicBoolean();\r
-    \r
-    public static final RecordType pdfOptions;\r
-\r
-    static {\r
-       pdfOptions = new RecordType();          \r
-       DoubleType mm = new DoubleType();\r
-       mm.setUnit("mm");\r
-       \r
-           // PDF metadata         \r
-       RecordType pdfRecord = new RecordType();\r
-           pdfRecord.addComponent("Title", Datatypes.STRING );\r
-           pdfRecord.addComponent("Author", Datatypes.STRING );\r
-           pdfRecord.addComponent("Subject", Datatypes.STRING );\r
-           pdfRecord.addComponent("Keywords", DataboardForm.TEXTBOX );     \r
-           // Formatter options \r
-           pdfRecord.addComponent("Compression", UnionType.newEnum("0 (No compression)", "1", "2", "3", "4", "5", "6", "7", "8", "9 (Best)"));\r
-           \r
-           // PDF Encryption\r
-       RecordType pdfSign = new RecordType();\r
-           StringType certificate = DataboardForm.fileOpenDialog("PKCS#12 keystore (.p12)", "*.p12", "PFX (.pfx)", "*.pfx"); //, "Privacy Enhanced Mail (.pem)", ".pem" \r
-           pdfSign.addComponent("Keystore", certificate);\r
-           pdfSign.addComponent("Keystore Password", DataboardForm.PASSWORD);\r
-           pdfSign.addComponent("Private Key Password", DataboardForm.PASSWORD);\r
-           pdfSign.addComponent("Sign Location", Datatypes.STRING);        \r
-           pdfSign.addComponent("Sign Reason", Datatypes.STRING);                  \r
-           \r
-           PageDesc[] descs = PageDesc.PDF_ITEMS;\r
-           String[] pageSizesStr = new String[ descs.length ];\r
-           for ( int i=0; i<descs.length; i++ ) pageSizesStr[i] = descs[i].getText();\r
-           UnionType pageSizes = UnionType.newEnum("A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10");\r
-           UnionType orientation = UnionType.newEnum("Portrait", "Landscape");\r
-           RecordType pagePrefs = new RecordType();\r
-           pagePrefs.addComponent("Size", pageSizes);\r
-           pagePrefs.addComponent("Orientation", orientation);\r
-           pagePrefs.addComponent("Margin Left", mm);\r
-           pagePrefs.addComponent("Margin Right", mm);\r
-           pagePrefs.addComponent("Margin Top", mm);\r
-           pagePrefs.addComponent("Margin Bottom", mm);\r
-           //pagePrefs.metadata.put("style", "dialog");\r
-           \r
-           pdfOptions.addComponent(S_PDF, pdfRecord);\r
-           pdfOptions.addComponent(S_SIGN, pdfSign);\r
-           pdfOptions.addComponent(S_PAGE, pagePrefs);\r
-    }\r
-    \r
-       @Override\r
-       public RecordType options(ExportContext context) throws ExportException {\r
-               return pdfOptions;              \r
-       }\r
-\r
-       @Override\r
-       public Object createFile(ExportContext ctx, File outputFile, Variant options) throws ExportException {\r
-               try {\r
-                       RecordAccessor ra = Accessors.getAccessor( options );\r
-                       \r
-            if (fontFactoryInitialized.compareAndSet(false, true)) {\r
-                // Only register directories once.\r
-                FontFactory.registerDirectories();\r
-            }\r
-            \r
-                       ExportPdfWriter writer = new ExportPdfWriter();\r
-                       \r
-                       Rectangle pageSize = null;\r
-                       writer.document = new Document(pageSize);\r
-                       writer.outputFile = outputFile;\r
-                       writer.fos = new FileOutputStream(writer.outputFile);\r
-                       writer.pdfCopy = new PdfCopy(writer.document, writer.fos); \r
-                       writer.pdfCopy.setPdfVersion(PdfWriter.PDF_VERSION_1_7);\r
-                       writer.fontMapper = new DefaultFontMapper();\r
-                       writer.options = options;\r
-                       writer.ctx = ctx;\r
-\r
-                       String creator = getCreator();\r
-                       writer.document.addCreator(creator);\r
-\r
-                       String s; \r
-                       s = (String) ra.getValue(P_PDF_TITLE, Bindings.STRING);\r
-                       if ( s!=null ) writer.document.addTitle(s);                     \r
-\r
-                       s = (String) ra.getValue(P_PDF_AUTHOR, Bindings.STRING);\r
-                       if ( s!=null ) writer.document.addAuthor(s);\r
-\r
-                       s = (String) ra.getValue(P_PDF_SUBJECT, Bindings.STRING);\r
-                       if ( s!=null ) writer.document.addSubject(s);\r
-\r
-                       s = (String) ra.getValue(P_PDF_KEYWORDS, Bindings.STRING);\r
-                       if ( s!=null ) writer.document.addKeywords(s);\r
-\r
-                       // Compression Level\r
-                       try {                   \r
-                       UnionAccessor ua = ra.getComponent(P_PDF_COMPRESSION);\r
-                       int tag = ua.getTag();                  \r
-                       writer.pdfCopy.setCompressionLevel( tag );\r
-                       writer.compressionLevel = tag;\r
-               } catch (ReferenceException re) {                       \r
-                       }\r
-\r
-                       // PageSize\r
-                       {                               \r
-                               Margins margins = MarginUtils.MARGINS_10mm;\r
-                               Double left = (Double) ra.getValue(P_PAGE_MARGIN_LEFT, Bindings.DOUBLE);\r
-                               if ( left!=null ) margins = margins.withSide(Margins.LEFT, new Margin(0, 0, left));\r
-                               Double right = (Double) ra.getValue(P_PAGE_MARGIN_RIGHT, Bindings.DOUBLE);\r
-                               if ( right!=null ) margins = margins.withSide(Margins.RIGHT, new Margin(0, 0, right));\r
-                               Double bottom = (Double) ra.getValue(P_PAGE_MARGIN_BOTTOM, Bindings.DOUBLE);\r
-                               if ( bottom!=null ) margins = margins.withSide(Margins.BOTTOM, new Margin(0, 0, bottom));\r
-                               Double top = (Double) ra.getValue(P_PAGE_MARGIN_TOP, Bindings.DOUBLE);\r
-                               if ( top!=null ) margins = margins.withSide(Margins.TOP, new Margin(0, 0, top));\r
-                               \r
-                               String paperName = "A4";\r
-                               try {                   \r
-                               UnionAccessor ua = ra.getComponent(P_PAGE_PAPERSIZE);\r
-                               int tag = ua.getTag();\r
-                               paperName = ua.type().getComponent(tag).name;                           \r
-                       } catch (ReferenceException re) {                       \r
-                               }\r
-                               \r
-                               PageOrientation pageOrientation = PageOrientation.Portrait;\r
-                               try {                   \r
-                               UnionAccessor ua = ra.getComponent(P_PAGE_ORIENTATION);\r
-                               int tag = ua.getTag();\r
-                               String str = ua.type().getComponent(tag).name;\r
-                               pageOrientation = PageOrientation.valueOf( str );\r
-                       } catch (ReferenceException re) {                       \r
-                               }\r
-                               \r
-                               PageDesc pd = PageDesc.getByName(paperName);\r
-                               pd = pd.withOrientation(pageOrientation);\r
-                               pd = pd.withMargins(margins);\r
-                               writer.margins = margins;\r
-                               writer.defaultPageDesc = pd;\r
-                               writer.defaultRectangle = ExportPdfWriter.toRectangle( writer.defaultPageDesc );\r
-                               writer.document.setPageSize( writer.defaultRectangle );\r
-                       }\r
-                       \r
-                       // Add Developer Extension - not used\r
-//             PdfName companyName = new PdfName("SMTC");          \r
-//         PdfDeveloperExtension ext = new PdfDeveloperExtension(companyName, PdfWriter.PDF_VERSION_1_7, 3);\r
-//         writer.addDeveloperExtension( ext );\r
-                       \r
-                       \r
-            writer.document.open();\r
-            writer.cb = writer.pdfCopy.getDirectContent();\r
-                       \r
-                       return writer;\r
-               } catch (FileNotFoundException e) {\r
-                       throw new ExportException( e );\r
-               } catch (DocumentException e) {\r
-                       throw new ExportException( e );\r
-               } catch (AccessorConstructionException e) {\r
-                       throw new ExportException( e );\r
-               } catch (AccessorException e) {\r
-                       throw new ExportException( e );\r
-               }\r
-       }\r
-\r
-       @Override\r
-       public Object openFile(ExportContext context, File inputFile, Variant options) throws ExportException {\r
-               try {\r
-                       return new ImportPdfReader(inputFile);\r
-               } catch (IOException e) {\r
-                       throw new ExportException(e);\r
-               }\r
-       }\r
-       \r
-       @Override\r
-       public List<String> validate(ExportContext context, Variant options) throws ExportException {\r
-               List<String> problems = new ArrayList<String>();\r
-               \r
-               try {\r
-                       RecordAccessor ra = Accessors.getAccessor( options );\r
-\r
-                       // Assert the keystore file exists, if set.\r
-                       String keystoreFileName = (String) ra.getValue(P_SIGN_KEYSTORE, Bindings.STRING);                                                       \r
-                       if ( keystoreFileName != null && !keystoreFileName.isEmpty() ) {\r
-                               File keystoreFile = new File( keystoreFileName );\r
-                               if ( !keystoreFile.exists() ) {\r
-                                       problems.add( "Keystore file was not found: "+keystoreFile );\r
-                               }\r
-                       }\r
-                       \r
-               } catch (AccessorConstructionException e) {\r
-                       throw new ExportException( e );\r
-               } catch (AccessorException e) {\r
-                       throw new ExportException( e );\r
-               }\r
-               \r
-               return problems;\r
-       }\r
-\r
-       @Override\r
-       public void closeFile(ExportContext context, Object handle) throws ExportException {\r
-               if ( handle instanceof ImportPdfReader ) {\r
-                       ImportPdfReader reader = (ImportPdfReader) handle;\r
-                       reader.close();\r
-               }\r
-               \r
-               if ( handle instanceof ExportPdfWriter ) {\r
-                       ExportPdfWriter writer = (ExportPdfWriter) handle;\r
-       \r
-                       writer.close();\r
-                       \r
-                       try {\r
-                               RecordAccessor ra = Accessors.getAccessor( writer.options );\r
-                               \r
-                               String keystoreFileName = (String) ra.getValue(P_SIGN_KEYSTORE, Bindings.STRING);                               \r
-                               String keystorePassword = (String) ra.getValue(P_SIGN_KEYSTOREPASSWORD, Bindings.STRING);\r
-                               String privateKeyPassword = (String) ra.getValue(P_SIGN_PRIVATEKEYPASSWORD, Bindings.STRING);\r
-                               String signLocation = (String) ra.getValue(P_SIGN_LOCATION, Bindings.STRING);\r
-                               String signReason = (String) ra.getValue(P_SIGN_REASON, Bindings.STRING);\r
-                               \r
-                               if ( keystoreFileName != null && !keystoreFileName.isEmpty() ) \r
-                               {\r
-                                       File keystoreFile = new File( keystoreFileName );\r
-                                       if ( !keystoreFile.exists() ) {\r
-                                               throw new ExportException( "Keystore file was not found: "+keystoreFile );\r
-                                       }\r
-                                       writer.sign(keystoreFile, keystorePassword, privateKeyPassword, signLocation, signReason);\r
-                               }\r
-       \r
-                       } catch (AccessorConstructionException e) {\r
-                               throw new ExportException( e.getClass().getName()+": "+e.getMessage() );\r
-                       } catch (AccessorException e) {\r
-                               throw new ExportException( e.getClass().getName()+": "+e.getMessage() );\r
-                       }\r
-                       \r
-                       // Encrypt\r
-                   /*\r
-                   writer.setEncryption(\r
-                               new Certificate[] {}, \r
-                               new int[] {PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING}, \r
-                               PdfWriter.STANDARD_ENCRYPTION_128);\r
-                   //writer.setEncryption(PdfWriter.STANDARD_ENCRYPTION_128, "", "password", PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY);\r
-                       \r
-                       int permission = PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY;\r
-                       PdfEncryption crypto = new PdfEncryption();\r
-                       //for (Certificate c : chain) crypto.addRecipient(c, permission);\r
-                       //crypto.addRecipient(chain[2], permission);\r
-               crypto.setCryptoMode(PdfWriter.ENCRYPTION_AES_128, 0);\r
-                       crypto.setupByEncryptionKey(key.getEncoded(), key.getEncoded().length*8);\r
-               crypto.getEncryptionDictionary();\r
-                       */\r
-               }\r
-       }\r
-\r
-       @Override\r
-       public void addAttachment(ExportContext ctx, Object handle, List<Content> attachments) throws ExportException {\r
-               ExportPdfWriter writer = (ExportPdfWriter) handle; \r
-\r
-       writer.pdfCopy.addViewerPreference(PdfName.USEATTACHMENTS, PdfBoolean.PDFTRUE);\r
-               for ( Content content : attachments ) {\r
-                       writer.addAttachment( content );\r
-               }               \r
-       }\r
-       \r
-       @Override\r
-       public void savePref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {\r
-        try {\r
-                       RecordAccessor ra = Accessors.getAccessor(options);                     \r
-                       String s; \r
-                       \r
-                       s = (String) ra.getValue(P_PDF_TITLE, Bindings.STRING);\r
-                       if ( s!=null ) contentScopeNode.put(P_PDF_TITLE.tail().toString(), s);\r
-\r
-                       s = (String) ra.getValue(P_PDF_AUTHOR, Bindings.STRING);\r
-                       if ( s!=null ) workbenchScopeNode.put(P_PDF_AUTHOR.tail().toString(), s);\r
-\r
-                       s = (String) ra.getValue(P_PDF_SUBJECT, Bindings.STRING);\r
-                       if ( s!=null ) contentScopeNode.put(P_PDF_SUBJECT.tail().toString(), s);\r
-\r
-                       s = (String) ra.getValue(P_PDF_KEYWORDS, Bindings.STRING);\r
-                       if ( s!=null ) contentScopeNode.put(P_PDF_KEYWORDS.tail().toString(), s);\r
-\r
-                       s = (String) ra.getValue(P_SIGN_KEYSTORE, Bindings.STRING);\r
-                       if ( s!=null ) workbenchScopeNode.put(P_SIGN_KEYSTORE.tail().toString(), s);\r
-\r
-                       s = (String) ra.getValue(P_SIGN_KEYSTOREPASSWORD, Bindings.STRING);\r
-                       if ( s!=null ) workbenchScopeNode.put(P_SIGN_KEYSTOREPASSWORD.tail().toString(), s);\r
-\r
-                       s = (String) ra.getValue(P_SIGN_PRIVATEKEYPASSWORD, Bindings.STRING);\r
-                       if ( s!=null ) workbenchScopeNode.put(P_SIGN_PRIVATEKEYPASSWORD.tail().toString(), s);\r
-\r
-                       s = (String) ra.getValue(P_SIGN_LOCATION, Bindings.STRING);\r
-                       if ( s!=null ) workbenchScopeNode.put(P_SIGN_LOCATION.tail().toString(), s);\r
-\r
-                       s = (String) ra.getValue(P_SIGN_REASON, Bindings.STRING);\r
-                       if ( s!=null ) workbenchScopeNode.put(P_SIGN_REASON.tail().toString(), s);\r
-                       \r
-                       try {                   \r
-                       UnionAccessor ua = ra.getComponent(P_PDF_COMPRESSION);\r
-                       int tag = ua.getTag();\r
-                       workbenchScopeNode.putInt(P_PDF_COMPRESSION.tail().toString(), tag);\r
-               } catch (ReferenceException re) {                       \r
-                       }\r
-                       \r
-                       Double d = (Double) ra.getValue(P_PAGE_MARGIN_LEFT, Bindings.DOUBLE);\r
-                       if ( d!=null ) contentScopeNode.putDouble(P_PAGE_MARGIN_LEFT.tail().toString(), d);\r
-\r
-                       d = (Double) ra.getValue(P_PAGE_MARGIN_RIGHT, Bindings.DOUBLE);\r
-                       if ( d!=null ) contentScopeNode.putDouble(P_PAGE_MARGIN_RIGHT.tail().toString(), d);\r
-                       \r
-                       d = (Double) ra.getValue(P_PAGE_MARGIN_BOTTOM, Bindings.DOUBLE);\r
-                       if ( d!=null ) contentScopeNode.putDouble(P_PAGE_MARGIN_BOTTOM.tail().toString(), d);\r
-\r
-                       d = (Double) ra.getValue(P_PAGE_MARGIN_TOP, Bindings.DOUBLE);\r
-                       if ( d!=null ) contentScopeNode.putDouble(P_PAGE_MARGIN_TOP.tail().toString(), d);\r
-                       \r
-                       try {                   \r
-                       UnionAccessor ua = ra.getComponent(P_PAGE_PAPERSIZE);\r
-                       int tag = ua.getTag();\r
-                       contentScopeNode.putInt(P_PAGE_PAPERSIZE.tail().toString(), tag);\r
-               } catch (ReferenceException re) {                       \r
-                       }\r
-                       \r
-                       try {                   \r
-                       UnionAccessor ua = ra.getComponent(P_PAGE_ORIENTATION);\r
-                       int tag = ua.getTag();\r
-                       contentScopeNode.putInt(P_PAGE_ORIENTATION.tail().toString(), tag);\r
-               } catch (ReferenceException re) {                       \r
-                       }\r
-                       \r
-               } catch (AccessorConstructionException e) {\r
-                       throw new ExportException(e);\r
-               } catch (AccessorException e) {\r
-                       throw new ExportException(e);\r
-               }\r
-       }\r
-\r
-       @Override\r
-       public void loadPref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {\r
-        try {\r
-                       RecordAccessor ra = Accessors.getAccessor(options);                     \r
-                       String s;\r
-                       \r
-                       s = contentScopeNode.get(P_PDF_TITLE.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_PDF_TITLE, Bindings.STRING, s);\r
-               \r
-                       s = workbenchScopeNode.get(P_PDF_AUTHOR.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_PDF_AUTHOR, Bindings.STRING, s);\r
-               \r
-                       s = contentScopeNode.get(P_PDF_SUBJECT.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_PDF_SUBJECT, Bindings.STRING, s);\r
-               \r
-                       s = contentScopeNode.get(P_PDF_KEYWORDS.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_PDF_KEYWORDS, Bindings.STRING, s);\r
-               \r
-                       s = workbenchScopeNode.get(P_SIGN_KEYSTORE.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_SIGN_KEYSTORE, Bindings.STRING, s);\r
-               \r
-                       s = workbenchScopeNode.get(P_SIGN_KEYSTOREPASSWORD.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_SIGN_KEYSTOREPASSWORD, Bindings.STRING, s);\r
-               \r
-                       s = workbenchScopeNode.get(P_SIGN_PRIVATEKEYPASSWORD.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_SIGN_PRIVATEKEYPASSWORD, Bindings.STRING, s);\r
-\r
-                       s = workbenchScopeNode.get(P_SIGN_LOCATION.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_SIGN_LOCATION, Bindings.STRING, s);\r
-                       \r
-                       s = workbenchScopeNode.get(P_SIGN_REASON.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_SIGN_REASON, Bindings.STRING, s);\r
-\r
-                       int tag = workbenchScopeNode.getInt(P_PDF_COMPRESSION.tail().toString(), -1);\r
-                       if ( tag>=0 )\r
-               try {                   \r
-                       UnionAccessor ua = ra.getComponent(P_PDF_COMPRESSION);\r
-                       ua.setComponentValue(tag, Bindings.VOID, null);\r
-               } catch (ReferenceException re) {                       \r
-                       }\r
-               \r
-               \r
-\r
-                       s = contentScopeNode.get(P_PAGE_MARGIN_LEFT.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_PAGE_MARGIN_LEFT, Bindings.DOUBLE, Double.valueOf(s));\r
-               \r
-                       s = contentScopeNode.get(P_PAGE_MARGIN_RIGHT.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_PAGE_MARGIN_RIGHT, Bindings.DOUBLE, Double.valueOf(s));\r
-               \r
-                       s = contentScopeNode.get(P_PAGE_MARGIN_TOP.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_PAGE_MARGIN_TOP, Bindings.DOUBLE, Double.valueOf(s));\r
-               \r
-                       s = contentScopeNode.get(P_PAGE_MARGIN_BOTTOM.tail().toString(), null);\r
-                       if ( s!=null ) ra.setValue(P_PAGE_MARGIN_BOTTOM, Bindings.DOUBLE, Double.valueOf(s));\r
-                       \r
-                       tag = contentScopeNode.getInt(P_PAGE_PAPERSIZE.tail().toString(), -1);\r
-                       if ( tag>=0 )\r
-               try {                   \r
-                       UnionAccessor ua = ra.getComponent(P_PAGE_PAPERSIZE);\r
-                       ua.setComponentValue(tag, Bindings.VOID, null);\r
-               } catch (ReferenceException re) {                       \r
-                       }\r
-                       \r
-                       tag = contentScopeNode.getInt(P_PAGE_ORIENTATION.tail().toString(), -1);\r
-                       if ( tag>=0 )\r
-               try {                   \r
-                       UnionAccessor ua = ra.getComponent(P_PAGE_ORIENTATION);\r
-                       ua.setComponentValue(tag, Bindings.VOID, null);\r
-               } catch (ReferenceException re) {                       \r
-                       }\r
-               \r
-               \r
-               } catch (AccessorConstructionException e) {\r
-                       throw new ExportException(e);\r
-               } catch (AccessorException e) {\r
-                       throw new ExportException(e);\r
-               }\r
-       }\r
-\r
-       @Override\r
-       public void fillDefaultPrefs( ExportContext ctx, Variant options) throws ExportException {\r
-        try {\r
-                       RecordAccessor ra = Accessors.getAccessor(options);     \r
-\r
-                       Preferences instPrefs = InstanceScope.INSTANCE.getNode( PAGE_PLUGIN_ID );\r
-                       Preferences defaultPrefs = DefaultScope.INSTANCE.getNode( PAGE_PLUGIN_ID );\r
-                       \r
-                       String value = ExporterUtils.getPrefString(instPrefs, defaultPrefs, P_DEFAULT_PAGE_SIZE);\r
-               if ( value != null ) {\r
-                       try {\r
-                    StringTokenizer tok = new StringTokenizer( value );\r
-                    String w = tok.nextToken().trim();\r
-                    String h = tok.nextToken().trim();\r
-                    String orientation = tok.nextToken().trim();\r
-                    if ( orientation!=null ) {\r
-                               try {                                                           \r
-                               UnionAccessor ua = ra.getComponent(P_PAGE_ORIENTATION);\r
-                               int index = ua.type().getComponentIndex2(orientation);\r
-                               if ( index<0 ) index = 1;\r
-                               ua.setComponentValue(index, Bindings.VOID, new Object());\r
-                       } catch (ReferenceException re) {                                                                       \r
-                               }\r
-                    }\r
-                    String centering = tok.nextToken().trim();\r
-                    String pagesize = tok.nextToken("\u0001").trim();\r
-                    ExporterUtils.setUnionValue(ra, P_PAGE_PAPERSIZE, pagesize);\r
-                    \r
-                    String margins = tok.nextToken().trim();                               \r
-                    if ( margins != null ) {\r
-                        String[] split = margins.split(";");\r
-                        if (split.length == 4) {\r
-                               for (int i=0; i<4; i++) {\r
-                                       String[] tok2 = split[i].split(" ");\r
-                                       String controlRelative = tok2[0];\r
-                                       String controlAbsolute = tok2[1];\r
-                                       String diagramAbsolute = tok2[2];\r
-                                       \r
-                                       ChildReference ref = null;\r
-                                       switch (i) {\r
-                                               case 0: ref = P_PAGE_MARGIN_TOP; break;\r
-                                               case 1: ref = P_PAGE_MARGIN_BOTTOM; break;\r
-                                               case 2: ref = P_PAGE_MARGIN_LEFT; break;\r
-                                               case 3: ref = P_PAGE_MARGIN_RIGHT; break;\r
-                                       }\r
-                                       double margin_mm = Double.valueOf(diagramAbsolute);\r
-                                               ra.setValue(ref, Bindings.DOUBLE, margin_mm);                                                           \r
-                               }                                               \r
-                        }\r
-                    }\r
-                       } catch( Exception e ) {\r
-                               // This is not so important that pdf export should fail.\r
-                               e.printStackTrace();\r
-                       }\r
-\r
-               }\r
-                       \r
-               String username = System.getProperty("user.name");\r
-               if ( username != null ) ra.setValue(P_PDF_AUTHOR, Bindings.STRING, username);\r
-\r
-               ra.setValue(P_SIGN_REASON, Bindings.STRING, "Document Created");\r
-               ExporterUtils.setUnionValue(ra, P_PDF_COMPRESSION, 9);          \r
-               \r
-               } catch (AccessorConstructionException e) {\r
-                       throw new ExportException(e);\r
-               } catch (AccessorException e) {\r
-                       throw new ExportException(e);\r
-               }\r
-       }       \r
-\r
-       public static String getCreator() {\r
-               String creator = null;\r
-               IProduct product = Platform.getProduct();\r
-               if (product != null) {\r
-                       creator = product.getDescription();\r
-                       if (creator == null) {\r
-                               creator = product.getName();\r
-                       }\r
-               }\r
-               if (creator == null) {\r
-                       creator = "Simantics";\r
-               }\r
-               return creator;\r
-       }\r
-\r
-       public static boolean isPdf(String filename) {\r
-               return PATTERN_PDF.matcher(filename).matches();\r
-       }\r
-       \r
-       public static boolean isPdf(File file) {\r
-               return PATTERN_PDF.matcher(file.getName()).matches();\r
-       }\r
-       \r
-}\r
+package org.simantics.export.core.pdf;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.runtime.IProduct;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.osgi.service.prefs.Preferences;
+import org.simantics.databoard.Accessors;
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Datatypes;
+import org.simantics.databoard.accessor.RecordAccessor;
+import org.simantics.databoard.accessor.UnionAccessor;
+import org.simantics.databoard.accessor.error.AccessorConstructionException;
+import org.simantics.databoard.accessor.error.AccessorException;
+import org.simantics.databoard.accessor.error.ReferenceException;
+import org.simantics.databoard.accessor.reference.ChildReference;
+import org.simantics.databoard.accessor.reference.LabelReference;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.databoard.forms.DataboardForm;
+import org.simantics.databoard.type.DoubleType;
+import org.simantics.databoard.type.RecordType;
+import org.simantics.databoard.type.StringType;
+import org.simantics.databoard.type.UnionType;
+import org.simantics.export.core.ExportContext;
+import org.simantics.export.core.error.ExportException;
+import org.simantics.export.core.intf.FormatClass;
+import org.simantics.export.core.manager.Content;
+import org.simantics.export.core.util.ExporterUtils;
+import org.simantics.utils.page.MarginUtils;
+import org.simantics.utils.page.MarginUtils.Margin;
+import org.simantics.utils.page.MarginUtils.Margins;
+import org.simantics.utils.page.PageDesc;
+import org.simantics.utils.page.PageOrientation;
+
+import com.lowagie.text.Document;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.FontFactory;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.DefaultFontMapper;
+import com.lowagie.text.pdf.PdfBoolean;
+import com.lowagie.text.pdf.PdfCopy;
+import com.lowagie.text.pdf.PdfName;
+import com.lowagie.text.pdf.PdfWriter;
+
+/**
+ * Represents the actions to Pdf File format in Export Core.
+ *
+ * @author toni.kalajainen@semantum.fi
+ */
+public class ExportPdfFormat implements FormatClass {
+
+       public static final Pattern PATTERN_PDF = Pattern.compile(".*\\.pdf$", Pattern.CASE_INSENSITIVE);
+       
+       // Options references
+       public static String S_PDF = "Portable Document Format (PDF)";
+       public static ChildReference P_PDF_TITLE = ChildReference.parsePath(S_PDF+"/Title");
+       public static ChildReference P_PDF_AUTHOR = ChildReference.parsePath(S_PDF+"/Author");
+       public static ChildReference P_PDF_SUBJECT = ChildReference.parsePath(S_PDF+"/Subject");
+       public static ChildReference P_PDF_KEYWORDS = ChildReference.parsePath(S_PDF+"/Keywords");
+       public static ChildReference P_PDF_COMPRESSION = ChildReference.parsePath(S_PDF+"/Compression");
+       
+       public static String S_SIGN = "Digital Signature";
+       public static LabelReference P_SIGN = new LabelReference( S_SIGN );
+       public static ChildReference P_SIGN_KEYSTORE = ChildReference.concatenate(P_SIGN, new LabelReference("Keystore") );     
+       public static ChildReference P_SIGN_KEYSTOREPASSWORD = ChildReference.concatenate(P_SIGN, new LabelReference("Keystore Password"));
+       public static ChildReference P_SIGN_PRIVATEKEYPASSWORD = ChildReference.concatenate(P_SIGN, new LabelReference("Private Key Password"));
+       public static ChildReference P_SIGN_LOCATION = ChildReference.concatenate(P_SIGN, new LabelReference("Sign Location")); 
+       public static ChildReference P_SIGN_REASON = ChildReference.concatenate(P_SIGN, new LabelReference("Sign Reason"));     
+
+       public static String S_PAGE = "Page Settings";
+       public static ChildReference P_PAGE = new LabelReference( S_PAGE );
+       public static ChildReference P_PAGE_PAPERSIZE = ChildReference.concatenate(P_PAGE, new LabelReference("Size"));
+       public static ChildReference P_PAGE_ORIENTATION = ChildReference.concatenate(P_PAGE, new LabelReference("Orientation"));
+       public static ChildReference P_PAGE_MARGIN_LEFT = ChildReference.concatenate(P_PAGE, new LabelReference("Margin Left"));
+       public static ChildReference P_PAGE_MARGIN_RIGHT = ChildReference.concatenate(P_PAGE, new LabelReference("Margin Right"));
+       public static ChildReference P_PAGE_MARGIN_TOP = ChildReference.concatenate(P_PAGE, new LabelReference("Margin Top"));
+       public static ChildReference P_PAGE_MARGIN_BOTTOM = ChildReference.concatenate(P_PAGE, new LabelReference("Margin Bottom"));
+       
+       // Preference page IDs
+    public static String PAGE_PLUGIN_ID = "org.simantics.modeling.ui";
+       
+    public static String P_DEFAULT_PAGE_SIZE        = "page.default.size";
+    
+    private static final AtomicBoolean fontFactoryInitialized = new AtomicBoolean();
+    
+    public static final RecordType pdfOptions;
+
+    static {
+       pdfOptions = new RecordType();          
+       DoubleType mm = new DoubleType();
+       mm.setUnit("mm");
+       
+           // PDF metadata         
+       RecordType pdfRecord = new RecordType();
+           pdfRecord.addComponent("Title", Datatypes.STRING );
+           pdfRecord.addComponent("Author", Datatypes.STRING );
+           pdfRecord.addComponent("Subject", Datatypes.STRING );
+           pdfRecord.addComponent("Keywords", DataboardForm.TEXTBOX );     
+           // Formatter options 
+           pdfRecord.addComponent("Compression", UnionType.newEnum("0 (No compression)", "1", "2", "3", "4", "5", "6", "7", "8", "9 (Best)"));
+           
+           // PDF Encryption
+       RecordType pdfSign = new RecordType();
+           StringType certificate = DataboardForm.fileOpenDialog("PKCS#12 keystore (.p12)", "*.p12", "PFX (.pfx)", "*.pfx"); //, "Privacy Enhanced Mail (.pem)", ".pem" 
+           pdfSign.addComponent("Keystore", certificate);
+           pdfSign.addComponent("Keystore Password", DataboardForm.PASSWORD);
+           pdfSign.addComponent("Private Key Password", DataboardForm.PASSWORD);
+           pdfSign.addComponent("Sign Location", Datatypes.STRING);        
+           pdfSign.addComponent("Sign Reason", Datatypes.STRING);                  
+           
+           PageDesc[] descs = PageDesc.PDF_ITEMS;
+           String[] pageSizesStr = new String[ descs.length ];
+           for ( int i=0; i<descs.length; i++ ) pageSizesStr[i] = descs[i].getText();
+           UnionType pageSizes = UnionType.newEnum("A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10");
+           UnionType orientation = UnionType.newEnum("Portrait", "Landscape");
+           RecordType pagePrefs = new RecordType();
+           pagePrefs.addComponent("Size", pageSizes);
+           pagePrefs.addComponent("Orientation", orientation);
+           pagePrefs.addComponent("Margin Left", mm);
+           pagePrefs.addComponent("Margin Right", mm);
+           pagePrefs.addComponent("Margin Top", mm);
+           pagePrefs.addComponent("Margin Bottom", mm);
+           //pagePrefs.metadata.put("style", "dialog");
+           
+           pdfOptions.addComponent(S_PDF, pdfRecord);
+           pdfOptions.addComponent(S_SIGN, pdfSign);
+           pdfOptions.addComponent(S_PAGE, pagePrefs);
+    }
+    
+       @Override
+       public RecordType options(ExportContext context) throws ExportException {
+               return pdfOptions;              
+       }
+
+       @Override
+       public Object createFile(ExportContext ctx, File outputFile, Variant options) throws ExportException {
+               try {
+                       RecordAccessor ra = Accessors.getAccessor( options );
+                       
+            if (fontFactoryInitialized.compareAndSet(false, true)) {
+                // Only register directories once.
+                FontFactory.registerDirectories();
+            }
+            
+                       ExportPdfWriter writer = new ExportPdfWriter();
+                       
+                       Rectangle pageSize = null;
+                       writer.document = new Document(pageSize);
+                       writer.outputFile = outputFile;
+                       writer.fos = new FileOutputStream(writer.outputFile);
+                       writer.pdfCopy = new PdfCopy(writer.document, writer.fos); 
+                       writer.pdfCopy.setPdfVersion(PdfWriter.PDF_VERSION_1_7);
+                       writer.fontMapper = new DefaultFontMapper();
+                       writer.options = options;
+                       writer.ctx = ctx;
+
+                       String creator = getCreator();
+                       writer.document.addCreator(creator);
+
+                       String s; 
+                       s = (String) ra.getValue(P_PDF_TITLE, Bindings.STRING);
+                       if ( s!=null ) writer.document.addTitle(s);                     
+
+                       s = (String) ra.getValue(P_PDF_AUTHOR, Bindings.STRING);
+                       if ( s!=null ) writer.document.addAuthor(s);
+
+                       s = (String) ra.getValue(P_PDF_SUBJECT, Bindings.STRING);
+                       if ( s!=null ) writer.document.addSubject(s);
+
+                       s = (String) ra.getValue(P_PDF_KEYWORDS, Bindings.STRING);
+                       if ( s!=null ) writer.document.addKeywords(s);
+
+                       // Compression Level
+                       try {                   
+                       UnionAccessor ua = ra.getComponent(P_PDF_COMPRESSION);
+                       int tag = ua.getTag();                  
+                       writer.pdfCopy.setCompressionLevel( tag );
+                       writer.compressionLevel = tag;
+               } catch (ReferenceException re) {                       
+                       }
+
+                       // PageSize
+                       {                               
+                               Margins margins = MarginUtils.MARGINS_10mm;
+                               Double left = (Double) ra.getValue(P_PAGE_MARGIN_LEFT, Bindings.DOUBLE);
+                               if ( left!=null ) margins = margins.withSide(Margins.LEFT, new Margin(0, 0, left));
+                               Double right = (Double) ra.getValue(P_PAGE_MARGIN_RIGHT, Bindings.DOUBLE);
+                               if ( right!=null ) margins = margins.withSide(Margins.RIGHT, new Margin(0, 0, right));
+                               Double bottom = (Double) ra.getValue(P_PAGE_MARGIN_BOTTOM, Bindings.DOUBLE);
+                               if ( bottom!=null ) margins = margins.withSide(Margins.BOTTOM, new Margin(0, 0, bottom));
+                               Double top = (Double) ra.getValue(P_PAGE_MARGIN_TOP, Bindings.DOUBLE);
+                               if ( top!=null ) margins = margins.withSide(Margins.TOP, new Margin(0, 0, top));
+                               
+                               String paperName = "A4";
+                               try {                   
+                               UnionAccessor ua = ra.getComponent(P_PAGE_PAPERSIZE);
+                               int tag = ua.getTag();
+                               paperName = ua.type().getComponent(tag).name;                           
+                       } catch (ReferenceException re) {                       
+                               }
+                               
+                               PageOrientation pageOrientation = PageOrientation.Portrait;
+                               try {                   
+                               UnionAccessor ua = ra.getComponent(P_PAGE_ORIENTATION);
+                               int tag = ua.getTag();
+                               String str = ua.type().getComponent(tag).name;
+                               pageOrientation = PageOrientation.valueOf( str );
+                       } catch (ReferenceException re) {                       
+                               }
+                               
+                               PageDesc pd = PageDesc.getByName(paperName);
+                               pd = pd.withOrientation(pageOrientation);
+                               pd = pd.withMargins(margins);
+                               writer.margins = margins;
+                               writer.defaultPageDesc = pd;
+                               writer.defaultRectangle = ExportPdfWriter.toRectangle( writer.defaultPageDesc );
+                               writer.document.setPageSize( writer.defaultRectangle );
+                       }
+                       
+                       // Add Developer Extension - not used
+//             PdfName companyName = new PdfName("SMTC");          
+//         PdfDeveloperExtension ext = new PdfDeveloperExtension(companyName, PdfWriter.PDF_VERSION_1_7, 3);
+//         writer.addDeveloperExtension( ext );
+                       
+                       
+            writer.document.open();
+            writer.cb = writer.pdfCopy.getDirectContent();
+                       
+                       return writer;
+               } catch (FileNotFoundException e) {
+                       throw new ExportException( e );
+               } catch (DocumentException e) {
+                       throw new ExportException( e );
+               } catch (AccessorConstructionException e) {
+                       throw new ExportException( e );
+               } catch (AccessorException e) {
+                       throw new ExportException( e );
+               }
+       }
+
+       @Override
+       public Object openFile(ExportContext context, File inputFile, Variant options) throws ExportException {
+               try {
+                       return new ImportPdfReader(inputFile);
+               } catch (IOException e) {
+                       throw new ExportException(e);
+               }
+       }
+       
+       @Override
+       public List<String> validate(ExportContext context, Variant options) throws ExportException {
+               List<String> problems = new ArrayList<String>();
+               
+               try {
+                       RecordAccessor ra = Accessors.getAccessor( options );
+
+                       // Assert the keystore file exists, if set.
+                       String keystoreFileName = (String) ra.getValue(P_SIGN_KEYSTORE, Bindings.STRING);                                                       
+                       if ( keystoreFileName != null && !keystoreFileName.isEmpty() ) {
+                               File keystoreFile = new File( keystoreFileName );
+                               if ( !keystoreFile.exists() ) {
+                                       problems.add( "Keystore file was not found: "+keystoreFile );
+                               }
+                       }
+                       
+               } catch (AccessorConstructionException e) {
+                       throw new ExportException( e );
+               } catch (AccessorException e) {
+                       throw new ExportException( e );
+               }
+               
+               return problems;
+       }
+
+       @Override
+       public void closeFile(ExportContext context, Object handle) throws ExportException {
+               if ( handle instanceof ImportPdfReader ) {
+                       ImportPdfReader reader = (ImportPdfReader) handle;
+                       reader.close();
+               }
+               
+               if ( handle instanceof ExportPdfWriter ) {
+                       ExportPdfWriter writer = (ExportPdfWriter) handle;
+       
+                       writer.close();
+                       
+                       try {
+                               RecordAccessor ra = Accessors.getAccessor( writer.options );
+                               
+                               String keystoreFileName = (String) ra.getValue(P_SIGN_KEYSTORE, Bindings.STRING);                               
+                               String keystorePassword = (String) ra.getValue(P_SIGN_KEYSTOREPASSWORD, Bindings.STRING);
+                               String privateKeyPassword = (String) ra.getValue(P_SIGN_PRIVATEKEYPASSWORD, Bindings.STRING);
+                               String signLocation = (String) ra.getValue(P_SIGN_LOCATION, Bindings.STRING);
+                               String signReason = (String) ra.getValue(P_SIGN_REASON, Bindings.STRING);
+                               
+                               if ( keystoreFileName != null && !keystoreFileName.isEmpty() ) 
+                               {
+                                       File keystoreFile = new File( keystoreFileName );
+                                       if ( !keystoreFile.exists() ) {
+                                               throw new ExportException( "Keystore file was not found: "+keystoreFile );
+                                       }
+                                       writer.sign(keystoreFile, keystorePassword, privateKeyPassword, signLocation, signReason);
+                               }
+       
+                       } catch (AccessorConstructionException e) {
+                               throw new ExportException( e.getClass().getName()+": "+e.getMessage() );
+                       } catch (AccessorException e) {
+                               throw new ExportException( e.getClass().getName()+": "+e.getMessage() );
+                       }
+                       
+                       // Encrypt
+                   /*
+                   writer.setEncryption(
+                               new Certificate[] {}, 
+                               new int[] {PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING}, 
+                               PdfWriter.STANDARD_ENCRYPTION_128);
+                   //writer.setEncryption(PdfWriter.STANDARD_ENCRYPTION_128, "", "password", PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY);
+                       
+                       int permission = PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY;
+                       PdfEncryption crypto = new PdfEncryption();
+                       //for (Certificate c : chain) crypto.addRecipient(c, permission);
+                       //crypto.addRecipient(chain[2], permission);
+               crypto.setCryptoMode(PdfWriter.ENCRYPTION_AES_128, 0);
+                       crypto.setupByEncryptionKey(key.getEncoded(), key.getEncoded().length*8);
+               crypto.getEncryptionDictionary();
+                       */
+               }
+       }
+
+       @Override
+       public void addAttachment(ExportContext ctx, Object handle, List<Content> attachments) throws ExportException {
+               ExportPdfWriter writer = (ExportPdfWriter) handle; 
+
+       writer.pdfCopy.addViewerPreference(PdfName.USEATTACHMENTS, PdfBoolean.PDFTRUE);
+               for ( Content content : attachments ) {
+                       writer.addAttachment( content );
+               }               
+       }
+       
+       @Override
+       public void savePref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {
+        try {
+                       RecordAccessor ra = Accessors.getAccessor(options);                     
+                       String s; 
+                       
+                       s = (String) ra.getValue(P_PDF_TITLE, Bindings.STRING);
+                       if ( s!=null ) contentScopeNode.put(P_PDF_TITLE.tail().toString(), s);
+
+                       s = (String) ra.getValue(P_PDF_AUTHOR, Bindings.STRING);
+                       if ( s!=null ) workbenchScopeNode.put(P_PDF_AUTHOR.tail().toString(), s);
+
+                       s = (String) ra.getValue(P_PDF_SUBJECT, Bindings.STRING);
+                       if ( s!=null ) contentScopeNode.put(P_PDF_SUBJECT.tail().toString(), s);
+
+                       s = (String) ra.getValue(P_PDF_KEYWORDS, Bindings.STRING);
+                       if ( s!=null ) contentScopeNode.put(P_PDF_KEYWORDS.tail().toString(), s);
+
+                       s = (String) ra.getValue(P_SIGN_KEYSTORE, Bindings.STRING);
+                       if ( s!=null ) workbenchScopeNode.put(P_SIGN_KEYSTORE.tail().toString(), s);
+
+                       s = (String) ra.getValue(P_SIGN_KEYSTOREPASSWORD, Bindings.STRING);
+                       if ( s!=null ) workbenchScopeNode.put(P_SIGN_KEYSTOREPASSWORD.tail().toString(), s);
+
+                       s = (String) ra.getValue(P_SIGN_PRIVATEKEYPASSWORD, Bindings.STRING);
+                       if ( s!=null ) workbenchScopeNode.put(P_SIGN_PRIVATEKEYPASSWORD.tail().toString(), s);
+
+                       s = (String) ra.getValue(P_SIGN_LOCATION, Bindings.STRING);
+                       if ( s!=null ) workbenchScopeNode.put(P_SIGN_LOCATION.tail().toString(), s);
+
+                       s = (String) ra.getValue(P_SIGN_REASON, Bindings.STRING);
+                       if ( s!=null ) workbenchScopeNode.put(P_SIGN_REASON.tail().toString(), s);
+                       
+                       try {                   
+                       UnionAccessor ua = ra.getComponent(P_PDF_COMPRESSION);
+                       int tag = ua.getTag();
+                       workbenchScopeNode.putInt(P_PDF_COMPRESSION.tail().toString(), tag);
+               } catch (ReferenceException re) {                       
+                       }
+                       
+                       Double d = (Double) ra.getValue(P_PAGE_MARGIN_LEFT, Bindings.DOUBLE);
+                       if ( d!=null ) contentScopeNode.putDouble(P_PAGE_MARGIN_LEFT.tail().toString(), d);
+
+                       d = (Double) ra.getValue(P_PAGE_MARGIN_RIGHT, Bindings.DOUBLE);
+                       if ( d!=null ) contentScopeNode.putDouble(P_PAGE_MARGIN_RIGHT.tail().toString(), d);
+                       
+                       d = (Double) ra.getValue(P_PAGE_MARGIN_BOTTOM, Bindings.DOUBLE);
+                       if ( d!=null ) contentScopeNode.putDouble(P_PAGE_MARGIN_BOTTOM.tail().toString(), d);
+
+                       d = (Double) ra.getValue(P_PAGE_MARGIN_TOP, Bindings.DOUBLE);
+                       if ( d!=null ) contentScopeNode.putDouble(P_PAGE_MARGIN_TOP.tail().toString(), d);
+                       
+                       try {                   
+                       UnionAccessor ua = ra.getComponent(P_PAGE_PAPERSIZE);
+                       int tag = ua.getTag();
+                       contentScopeNode.putInt(P_PAGE_PAPERSIZE.tail().toString(), tag);
+               } catch (ReferenceException re) {                       
+                       }
+                       
+                       try {                   
+                       UnionAccessor ua = ra.getComponent(P_PAGE_ORIENTATION);
+                       int tag = ua.getTag();
+                       contentScopeNode.putInt(P_PAGE_ORIENTATION.tail().toString(), tag);
+               } catch (ReferenceException re) {                       
+                       }
+                       
+               } catch (AccessorConstructionException e) {
+                       throw new ExportException(e);
+               } catch (AccessorException e) {
+                       throw new ExportException(e);
+               }
+       }
+
+       @Override
+       public void loadPref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {
+        try {
+                       RecordAccessor ra = Accessors.getAccessor(options);                     
+                       String s;
+                       
+                       s = contentScopeNode.get(P_PDF_TITLE.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_PDF_TITLE, Bindings.STRING, s);
+               
+                       s = workbenchScopeNode.get(P_PDF_AUTHOR.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_PDF_AUTHOR, Bindings.STRING, s);
+               
+                       s = contentScopeNode.get(P_PDF_SUBJECT.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_PDF_SUBJECT, Bindings.STRING, s);
+               
+                       s = contentScopeNode.get(P_PDF_KEYWORDS.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_PDF_KEYWORDS, Bindings.STRING, s);
+               
+                       s = workbenchScopeNode.get(P_SIGN_KEYSTORE.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_SIGN_KEYSTORE, Bindings.STRING, s);
+               
+                       s = workbenchScopeNode.get(P_SIGN_KEYSTOREPASSWORD.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_SIGN_KEYSTOREPASSWORD, Bindings.STRING, s);
+               
+                       s = workbenchScopeNode.get(P_SIGN_PRIVATEKEYPASSWORD.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_SIGN_PRIVATEKEYPASSWORD, Bindings.STRING, s);
+
+                       s = workbenchScopeNode.get(P_SIGN_LOCATION.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_SIGN_LOCATION, Bindings.STRING, s);
+                       
+                       s = workbenchScopeNode.get(P_SIGN_REASON.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_SIGN_REASON, Bindings.STRING, s);
+
+                       int tag = workbenchScopeNode.getInt(P_PDF_COMPRESSION.tail().toString(), -1);
+                       if ( tag>=0 )
+               try {                   
+                       UnionAccessor ua = ra.getComponent(P_PDF_COMPRESSION);
+                       ua.setComponentValue(tag, Bindings.VOID, null);
+               } catch (ReferenceException re) {                       
+                       }
+               
+               
+
+                       s = contentScopeNode.get(P_PAGE_MARGIN_LEFT.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_PAGE_MARGIN_LEFT, Bindings.DOUBLE, Double.valueOf(s));
+               
+                       s = contentScopeNode.get(P_PAGE_MARGIN_RIGHT.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_PAGE_MARGIN_RIGHT, Bindings.DOUBLE, Double.valueOf(s));
+               
+                       s = contentScopeNode.get(P_PAGE_MARGIN_TOP.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_PAGE_MARGIN_TOP, Bindings.DOUBLE, Double.valueOf(s));
+               
+                       s = contentScopeNode.get(P_PAGE_MARGIN_BOTTOM.tail().toString(), null);
+                       if ( s!=null ) ra.setValue(P_PAGE_MARGIN_BOTTOM, Bindings.DOUBLE, Double.valueOf(s));
+                       
+                       tag = contentScopeNode.getInt(P_PAGE_PAPERSIZE.tail().toString(), -1);
+                       if ( tag>=0 )
+               try {                   
+                       UnionAccessor ua = ra.getComponent(P_PAGE_PAPERSIZE);
+                       ua.setComponentValue(tag, Bindings.VOID, null);
+               } catch (ReferenceException re) {                       
+                       }
+                       
+                       tag = contentScopeNode.getInt(P_PAGE_ORIENTATION.tail().toString(), -1);
+                       if ( tag>=0 )
+               try {                   
+                       UnionAccessor ua = ra.getComponent(P_PAGE_ORIENTATION);
+                       ua.setComponentValue(tag, Bindings.VOID, null);
+               } catch (ReferenceException re) {                       
+                       }
+               
+               
+               } catch (AccessorConstructionException e) {
+                       throw new ExportException(e);
+               } catch (AccessorException e) {
+                       throw new ExportException(e);
+               }
+       }
+
+       @Override
+       public void fillDefaultPrefs( ExportContext ctx, Variant options) throws ExportException {
+        try {
+                       RecordAccessor ra = Accessors.getAccessor(options);     
+
+                       Preferences instPrefs = InstanceScope.INSTANCE.getNode( PAGE_PLUGIN_ID );
+                       Preferences defaultPrefs = DefaultScope.INSTANCE.getNode( PAGE_PLUGIN_ID );
+                       
+                       String value = ExporterUtils.getPrefString(instPrefs, defaultPrefs, P_DEFAULT_PAGE_SIZE);
+               if ( value != null ) {
+                       try {
+                    StringTokenizer tok = new StringTokenizer( value );
+                    String w = tok.nextToken().trim();
+                    String h = tok.nextToken().trim();
+                    String orientation = tok.nextToken().trim();
+                    if ( orientation!=null ) {
+                               try {                                                           
+                               UnionAccessor ua = ra.getComponent(P_PAGE_ORIENTATION);
+                               int index = ua.type().getComponentIndex2(orientation);
+                               if ( index<0 ) index = 1;
+                               ua.setComponentValue(index, Bindings.VOID, new Object());
+                       } catch (ReferenceException re) {                                                                       
+                               }
+                    }
+                    String centering = tok.nextToken().trim();
+                    String pagesize = tok.nextToken("\u0001").trim();
+                    ExporterUtils.setUnionValue(ra, P_PAGE_PAPERSIZE, pagesize);
+                    
+                    String margins = tok.nextToken().trim();                               
+                    if ( margins != null ) {
+                        String[] split = margins.split(";");
+                        if (split.length == 4) {
+                               for (int i=0; i<4; i++) {
+                                       String[] tok2 = split[i].split(" ");
+                                       String controlRelative = tok2[0];
+                                       String controlAbsolute = tok2[1];
+                                       String diagramAbsolute = tok2[2];
+                                       
+                                       ChildReference ref = null;
+                                       switch (i) {
+                                               case 0: ref = P_PAGE_MARGIN_TOP; break;
+                                               case 1: ref = P_PAGE_MARGIN_BOTTOM; break;
+                                               case 2: ref = P_PAGE_MARGIN_LEFT; break;
+                                               case 3: ref = P_PAGE_MARGIN_RIGHT; break;
+                                       }
+                                       double margin_mm = Double.valueOf(diagramAbsolute);
+                                               ra.setValue(ref, Bindings.DOUBLE, margin_mm);                                                           
+                               }                                               
+                        }
+                    }
+                       } catch( Exception e ) {
+                               // This is not so important that pdf export should fail.
+                               e.printStackTrace();
+                       }
+
+               }
+                       
+               String username = System.getProperty("user.name");
+               if ( username != null ) ra.setValue(P_PDF_AUTHOR, Bindings.STRING, username);
+
+               ra.setValue(P_SIGN_REASON, Bindings.STRING, "Document Created");
+               ExporterUtils.setUnionValue(ra, P_PDF_COMPRESSION, 9);          
+               
+               } catch (AccessorConstructionException e) {
+                       throw new ExportException(e);
+               } catch (AccessorException e) {
+                       throw new ExportException(e);
+               }
+       }       
+
+       public static String getCreator() {
+               String creator = null;
+               IProduct product = Platform.getProduct();
+               if (product != null) {
+                       creator = product.getDescription();
+                       if (creator == null) {
+                               creator = product.getName();
+                       }
+               }
+               if (creator == null) {
+                       creator = "Simantics";
+               }
+               return creator;
+       }
+
+       public static boolean isPdf(String filename) {
+               return PATTERN_PDF.matcher(filename).matches();
+       }
+       
+       public static boolean isPdf(File file) {
+               return PATTERN_PDF.matcher(file.getName()).matches();
+       }
+       
+}