Source Code Cross Referenced for STDocument.java in  » PDF » jPod » de » intarsys » pdf » st » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » PDF » jPod » de.intarsys.pdf.st 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 2007, intarsys consulting GmbH
0003:         *
0004:         * Redistribution and use in source and binary forms, with or without
0005:         * modification, are permitted provided that the following conditions are met:
0006:         *
0007:         * - Redistributions of source code must retain the above copyright notice,
0008:         *   this list of conditions and the following disclaimer.
0009:         *
0010:         * - Redistributions in binary form must reproduce the above copyright notice,
0011:         *   this list of conditions and the following disclaimer in the documentation
0012:         *   and/or other materials provided with the distribution.
0013:         *
0014:         * - Neither the name of intarsys nor the names of its contributors may be used
0015:         *   to endorse or promote products derived from this software without specific
0016:         *   prior written permission.
0017:         *
0018:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021:         * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022:         * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023:         * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024:         * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026:         * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0028:         * POSSIBILITY OF SUCH DAMAGE.
0029:         */
0030:        package de.intarsys.pdf.st;
0031:
0032:        import java.io.FileNotFoundException;
0033:        import java.io.IOException;
0034:        import java.io.InputStream;
0035:        import java.io.OutputStream;
0036:        import java.util.Collection;
0037:        import java.util.HashMap;
0038:        import java.util.HashSet;
0039:        import java.util.Iterator;
0040:        import java.util.Map;
0041:        import java.util.NoSuchElementException;
0042:        import java.util.Set;
0043:        import java.util.logging.Level;
0044:        import java.util.logging.Logger;
0045:
0046:        import de.intarsys.pdf.cds.CDSDate;
0047:        import de.intarsys.pdf.cos.COSCatalog;
0048:        import de.intarsys.pdf.cos.COSDictionary;
0049:        import de.intarsys.pdf.cos.COSDocument;
0050:        import de.intarsys.pdf.cos.COSIndirectObject;
0051:        import de.intarsys.pdf.cos.COSInfoDict;
0052:        import de.intarsys.pdf.cos.COSName;
0053:        import de.intarsys.pdf.cos.COSObject;
0054:        import de.intarsys.pdf.cos.COSObjectKey;
0055:        import de.intarsys.pdf.cos.COSObjectWalkerDeep;
0056:        import de.intarsys.pdf.cos.COSRuntimeException;
0057:        import de.intarsys.pdf.cos.COSTrailer;
0058:        import de.intarsys.pdf.cos.COSVisitorException;
0059:        import de.intarsys.pdf.crypt.COSEncryption;
0060:        import de.intarsys.pdf.crypt.COSSecurityException;
0061:        import de.intarsys.pdf.crypt.ISystemSecurityHandler;
0062:        import de.intarsys.pdf.crypt.PasswordProvider;
0063:        import de.intarsys.pdf.crypt.SystemSecurityHandler;
0064:        import de.intarsys.pdf.parser.COSDocumentParser;
0065:        import de.intarsys.pdf.parser.COSLoadError;
0066:        import de.intarsys.pdf.parser.COSLoadException;
0067:        import de.intarsys.pdf.writer.COSWriter;
0068:        import de.intarsys.tools.locator.ILocator;
0069:        import de.intarsys.tools.locator.ILocatorSupport;
0070:        import de.intarsys.tools.locator.TransientLocator;
0071:        import de.intarsys.tools.message.MessageBundle;
0072:        import de.intarsys.tools.randomaccess.BufferedRandomAccess;
0073:        import de.intarsys.tools.randomaccess.IRandomAccess;
0074:        import de.intarsys.tools.stream.StreamTools;
0075:
0076:        /**
0077:         * The most physical abstraction of a PDF document. This object handles the
0078:         * random access representation of the PDF file.
0079:         * <p>
0080:         * An STDocument manages the cross ref access to data stream positions from COS
0081:         * level objects. As such the ST and the COS package are highly interdependent.
0082:         */
0083:        public class STDocument implements  ILocatorSupport {
0084:            /**
0085:             * A counter for naming new documents
0086:             */
0087:            private static int COUNTER = 0;
0088:
0089:            /** our current fdf version number * */
0090:            public static final STDocType DOCTYPE_FDF = new STDocType(
0091:                    "FDF", "1.2"); //$NON-NLS-1$ //$NON-NLS-2$
0092:
0093:            /** our current pdf version number * */
0094:            public static final STDocType DOCTYPE_PDF = new STDocType(
0095:                    "PDF", "1.4"); //$NON-NLS-1$ //$NON-NLS-2$
0096:
0097:            /** The logger to be used in this package */
0098:            private static Logger Log = PACKAGE.Log;
0099:
0100:            /**
0101:             * NLS
0102:             */
0103:            private static final MessageBundle Msg = PACKAGE.Messages;
0104:
0105:            public static final String OPTION_WRITEMODEHINT = "writeModeHint"; //$NON-NLS-1$
0106:
0107:            /**
0108:             * Create a new document representing the data referenced by locator.
0109:             * 
0110:             * @param locator
0111:             *            The locator to the documents data
0112:             * 
0113:             * @return A new document representing the data referenced by locator.
0114:             * @throws IOException
0115:             * @throws COSLoadException
0116:             */
0117:            public static STDocument createFromLocator(ILocator locator)
0118:                    throws IOException, COSLoadException {
0119:                if (!locator.exists()) {
0120:                    throw new FileNotFoundException("'" + locator.getFullName() //$NON-NLS-1$
0121:                            + "' not found"); //$NON-NLS-1$
0122:                }
0123:                STDocument result = new STDocument(locator);
0124:                result.initializeFromLocator();
0125:                return result;
0126:            }
0127:
0128:            protected static String createName(String typeName) {
0129:                COUNTER++;
0130:                return Msg
0131:                        .getString(
0132:                                "STDocument.documentName.new", typeName, new Integer(COUNTER)); //$NON-NLS-1$
0133:            }
0134:
0135:            /**
0136:             * create a new empty pdf document.
0137:             * 
0138:             * @return A new empty pdf document
0139:             */
0140:            public static STDocument createNew() {
0141:                return createNew(DOCTYPE_PDF);
0142:            }
0143:
0144:            /**
0145:             * create a new empty document.
0146:             * 
0147:             * @return A new empty document
0148:             */
0149:            public static STDocument createNew(STDocType docType) {
0150:                STDocument doc = new STDocument();
0151:                doc.initializeFromScratch(docType);
0152:                return doc;
0153:            }
0154:
0155:            private Object accessLock = new Object();
0156:
0157:            /**
0158:             * The collection of changed objects within the document since last save
0159:             */
0160:            private Set changes = new HashSet();
0161:
0162:            private boolean closed = false;
0163:
0164:            /**
0165:             * Flag if this document is changed
0166:             */
0167:            private boolean dirty = false;
0168:
0169:            private COSDocument doc;
0170:
0171:            /**
0172:             * The document's doc type.
0173:             * 
0174:             * <p>
0175:             * This value is read from the file document header.
0176:             * </p>
0177:             */
0178:            private STDocType docType;
0179:
0180:            /**
0181:             * A map of indirect objects in the document.
0182:             */
0183:            private Map keyToObject = new HashMap();
0184:
0185:            /**
0186:             * The locator for the document physics
0187:             */
0188:            private ILocator locator;
0189:
0190:            /**
0191:             * The next free COSObjectKey to use for a new indirect object
0192:             */
0193:            private COSObjectKey nextKey;
0194:
0195:            /**
0196:             * The parser used for this document
0197:             */
0198:            private COSDocumentParser parser;
0199:
0200:            /**
0201:             * The random access stream to read the documents data
0202:             */
0203:            private IRandomAccess randomAccess;
0204:
0205:            /**
0206:             * The security handler used for encrypting/decrypting this documents
0207:             * content
0208:             */
0209:            private ISystemSecurityHandler systemSecurityHandler;
0210:
0211:            private EnumWriteMode writeModeHint = (EnumWriteMode) EnumWriteMode.META
0212:                    .getDefault();
0213:
0214:            /**
0215:             * The most recent x reference section.
0216:             * <p>
0217:             * When a new document is created or initialized from a data stream, a new
0218:             * empty XRef Section is always created for holding the changes to come.
0219:             */
0220:            private STXRefSection xRefSection;
0221:
0222:            /**
0223:             * A new empty document.
0224:             * <p>
0225:             * Use always the factory method, this is not completely initialized.
0226:             */
0227:            protected STDocument() {
0228:                //
0229:            }
0230:
0231:            /**
0232:             * A new document bound to a locator.
0233:             * 
0234:             * @param locator
0235:             *            The locator to the documents data.
0236:             */
0237:            protected STDocument(ILocator locator) {
0238:                setLocator(locator);
0239:            }
0240:
0241:            /**
0242:             * Mark object as changed within this document.
0243:             * 
0244:             * @param object
0245:             *            The object that is new or changed
0246:             */
0247:            public void addChangedReference(COSIndirectObject object) {
0248:                setDirty(true);
0249:                changes.add(object);
0250:            }
0251:
0252:            /**
0253:             * Add another indirect object to the document.
0254:             * 
0255:             * @param newRef
0256:             *            The new indirect object.
0257:             */
0258:            public void addObjectReference(COSIndirectObject newRef) {
0259:                COSObjectKey key = newRef.getKey();
0260:                getKeyToObject().put(key, newRef);
0261:            }
0262:
0263:            protected void checkConsistency() throws COSLoadError {
0264:                if (getDocType() == null) {
0265:                    throw new COSLoadError("unknown document type"); //$NON-NLS-1$
0266:                }
0267:                if (getDocType().isPDF()) {
0268:                    if (getXRefSection() == null) {
0269:                        throw new COSLoadError("x ref section missing"); //$NON-NLS-1$
0270:                    }
0271:                    if (getXRefSection().cosGetDict() == null) {
0272:                        throw new COSLoadError("trailer missing"); //$NON-NLS-1$
0273:                    }
0274:                }
0275:            }
0276:
0277:            /**
0278:             * Close the document. Accessing a documents content is undefined after
0279:             * <code>close</code>.
0280:             * 
0281:             * @throws IOException
0282:             */
0283:            public void close() throws IOException {
0284:                synchronized (getAccessLock()) {
0285:                    if (isClosed()) {
0286:                        return;
0287:                    }
0288:                    if (getRandomAccess() != null) {
0289:                        getRandomAccess().close();
0290:                        setClosed(true);
0291:                        setRandomAccess(null);
0292:                    }
0293:                }
0294:            }
0295:
0296:            /**
0297:             * Return a deep copy of the document. This will create a copy of the
0298:             * documents content. The new documents location (random access) is
0299:             * undefined. The objects will not preserve their key values.
0300:             * 
0301:             * @return A deep copy of this.
0302:             */
0303:            public STDocument copyDeep() {
0304:                STDocument result = STDocument.createNew();
0305:                COSDictionary newTrailer = (COSDictionary) cosGetTrailer()
0306:                        .copyDeep();
0307:                newTrailer.remove(COSTrailer.DK_Prev);
0308:                newTrailer.remove(COSTrailer.DK_Size);
0309:                newTrailer.remove(STXRefSection.DK_XRefStm);
0310:                ((STTrailerXRefSection) result.getXRefSection())
0311:                        .cosSetDict(newTrailer);
0312:                result.systemSecurityHandler = getSystemSecurityHandler();
0313:                String name = Msg.getString(
0314:                        "STDocument.documentName.copyOf", getName()); //$NON-NLS-1$
0315:                result.locator = new TransientLocator(name, getDocType()
0316:                        .getTypeName());
0317:                return result;
0318:            }
0319:
0320:            /**
0321:             * The documents trailer dictionary
0322:             * 
0323:             * @return The documents trailer dictionary
0324:             */
0325:            public COSDictionary cosGetTrailer() {
0326:                return getXRefSection().cosGetDict();
0327:            }
0328:
0329:            public STXRefSection createNewXRefSection() {
0330:                if (getXRefSection().getOffset() != -1) {
0331:                    // create a new empty xref section for changes...
0332:                    return getXRefSection().createSuccessor();
0333:                }
0334:                return getXRefSection();
0335:            }
0336:
0337:            /**
0338:             * Create a new valid key for use in the document.
0339:             * 
0340:             * @return A new valid key for use in the document.
0341:             */
0342:            public COSObjectKey createObjectKey() {
0343:                nextKey = nextKey.createNextKey();
0344:                return nextKey;
0345:            }
0346:
0347:            /**
0348:             * Create a new random access object for the document data.
0349:             * 
0350:             * @param pLocator
0351:             *            The locator to the document data.
0352:             * @return Create a new random access object for the document data.
0353:             * @throws IOException
0354:             */
0355:            protected IRandomAccess createRandomAccess(ILocator pLocator)
0356:                    throws IOException {
0357:                if (pLocator == null) {
0358:                    return null;
0359:                }
0360:                IRandomAccess baseAccess = pLocator.getRandomAccess();
0361:
0362:                // return baseAccess;
0363:                BufferedRandomAccess bufferedAccess = new BufferedRandomAccess(
0364:                        baseAccess, 4096);
0365:                return bufferedAccess;
0366:            }
0367:
0368:            /**
0369:             * Start a garbage collection for the receiver. In a garbage collection
0370:             * every indirect object currently unused (unreachable from the catalog) is
0371:             * removed.
0372:             * 
0373:             */
0374:            public void garbageCollect() {
0375:                COSObjectWalkerDeep walker = new COSObjectWalkerDeep();
0376:                try {
0377:                    cosGetTrailer().accept(walker);
0378:                } catch (COSVisitorException e) {
0379:                    // won't happen
0380:                }
0381:
0382:                // prepare new empty x ref section
0383:                STTrailerXRefSection emptyXRefSection = new STTrailerXRefSection(
0384:                        this );
0385:                COSDictionary emptyTrailer = emptyXRefSection.cosGetDict();
0386:                emptyTrailer.addAll(cosGetTrailer());
0387:                emptyTrailer.remove(COSTrailer.DK_Prev);
0388:                emptyTrailer.remove(COSTrailer.DK_Size);
0389:                emptyTrailer.remove(STXRefSection.DK_XRefStm);
0390:                setXRefSection(emptyXRefSection);
0391:                // prepare new object collection
0392:                getKeyToObject().clear();
0393:                getChanges().clear();
0394:                nextKey = new COSObjectKey(0, 0);
0395:                for (Iterator i = walker.getVisited().iterator(); i.hasNext();) {
0396:                    COSIndirectObject o = (COSIndirectObject) i.next();
0397:                    // force new key
0398:                    o.setKey(null);
0399:                    addObjectReference(o);
0400:                    o.setDirty(true);
0401:                }
0402:            }
0403:
0404:            public Object getAccessLock() {
0405:                return accessLock;
0406:            }
0407:
0408:            public Collection getChanges() {
0409:                return changes;
0410:            }
0411:
0412:            public COSDocument getDoc() {
0413:                return doc;
0414:            }
0415:
0416:            public STDocType getDocType() {
0417:                return docType;
0418:            }
0419:
0420:            public int getIncrementalCount() {
0421:                return getXRefSection().getIncrementalCount();
0422:            }
0423:
0424:            /**
0425:             * THe documents objects.
0426:             * 
0427:             * @return THe documents objects.
0428:             */
0429:            protected Map getKeyToObject() {
0430:                return keyToObject;
0431:            }
0432:
0433:            /**
0434:             * THe locator for the document data.
0435:             * 
0436:             * @return THe locator for the document data.
0437:             */
0438:            public ILocator getLocator() {
0439:                return locator;
0440:            }
0441:
0442:            /**
0443:             * A name for the document.
0444:             * <p>
0445:             * This is either a "local" name or the name of the locator reference if
0446:             * present.
0447:             * 
0448:             * @return A name for the document
0449:             */
0450:            public String getName() {
0451:                return getLocator().getLocalName();
0452:            }
0453:
0454:            /**
0455:             * The indirect object with object number objNum and generation number
0456:             * genNum is looked up in the document. If the indirect object is not yet
0457:             * available, it is created and registered.
0458:             * 
0459:             * @param key
0460:             * 
0461:             * @return The indirect object with object number objNum and generation
0462:             *         number genNum
0463:             */
0464:            public COSIndirectObject getObjectReference(COSObjectKey key) {
0465:                COSIndirectObject result = (COSIndirectObject) getKeyToObject()
0466:                        .get(key);
0467:                if (result == null) {
0468:                    result = COSIndirectObject.create(this , key);
0469:                    // todo 1 @mit this call should not be necessary
0470:                    addObjectReference(result);
0471:                }
0472:                return result;
0473:            }
0474:
0475:            /**
0476:             * The parser used for decoding the document data stream.
0477:             * 
0478:             * @return The parser used for decoding the document data stream.
0479:             */
0480:            public COSDocumentParser getParser() {
0481:                return parser;
0482:            }
0483:
0484:            /**
0485:             * The random access object for the documents data. Be aware that using the
0486:             * IRandomAccess after it is closed will throw an IOException.
0487:             * 
0488:             * @return The random access object for the documents data.
0489:             */
0490:            public IRandomAccess getRandomAccess() {
0491:                return randomAccess;
0492:            }
0493:
0494:            /**
0495:             * The documents security handler
0496:             * 
0497:             * @return The documents security handler
0498:             */
0499:            public ISystemSecurityHandler getSystemSecurityHandler() {
0500:                return systemSecurityHandler;
0501:            }
0502:
0503:            public COSTrailer getTrailer() {
0504:                return (COSTrailer) COSTrailer.META
0505:                        .createFromCos(cosGetTrailer());
0506:            }
0507:
0508:            /**
0509:             * The version of the PDF spec for this document
0510:             * 
0511:             * @return The version of the PDF spec for this document
0512:             */
0513:            public String getVersion() {
0514:                // todo 1 @mit fix version
0515:                return getDocType().toString();
0516:            }
0517:
0518:            /**
0519:             * The write mode to be used when the document is written the next time. If
0520:             * defined this overrides any hint that is used when saving the document.
0521:             * The write mode is reset after each "save".
0522:             * 
0523:             * @return The write mode to be used when the document is written.
0524:             */
0525:            public EnumWriteMode getWriteModeHint() {
0526:                return writeModeHint;
0527:            }
0528:
0529:            /**
0530:             * The most recent STXrefSection of the document.
0531:             * 
0532:             * @return The most recent STXrefSection of the document.
0533:             */
0534:            public STXRefSection getXRefSection() {
0535:                return xRefSection;
0536:            }
0537:
0538:            public void incrementalGarbageCollect() {
0539:                final Set unknown = new HashSet(getChanges());
0540:                COSObjectWalkerDeep stripper = new COSObjectWalkerDeep(false) {
0541:                    public Object visitFromIndirectObject(COSIndirectObject io)
0542:                            throws COSVisitorException {
0543:                        unknown.remove(io);
0544:                        return super .visitFromIndirectObject(io);
0545:                    }
0546:                };
0547:                try {
0548:                    cosGetTrailer().accept(stripper);
0549:                } catch (COSVisitorException e) {
0550:                    // won't happen
0551:                }
0552:                getChanges().removeAll(unknown);
0553:            }
0554:
0555:            /**
0556:             * Load the encryption parameters and initialize the security handler
0557:             * context.
0558:             * 
0559:             * @throws IOException
0560:             * 
0561:             */
0562:            protected void initEncryption() throws IOException {
0563:                systemSecurityHandler = null;
0564:                COSEncryption encryption = COSEncryption
0565:                        .getEncryptionIn(getXRefSection());
0566:                if (encryption != null) {
0567:                    systemSecurityHandler = SystemSecurityHandler
0568:                            .create(encryption);
0569:                    if (systemSecurityHandler == null) {
0570:                        throw new COSRuntimeException(
0571:                                "Unsupported encryption algorithm"); //$NON-NLS-1$
0572:                    }
0573:                    try {
0574:                        systemSecurityHandler.init(this , encryption);
0575:                        // force authentication early, /AuthEvent not yet supported
0576:                        systemSecurityHandler.authenticate(PasswordProvider
0577:                                .get());
0578:                    } catch (COSSecurityException e) {
0579:                        IOException ioe = new IOException(e.getMessage());
0580:                        ioe.initCause(e);
0581:                        throw ioe;
0582:                    }
0583:                }
0584:            }
0585:
0586:            /**
0587:             * Initialize the document from its data.
0588:             * 
0589:             * @throws IOException
0590:             * @throws COSLoadException
0591:             */
0592:            protected void initializeFromLocator() throws IOException,
0593:                    COSLoadException {
0594:                parser = new COSDocumentParser(this );
0595:                streamLoad();
0596:            }
0597:
0598:            /**
0599:             * Initialize a new empty document
0600:             */
0601:            protected void initializeFromScratch(STDocType pDocType) {
0602:                setDocType(pDocType);
0603:                String name = createName(getDocType().getTypeName());
0604:                locator = new TransientLocator(name, pDocType.getTypeName());
0605:                parser = new COSDocumentParser(this );
0606:                setXRefSection(new STTrailerXRefSection(this ));
0607:                nextKey = new COSObjectKey(0, 0);
0608:                cosGetTrailer().put(COSTrailer.DK_Root,
0609:                        COSCatalog.META.createNew().cosGetDict());
0610:                setDirty(true);
0611:            }
0612:
0613:            public boolean isClosed() {
0614:                return closed;
0615:            }
0616:
0617:            /**
0618:             * <code>true</code> if this has been changed.
0619:             * 
0620:             * @return <code>true</code> if this has been changed.
0621:             */
0622:            public boolean isDirty() {
0623:                return dirty;
0624:            }
0625:
0626:            /**
0627:             * @return if the document has an {@link ISystemSecurityHandler}
0628:             */
0629:            public boolean isEncrypted() {
0630:                return getSystemSecurityHandler() != null;
0631:            }
0632:
0633:            public boolean isNew() {
0634:                return (getXRefSection().getOffset() == -1)
0635:                        && (getXRefSection().getPrevious() == null);
0636:            }
0637:
0638:            /**
0639:             * <code>true</code> if this is read only.
0640:             * 
0641:             * @return <code>true</code> if this is read only.
0642:             */
0643:            public boolean isReadOnly() {
0644:                return (getRandomAccess() == null)
0645:                        || getRandomAccess().isReadOnly();
0646:            }
0647:
0648:            /**
0649:             * <code>true</code> if this has only streamed xref sections.
0650:             * 
0651:             * @return <code>true</code> if this has only streamed xref sections.
0652:             */
0653:            public boolean isStreamed() {
0654:                if (getXRefSection() != null) {
0655:                    return getXRefSection().isStreamed();
0656:                }
0657:                return false;
0658:            }
0659:
0660:            /**
0661:             * Load a COSObject from the documents data.
0662:             * 
0663:             * @param ref
0664:             *            The object reference to be loaded.
0665:             * @throws IOException
0666:             * @throws COSLoadException
0667:             */
0668:            public COSObject load(COSIndirectObject ref) throws IOException,
0669:                    COSLoadException {
0670:                int objectNumber = ref.getKey().getObjectNumber();
0671:                return load(objectNumber);
0672:            }
0673:
0674:            protected COSObject load(int objectNumber) throws IOException,
0675:                    COSLoadException {
0676:                synchronized (getAccessLock()) {
0677:                    return getXRefSection().load(objectNumber,
0678:                            getSystemSecurityHandler());
0679:                }
0680:            }
0681:
0682:            public void loadAll() throws IOException, COSLoadException {
0683:                synchronized (getAccessLock()) {
0684:                    for (int i = 0; i < getXRefSection().getSize(); i++) {
0685:                        getXRefSection().load(i, getSystemSecurityHandler());
0686:                    }
0687:                }
0688:            }
0689:
0690:            /**
0691:             * The number of objects currently loaded.
0692:             * 
0693:             * @return The number of objects currently loaded.
0694:             */
0695:            public int loadedSize() {
0696:                int result = 0;
0697:                for (Iterator it = getKeyToObject().values().iterator(); it
0698:                        .hasNext();) {
0699:                    COSIndirectObject ref = (COSIndirectObject) it.next();
0700:                    if (!ref.isSwapped()) {
0701:                        result++;
0702:                    }
0703:                }
0704:                return result;
0705:            }
0706:
0707:            /**
0708:             * An iterator on the indirect objects of the storage layer document. This
0709:             * includes garbage and purely technical objects like x ref streams.
0710:             * 
0711:             * @return An iterator on the indirect objects of the storage layer
0712:             *         document. This includes garbage and purely technical objects like
0713:             *         x ref streams.
0714:             */
0715:            public Iterator objects() {
0716:                return new Iterator() {
0717:                    int i = 1;
0718:
0719:                    public boolean hasNext() {
0720:                        return i < getXRefSection().getSize();
0721:                    }
0722:
0723:                    public Object next() {
0724:                        if (!hasNext()) {
0725:                            throw new NoSuchElementException(""); //$NON-NLS-1$
0726:                        }
0727:                        COSObjectKey key = new COSObjectKey(i++, 0);
0728:                        return getObjectReference(key);
0729:                    }
0730:
0731:                    public void remove() {
0732:                        throw new UnsupportedOperationException(
0733:                                "remove not supported"); //$NON-NLS-1$
0734:                    }
0735:                };
0736:            }
0737:
0738:            /**
0739:             * @throws IOException
0740:             * 
0741:             */
0742:            protected void open() throws IOException {
0743:                synchronized (getAccessLock()) {
0744:                    if ((randomAccess != null) && !isClosed()) {
0745:                        throw new IllegalStateException(
0746:                                "can't open an open document"); //$NON-NLS-1$
0747:                    }
0748:                    setRandomAccess(createRandomAccess(getLocator()));
0749:                }
0750:            }
0751:
0752:            /**
0753:             * Reparses the XREF sections without actually instantiating. Used for
0754:             * collecting errors on XREF level
0755:             * 
0756:             * @throws IOException
0757:             * @throws COSLoadException
0758:             */
0759:            public void reparseFromLocator() throws IOException,
0760:                    COSLoadException {
0761:                synchronized (getAccessLock()) {
0762:                    int offset = getParser().searchLastStartXRef(
0763:                            getRandomAccess());
0764:                    AbstractXRefParser xRefParser;
0765:                    if (getParser().isTokenXRefAt(getRandomAccess(), offset)) {
0766:                        xRefParser = new XRefTrailerParser(this , getParser());
0767:                    } else {
0768:                        xRefParser = new XRefStreamParser(this , getParser());
0769:                    }
0770:                    getRandomAccess().seek(offset);
0771:                    xRefParser.parse(getRandomAccess());
0772:                }
0773:            }
0774:
0775:            /**
0776:             * Assign a new locator to the document.
0777:             * <p>
0778:             * The documents data is completely copied to the new location.
0779:             * 
0780:             * @param newLocator
0781:             *            The new locator for the documents data.
0782:             * 
0783:             * @throws IOException
0784:             */
0785:            protected void replaceLocator(ILocator newLocator)
0786:                    throws IOException {
0787:                synchronized (getAccessLock()) {
0788:                    if (newLocator.equals(getLocator())) {
0789:                        return;
0790:                    }
0791:                    ILocator oldLocator = getLocator();
0792:                    IRandomAccess oldRandomAccess = getRandomAccess();
0793:                    try {
0794:                        setLocator(newLocator);
0795:                        setRandomAccess(null);
0796:                        open();
0797:                        IRandomAccess newRandomAccess = getRandomAccess();
0798:                        if (newRandomAccess.isReadOnly()) {
0799:                            throw new FileNotFoundException();
0800:                        }
0801:                        if (newRandomAccess.getLength() > 0) {
0802:                            newRandomAccess.setLength(0);
0803:                        }
0804:                        if (oldRandomAccess != null) {
0805:                            InputStream is = oldRandomAccess.asInputStream();
0806:                            OutputStream os = newRandomAccess.asOutputStream();
0807:                            oldRandomAccess.seek(0);
0808:                            StreamTools.copyStream(is, false, os, false);
0809:                        }
0810:                        StreamTools.close(oldRandomAccess);
0811:                    } catch (Exception e) {
0812:                        // undo changes
0813:                        StreamTools.close(getRandomAccess());
0814:                        setLocator(oldLocator);
0815:                        setRandomAccess(oldRandomAccess);
0816:                    }
0817:                }
0818:            }
0819:
0820:            public void restore(ILocator newLocator) throws IOException,
0821:                    COSLoadException {
0822:                synchronized (getAccessLock()) {
0823:                    if (newLocator.equals(getLocator())) {
0824:                        return;
0825:                    }
0826:                    IRandomAccess oldRandomAccess = getRandomAccess();
0827:                    StreamTools.close(oldRandomAccess);
0828:                    setRandomAccess(null);
0829:                    setLocator(newLocator);
0830:                    changes.clear();
0831:                    keyToObject.clear();
0832:                    closed = false;
0833:                    dirty = false;
0834:                    streamLoad();
0835:                }
0836:                getDoc().triggerChangedAll();
0837:            }
0838:
0839:            public void save() throws IOException {
0840:                save(getLocator(), null);
0841:            }
0842:
0843:            public void save(ILocator pLocator) throws IOException {
0844:                save(pLocator, null);
0845:            }
0846:
0847:            public void save(ILocator pLocator, Map options) throws IOException {
0848:                // options could be null, when called from save(), even if a locator
0849:                // exists.
0850:                if (options == null) {
0851:                    options = new HashMap();
0852:                }
0853:                if ((pLocator != null) && (pLocator != getLocator())) {
0854:                    replaceLocator(pLocator);
0855:                }
0856:                boolean incremental = true;
0857:                EnumWriteMode writeMode = doc.getWriteModeHint();
0858:                // reset write mode
0859:                doc.setWriteModeHint(EnumWriteMode.UNDEFINED);
0860:                if (writeMode.isUndefined()) {
0861:                    Object tempHint = options.get(OPTION_WRITEMODEHINT);
0862:                    if (tempHint instanceof  EnumWriteMode) {
0863:                        writeMode = (EnumWriteMode) tempHint;
0864:                    }
0865:                }
0866:                if (writeMode.isFull()) {
0867:                    incremental = false;
0868:                }
0869:                IRandomAccess tempRandomAccess = getRandomAccess();
0870:                if (tempRandomAccess == null) {
0871:                    throw new IOException("nowhere to write to"); //$NON-NLS-1$
0872:                }
0873:                if (tempRandomAccess.isReadOnly()) {
0874:                    throw new FileNotFoundException("destination is read only"); //$NON-NLS-1$
0875:                }
0876:                COSWriter writer = new COSWriter(tempRandomAccess,
0877:                        getSystemSecurityHandler());
0878:                writer.setIncremental(incremental);
0879:                writer.writeDocument(this );
0880:            }
0881:
0882:            protected void setClosed(boolean closed) {
0883:                this .closed = closed;
0884:            }
0885:
0886:            /**
0887:             * Set the change flag of this.
0888:             * 
0889:             * @param dirty
0890:             *            <code>true</code> if this should be marked as changed
0891:             */
0892:            public void setDirty(boolean dirty) {
0893:                this .dirty = dirty;
0894:                if (!dirty) {
0895:                    changes.clear();
0896:                }
0897:            }
0898:
0899:            public void setDoc(COSDocument doc) {
0900:                this .doc = doc;
0901:                getXRefSection().setCOSDoc(getDoc());
0902:            }
0903:
0904:            protected void setDocType(STDocType docType) {
0905:                this .docType = docType;
0906:            }
0907:
0908:            protected void setLocator(ILocator locator) {
0909:                this .locator = locator;
0910:            }
0911:
0912:            /**
0913:             * Rename the document locally.
0914:             * <p>
0915:             * This has no effect if a locator is present.
0916:             * 
0917:             * @param name
0918:             *            The new local name of this
0919:             */
0920:            public void setName(String name) {
0921:                if (getLocator() instanceof  TransientLocator) {
0922:                    ((TransientLocator) getLocator()).setLocalName(name);
0923:                }
0924:            }
0925:
0926:            /**
0927:             * Assign the IRAndomAccess to the documetns data.
0928:             * 
0929:             * @param randomAccess
0930:             *            the IRAndomAccess to the documetns data.
0931:             */
0932:            protected void setRandomAccess(IRandomAccess randomAccess) {
0933:                this .randomAccess = randomAccess;
0934:            }
0935:
0936:            /**
0937:             * The write mode to be used when the document is written the next time. If
0938:             * defined this overrides any hint that is used when saving the document.
0939:             * The write mode is reset after each "save".
0940:             * 
0941:             * @param writeMode
0942:             *            The write mode to be used when the document is written.
0943:             */
0944:            public void setWriteModeHint(EnumWriteMode writeMode) {
0945:                if (writeMode == null) {
0946:                    throw new IllegalArgumentException(
0947:                            "write mode can't be null"); //$NON-NLS-1$
0948:                }
0949:                this .writeModeHint = writeMode;
0950:            }
0951:
0952:            /**
0953:             * Attach the most recent x ref section to the document.
0954:             * 
0955:             * @param xRefSection
0956:             *            The x ref section representing the most recent document
0957:             *            changes.
0958:             */
0959:            public void setXRefSection(STXRefSection xRefSection) {
0960:                this .xRefSection = xRefSection;
0961:                if (getDoc() != null) {
0962:                    getXRefSection().setCOSDoc(getDoc());
0963:                }
0964:            }
0965:
0966:            protected void streamLoad() throws IOException, COSLoadException {
0967:                try {
0968:                    open();
0969:                    STXRefSection initialXRefSection;
0970:                    setDocType(getParser().parseHeader(getRandomAccess()));
0971:                    try {
0972:                        int offset = getParser().searchLastStartXRef(
0973:                                getRandomAccess());
0974:                        AbstractXRefParser xRefParser;
0975:                        if (getParser()
0976:                                .isTokenXRefAt(getRandomAccess(), offset)) {
0977:                            xRefParser = new XRefTrailerParser(this ,
0978:                                    getParser());
0979:                        } else {
0980:                            xRefParser = new XRefStreamParser(this , getParser());
0981:                        }
0982:                        getRandomAccess().seek(offset);
0983:                        initialXRefSection = xRefParser
0984:                                .parse(getRandomAccess());
0985:                    } catch (Exception ex) {
0986:                        Log.log(Level.FINEST, "error parsing " //$NON-NLS-1$
0987:                                + getLocator().getFullName(), ex);
0988:                        // TODO 2 log warning, trailer can't be parsed
0989:                        initialXRefSection = new XRefFallbackParser(this ,
0990:                                getParser()).parse(getRandomAccess());
0991:                    }
0992:                    setXRefSection(initialXRefSection);
0993:                    nextKey = new COSObjectKey(
0994:                            initialXRefSection.getSize() - 1, 0);
0995:                    initEncryption();
0996:                    checkConsistency();
0997:                } catch (IOException e) {
0998:                    try {
0999:                        close();
1000:                    } catch (IOException ce) {
1001:                        // ignore
1002:                    }
1003:                    throw e;
1004:                } catch (COSLoadException e) {
1005:                    try {
1006:                        close();
1007:                    } catch (IOException ce) {
1008:                        // ignore
1009:                    }
1010:                    throw e;
1011:                }
1012:            }
1013:
1014:            public void updateModificationDate() {
1015:                COSDictionary infoDict = cosGetTrailer()
1016:                        .get(COSTrailer.DK_Info).asDictionary();
1017:                if (infoDict == null) {
1018:                    return;
1019:                }
1020:                infoDict.put(COSInfoDict.DK_ModDate, new CDSDate()
1021:                        .cosGetObject());
1022:            }
1023:
1024:            /**
1025:             * <code>true</code> if this document is linearized.
1026:             * <p>
1027:             * When linearized reading is truly implemented, this check should be made
1028:             * using the document length instead for performance reasons.
1029:             * 
1030:             * @return <code>true</code> if this document is linearized.
1031:             */
1032:            public boolean isLinearized() {
1033:                return getLinearizedDict() != null;
1034:            }
1035:
1036:            /**
1037:             * The /Linearized dictionary of the document. The /Linearized dictionary is
1038:             * represented by the first entry in the (logically) first XRef section.
1039:             * <p>
1040:             * Note that this method may NOT return a dictionary even if the document
1041:             * contains a /Linearized dictionary as the first object. This is the case
1042:             * when the document was linearized and was written with an incremental
1043:             * change so that the linearization is obsolete.
1044:             * 
1045:             * @return The valid /Linearized dictionary of the document.
1046:             */
1047:            public COSDictionary getLinearizedDict() {
1048:                int objectNumber = 0;
1049:                Iterator it = getXRefSection().entryIterator();
1050:                while (it.hasNext()) {
1051:                    STXRefEntry entry = (STXRefEntry) it.next();
1052:                    if (entry.getObjectNumber() != 0) {
1053:                        objectNumber = entry.getObjectNumber();
1054:                        break;
1055:                    }
1056:                }
1057:                try {
1058:                    COSDictionary result = load(objectNumber).asDictionary();
1059:                    if (result != null) {
1060:                        COSObject version = result.get(COSName
1061:                                .constant("Linearized"));
1062:                        if (!version.isNull()) {
1063:                            return result;
1064:                        }
1065:                    }
1066:                } catch (Exception e) {
1067:                    // ignore
1068:                }
1069:                return null;
1070:            }
1071:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.