]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/DiagramPrinter.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / pdf / DiagramPrinter.java
index 1b916fcb0b884524614d205b1da61851b70a236d..e3101dce2e31ea8d2e200d9f96f56c692e6e463f 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.modeling.ui.pdf;\r
-\r
-import java.io.FileNotFoundException;\r
-import java.io.FileOutputStream;\r
-import java.security.Security;\r
-import java.util.Collection;\r
-import java.util.concurrent.atomic.AtomicBoolean;\r
-\r
-import org.eclipse.core.runtime.IProduct;\r
-import org.eclipse.core.runtime.IProgressMonitor;\r
-import org.eclipse.core.runtime.OperationCanceledException;\r
-import org.eclipse.core.runtime.Platform;\r
-import org.eclipse.core.runtime.SubMonitor;\r
-import org.simantics.db.RequestProcessor;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.util.SessionGarbageCollection;\r
-import org.simantics.db.management.ISessionContext;\r
-import org.simantics.document.DocumentSettings;\r
-import org.simantics.document.DocumentUtils;\r
-import org.simantics.export.core.pdf.ServiceBasedPdfExportPageEvent;\r
-import org.simantics.modeling.requests.CollectionRequest;\r
-import org.simantics.modeling.requests.CollectionResult;\r
-import org.simantics.modeling.requests.Node;\r
-import org.simantics.modeling.ui.preferences.DiagramPreferenceUtil;\r
-import org.simantics.ui.jobs.SessionGarbageCollectorJob;\r
-import org.simantics.utils.page.PageDesc;\r
-import org.simantics.utils.page.PageOrientation;\r
-import org.simantics.utils.threads.WorkerThread;\r
-\r
-import com.kitfox.svg.SVGCache;\r
-import com.lowagie.text.Document;\r
-import com.lowagie.text.DocumentException;\r
-import com.lowagie.text.FontFactory;\r
-import com.lowagie.text.PageSize;\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.PdfContentByte;\r
-import com.lowagie.text.pdf.PdfName;\r
-import com.lowagie.text.pdf.PdfTemplate;\r
-import com.lowagie.text.pdf.PdfWriter;\r
-\r
-public class DiagramPrinter {\r
-\r
-    public static CollectionResult browse(IProgressMonitor monitor, RequestProcessor processor, Resource[] input) throws DatabaseException {\r
-        final CollectionResult result = processor.syncRequest(new CollectionRequest(monitor, DiagramPreferenceUtil.getDefaultPreferences().getCompletePageDesc(), input));\r
-        return result;\r
-    }\r
-\r
-    private static final AtomicBoolean fontFactoryInitialized = new AtomicBoolean();\r
-\r
-    /**\r
-     * @param monitor the progress monitor to use for reporting progress to the\r
-     *        user. It is the caller's responsibility to call done() on the\r
-     *        given monitor. Accepts <code>null</code>, indicating that no\r
-     *        progress should be reported and that the operation cannot be\r
-     *        cancelled.\r
-     * \r
-     * @param exportPath\r
-     * @param flattenedNodes\r
-     * @param sessionContext\r
-     * @throws DocumentException\r
-     * @throws FileNotFoundException\r
-     */\r
-    public static void printToPdf(\r
-               IProgressMonitor monitor, \r
-               PDFExportPlan exportPlan, \r
-               String exportPath, \r
-               Collection<Node> flattenedNodes,\r
-            ISessionContext sessionContext) \r
-    throws PdfException {\r
-        Collection<Node> flattened = flattenedNodes;\r
-\r
-        SubMonitor progress = SubMonitor.convert(monitor, "Export to PDF", flattened.size() * 2);\r
-\r
-        WorkerThread workerThread = new WorkerThread("Diagram PDF Painter");\r
-        workerThread.start();\r
-\r
-        PdfWriter writer = null;\r
-        Document document = null;\r
-\r
-        try {\r
-            progress.subTask("Loading system fonts");\r
-            DefaultFontMapper mapper = new DefaultFontMapper();\r
-            if (fontFactoryInitialized.compareAndSet(false, true)) {\r
-                // Only register directories once.\r
-                FontFactory.registerDirectories();\r
-            }\r
-\r
-            SessionGarbageCollectorJob.getInstance().setEnabled(false);\r
-\r
-\r
-            boolean first = true;           \r
-            int i = 0;\r
-            for (Node d : flattened) {\r
-                ++i;\r
-                \r
-                //System.out.println("PAGE DESC: " + d.getPageDesc());\r
-                //System.out.println("PAGE SIZE: " + pageSize);\r
-\r
-                Rectangle pageSize = toPageSize(d.getPageDesc());\r
-                if (writer == null) {\r
-                    document = new Document(pageSize);\r
-                    writer = PdfWriter.getInstance(document, new FileOutputStream(exportPath));\r
-                   writer.setPdfVersion(PdfWriter.PDF_VERSION_1_7);\r
-                   writer.setPageEvent(new ServiceBasedPdfExportPageEvent());\r
-                   if ( exportPlan.attachTG ) {\r
-                       writer.addViewerPreference(PdfName.USEATTACHMENTS, PdfBoolean.PDFTRUE);\r
-                   }\r
-   \r
-                   String creator = getCreator();\r
-                   document.addCreator(creator);\r
-\r
-                   /*\r
-                       File keystoreFile = new File("c:\\0009278.p12");\r
-                       String password = "ka7GfzI9Oq";\r
-\r
-                       try {\r
-                               KeyStore ks = KeyStore.getInstance("pkcs12");\r
-                               ks.load(new FileInputStream(keystoreFile), password.toCharArray());\r
-                               List<String> aliases = Collections.list(ks.aliases());\r
-                               String alias = aliases.get(0);\r
-                               PrivateKey key = (PrivateKey)ks.getKey(alias, password.toCharArray());\r
-                               Certificate[] chain = ks.getCertificateChain(alias);\r
-                               int permission = PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY;\r
-                               \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
-                       } catch (Exception e) {\r
-                               e.printStackTrace();\r
-                       }*/\r
-                   \r
-                   /*\r
-                   writer.setEncryption(\r
-                               new Certificate[] {}, \r
-                               new int[] {PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING}, \r
-                               PdfWriter.STANDARD_ENCRYPTION_128);\r
-                               */\r
-                   //writer.setEncryption(PdfWriter.STANDARD_ENCRYPTION_128, "", "password", PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY);\r
-                       \r
-                   \r
-//                     PdfName companyName = new PdfName("SMTC");          \r
-//                 PdfDeveloperExtension ext = new PdfDeveloperExtension(companyName, PdfWriter.PDF_VERSION_1_7, 3);\r
-//                 writer.addDeveloperExtension( ext );\r
-                   \r
-                    document.open();\r
-                }\r
-\r
-                if (!first) {\r
-                document.setPageSize(pageSize);\r
-                document.newPage();\r
-                }\r
-\r
-                /*\r
-                /// ATTACHMENTS - TG ///\r
-                byte[] attachment = null;\r
-                       if ( exportPlan.attachTG && !d.getDefiningResources().isEmpty() ) \r
-                try {\r
-                    PdfDictionary fileParameter = new PdfDictionary();\r
-\r
-                       {\r
-                               final Resource composite = d.getDefiningResources().iterator().next();                                          \r
-                               final Session session = exportPlan.sessionContext.getSession();\r
-                               \r
-                           SimanticsClipboard clipboard = session.syncRequest(new Read<SimanticsClipboard>() {\r
-                               @Override\r
-                               public SimanticsClipboard perform(ReadGraph graph) throws DatabaseException {\r
-                                   CopyHandler ch = graph.adapt(composite, CopyHandler.class);\r
-                                   SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();\r
-                                   ch.copyToClipboard(graph, clipboard);\r
-                                   return clipboard;\r
-                               }\r
-                           });\r
-                           for (Set<Representation> object : clipboard.getContents()) {\r
-                               TransferableGraph1 tg = ClipboardUtils.accept(object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH);\r
-                               String filename = d.getName()+".diagram";\r
-                               try {\r
-                                       byte[] data = DataContainers.writeFile(                                 \r
-                                               new DataContainer("aprosDiagram", 1, new Variant(TransferableGraph1.BINDING, tg))\r
-                                       );\r
-                                           PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(\r
-                                                       writer, \r
-                                                       "/Diagram", filename, data, true, "application/simantics/diagram", \r
-                                                       fileParameter);\r
-                                           writer.addFileAttachment(d.getName()+".diagram", fs);\r
-                               } catch ( NullPointerException npe ) {\r
-                                       throw new PdfException("Experiment must be activated to export attachments"+npe.getMessage(), npe);\r
-                               }\r
-                           }\r
-                       }\r
-\r
-                } catch (DatabaseException e) {\r
-                    e.printStackTrace();\r
-                } catch (IOException e) {\r
-                    e.printStackTrace();\r
-                }\r
-                */\r
-                //////////////////////////\r
-                \r
-                String diagramName = formDiagramName(d, true);\r
-                String subTask = "Page (" + i + "/" + flattened.size() + "): " + diagramName;\r
-\r
-                Resource diagram = d.getDiagramResource();\r
-                if (diagram == null) {\r
-                    // No diagram, skip page.\r
-                    subTask += " skipped, no diagram.";\r
-                    System.out.println(subTask);\r
-                    continue;\r
-                }\r
-\r
-                System.out.println(subTask);\r
-                progress.subTask(subTask);\r
-\r
-                try {\r
-                    PDFPainter.render(workerThread, sessionContext, exportPlan, d, writer, mapper,\r
-                            pageSize, d.getPageDesc(), exportPlan.fitContentToPageMargins, 10000);\r
-                } catch (InterruptedException e) {\r
-                    e.printStackTrace();\r
-                } catch (DatabaseException e) {\r
-                    e.printStackTrace();\r
-                }\r
-\r
-                // Paint diagram path/name on the page\r
-                // TODO: remove this hard coded diagram name printing and\r
-                // replace it with a page templates that is loaded along with\r
-                // the rest of the diagram\r
-\r
-                int w = (int) pageSize.getWidth();\r
-                int h = (int) pageSize.getHeight();\r
-\r
-                // Write Page Number\r
-                PdfContentByte cb = writer.getDirectContent();\r
-\r
-//                PdfTemplate tp = cb.createTemplate(w, h);\r
-//                Graphics2D g2d = tp.createGraphics(w, h, mapper);\r
-//                g2d.setColor(Color.black);\r
-//                java.awt.Font thisFont = new java.awt.Font("Arial", java.awt.Font.ITALIC, 10);\r
-//                g2d.setFont(thisFont);\r
-//                FontMetrics metrics = g2d.getFontMetrics();\r
-//                int width = metrics.stringWidth(diagramName);\r
-//                g2d.drawString(diagramName, (w - width) / 2, document.getPageSize().getHeight() - PageDesc.toPoints(5));\r
-//                g2d.dispose();\r
-//                cb.addTemplate(tp, 0, 0);\r
-\r
-                /// ATTACHMENTS - Write WIKI ///\r
-                if ( exportPlan.attachWiki && !d.getDefiningResources().isEmpty() ) {\r
-                    final Session session = exportPlan.sessionContext.getSession();\r
-                    Resource composite = d.getDefiningResources().iterator().next();\r
-                    DocumentUtils du = new DocumentUtils();\r
-                    StringBuilder wiki = new StringBuilder();\r
-                    StringBuilder css = new StringBuilder();\r
-                    du.getDocumentWikiTextRecursive(session, composite, wiki, css);\r
-                       DocumentSettings settings = du.getDocumentSettings(session, composite);\r
-                    PdfTemplate tp_ = cb.createTemplate(w, h);\r
-                    if ( wiki.length()>0 ) {\r
-                        String wikiText = wiki.toString();\r
-                        String cssText = css.toString();\r
-                        du.print(session, composite, wikiText, cssText, settings, tp_.getPdfWriter(), document);\r
-                    }\r
-                    cb.addTemplate(tp_, 0, 0);\r
-                }\r
-                //////////////////////////\r
-\r
-                progress.worked(1);\r
-                first = false;\r
-\r
-                if (progress.isCanceled())\r
-                    throw new OperationCanceledException();\r
-\r
-                System.out.println("GC");\r
-                SVGCache.getSVGUniverse().clearUnreferenced();\r
-                SessionGarbageCollection.gc(null, sessionContext.getSession(), true, null);\r
-                System.gc();\r
-                System.out.println("GC finished");\r
-                progress.worked(1);\r
-            }\r
-               } catch (DatabaseException e) {\r
-                       throw new PdfException(e);\r
-               } catch (FileNotFoundException e) {\r
-                       throw new PdfException(e);\r
-               } catch (DocumentException e) {\r
-                       throw new PdfException(e);\r
-               } finally {\r
-            workerThread.stopDispatchingEvents(true);\r
-            System.out.println("closing document");\r
-            try {\r
-               if ( document!=null ) document.close();\r
-                if ( writer!=null ) writer.close();\r
-            } catch(RuntimeException e) {\r
-               e.printStackTrace();\r
-            }\r
-            System.out.println("document closed");\r
-            SessionGarbageCollectorJob.getInstance().setEnabled(true).scheduleAfterQuietTime();\r
-        }\r
-    }\r
-\r
-    public static Rectangle toPageSize(PageDesc pageDesc) {\r
-        String arg = PageDesc.toPoints(pageDesc.getWidth()) + " " + PageDesc.toPoints(pageDesc.getHeight());\r
-        Rectangle r = PageSize.getRectangle(arg);\r
-\r
-        if (PageOrientation.Landscape == pageDesc.getOrientation())\r
-            r = r.rotate();\r
-\r
-        // Disable inherent borders from the PDF writer.\r
-        r.setBorder(0);\r
-\r
-        return r;\r
-    }\r
-\r
-    public static String formDiagramName(Node node, boolean parents) {\r
-        Node d = node;\r
-        String ret = d.getName();\r
-        if (parents) {\r
-            while (d.getParent() != null) {\r
-                d = d.getParent();\r
-                ret = d.getName() + " / " + ret;\r
-            }\r
-        }\r
-//        String[] pg = node.getPartOfGroups();\r
-//        if (pg.length > 0)\r
-//            ret += " [" + EString.implode(pg, " / ") + " / " + node.getName() + "]";\r
-        return ret;\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
-    static {\r
-               Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());\r
-    }\r
-\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.modeling.ui.pdf;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.security.Security;
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.eclipse.core.runtime.IProduct;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SubMonitor;
+import org.simantics.db.RequestProcessor;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.util.SessionGarbageCollection;
+import org.simantics.db.management.ISessionContext;
+import org.simantics.document.DocumentSettings;
+import org.simantics.document.DocumentUtils;
+import org.simantics.export.core.pdf.ServiceBasedPdfExportPageEvent;
+import org.simantics.modeling.requests.CollectionRequest;
+import org.simantics.modeling.requests.CollectionResult;
+import org.simantics.modeling.requests.Node;
+import org.simantics.modeling.ui.preferences.DiagramPreferenceUtil;
+import org.simantics.ui.jobs.SessionGarbageCollectorJob;
+import org.simantics.utils.page.PageDesc;
+import org.simantics.utils.page.PageOrientation;
+import org.simantics.utils.threads.WorkerThread;
+
+import com.kitfox.svg.SVGCache;
+import com.lowagie.text.Document;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.FontFactory;
+import com.lowagie.text.PageSize;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.DefaultFontMapper;
+import com.lowagie.text.pdf.PdfBoolean;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.pdf.PdfName;
+import com.lowagie.text.pdf.PdfTemplate;
+import com.lowagie.text.pdf.PdfWriter;
+
+public class DiagramPrinter {
+
+    public static CollectionResult browse(IProgressMonitor monitor, RequestProcessor processor, Resource[] input) throws DatabaseException {
+        final CollectionResult result = processor.syncRequest(new CollectionRequest(monitor, DiagramPreferenceUtil.getDefaultPreferences().getCompletePageDesc(), input));
+        return result;
+    }
+
+    private static final AtomicBoolean fontFactoryInitialized = new AtomicBoolean();
+
+    /**
+     * @param monitor the progress monitor to use for reporting progress to the
+     *        user. It is the caller's responsibility to call done() on the
+     *        given monitor. Accepts <code>null</code>, indicating that no
+     *        progress should be reported and that the operation cannot be
+     *        cancelled.
+     * 
+     * @param exportPath
+     * @param flattenedNodes
+     * @param sessionContext
+     * @throws DocumentException
+     * @throws FileNotFoundException
+     */
+    public static void printToPdf(
+               IProgressMonitor monitor, 
+               PDFExportPlan exportPlan, 
+               String exportPath, 
+               Collection<Node> flattenedNodes,
+            ISessionContext sessionContext) 
+    throws PdfException {
+        Collection<Node> flattened = flattenedNodes;
+
+        SubMonitor progress = SubMonitor.convert(monitor, "Export to PDF", flattened.size() * 2);
+
+        WorkerThread workerThread = new WorkerThread("Diagram PDF Painter");
+        workerThread.start();
+
+        PdfWriter writer = null;
+        Document document = null;
+
+        try {
+            progress.subTask("Loading system fonts");
+            DefaultFontMapper mapper = new DefaultFontMapper();
+            if (fontFactoryInitialized.compareAndSet(false, true)) {
+                // Only register directories once.
+                FontFactory.registerDirectories();
+            }
+
+            SessionGarbageCollectorJob.getInstance().setEnabled(false);
+
+
+            boolean first = true;           
+            int i = 0;
+            for (Node d : flattened) {
+                ++i;
+                
+                //System.out.println("PAGE DESC: " + d.getPageDesc());
+                //System.out.println("PAGE SIZE: " + pageSize);
+
+                Rectangle pageSize = toPageSize(d.getPageDesc());
+                if (writer == null) {
+                    document = new Document(pageSize);
+                    writer = PdfWriter.getInstance(document, new FileOutputStream(exportPath));
+                   writer.setPdfVersion(PdfWriter.PDF_VERSION_1_7);
+                   writer.setPageEvent(new ServiceBasedPdfExportPageEvent());
+                   if ( exportPlan.attachTG ) {
+                       writer.addViewerPreference(PdfName.USEATTACHMENTS, PdfBoolean.PDFTRUE);
+                   }
+   
+                   String creator = getCreator();
+                   document.addCreator(creator);
+
+                   /*
+                       File keystoreFile = new File("c:\\0009278.p12");
+                       String password = "ka7GfzI9Oq";
+
+                       try {
+                               KeyStore ks = KeyStore.getInstance("pkcs12");
+                               ks.load(new FileInputStream(keystoreFile), password.toCharArray());
+                               List<String> aliases = Collections.list(ks.aliases());
+                               String alias = aliases.get(0);
+                               PrivateKey key = (PrivateKey)ks.getKey(alias, password.toCharArray());
+                               Certificate[] chain = ks.getCertificateChain(alias);
+                               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();
+                       
+                               
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                       }*/
+                   
+                   /*
+                   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);
+                       
+                   
+//                     PdfName companyName = new PdfName("SMTC");          
+//                 PdfDeveloperExtension ext = new PdfDeveloperExtension(companyName, PdfWriter.PDF_VERSION_1_7, 3);
+//                 writer.addDeveloperExtension( ext );
+                   
+                    document.open();
+                }
+
+                if (!first) {
+                document.setPageSize(pageSize);
+                document.newPage();
+                }
+
+                /*
+                /// ATTACHMENTS - TG ///
+                byte[] attachment = null;
+                       if ( exportPlan.attachTG && !d.getDefiningResources().isEmpty() ) 
+                try {
+                    PdfDictionary fileParameter = new PdfDictionary();
+
+                       {
+                               final Resource composite = d.getDefiningResources().iterator().next();                                          
+                               final Session session = exportPlan.sessionContext.getSession();
+                               
+                           SimanticsClipboard clipboard = session.syncRequest(new Read<SimanticsClipboard>() {
+                               @Override
+                               public SimanticsClipboard perform(ReadGraph graph) throws DatabaseException {
+                                   CopyHandler ch = graph.adapt(composite, CopyHandler.class);
+                                   SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();
+                                   ch.copyToClipboard(graph, clipboard);
+                                   return clipboard;
+                               }
+                           });
+                           for (Set<Representation> object : clipboard.getContents()) {
+                               TransferableGraph1 tg = ClipboardUtils.accept(object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH);
+                               String filename = d.getName()+".diagram";
+                               try {
+                                       byte[] data = DataContainers.writeFile(                                 
+                                               new DataContainer("aprosDiagram", 1, new Variant(TransferableGraph1.BINDING, tg))
+                                       );
+                                           PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(
+                                                       writer, 
+                                                       "/Diagram", filename, data, true, "application/simantics/diagram", 
+                                                       fileParameter);
+                                           writer.addFileAttachment(d.getName()+".diagram", fs);
+                               } catch ( NullPointerException npe ) {
+                                       throw new PdfException("Experiment must be activated to export attachments"+npe.getMessage(), npe);
+                               }
+                           }
+                       }
+
+                } catch (DatabaseException e) {
+                    e.printStackTrace();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                */
+                //////////////////////////
+                
+                String diagramName = formDiagramName(d, true);
+                String subTask = "Page (" + i + "/" + flattened.size() + "): " + diagramName;
+
+                Resource diagram = d.getDiagramResource();
+                if (diagram == null) {
+                    // No diagram, skip page.
+                    subTask += " skipped, no diagram.";
+                    System.out.println(subTask);
+                    continue;
+                }
+
+                System.out.println(subTask);
+                progress.subTask(subTask);
+
+                try {
+                    PDFPainter.render(workerThread, sessionContext, exportPlan, d, writer, mapper,
+                            pageSize, d.getPageDesc(), exportPlan.fitContentToPageMargins, 10000);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                } catch (DatabaseException e) {
+                    e.printStackTrace();
+                }
+
+                // Paint diagram path/name on the page
+                // TODO: remove this hard coded diagram name printing and
+                // replace it with a page templates that is loaded along with
+                // the rest of the diagram
+
+                int w = (int) pageSize.getWidth();
+                int h = (int) pageSize.getHeight();
+
+                // Write Page Number
+                PdfContentByte cb = writer.getDirectContent();
+
+//                PdfTemplate tp = cb.createTemplate(w, h);
+//                Graphics2D g2d = tp.createGraphics(w, h, mapper);
+//                g2d.setColor(Color.black);
+//                java.awt.Font thisFont = new java.awt.Font("Arial", java.awt.Font.ITALIC, 10);
+//                g2d.setFont(thisFont);
+//                FontMetrics metrics = g2d.getFontMetrics();
+//                int width = metrics.stringWidth(diagramName);
+//                g2d.drawString(diagramName, (w - width) / 2, document.getPageSize().getHeight() - PageDesc.toPoints(5));
+//                g2d.dispose();
+//                cb.addTemplate(tp, 0, 0);
+
+                /// ATTACHMENTS - Write WIKI ///
+                if ( exportPlan.attachWiki && !d.getDefiningResources().isEmpty() ) {
+                    final Session session = exportPlan.sessionContext.getSession();
+                    Resource composite = d.getDefiningResources().iterator().next();
+                    DocumentUtils du = new DocumentUtils();
+                    StringBuilder wiki = new StringBuilder();
+                    StringBuilder css = new StringBuilder();
+                    du.getDocumentWikiTextRecursive(session, composite, wiki, css);
+                       DocumentSettings settings = du.getDocumentSettings(session, composite);
+                    PdfTemplate tp_ = cb.createTemplate(w, h);
+                    if ( wiki.length()>0 ) {
+                        String wikiText = wiki.toString();
+                        String cssText = css.toString();
+                        du.print(session, composite, wikiText, cssText, settings, tp_.getPdfWriter(), document);
+                    }
+                    cb.addTemplate(tp_, 0, 0);
+                }
+                //////////////////////////
+
+                progress.worked(1);
+                first = false;
+
+                if (progress.isCanceled())
+                    throw new OperationCanceledException();
+
+                System.out.println("GC");
+                SVGCache.getSVGUniverse().clearUnreferenced();
+                SessionGarbageCollection.gc(null, sessionContext.getSession(), true, null);
+                System.gc();
+                System.out.println("GC finished");
+                progress.worked(1);
+            }
+               } catch (DatabaseException e) {
+                       throw new PdfException(e);
+               } catch (FileNotFoundException e) {
+                       throw new PdfException(e);
+               } catch (DocumentException e) {
+                       throw new PdfException(e);
+               } finally {
+            workerThread.stopDispatchingEvents(true);
+            System.out.println("closing document");
+            try {
+               if ( document!=null ) document.close();
+                if ( writer!=null ) writer.close();
+            } catch(RuntimeException e) {
+               e.printStackTrace();
+            }
+            System.out.println("document closed");
+            SessionGarbageCollectorJob.getInstance().setEnabled(true).scheduleAfterQuietTime();
+        }
+    }
+
+    public static Rectangle toPageSize(PageDesc pageDesc) {
+        String arg = PageDesc.toPoints(pageDesc.getWidth()) + " " + PageDesc.toPoints(pageDesc.getHeight());
+        Rectangle r = PageSize.getRectangle(arg);
+
+        if (PageOrientation.Landscape == pageDesc.getOrientation())
+            r = r.rotate();
+
+        // Disable inherent borders from the PDF writer.
+        r.setBorder(0);
+
+        return r;
+    }
+
+    public static String formDiagramName(Node node, boolean parents) {
+        Node d = node;
+        String ret = d.getName();
+        if (parents) {
+            while (d.getParent() != null) {
+                d = d.getParent();
+                ret = d.getName() + " / " + ret;
+            }
+        }
+//        String[] pg = node.getPartOfGroups();
+//        if (pg.length > 0)
+//            ret += " [" + EString.implode(pg, " / ") + " / " + node.getName() + "]";
+        return ret;
+    }
+
+       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;
+       }
+
+    static {
+               Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
+    }
+
 }
\ No newline at end of file