You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tika.apache.org by ta...@apache.org on 2018/12/13 15:31:14 UTC
[tika] 02/02: TIKA-2792 -- revert mp4parser dependency
This is an automated email from the ASF dual-hosted git repository.
tallison pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tika.git
commit 8187f21aecf17d6796c36f2ef2f3d39ca6364ab0
Author: TALLISON <ta...@apache.org>
AuthorDate: Thu Dec 13 10:24:47 2018 -0500
TIKA-2792 -- revert mp4parser dependency
---
tika-parsers/pom.xml | 8 +-
.../tika/parser/mp4/DirectFileReadDataSource.java | 127 ++++++++
.../java/org/apache/tika/parser/mp4/MP4Parser.java | 337 +++++++++++----------
3 files changed, 300 insertions(+), 172 deletions(-)
diff --git a/tika-parsers/pom.xml b/tika-parsers/pom.xml
index 230ff1b..248aea9 100644
--- a/tika-parsers/pom.xml
+++ b/tika-parsers/pom.xml
@@ -292,14 +292,10 @@
<version>7.0</version>
</dependency>
<dependency>
- <!-- 1.9.37 was built with jdk9 and
- causes: Method rewind()Ljava/nio/ByteBuffer;
- does not exist in class java.nio.ByteBuffer -->
- <groupId>org.mp4parser</groupId>
+ <groupId>com.googlecode.mp4parser</groupId>
<artifactId>isoparser</artifactId>
- <version>1.9.36</version>
+ <version>1.1.22</version>
</dependency>
-
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
diff --git a/tika-parsers/src/main/java/org/apache/tika/parser/mp4/DirectFileReadDataSource.java b/tika-parsers/src/main/java/org/apache/tika/parser/mp4/DirectFileReadDataSource.java
new file mode 100644
index 0000000..698a106
--- /dev/null
+++ b/tika-parsers/src/main/java/org/apache/tika/parser/mp4/DirectFileReadDataSource.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.parser.mp4;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+
+import com.googlecode.mp4parser.DataSource;
+
+/**
+ * A {@link DataSource} implementation that relies on direct reads from a {@link RandomAccessFile}.
+ * It should be slower than {@link com.googlecode.mp4parser.FileDataSourceImpl} but does not incur the implicit file locks of
+ * memory mapped I/O on some JVMs. This implementation allows for a more controlled deletion of files
+ * and might be preferred when working with temporary files.
+ * @see <a href="http://bugs.java.com/view_bug.do?bug_id=4724038">JDK-4724038 : (fs) Add unmap method to MappedByteBuffer</a>
+ * @see <a href="http://bugs.java.com/view_bug.do?bug_id=6359560">JDK-6359560 : (fs) File.deleteOnExit() doesn't work when MappedByteBuffer exists (win)</a>
+ */
+public class DirectFileReadDataSource implements DataSource {
+
+ private static final int TRANSFER_SIZE = 8192;
+
+ private RandomAccessFile raf;
+
+ public DirectFileReadDataSource(File f) throws IOException {
+ this.raf = new RandomAccessFile(f, "r");
+ }
+
+ public int read(ByteBuffer byteBuffer) throws IOException {
+ int len = byteBuffer.remaining();
+ int totalRead = 0;
+ int bytesRead = 0;
+ byte[] buf = new byte[TRANSFER_SIZE];
+ while (totalRead < len) {
+ int bytesToRead = Math.min((len - totalRead), TRANSFER_SIZE);
+ bytesRead = raf.read(buf, 0, bytesToRead);
+ if (bytesRead < 0) {
+ break;
+ } else {
+ totalRead += bytesRead;
+ }
+ byteBuffer.put(buf, 0, bytesRead);
+ }
+ if (bytesRead < 0 && position() == size() && byteBuffer.hasRemaining()) {
+ throw new IOException("End of stream reached earlier than expected");
+ }
+ return ((bytesRead < 0) && (totalRead == 0)) ? -1 : totalRead;
+ }
+
+ public int readAllInOnce(ByteBuffer byteBuffer) throws IOException {
+ if (byteBuffer.remaining() > raf.length()) {
+ throw new IOException("trying to readAllInOnce past end of stream");
+ }
+ byte[] buf = new byte[byteBuffer.remaining()];
+ int read = raf.read(buf);
+ byteBuffer.put(buf, 0, read);
+ return read;
+ }
+
+ public long size() throws IOException {
+ return raf.length();
+ }
+
+ public long position() throws IOException {
+ return raf.getFilePointer();
+ }
+
+ public void position(long nuPos) throws IOException {
+ if (nuPos > raf.length()) {
+ throw new IOException("requesting seek past end of stream");
+ }
+ raf.seek(nuPos);
+ }
+
+ public long transferTo(long position, long count, WritableByteChannel target) throws IOException {
+ return target.write(map(position, count));
+ }
+
+ public ByteBuffer map(long startPosition, long size) throws IOException {
+ if (startPosition < 0 || size < 0) {
+ throw new IOException("startPosition and size must both be >= 0");
+ }
+ //make sure that start+size aren't greater than avail size
+ //in raf.
+ BigInteger end = BigInteger.valueOf(startPosition);
+ end = end.add(BigInteger.valueOf(size));
+ if (end.compareTo(BigInteger.valueOf(raf.length())) > 0) {
+ throw new IOException("requesting read past end of stream");
+ }
+
+ raf.seek(startPosition);
+ int payLoadSize = l2i(size);
+ //hack to check for potential overflow
+ if (Long.MAX_VALUE-payLoadSize < startPosition ||
+ Long.MAX_VALUE-payLoadSize > raf.length()) {
+ throw new IOException("requesting read past end of stream");
+ }
+ byte[] payload = new byte[payLoadSize];
+ raf.readFully(payload);
+ return ByteBuffer.wrap(payload);
+ }
+
+ @Override
+ public void close() throws IOException {
+ raf.close();
+ }
+
+}
\ No newline at end of file
diff --git a/tika-parsers/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java b/tika-parsers/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java
index c483433..afa63b8 100644
--- a/tika-parsers/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java
+++ b/tika-parsers/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java
@@ -16,6 +16,36 @@
*/
package org.apache.tika.parser.mp4;
+
+import com.coremedia.iso.IsoFile;
+import com.coremedia.iso.boxes.Box;
+import com.coremedia.iso.boxes.Container;
+import com.coremedia.iso.boxes.FileTypeBox;
+import com.coremedia.iso.boxes.MetaBox;
+import com.coremedia.iso.boxes.MovieBox;
+import com.coremedia.iso.boxes.MovieHeaderBox;
+import com.coremedia.iso.boxes.SampleDescriptionBox;
+import com.coremedia.iso.boxes.SampleTableBox;
+import com.coremedia.iso.boxes.TrackBox;
+import com.coremedia.iso.boxes.TrackHeaderBox;
+import com.coremedia.iso.boxes.UserDataBox;
+import com.coremedia.iso.boxes.apple.AppleItemListBox;
+import com.coremedia.iso.boxes.sampleentry.AudioSampleEntry;
+import com.googlecode.mp4parser.DataSource;
+import com.googlecode.mp4parser.boxes.apple.AppleAlbumBox;
+import com.googlecode.mp4parser.boxes.apple.AppleArtist2Box;
+import com.googlecode.mp4parser.boxes.apple.AppleArtistBox;
+import com.googlecode.mp4parser.boxes.apple.AppleCommentBox;
+import com.googlecode.mp4parser.boxes.apple.AppleCompilationBox;
+import com.googlecode.mp4parser.boxes.apple.AppleDiskNumberBox;
+import com.googlecode.mp4parser.boxes.apple.AppleEncoderBox;
+import com.googlecode.mp4parser.boxes.apple.AppleGenreBox;
+import com.googlecode.mp4parser.boxes.apple.AppleNameBox;
+import com.googlecode.mp4parser.boxes.apple.AppleRecordingYear2Box;
+import com.googlecode.mp4parser.boxes.apple.AppleTrackAuthorBox;
+import com.googlecode.mp4parser.boxes.apple.AppleTrackNumberBox;
+import com.googlecode.mp4parser.boxes.apple.Utf8AppleDataBox;
+import org.apache.poi.ss.formula.functions.T;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
import org.apache.tika.io.TikaInputStream;
@@ -28,33 +58,6 @@ import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.AbstractParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.XHTMLContentHandler;
-import org.mp4parser.Box;
-import org.mp4parser.Container;
-import org.mp4parser.IsoFile;
-import org.mp4parser.boxes.apple.AppleAlbumBox;
-import org.mp4parser.boxes.apple.AppleArtist2Box;
-import org.mp4parser.boxes.apple.AppleArtistBox;
-import org.mp4parser.boxes.apple.AppleCommentBox;
-import org.mp4parser.boxes.apple.AppleCompilationBox;
-import org.mp4parser.boxes.apple.AppleDiskNumberBox;
-import org.mp4parser.boxes.apple.AppleEncoderBox;
-import org.mp4parser.boxes.apple.AppleGenreBox;
-import org.mp4parser.boxes.apple.AppleItemListBox;
-import org.mp4parser.boxes.apple.AppleNameBox;
-import org.mp4parser.boxes.apple.AppleRecordingYear2Box;
-import org.mp4parser.boxes.apple.AppleTrackAuthorBox;
-import org.mp4parser.boxes.apple.AppleTrackNumberBox;
-import org.mp4parser.boxes.apple.Utf8AppleDataBox;
-import org.mp4parser.boxes.iso14496.part12.FileTypeBox;
-import org.mp4parser.boxes.iso14496.part12.MetaBox;
-import org.mp4parser.boxes.iso14496.part12.MovieBox;
-import org.mp4parser.boxes.iso14496.part12.MovieHeaderBox;
-import org.mp4parser.boxes.iso14496.part12.SampleDescriptionBox;
-import org.mp4parser.boxes.iso14496.part12.SampleTableBox;
-import org.mp4parser.boxes.iso14496.part12.TrackBox;
-import org.mp4parser.boxes.iso14496.part12.TrackHeaderBox;
-import org.mp4parser.boxes.iso14496.part12.UserDataBox;
-import org.mp4parser.boxes.sampleentry.AudioSampleEntry;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
@@ -73,7 +76,7 @@ import java.util.Set;
/**
* Parser for the MP4 media container format, as well as the older
* QuickTime format that MP4 is based on.
- *
+ *
* This uses the MP4Parser project from http://code.google.com/p/mp4parser/
* to do the underlying parsing
*/
@@ -81,12 +84,12 @@ public class MP4Parser extends AbstractParser {
/** Serial version UID */
private static final long serialVersionUID = 84011216792285L;
/** TODO Replace this with a 2dp Duration Property Converter */
- private static final DecimalFormat DURATION_FORMAT =
- (DecimalFormat)NumberFormat.getNumberInstance(Locale.ROOT);
+ private static final DecimalFormat DURATION_FORMAT =
+ (DecimalFormat)NumberFormat.getNumberInstance(Locale.ROOT);
static {
DURATION_FORMAT.applyPattern("0.0#");
}
-
+
// Ensure this stays in Sync with the entries in tika-mimetypes.xml
private static final Map<MediaType,List<String>> typesMap = new HashMap<MediaType, List<String>>();
static {
@@ -125,41 +128,42 @@ public class MP4Parser extends AbstractParser {
TemporaryResources tmp = new TemporaryResources();
TikaInputStream tstream = TikaInputStream.get(stream, tmp);
- try (IsoFile isoFile = new IsoFile(tstream.getFile())) {
- tmp.addResource(isoFile);
-
- // Grab the file type box
- FileTypeBox fileType = getOrNull(isoFile, FileTypeBox.class);
- if (fileType != null) {
- // Identify the type
- MediaType type = MediaType.application("mp4");
- for (Map.Entry<MediaType, List<String>> e : typesMap.entrySet()) {
- if (e.getValue().contains(fileType.getMajorBrand())) {
- type = e.getKey();
- break;
+ try (DataSource dataSource = new DirectFileReadDataSource(tstream.getFile())) {
+ try (IsoFile isoFile = new IsoFile(dataSource)) {
+ tmp.addResource(isoFile);
+
+ // Grab the file type box
+ FileTypeBox fileType = getOrNull(isoFile, FileTypeBox.class);
+ if (fileType != null) {
+ // Identify the type
+ MediaType type = MediaType.application("mp4");
+ for (Map.Entry<MediaType, List<String>> e : typesMap.entrySet()) {
+ if (e.getValue().contains(fileType.getMajorBrand())) {
+ type = e.getKey();
+ break;
+ }
}
- }
- metadata.set(Metadata.CONTENT_TYPE, type.toString());
+ metadata.set(Metadata.CONTENT_TYPE, type.toString());
- if (type.getType().equals("audio")) {
- metadata.set(XMPDM.AUDIO_COMPRESSOR, fileType.getMajorBrand().trim());
+ if (type.getType().equals("audio")) {
+ metadata.set(XMPDM.AUDIO_COMPRESSOR, fileType.getMajorBrand().trim());
+ }
+ } else {
+ // Some older QuickTime files lack the FileType
+ metadata.set(Metadata.CONTENT_TYPE, "video/quicktime");
}
- } else {
- // Some older QuickTime files lack the FileType
- metadata.set(Metadata.CONTENT_TYPE, "video/quicktime");
- }
- // Get the main MOOV box
- MovieBox moov = getOrNull(isoFile, MovieBox.class);
- if (moov == null) {
- // Bail out
- return;
- }
+ // Get the main MOOV box
+ MovieBox moov = getOrNull(isoFile, MovieBox.class);
+ if (moov == null) {
+ // Bail out
+ return;
+ }
- XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
- xhtml.startDocument();
+ XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
+ xhtml.startDocument();
// Pull out some information from the header box
@@ -169,131 +173,132 @@ public class MP4Parser extends AbstractParser {
metadata.set(TikaCoreProperties.CREATED, mHeader.getCreationTime());
metadata.set(TikaCoreProperties.MODIFIED, mHeader.getModificationTime());
- // Get the duration
- double durationSeconds = ((double) mHeader.getDuration()) / mHeader.getTimescale();
- metadata.set(XMPDM.DURATION, DURATION_FORMAT.format(durationSeconds));
-
- // The timescale is normally the sampling rate
- metadata.set(XMPDM.AUDIO_SAMPLE_RATE, (int) mHeader.getTimescale());
- }
+ // Get the duration
+ double durationSeconds = ((double) mHeader.getDuration()) / mHeader.getTimescale();
+ metadata.set(XMPDM.DURATION, DURATION_FORMAT.format(durationSeconds));
+ // The timescale is normally the sampling rate
+ metadata.set(XMPDM.AUDIO_SAMPLE_RATE, (int) mHeader.getTimescale());
+ }
- // Get some more information from the track header
- // TODO Decide how to handle multiple tracks
- List<TrackBox> tb = moov.getBoxes(TrackBox.class);
- if (tb.size() > 0) {
- TrackBox track = tb.get(0);
- TrackHeaderBox header = track.getTrackHeaderBox();
- // Get the creation and modification dates
- metadata.set(TikaCoreProperties.CREATED, header.getCreationTime());
- metadata.set(TikaCoreProperties.MODIFIED, header.getModificationTime());
-
- // Get the video with and height
- metadata.set(Metadata.IMAGE_WIDTH, (int) header.getWidth());
- metadata.set(Metadata.IMAGE_LENGTH, (int) header.getHeight());
-
- // Get the sample information
- SampleTableBox samples = track.getSampleTableBox();
- SampleDescriptionBox sampleDesc = samples.getSampleDescriptionBox();
- if (sampleDesc != null) {
- // Look for the first Audio Sample, if present
- AudioSampleEntry sample = getOrNull(sampleDesc, AudioSampleEntry.class);
- if (sample != null) {
- XMPDM.ChannelTypePropertyConverter.convertAndSet(metadata, sample.getChannelCount());
- //metadata.set(XMPDM.AUDIO_SAMPLE_TYPE, sample.getSampleSize()); // TODO Num -> Type mapping
- metadata.set(XMPDM.AUDIO_SAMPLE_RATE, (int) sample.getSampleRate());
- //metadata.set(XMPDM.AUDIO_, sample.getSamplesPerPacket());
- //metadata.set(XMPDM.AUDIO_, sample.getBytesPerSample());
+ // Get some more information from the track header
+ // TODO Decide how to handle multiple tracks
+ List<TrackBox> tb = moov.getBoxes(TrackBox.class);
+ if (tb.size() > 0) {
+ TrackBox track = tb.get(0);
+
+ TrackHeaderBox header = track.getTrackHeaderBox();
+ // Get the creation and modification dates
+ metadata.set(TikaCoreProperties.CREATED, header.getCreationTime());
+ metadata.set(TikaCoreProperties.MODIFIED, header.getModificationTime());
+
+ // Get the video with and height
+ metadata.set(Metadata.IMAGE_WIDTH, (int) header.getWidth());
+ metadata.set(Metadata.IMAGE_LENGTH, (int) header.getHeight());
+
+ // Get the sample information
+ SampleTableBox samples = track.getSampleTableBox();
+ SampleDescriptionBox sampleDesc = samples.getSampleDescriptionBox();
+ if (sampleDesc != null) {
+ // Look for the first Audio Sample, if present
+ AudioSampleEntry sample = getOrNull(sampleDesc, AudioSampleEntry.class);
+ if (sample != null) {
+ XMPDM.ChannelTypePropertyConverter.convertAndSet(metadata, sample.getChannelCount());
+ //metadata.set(XMPDM.AUDIO_SAMPLE_TYPE, sample.getSampleSize()); // TODO Num -> Type mapping
+ metadata.set(XMPDM.AUDIO_SAMPLE_RATE, (int) sample.getSampleRate());
+ //metadata.set(XMPDM.AUDIO_, sample.getSamplesPerPacket());
+ //metadata.set(XMPDM.AUDIO_, sample.getBytesPerSample());
+ }
}
}
- }
- // Get metadata from the User Data Box
- UserDataBox userData = getOrNull(moov, UserDataBox.class);
- if (userData != null) {
- MetaBox meta = getOrNull(userData, MetaBox.class);
-
- // Check for iTunes Metadata
- // See http://atomicparsley.sourceforge.net/mpeg-4files.html and
- // http://code.google.com/p/mp4v2/wiki/iTunesMetadata for more on these
- AppleItemListBox apple = getOrNull(meta, AppleItemListBox.class);
- if (apple != null) {
- // Title
- AppleNameBox title = getOrNull(apple, AppleNameBox.class);
- addMetadata(TikaCoreProperties.TITLE, metadata, title);
-
- // Artist
- AppleArtistBox artist = getOrNull(apple, AppleArtistBox.class);
- addMetadata(TikaCoreProperties.CREATOR, metadata, artist);
- addMetadata(XMPDM.ARTIST, metadata, artist);
-
- // Album Artist
- AppleArtist2Box artist2 = getOrNull(apple, AppleArtist2Box.class);
- addMetadata(XMPDM.ALBUM_ARTIST, metadata, artist2);
-
- // Album
- AppleAlbumBox album = getOrNull(apple, AppleAlbumBox.class);
- addMetadata(XMPDM.ALBUM, metadata, album);
-
- // Composer
- AppleTrackAuthorBox composer = getOrNull(apple, AppleTrackAuthorBox.class);
- addMetadata(XMPDM.COMPOSER, metadata, composer);
-
- // Genre
- AppleGenreBox genre = getOrNull(apple, AppleGenreBox.class);
- addMetadata(XMPDM.GENRE, metadata, genre);
-
- // Year
- AppleRecordingYear2Box year = getOrNull(apple, AppleRecordingYear2Box.class);
- if (year != null) {
- metadata.set(XMPDM.RELEASE_DATE, year.getValue());
- }
+ // Get metadata from the User Data Box
+ UserDataBox userData = getOrNull(moov, UserDataBox.class);
+ if (userData != null) {
+ MetaBox meta = getOrNull(userData, MetaBox.class);
+
+ // Check for iTunes Metadata
+ // See http://atomicparsley.sourceforge.net/mpeg-4files.html and
+ // http://code.google.com/p/mp4v2/wiki/iTunesMetadata for more on these
+ AppleItemListBox apple = getOrNull(meta, AppleItemListBox.class);
+ if (apple != null) {
+ // Title
+ AppleNameBox title = getOrNull(apple, AppleNameBox.class);
+ addMetadata(TikaCoreProperties.TITLE, metadata, title);
+
+ // Artist
+ AppleArtistBox artist = getOrNull(apple, AppleArtistBox.class);
+ addMetadata(TikaCoreProperties.CREATOR, metadata, artist);
+ addMetadata(XMPDM.ARTIST, metadata, artist);
+
+ // Album Artist
+ AppleArtist2Box artist2 = getOrNull(apple, AppleArtist2Box.class);
+ addMetadata(XMPDM.ALBUM_ARTIST, metadata, artist2);
+
+ // Album
+ AppleAlbumBox album = getOrNull(apple, AppleAlbumBox.class);
+ addMetadata(XMPDM.ALBUM, metadata, album);
+
+ // Composer
+ AppleTrackAuthorBox composer = getOrNull(apple, AppleTrackAuthorBox.class);
+ addMetadata(XMPDM.COMPOSER, metadata, composer);
+
+ // Genre
+ AppleGenreBox genre = getOrNull(apple, AppleGenreBox.class);
+ addMetadata(XMPDM.GENRE, metadata, genre);
+
+ // Year
+ AppleRecordingYear2Box year = getOrNull(apple, AppleRecordingYear2Box.class);
+ if (year != null) {
+ metadata.set(XMPDM.RELEASE_DATE, year.getValue());
+ }
- // Track number
- AppleTrackNumberBox trackNum = getOrNull(apple, AppleTrackNumberBox.class);
- if (trackNum != null) {
- metadata.set(XMPDM.TRACK_NUMBER, trackNum.getA());
- //metadata.set(XMPDM.NUMBER_OF_TRACKS, trackNum.getB()); // TODO
- }
+ // Track number
+ AppleTrackNumberBox trackNum = getOrNull(apple, AppleTrackNumberBox.class);
+ if (trackNum != null) {
+ metadata.set(XMPDM.TRACK_NUMBER, trackNum.getA());
+ //metadata.set(XMPDM.NUMBER_OF_TRACKS, trackNum.getB()); // TODO
+ }
- // Disc number
- AppleDiskNumberBox discNum = getOrNull(apple, AppleDiskNumberBox.class);
- if (discNum != null) {
- metadata.set(XMPDM.DISC_NUMBER, discNum.getA());
- }
+ // Disc number
+ AppleDiskNumberBox discNum = getOrNull(apple, AppleDiskNumberBox.class);
+ if (discNum != null) {
+ metadata.set(XMPDM.DISC_NUMBER, discNum.getA());
+ }
- // Compilation
- AppleCompilationBox compilation = getOrNull(apple, AppleCompilationBox.class);
- if (compilation != null) {
- metadata.set(XMPDM.COMPILATION, (int) compilation.getValue());
- }
+ // Compilation
+ AppleCompilationBox compilation = getOrNull(apple, AppleCompilationBox.class);
+ if (compilation != null) {
+ metadata.set(XMPDM.COMPILATION, (int) compilation.getValue());
+ }
- // Comment
- AppleCommentBox comment = getOrNull(apple, AppleCommentBox.class);
- addMetadata(XMPDM.LOG_COMMENT, metadata, comment);
+ // Comment
+ AppleCommentBox comment = getOrNull(apple, AppleCommentBox.class);
+ addMetadata(XMPDM.LOG_COMMENT, metadata, comment);
- // Encoder
- AppleEncoderBox encoder = getOrNull(apple, AppleEncoderBox.class);
- if (encoder != null) {
- metadata.set(XMP.CREATOR_TOOL, encoder.getValue());
- }
+ // Encoder
+ AppleEncoderBox encoder = getOrNull(apple, AppleEncoderBox.class);
+ if (encoder != null) {
+ metadata.set(XMP.CREATOR_TOOL, encoder.getValue());
+ }
- // As text
- for (Box box : apple.getBoxes()) {
- if (box instanceof Utf8AppleDataBox) {
- xhtml.element("p", ((Utf8AppleDataBox) box).getValue());
+ // As text
+ for (Box box : apple.getBoxes()) {
+ if (box instanceof Utf8AppleDataBox) {
+ xhtml.element("p", ((Utf8AppleDataBox) box).getValue());
+ }
}
}
- }
- // TODO Check for other kinds too
- }
+ // TODO Check for other kinds too
+ }
- // All done
- xhtml.endDocument();
+ // All done
+ xhtml.endDocument();
+ }
} finally {
tmp.dispose();
}