001: /*
002: * Copyright 2005-2007 Noelios Consulting.
003: *
004: * The contents of this file are subject to the terms of the Common Development
005: * and Distribution License (the "License"). You may not use this file except in
006: * compliance with the License.
007: *
008: * You can obtain a copy of the license at
009: * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
010: * language governing permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL HEADER in each file and
013: * include the License file at http://www.opensource.org/licenses/cddl1.txt If
014: * applicable, add the following below this CDDL HEADER, with the fields
015: * enclosed by brackets "[]" replaced with your own identifying information:
016: * Portions Copyright [yyyy] [name of copyright owner]
017: */
018:
019: package org.restlet.resource;
020:
021: import java.io.File;
022: import java.io.FileInputStream;
023: import java.io.FileNotFoundException;
024: import java.io.IOException;
025: import java.io.OutputStream;
026: import java.nio.channels.FileChannel;
027: import java.nio.channels.WritableByteChannel;
028: import java.util.Date;
029:
030: import org.restlet.data.LocalReference;
031: import org.restlet.data.MediaType;
032: import org.restlet.util.ByteUtils;
033:
034: /**
035: * Representation based on a file.
036: *
037: * @author Jerome Louvel (contact@noelios.com)
038: */
039: public class FileRepresentation extends Representation {
040: /** The file descriptor. */
041: private File file;
042:
043: /**
044: * Constructor.
045: *
046: * @param file
047: * The represented file.
048: * @param mediaType
049: * The representation's media type.
050: * @param timeToLive
051: * The time to live before it expires (in seconds).
052: */
053: public FileRepresentation(File file, MediaType mediaType,
054: int timeToLive) {
055: super (mediaType);
056: this .file = file;
057: setModificationDate(new Date(file.lastModified()));
058: setExpirationDate(new Date(System.currentTimeMillis()
059: + (1000L * timeToLive)));
060: setMediaType(mediaType);
061: }
062:
063: /**
064: * Constructor.
065: *
066: * @param path
067: * The path name or file URI of the represented file.
068: * @param mediaType
069: * The representation's media type.
070: * @param timeToLive
071: * The time to live before it expires (in seconds).
072: * @see java.io.File#File(String)
073: */
074: public FileRepresentation(String path, MediaType mediaType,
075: int timeToLive) {
076: this (createFile(path), mediaType, timeToLive);
077: }
078:
079: /**
080: * Creates a new file by detecting if the name is a URI or a simple path
081: * name.
082: *
083: * @param path
084: * The path name or file URI of the represented file.
085: * @return The associated File instance.
086: */
087: private static File createFile(String path) {
088: if (path.startsWith("file://")) {
089: return new LocalReference(path).getFile();
090: } else {
091: return new File(path);
092: }
093: }
094:
095: /**
096: * Returns a readable byte channel. If it is supported by a file a read-only
097: * instance of FileChannel is returned.
098: *
099: * @return A readable byte channel.
100: */
101: public FileChannel getChannel() throws IOException {
102: try {
103: return new FileInputStream(file).getChannel();
104: } catch (FileNotFoundException fnfe) {
105: throw new IOException(
106: "Couldn't get the channel. File not found");
107: }
108: }
109:
110: /**
111: * Returns the size in bytes if known, UNKNOWN_SIZE (-1) otherwise.
112: *
113: * @return The size in bytes if known, UNKNOWN_SIZE (-1) otherwise.
114: */
115: public long getSize() {
116: if (super .getSize() != UNKNOWN_SIZE) {
117: return super .getSize();
118: } else {
119: return this .file.length();
120: }
121: }
122:
123: /**
124: * Returns a stream with the representation's content.
125: *
126: * @return A stream with the representation's content.
127: */
128: public FileInputStream getStream() throws IOException {
129: try {
130: return new FileInputStream(file);
131: } catch (FileNotFoundException fnfe) {
132: throw new IOException(
133: "Couldn't get the stream. File not found");
134: }
135: }
136:
137: /**
138: * Converts the representation to a string value. Be careful when using this
139: * method as the conversion of large content to a string fully stored in
140: * memory can result in OutOfMemoryErrors being thrown.
141: *
142: * @return The representation as a string value.
143: */
144: public String getText() throws IOException {
145: return ByteUtils.toString(getStream(), this .getCharacterSet());
146: }
147:
148: /**
149: * Writes the representation to a byte stream.
150: *
151: * @param outputStream
152: * The output stream.
153: */
154: public void write(OutputStream outputStream) throws IOException {
155: ByteUtils.write(getStream(), outputStream);
156: }
157:
158: /**
159: * Writes the representation to a byte channel. Optimizes using the file
160: * channel transferTo method.
161: *
162: * @param writableChannel
163: * A writable byte channel.
164: */
165: public void write(WritableByteChannel writableChannel)
166: throws IOException {
167: FileChannel fc = getChannel();
168: long position = 0;
169: long count = fc.size();
170: long written = 0;
171:
172: while (count > 0) {
173: written = fc.transferTo(position, count, writableChannel);
174: position += written;
175: count -= written;
176: }
177: }
178:
179: }
|