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 && typeName.endsWith("/*"); 205 } 206 207 /** 208 * Invoke the MIME type specific behavior for this MIME type. 209 * Returned value can be one of several types: 210 * <ol> 211 * <li>A thread -- the caller can choose when to launch this thread. 212 * <li>A string -- the string is loaded into the browser directly. 213 * <li>An input stream -- the caller can read from this byte stream and 214 * will typically store the results in a file. 215 * <li>A document (?) -- 216 * </ol> 217 */ 218 public Object launch(java.net.URLConnection urlc, InputStream is, MimeTable mt) throws ApplicationLaunchException { 219 switch (action) { 220 case SAVE_TO_FILE: 221 // REMIND: is this really the right thing to do? 222 try { 223 return is; 224 } catch(Exception e) { 225 // I18N 226 return "Load to file failed:\n" + e; 227 } 228 229 case LOAD_INTO_BROWSER: 230 // REMIND: invoke the content handler? 231 // may be the right thing to do, may not be -- short term 232 // where docs are not loaded asynch, loading and returning 233 // the content is the right thing to do. 234 try { 235 return urlc.getContent(); 236 } catch (Exception e) { 237 return null; 238 } 239 240 case LAUNCH_APPLICATION: 241 { 242 String threadName = command; 243 int fst = threadName.indexOf(' '); 244 if (fst > 0) { 245 threadName = threadName.substring(0, fst); 246 } 247 248 return new MimeLauncher(this, urlc, is, 249 mt.getTempFileTemplate(), threadName); 250 } 251 252 case UNKNOWN: 253 // REMIND: What to do here? 254 return null; 255 } 256 257 return null; 258 } 259 260 public boolean matches(String type) { 261 if (starred) { 262 // REMIND: is this the right thing or not? 263 return type.startsWith(typeName); 264 } else { 265 return type.equals(typeName); 266 } 267 } 268 269 public Object clone() { 270 // return a shallow copy of this. 271 MimeEntry theClone = new MimeEntry(typeName); 272 theClone.action = action; 273 theClone.command = command; 274 theClone.description = description; 275 theClone.imageFileName = imageFileName; 276 theClone.tempFileNameTemplate = tempFileNameTemplate; 277 theClone.fileExtensions = fileExtensions; 278 279 return theClone; 280 } 281 282 public synchronized String toProperty() { 283 StringJoiner sj = new StringJoiner("; "); 284 285 int action = getAction(); 286 if (action != MimeEntry.UNKNOWN) { 287 sj.add("action=" + actionKeywords[action]); 288 } 289 290 String command = getLaunchString(); 291 if (command != null && command.length() > 0) { 292 sj.add("application=" + command); 293 } 294 295 String image = getImageFileName(); 296 if (image != null) { 297 sj.add("icon=" + image); 298 } 299 300 String extensions = getExtensionsAsList(); 301 if (!extensions.isEmpty()) { 302 sj.add("file_extensions=" + extensions); 303 } 304 305 String description = getDescription(); 306 if (description != null && !description.equals(getType())) { 307 sj.add("description=" + description); 308 } 309 310 return sj.toString(); 311 } 312 313 public String toString() { 314 return "MimeEntry[contentType=" + typeName 315 + ", image=" + imageFileName 316 + ", action=" + action 317 + ", command=" + command 318 + ", extensions=" + getExtensionsAsList() 319 + "]"; 320 } 321 }