1 19 20 package org.netbeans.api.editor.mimelookup; 21 22 import java.lang.ref.Reference ; 23 import java.lang.ref.SoftReference ; 24 import java.util.ArrayList ; 25 import java.util.HashMap ; 26 import java.util.Map ; 27 import java.util.regex.Matcher ; 28 import java.util.regex.Pattern ; 29 import org.netbeans.modules.editor.mimelookup.MimePathLookup; 30 31 95 public final class MimePath { 96 97 101 public static final MimePath EMPTY = new MimePath(); 102 103 104 private static final Object LOCK = new Object (); 105 106 107 private static final ArrayList <MimePath> LRU = new ArrayList <MimePath>(); 108 109 static final int MAX_LRU_SIZE = 3; 111 112 private static final String REG_NAME = "[[\\p{Alnum}][!#$&.+\\-^_]]{1,127}"; private static final Pattern MIME_TYPE_PATTERN = Pattern.compile("^" + REG_NAME + "/{1}" + REG_NAME + "$"); 115 128 public static MimePath get(String mimeType) { 129 if (mimeType == null || mimeType.length() == 0){ 130 return EMPTY; 131 } else { 132 return get(EMPTY, mimeType); 133 } 134 } 135 136 154 public static MimePath get(MimePath prefix, String mimeType) { 155 return prefix.getEmbedded(mimeType); 156 } 157 158 175 public static MimePath parse(String path) { 176 return parseImpl(path); 177 } 178 179 184 private final MimePath[] mimePaths; 185 186 189 private final String path; 190 191 194 private final String mimeType; 195 196 199 private Map <String , SoftReference <MimePath>> mimeType2mimePathRef; 200 201 204 private MimePathLookup lookup; 205 206 209 private final String LOOKUP_LOCK = new String ("MimePath.LOOKUP_LOCK"); 211 private MimePath(MimePath prefix, String mimeType) { 212 int prefixSize = prefix.size(); 213 this.mimePaths = new MimePath[prefixSize + 1]; 214 System.arraycopy(prefix.mimePaths, 0, this.mimePaths, 0, prefixSize); 215 this.mimePaths[prefixSize] = this; 216 String prefixPath = prefix.path; 217 this.path = (prefixPath != null && prefixPath.length() > 0 ) ? 218 (prefixPath + '/' + mimeType).intern() : mimeType.intern(); 220 this.mimeType = mimeType; 221 } 222 223 224 private MimePath() { 225 this.mimePaths = new MimePath[0]; 226 this.path = ""; this.mimeType = ""; } 229 230 237 public String getPath() { 238 return path; 239 } 240 241 250 public int size() { 251 return mimePaths.length; 252 } 253 254 268 public String getMimeType(int index) { 269 return mimePaths[index].mimeType; 270 } 271 272 285 public MimePath getPrefix(int size) { 286 return (size == 0) 287 ? EMPTY 288 : mimePaths[size - 1]; 289 } 290 291 private MimePath getEmbedded(String mimeType) { 292 synchronized (LOCK) { 296 if (mimeType2mimePathRef == null) { 297 mimeType2mimePathRef = new HashMap <String , SoftReference <MimePath>>(); 298 } 299 Reference mpRef = mimeType2mimePathRef.get(mimeType); 300 MimePath mimePath; 301 if (mpRef == null || (mimePath = (MimePath)mpRef.get()) == null) { 302 Matcher m = MIME_TYPE_PATTERN.matcher(mimeType); 304 if (!m.matches()) { 305 throw new IllegalArgumentException ("Invalid mimeType=\"" + mimeType + "\""); } 307 308 mimePath = new MimePath(this, mimeType); 310 mimeType2mimePathRef.put(mimeType, new SoftReference <MimePath>(mimePath)); 311 312 LRU.add(0, mimePath); 314 if (LRU.size() > MAX_LRU_SIZE) { 315 LRU.remove(LRU.size() - 1); 316 } 317 } 318 319 return mimePath; 320 } 321 } 322 323 private static MimePath parseImpl(String path) { 324 if (path == null) { 325 throw new IllegalArgumentException ("path cannot be null"); } 327 MimePath mimePath = EMPTY; 328 int pathLen = path.length(); 329 int startIndex = 0; 330 while (true) { 331 int index = startIndex; 332 int slashIndex = -1; 333 while (index < pathLen) { 335 if (path.charAt(index) == '/') { slashIndex = index; 337 break; } 339 index++; 340 } 341 if (slashIndex == -1) { if (index != startIndex) { 343 throw new IllegalArgumentException ("mimeType '" + path.substring(startIndex) + "' does not contain '/'."); } 346 break; 348 } 349 index++; while (index < pathLen) { 351 if (path.charAt(index) == '/') { if (index == slashIndex + 1) { throw new IllegalArgumentException ("Two successive slashes in '" + path.substring(startIndex) + "'"); } 356 break; 357 } 358 index++; 359 } 360 if (index == slashIndex + 1) { throw new IllegalArgumentException ("Empty string after '/' in '" + path.substring(startIndex) + "'"); } 364 365 String mimeType = path.substring(startIndex, index); 367 mimePath = get(mimePath, mimeType); 368 369 startIndex = index + 1; } 371 return mimePath; 372 } 373 374 382 MimePathLookup getLookup() { 383 synchronized (LOOKUP_LOCK) { 384 if (lookup == null) { 385 lookup = new MimePathLookup(this); 386 } 387 return lookup; 388 } 389 } 390 391 } 392 | Popular Tags |