1 /* 2 * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.net.www; 27 import java.net.URL; 28 import java.io.*; 29 import java.util.StringJoiner; 30 import java.util.StringTokenizer; 31 32 public class MimeEntry implements Cloneable { 33 private String typeName; // of the form: "type/subtype" 34 private String tempFileNameTemplate; 35 36 private int action; 37 private String command; 38 private String description; 39 private String imageFileName; 40 private String fileExtensions[]; 41 42 boolean starred; 43 44 // Actions 45 public static final int UNKNOWN = 0; 46 public static final int LOAD_INTO_BROWSER = 1; 47 public static final int SAVE_TO_FILE = 2; 48 public static final int LAUNCH_APPLICATION = 3; 49 50 static final String[] actionKeywords = { 51 "unknown", 52 "browser", 53 "save", 54 "application", 55 }; 56 57 /** 58 * Construct an empty entry of the given type and subtype. 59 */ 60 public MimeEntry(String type) { 61 // Default action is UNKNOWN so clients can decide what the default 62 // should be, typically save to file or ask user. 63 this(type, UNKNOWN, null, null, null); 64 } 65 66 // 67 // The next two constructors are used only by the deprecated 68 // PlatformMimeTable classes or, in last case, is called by the public 69 // constructor. They are kept here anticipating putting support for 70 // mailcap formatted config files back in (so BOTH the properties format 71 // and the mailcap formats are supported). 72 // 73 MimeEntry(String type, String imageFileName, String extensionString) { 74 typeName = type.toLowerCase(); 75 action = UNKNOWN; 76 command = null; 77 this.imageFileName = imageFileName; 78 setExtensions(extensionString); 79 starred = isStarred(typeName); 80 } 81 82 // For use with MimeTable::parseMailCap 83 MimeEntry(String typeName, int action, String command, 84 String tempFileNameTemplate) { 85 this.typeName = typeName.toLowerCase(); 86 this.action = action; 87 this.command = command; 88 this.imageFileName = null; 89 this.fileExtensions = null; 90 91 this.tempFileNameTemplate = tempFileNameTemplate; 92 } 93 94 // This is the one called by the public constructor. 95 MimeEntry(String typeName, int action, String command, 96 String imageFileName, String fileExtensions[]) { 97 98 this.typeName = typeName.toLowerCase(); 99 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.getProperty( 157 "java.net.ftp.imagepath."+filename); 158 } 159 else { 160 imageFileName = filename; 161 } 162 163 if (filename.lastIndexOf('.') < 0) { 164 imageFileName = imageFileName + ".gif"; 165 } 166 } 167 168 public String getTempFileTemplate() { 169 return tempFileNameTemplate; 170 } 171 172 public synchronized String[] getExtensions() { 173 return fileExtensions; 174 } 175 176 public synchronized String getExtensionsAsList() { 177 String extensionsAsString = ""; 178 if (fileExtensions != null) { 179 for (int i = 0; i < fileExtensions.length; i++) { 180 extensionsAsString += fileExtensions[i]; 181 if (i < (fileExtensions.length - 1)) { 182 extensionsAsString += ","; 183 } 184 } 185 } 186 187 return extensionsAsString; 188 } 189 190 public synchronized void setExtensions(String extensionString) { 191 StringTokenizer extTokens = new StringTokenizer(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) 205 && (typeName.length() > 0) 206 && (typeName.endsWith("/*")); 207 } 208 209 /** 210 * Invoke the MIME type specific behavior for this MIME type. 211 * Returned value can be one of several types: 212 * <ol> 213 * <li>A thread -- the caller can choose when to launch this thread. 214 * <li>A string -- the string is loaded into the browser directly. 215 * <li>An input stream -- the caller can read from this byte stream and 216 * will typically store the results in a file. 217 * <li>A document (?) -- 218 * </ol> 219 */ 220 public Object launch(java.net.URLConnection urlc, InputStream is, MimeTable mt) throws ApplicationLaunchException { 221 switch (action) { 222 case SAVE_TO_FILE: 223 // REMIND: 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 // REMIND: 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 { 244 String threadName = command; 245 int fst = threadName.indexOf(' '); 246 if (fst > 0) { 247 threadName = threadName.substring(0, fst); 248 } 249 250 return new MimeLauncher(this, urlc, is, 251 mt.getTempFileTemplate(), threadName); 252 } 253 254 case UNKNOWN: 255 // REMIND: What to do here? 256 return null; 257 } 258 259 return null; 260 } 261 262 public boolean matches(String type) { 263 if (starred) { 264 // REMIND: is this the right thing or not? 265 return type.startsWith(typeName); 266 } else { 267 return type.equals(typeName); 268 } 269 } 270 271 public Object clone() { 272 // return a shallow copy of this. 273 MimeEntry theClone = new MimeEntry(typeName); 274 theClone.action = action; 275 theClone.command = command; 276 theClone.description = description; 277 theClone.imageFileName = imageFileName; 278 theClone.tempFileNameTemplate = tempFileNameTemplate; 279 theClone.fileExtensions = fileExtensions; 280 281 return theClone; 282 } 283 284 public synchronized String toProperty() { 285 StringJoiner sj = new StringJoiner("; "); 286 287 int action = getAction(); 288 if (action != MimeEntry.UNKNOWN) { 289 sj.add("action=" + actionKeywords[action]); 290 } 291 292 String command = getLaunchString(); 293 if (command != null && command.length() > 0) { 294 sj.add("application=" + command); 295 } 296 297 String image = getImageFileName(); 298 if (image != null) { 299 sj.add("icon=" + image); 300 } 301 302 String extensions = getExtensionsAsList(); 303 if (extensions.length() > 0) { 304 sj.add("file_extensions=" + extensions); 305 } 306 307 String description = getDescription(); 308 if (description != null && !description.equals(getType())) { 309 sj.add("description=" + description); 310 } 311 312 return sj.toString(); 313 } 314 315 public String toString() { 316 return "MimeEntry[contentType=" + typeName 317 + ", image=" + imageFileName 318 + ", action=" + action 319 + ", command=" + command 320 + ", extensions=" + getExtensionsAsList() 321 + "]"; 322 } 323 }