001: /*
002: * @(#)MimeEntry.java 1.32 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.net.www;
029:
030: import java.net.URL;
031: import java.io.*;
032: import java.util.StringTokenizer;
033:
034: public class MimeEntry implements Cloneable {
035: public static final String defaultImagePath = "doc:/lib/images/ftp";
036:
037: private String typeName; // of the form: "type/subtype"
038: private String tempFileNameTemplate;
039:
040: private int action;
041: private String command;
042: private String description;
043: private String imageFileName;
044: private String fileExtensions[];
045:
046: boolean starred;
047:
048: // Actions
049: public static final int UNKNOWN = 0;
050: public static final int LOAD_INTO_BROWSER = 1;
051: public static final int SAVE_TO_FILE = 2;
052: public static final int LAUNCH_APPLICATION = 3;
053:
054: static final String[] actionKeywords = { "unknown", "browser",
055: "save", "application", };
056:
057: /**
058: * Construct an empty entry of the given type and subtype.
059: */
060: public MimeEntry(String type) {
061: // Default action is UNKNOWN so clients can decide what the default
062: // should be, typically save to file or ask user.
063: this (type, UNKNOWN, null, null, null);
064: }
065:
066: //
067: // The next two constructors are used only by the deprecated
068: // PlatformMimeTable classes or, in last case, is called by the public
069: // constructor. They are kept here anticipating putting support for
070: // mailcap formatted config files back in (so BOTH the properties format
071: // and the mailcap formats are supported).
072: //
073: MimeEntry(String type, String imageFileName, String extensionString) {
074: typeName = type.toLowerCase();
075: action = UNKNOWN;
076: command = null;
077: this .imageFileName = imageFileName;
078: setExtensions(extensionString);
079: starred = isStarred(typeName);
080: }
081:
082: // For use with MimeTable::parseMailCap
083: MimeEntry(String typeName, int action, String command,
084: String tempFileNameTemplate) {
085: this .typeName = typeName.toLowerCase();
086: this .action = action;
087: this .command = command;
088: this .imageFileName = null;
089: this .fileExtensions = null;
090:
091: this .tempFileNameTemplate = tempFileNameTemplate;
092: }
093:
094: // This is the one called by the public constructor.
095: MimeEntry(String typeName, int action, String command,
096: String imageFileName, String fileExtensions[]) {
097:
098: this .typeName = typeName.toLowerCase();
099: this .action = action;
100: this .command = command;
101: this .imageFileName = imageFileName;
102: this .fileExtensions = fileExtensions;
103:
104: starred = isStarred(typeName);
105:
106: }
107:
108: public synchronized String getType() {
109: return typeName;
110: }
111:
112: public synchronized void setType(String type) {
113: typeName = type.toLowerCase();
114: }
115:
116: public synchronized int getAction() {
117: return action;
118: }
119:
120: public synchronized void setAction(int action, String command) {
121: this .action = action;
122: this .command = command;
123: }
124:
125: public synchronized void setAction(int action) {
126: this .action = action;
127: }
128:
129: public synchronized String getLaunchString() {
130: return command;
131: }
132:
133: public synchronized void setCommand(String command) {
134: this .command = command;
135: }
136:
137: public synchronized String getDescription() {
138: return (description != null ? description : typeName);
139: }
140:
141: public synchronized void setDescription(String description) {
142: this .description = description;
143: }
144:
145: // ??? what to return for the image -- the file name or should this return
146: // something more advanced like an image source or something?
147: // returning the name has the least policy associated with it.
148: // pro tempore, we'll use the name
149: public String getImageFileName() {
150: return imageFileName;
151: }
152:
153: public synchronized void setImageFileName(String filename) {
154: File file = new File(filename);
155: if (file.getParent() == null) {
156: imageFileName = System
157: .getProperty("java.net.ftp.imagepath." + filename);
158: } else {
159: imageFileName = filename;
160: }
161:
162: if (filename.lastIndexOf('.') < 0) {
163: imageFileName = imageFileName + ".gif";
164: }
165: }
166:
167: public String getTempFileTemplate() {
168: return tempFileNameTemplate;
169: }
170:
171: public synchronized String[] getExtensions() {
172: return fileExtensions;
173: }
174:
175: public synchronized String getExtensionsAsList() {
176: String extensionsAsString = "";
177: if (fileExtensions != null) {
178: for (int i = 0; i < fileExtensions.length; i++) {
179: extensionsAsString += fileExtensions[i];
180: if (i < (fileExtensions.length - 1)) {
181: extensionsAsString += ",";
182: }
183: }
184: }
185:
186: return extensionsAsString;
187: }
188:
189: public synchronized void setExtensions(String extensionString) {
190: StringTokenizer extTokens = new StringTokenizer(
191: extensionString, ",");
192: int numExts = extTokens.countTokens();
193: String extensionStrings[] = new String[numExts];
194:
195: for (int i = 0; i < numExts; i++) {
196: String ext = (String) extTokens.nextElement();
197: extensionStrings[i] = ext.trim();
198: }
199:
200: fileExtensions = extensionStrings;
201: }
202:
203: private boolean isStarred(String typeName) {
204: return (typeName != null) && (typeName.length() > 0)
205: && (typeName.endsWith("/*"));
206: }
207:
208: /**
209: * Invoke the MIME type specific behavior for this MIME type.
210: * Returned value can be one of several types:
211: * <ol>
212: * <li>A thread -- the caller can choose when to launch this thread.
213: * <li>A string -- the string is loaded into the browser directly.
214: * <li>An input stream -- the caller can read from this byte stream and
215: * will typically store the results in a file.
216: * <li>A document (?) --
217: * </ol>
218: */
219: public Object launch(java.net.URLConnection urlc, InputStream is,
220: MimeTable mt) throws ApplicationLaunchException {
221: switch (action) {
222: case SAVE_TO_FILE:
223: // is this really the right thing to do?
224: try {
225: return is;
226: } catch (Exception e) {
227: // I18N
228: return "Load to file failed:\n" + e;
229: }
230:
231: case LOAD_INTO_BROWSER:
232: // invoke the content handler?
233: // may be the right thing to do, may not be -- short term
234: // where docs are not loaded asynch, loading and returning
235: // the content is the right thing to do.
236: try {
237: return urlc.getContent();
238: } catch (Exception e) {
239: return null;
240: }
241:
242: case LAUNCH_APPLICATION: {
243: String threadName = command;
244: int fst = threadName.indexOf(' ');
245: if (fst > 0) {
246: threadName = threadName.substring(0, fst);
247: }
248:
249: return new MimeLauncher(this , urlc, is, mt
250: .getTempFileTemplate(), threadName);
251: }
252:
253: case UNKNOWN:
254: return null;
255: }
256:
257: return null;
258: }
259:
260: public boolean matches(String type) {
261: if (starred) {
262: return type.startsWith(typeName);
263: } else {
264: return type.equals(typeName);
265: }
266: }
267:
268: public Object clone() {
269: // return a shallow copy of this.
270: MimeEntry theClone = new MimeEntry(typeName);
271: theClone.action = action;
272: theClone.command = command;
273: theClone.description = description;
274: theClone.imageFileName = imageFileName;
275: theClone.tempFileNameTemplate = tempFileNameTemplate;
276: theClone.fileExtensions = fileExtensions;
277:
278: return theClone;
279: }
280:
281: public synchronized String toProperty() {
282: StringBuffer buf = new StringBuffer();
283:
284: String separator = "; ";
285: boolean needSeparator = false;
286:
287: int action = getAction();
288: if (action != MimeEntry.UNKNOWN) {
289: buf.append("action=" + actionKeywords[action]);
290: needSeparator = true;
291: }
292:
293: String command = getLaunchString();
294: if (command != null && command.length() > 0) {
295: if (needSeparator) {
296: buf.append(separator);
297: }
298: buf.append("application=" + command);
299: needSeparator = true;
300: }
301:
302: if (getImageFileName() != null) {
303: if (needSeparator) {
304: buf.append(separator);
305: }
306: buf.append("icon=" + getImageFileName());
307: needSeparator = true;
308: }
309:
310: String extensions = getExtensionsAsList();
311: if (extensions.length() > 0) {
312: if (needSeparator) {
313: buf.append(separator);
314: }
315: buf.append("file_extensions=" + extensions);
316: needSeparator = true;
317: }
318:
319: String description = getDescription();
320: if (description != null && !description.equals(getType())) {
321: if (needSeparator) {
322: buf.append(separator);
323: }
324: buf.append("description=" + description);
325: }
326:
327: return buf.toString();
328: }
329:
330: public String toString() {
331: return "MimeEntry[contentType=" + typeName + ", image="
332: + imageFileName + ", action=" + action + ", command="
333: + command + ", extensions=" + getExtensionsAsList()
334: + "]";
335: }
336: }
|