1 #ifndef __XMPFiles_hpp__
2 #define __XMPFiles_hpp__	1
3 
4 // =================================================================================================
5 // ADOBE SYSTEMS INCORPORATED
6 // Copyright 2002-2007 Adobe Systems Incorporated
7 // All Rights Reserved
8 //
9 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
10 // of the Adobe license agreement accompanying it.
11 // =================================================================================================
12 
13 #include <string>
14 
15 #define TXMP_STRING_TYPE std::string
16 #include "XMP.hpp"
17 
18 #if XMP_UNIXBuild
19 typedef int LFA_FileRef;
20 #else
21 typedef void * LFA_FileRef;
22 #endif
23 
24 class XMPFileHandler;
25 
26 // =================================================================================================
27 /// \file XMPFiles.hpp
28 /// \brief High level support to access metadata in files of interest to Adobe applications.
29 ///
30 /// This header ...
31 ///
32 // =================================================================================================
33 
34 // =================================================================================================
35 // *** Usage Notes (eventually to become Doxygen comments) ***
36 // ===========================================================
37 //
38 // This is the main part of the internal (DLL side) implementation of XMPFiles. Other parts are
39 // the entry point wrappers and the file format handlers. The XMPFiles class distills the client
40 // API from TXMPFiles.hpp, removing convenience overloads and substituting a pointer/length pair
41 // for output strings.
42 //
43 // The wrapper functions provide a stable binary interface and perform minor impedance correction
44 // between the client template API from TDocMeta.hpp and the DLL's XMPFiles class. The details of
45 // the wrappers should be considered private.
46 //
47 // File handlers are registered during DLL initialization with hard coded calls in Init_XMPFiles.
48 // Each file handler provides 2 standalone functions, CheckFormatProc and DocMetaHandlerCTor, plus a
49 // class derived from DocMetaHandler. The format and capability flags are passed when registering.
50 // This allows the same physical handler to be registered for multiple formats.
51 //
52 // -------------------------------------------------------------------------------------------------
53 //
54 // Basic outlines of the processing by the XMPFiles methods:
55 //
56 //	Constructor:
57 //		- Minimal work to create an empty XMPFiles object, set the ref count to 1.
58 //
59 //	Destructor:
60 //		- Decrement the ref count, return if greater than zero.
61 //		- Call LFA_Close if necessary.
62 //
63 //	UnlockLib & UnlockObj:
64 //		- Release the thread lock. Same for now, no per-object lock.
65 //
66 //	GetFormatInfo:
67 //		- Return the flags for the registered handler.
68 //
69 //	OpenFile:
70 //		- The physical file is opened via LFA_OpenFile.
71 //		- A handler is selected by calling the registered format checkers.
72 //		- The handler object is created by calling the registered constructor proc.
73 //
74 //	CloseFile:
75 //		- Return if there is no open file (not an error).
76 //		- If not a crash-safe update (includes read-only or no update), or the handler owns the file:
77 //			- Throw an exception if the handler owns the file but does not support safe update.
78 //			- If the file needs updating, call the handler's UpdateFile method.
79 //		- else:
80 //			- If the handler supports file rewrite:
81 //				- *** This might not preserve ownership and permissions.
82 //				- Create an empty temp file.
83 //				- Call the handler's WriteFile method, writing to the temp file.
84 //			- else
85 //				- *** This preserves ownership, permissions, and Mac resources.
86 //				- Copy the original file to a temp name (Mac data fork only).
87 //				- Rename the original file to a different temp name.
88 //				- Rename the copy file back to the original name.
89 //				- Call the handler's UpdateFile method for the "original as temp" file.
90 //			- Close both the original and temp files.
91 //			- Delete the file with the original name.
92 //			- Rename the temp file to the original name.
93 //		- Delete the handler object.
94 //		- Call LFA_Close if necessary.
95 //
96 //	GetFileInfo:
97 //		- Return the file info from the XMPFiles member variables.
98 //
99 //	GetXMP:
100 //		- Throw an exception if there is no open file.
101 //		- Call the handler's GetXMP method.
102 //
103 //	PutXMP:
104 //		- Throw an exception if there is no open file.
105 //		- Call the handler's PutXMP method.
106 //
107 //	CanPutXMP:
108 //		- Implement roughly as shown in TXMPFiles.hpp, there is no handler CanPutXMP method.
109 //
110 // -------------------------------------------------------------------------------------------------
111 //
112 // The format checker should do nothing but the minimal work to identify the overall file format.
113 // In particular it should not look for XMP or other metadata. Note that the format checker has no
114 // means to carry state forward, it just returns a yes/no answer about a particular file format.
115 //
116 // The format checker and file handler should use the LFA_* functions for all I/O. They should not
117 // open or close the file themselves unless the handler sets the "handler-owns-file" flag.
118 //
119 // The format checker is passed the format being checked, allowing one checker to handle multiple
120 // formats. It is passed the LFA file ref so that it can do additional reads if necessary. The
121 // buffer is from the start of the file, the file will be positioned to the byte following the
122 // buffer. The buffer length will be at least 4K, unless the file is smaller in which case it will
123 // be the length of the file. This buffer may be reused for additional reads.
124 //
125 // Identifying some file formats can require checking variable length strings. Doing seeks and reads
126 // for each is suboptimal. There are utilities to maintain a rolling buffer and ensure that a given
127 // amount of data is available. See the template file handler code for details.
128 //
129 // -------------------------------------------------------------------------------------------------
130 //
131 // The file handler has no explicit open and close methods. These are implicit in the handler's
132 // constructor and destructor. The file handler should use the XMPFiles member variables for the
133 // active file ref (and path if necessary), unless it owns the file. Note that these might change
134 // between the open and close in the case of crash-safe updates. Don't copy the XMPFiles member
135 // variables in the handler's constructor, save the pointer to the XMPFiles object and access
136 // directly as needed.
137 //
138 // The handler should have an UpdateFile method. This is called from XMPFiles::CloseFile if the
139 // file needs to be updated. The handler's destructor must only close the file, not update it.
140 // The handler can optionally have a WriteFile method, if it can rewrite the entire file.
141 //
142 // The handler is free to use its best judgement about caching parts of the file in memory. Overall
143 // speed of a single open/get/put/close cycle is probably the best goal, assuming a modern processor
144 // with a reasonable (significant but not enormous) amount of RAM.
145 //
146 // The handler methods will be called in a per-object thread safe manner. Concurrent access might
147 // occur for different objects, but not for the same object. The handler's constructor and destructor
148 // will always be globally serialized, so they can safely modify global data structures.
149 //
150 // (Testing issue: What about separate XMPFiles objects accessing the same file?)
151 //
152 // Handler's must not have any global objects that are heap allocated. Use pointers to objects that
153 // are allocated and deleted during the XMPFiles initialization and termination process. Some
154 // client apps are very picky about what they detect as memory leaks.
155 //
156 //    static char gSomeBuffer [10*1000];          // OK, not from the heap.
157 //    static std::string gSomeString;             // Not OK, content from the heap.
158 //    static std::vector<int> gSomeVector;        // Not OK, content from the heap.
159 //    static std::string * gSomeString = 0;       // OK, alloc at init, delete at term.
160 //    static std::vector<int> * gSomeVector = 0;  // OK, alloc at init, delete at term.
161 //
162 // =================================================================================================
163 
164 class XMPFiles {
165 public:
166 
167 	static void GetVersionInfo ( XMP_VersionInfo * info );
168 
169     static bool Initialize ( XMP_OptionBits options = 0 );
170     static void Terminate();
171 
172 	XMPFiles();
173 	virtual ~XMPFiles();
174 
175 	static void UnlockLib();
176 	void UnlockObj();
177 
178 	static bool GetFormatInfo ( XMP_FileFormat   format,
179                                 XMP_OptionBits * flags = 0 );
180 
181 	static XMP_FileFormat CheckFileFormat    ( XMP_StringPtr filePath );
182 	static XMP_FileFormat CheckPackageFormat ( XMP_StringPtr folderPath );
183 
184 	bool OpenFile ( XMP_StringPtr  filePath,
185 			        XMP_FileFormat format = kXMP_UnknownFile,
186 			        XMP_OptionBits openFlags = 0 );
187 
188 	void CloseFile ( XMP_OptionBits closeFlags = 0 );
189 
190 	bool GetFileInfo ( XMP_StringPtr *  filePath = 0,
191                        XMP_StringLen *  filePathLen = 0,
192 			           XMP_OptionBits * openFlags = 0,
193 			           XMP_FileFormat * format = 0,
194 			           XMP_OptionBits * handlerFlags = 0 );
195 
196 	void SetAbortProc ( XMP_AbortProc abortProc,
197 						void *        abortArg );
198 
199 	bool GetXMP ( SXMPMeta *       xmpObj = 0,
200 		          XMP_StringPtr *  xmpPacket = 0,
201 		          XMP_StringLen *  xmpPacketLen = 0,
202                   XMP_PacketInfo * packetInfo = 0 );
203 
204 	bool GetThumbnail ( XMP_ThumbnailInfo * tnailInfo );
205 
206 	void PutXMP ( const SXMPMeta & xmpObj );
207 
208 	void PutXMP ( XMP_StringPtr xmpPacket,
209                   XMP_StringLen xmpPacketLen = kXMP_UseNullTermination );
210 
211 	bool CanPutXMP ( const SXMPMeta & xmpObj );
212 
213 	bool CanPutXMP ( XMP_StringPtr xmpPacket,
214                      XMP_StringLen xmpPacketLen = kXMP_UseNullTermination );
215 
216 	// Leave this data public so file handlers can see it.
217 
218 	XMP_Int32 clientRefs;	// ! Must be signed to allow decrement from zero.
219 
220 	XMP_FileFormat   format;
221 	LFA_FileRef      fileRef;		// Non-zero if a file is open.
222 	std::string      filePath;
223 	XMP_OptionBits   openFlags;
224 	XMPFileHandler * handler;		// Non-null if a file is open.
225 	void *           handlerTemp;	// For use between the CheckProc and handler creation.
226 
227 	XMP_AbortProc    abortProc;
228 	void *           abortArg;
229 
230 };	// XMPFiles
231 
232 #endif /* __XMPFiles_hpp__ */
233