/* Copyright (c) 2008 Google Inc. * * Licensed 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 com.google.gdata.data.media; import com.google.gdata.client.GDataProtocol; import com.google.gdata.data.IEntry; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.activation.DataHandler; import javax.mail.MessagingException; import javax.mail.internet.InternetHeaders; import javax.mail.internet.MimeBodyPart; /** * The MediaBodyPart class extends the base MimeBodyPart implementation * to provide streaming media support for GData MIME multipart content. * When the body part contains media content (anything other than * "application/atom+xml"), the body part will use a custom * {@link DataHandler} implementation that keeps the data in raw stream format. * * * @see GDataContentHandler * @see MediaSource * @see MediaMultipart */ public class MediaBodyPart extends MimeBodyPart { private MediaSource mediaSource; /** * The MediaDataHandler class customizes the {@link DataHandler} class * of the Java Activation Framework. It simply wraps the original * {@link MediaSource} instance associated with the media, and returns it * as the content representation for the data. */ private static class MediaSourceDataHandler extends DataHandler { MediaSource source; private MediaSourceDataHandler(MediaSource ds) { super(ds); source = ds; } @Override public Object getContent() { // In the case of the MediaSource handler, the content representation // is just a reference to the underlying media source. return source; } @Override public void writeTo(OutputStream os) throws IOException { MediaSource.Output.writeTo(source, os); } } public MediaBodyPart() { super(); } public MediaBodyPart(InputStream is) throws MessagingException { // Process the headers from the input stream super(new InternetHeaders(is), null); // Create a media stream source to read the remaining data, using the // content type information from the headers. mediaSource = new MediaStreamSource(is, getContentType()); initMediaDataHandler(); } public MediaBodyPart(IEntry entry) throws MessagingException { super(); setContent(entry, "application/atom+xml"); setHeader("Content-Type", "application/atom+xml"); } public MediaBodyPart(MediaSource mediaSource) throws MessagingException { super(); this.mediaSource = mediaSource; //headers.setHeader("Content-Type", mediaSource.getContentType()); setHeader("Content-Type", mediaSource.getContentType()); String etag = mediaSource.getEtag(); if (etag != null) { setHeader(GDataProtocol.Header.ETAG, etag); } initMediaDataHandler(); } public MediaBodyPart(InternetHeaders headers, byte [] content) throws MessagingException { super(headers, content); // javax.mail.util.SharedByteArrayInputStream here. String contentType = getContentType(); MediaStreamSource mediaStreamSource = new MediaStreamSource(new ByteArrayInputStream(content), contentType); String etag = getHeader(GDataProtocol.Header.ETAG, null); if (etag != null) { mediaStreamSource.setEtag(etag); } mediaSource = mediaStreamSource; initMediaDataHandler(); } /** * Initializes the {@link DataHandler} associated with the body part * when it contains media content. */ private void initMediaDataHandler() throws MessagingException { // Cannot call setDataHandler() because it invalidates header data // Fortunately, 'dh' is a protected field on the base class. if (!isAtomPart()) { // For media content, simply wrap the media source. dh = new MediaSourceDataHandler(mediaSource); } else { // For Atom content, use standard Java activation handling. dh = new DataHandler(mediaSource); } } /** * Returns {@code true} if the body part contains Atom data. */ public boolean isAtomPart() throws MessagingException { return isMimeType("application/atom+xml"); } /** * Returns the media source associated with the body part. */ public MediaSource getMediaSource() { return mediaSource; } }