1 29 package net.sf.packtag.tag; 30 31 import java.io.BufferedInputStream ; 32 import java.io.ByteArrayOutputStream ; 33 import java.io.File ; 34 import java.io.FileInputStream ; 35 import java.io.FileNotFoundException ; 36 import java.io.FileWriter ; 37 import java.io.IOException ; 38 import java.io.InputStream ; 39 import java.io.PrintWriter ; 40 import java.util.ArrayList ; 41 import java.util.List ; 42 import java.util.zip.GZIPOutputStream ; 43 44 import javax.servlet.ServletContext ; 45 import javax.servlet.http.HttpServletRequest ; 46 import javax.servlet.jsp.JspException ; 47 import javax.servlet.jsp.JspTagException ; 48 import javax.servlet.jsp.JspWriter ; 49 import javax.servlet.jsp.tagext.BodyContent ; 50 import javax.servlet.jsp.tagext.BodyTagSupport ; 51 52 import net.sf.packtag.cache.PackCache; 53 import net.sf.packtag.cache.Resource; 54 import net.sf.packtag.implementation.DisabledPackStrategy; 55 import net.sf.packtag.strategy.PackException; 56 import net.sf.packtag.strategy.PackStrategy; 57 import net.sf.packtag.util.CombinedInputStream; 58 import net.sf.packtag.util.ContextConfiguration; 59 60 61 62 68 public abstract class BaseTag extends BodyTagSupport { 69 70 private static final long serialVersionUID = -3714373962322644843L; 71 72 protected final static String EMPTY_STRING = ""; 73 protected final static String SLASH = "/"; 74 75 private final static String ATTRIBUTE_SRC = "src"; 76 private final static String ATTRIBUTE_COMPRESS = "compress"; 77 78 private final static String SRC_TAG_START = "<src>"; 79 private final static String SRC_TAG_END = "</src>"; 80 81 82 private static Boolean standardTaglibAvailable = null; 83 84 private String src; 85 private Boolean compress = Boolean.TRUE; 86 private boolean enabled = true; 87 88 89 public BaseTag() { 90 } 91 92 93 public int doStartTag() throws JspTagException { 94 return EVAL_BODY_BUFFERED; 95 } 96 97 98 public int doEndTag() throws JspException { 99 String sqp = determineShortQualifiedPath(); 100 boolean sqpDefined = (sqp != null) && !sqp.equals(EMPTY_STRING); 101 try { 102 if (sqpDefined) { 104 handleSingleResource(sqp, true); 105 } 106 107 else { 109 handleCombinedResource(); 110 } 111 } 112 catch (PackException pex) { 113 promoteError(pex.getMessage(), pex); 114 } 115 catch (Exception ex) { 116 StringBuffer buffer = new StringBuffer (); 117 buffer.append("Pack did not perfom successfull on "); 118 buffer.append(sqpDefined ? "'" + sqp + "': " : "combined Resource: "); 119 buffer.append(ex.getMessage()); 120 promoteError(buffer.toString(), ex); 121 } 122 123 return EVAL_PAGE; 124 } 125 126 127 protected String determineShortQualifiedPath() { 128 return getSrc(); 136 } 137 138 139 144 private boolean handleSingleResource(String sqp, boolean writePackedResource) throws Exception { 145 boolean reloaded = false; 146 if (isEnabled()) { 147 Resource resource = null; 148 if (PackCache.existResource(sqp)) { 149 resource = PackCache.getResourceBySqp(sqp); 150 if (hasResourceChanged(resource)) { 151 resource = reloadSingleResource(resource.getShortQualifiedPath()); 152 reloaded = true; 153 } 154 } 155 else { 156 resource = reloadSingleResource(sqp); 157 reloaded = true; 158 } 159 if (writePackedResource) { 160 writeResouce(pageContext.getOut(), resource.getFullQualifiedPath()); 161 } 162 } 163 else { 164 writeResouce(pageContext.getOut(), sqp); 166 } 167 return reloaded; 168 } 169 170 171 175 private void handleCombinedResource() throws Exception { 176 BodyContent bc = getBodyContent(); 177 String bodyString = bc.getString().trim(); 178 if ((bodyString != null) && !bodyString.equals(EMPTY_STRING)) { 179 boolean reloaded = false; 181 List sqps = parseBody(bodyString); 182 if (sqps.size() == 0) { 183 throw new PackException("No resources were specified."); 184 } 185 for (int i = 0; i < sqps.size(); i++) { 186 String currentSqp = (String )sqps.get(i); 187 reloaded |= handleSingleResource(currentSqp, false); 188 } 189 190 if (isEnabled()) { 193 Resource resource = null; 194 String combinedSqp = sqps.toString(); 195 if (PackCache.existResource(combinedSqp) && !reloaded) { 196 resource = PackCache.getResourceBySqp(combinedSqp); 197 } 198 else { 199 resource = reloadCombinedResource(sqps); 200 } 201 writeResouce(pageContext.getOut(), resource.getFullQualifiedPath()); 202 } 203 } 204 205 else { 207 throw new PackException("No resources were specified"); 208 } 209 } 210 211 212 213 private InputStream getCombinedResourceStream(List sqps) throws PackException { 214 InputStream [] streams = new InputStream [sqps.size()]; 215 for (int i = 0; i < sqps.size(); i++) { 216 String sqp = (String )sqps.get(i); 217 InputStream resourceAsStream = getResourceStream(sqp); 218 streams[i] = resourceAsStream; 219 } 220 return new CombinedInputStream(streams); 221 } 222 223 224 private InputStream getResourceStream(String sqp) throws PackException { 225 if (isFileCheckTimestamps()) { 226 String realPath = pageContext.getServletContext().getRealPath(sqp); 227 File file = new File (realPath); 228 try { 229 return new BufferedInputStream (new FileInputStream (file)); 230 } 231 catch (FileNotFoundException fnfe) { 232 throw new PackException("Resource not found (" + sqp + ")", fnfe); 233 } 234 } 235 else { 236 return pageContext.getServletContext().getResourceAsStream(sqp); 240 } 241 } 242 243 244 245 private void promoteError(String message, Exception ex) throws JspTagException { 246 if (isHideErros()) { 247 try { 249 pageContext.getOut().write("<!-- "); 250 pageContext.getOut().write(message); 251 pageContext.getOut().write(" -->"); 252 } 253 catch (IOException ioex) { 254 } 256 } 257 else { 258 throw new JspTagException (message); } 260 } 261 262 263 264 private byte[] gzipString(String text) throws IOException { 265 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 266 GZIPOutputStream zos = new GZIPOutputStream (baos); 267 byte[] bytes = text.getBytes(); 268 zos.write(bytes, 0, bytes.length); 269 zos.finish(); 270 return baos.toByteArray(); 271 } 272 273 274 275 private Resource reloadSingleResource(String sqp) throws Exception { 276 String packedResource = getPackStrategyDelegate().pack(getResourceStream(sqp)); 277 Resource resource = new Resource(false, packedResource.hashCode()); 278 if (isCachetypeServlet()) { 279 resource.setMinifedResource(packedResource); 281 resource.setGzippedResource(gzipString(packedResource)); 282 } 283 if (isFileCheckTimestamps()) { 284 resource.setFileTimestamp(getFileLastModifiedTimeStamp(sqp)); 285 } 286 if (isCachetypeFile()) { 287 storeFile(resource, packedResource); 288 } 289 resource.setShortQualifiedPath(sqp); 290 resource.setFullQualifiedPath(determineFullQualifiedPath(resource)); 291 292 PackCache.store(resource, true); 293 return resource; 294 } 295 296 297 298 private Resource reloadCombinedResource(List sqps) throws Exception { 299 InputStream stream = getCombinedResourceStream(sqps); 300 String packedResource = getPackStrategyDelegate().pack(stream); 301 302 Resource resource = new Resource(true, packedResource.hashCode()); 303 if (isCachetypeServlet()) { 304 resource.setMinifedResource(packedResource); 306 resource.setGzippedResource(gzipString(packedResource)); 307 } 308 if (isCachetypeFile()) { 309 storeFile(resource, packedResource); 310 } 311 resource.setShortQualifiedPath(sqps.toString()); 312 resource.setFullQualifiedPath(determineFullQualifiedPath(resource)); 313 314 PackCache.store(resource, false); 315 return resource; 316 } 317 318 319 320 private void storeFile(Resource resource, String packedResource) throws IOException { 321 String cacheFilePath = getCacheFilePath() + SLASH; 322 String realPath = pageContext.getServletContext().getRealPath(SLASH) + cacheFilePath; 323 File fileRealPath = new File (realPath); 324 if (!fileRealPath.exists()) { 325 fileRealPath.mkdirs(); 326 } 327 File fileFqp = new File (realPath + determineFileName(resource)); 328 if (fileFqp.exists()) { 329 fileFqp.delete(); 330 } 331 fileFqp.createNewFile(); 332 FileWriter writer = new FileWriter (fileFqp); 333 writer.write(packedResource); 334 writer.flush(); 335 writer.close(); 336 } 337 338 339 public String determineFullQualifiedPath(Resource resource) throws Exception { 340 StringBuffer buffer = new StringBuffer (); 341 if (isCachetypeDisabled()) { 342 buffer.append(resource.getShortQualifiedPath()); 343 } 344 else if (isCachetypeServlet()) { 345 buffer.append(getContextPath()); 346 buffer.append(getCacheServletPath() + "?h="); 347 buffer.append(resource.getMinifiedHashcode()); 348 } 349 else { 351 buffer.append(getContextPath()); 352 buffer.append(SLASH); 353 buffer.append(getCacheFilePath()); 354 buffer.append(SLASH); 355 buffer.append(determineFileName(resource)); 356 } 357 return buffer.toString(); 358 } 359 360 361 private String determineFileName(Resource resource) { 362 StringBuffer buffer = new StringBuffer (); 363 buffer.append("h"); 364 buffer.append(resource.getMinifiedHashcode()); 365 buffer.append("."); 366 buffer.append(getResourceExtension()); 367 return buffer.toString(); 368 } 369 370 371 private boolean hasResourceChanged(Resource resource) { 372 if (isFileCheckTimestamps()) { 373 long lastModified = getFileLastModifiedTimeStamp(resource.getShortQualifiedPath()); 374 if (lastModified != resource.getFileTimestamp()) { 375 return true; 376 } 377 } 378 return false; 379 } 380 381 382 private long getFileLastModifiedTimeStamp(String path) { 383 String realPath = pageContext.getServletContext().getRealPath(path); 384 File file = new File (realPath); 385 return file.lastModified(); 386 } 387 388 389 396 private List parseBody(String bodyString) { 397 int bodyIndex = 0; 398 List resources = new ArrayList (); 399 while(bodyIndex < (bodyString.length() - 1)) { 400 int indexSrcStart = bodyString.indexOf(SRC_TAG_START, bodyIndex); 401 if (indexSrcStart == -1) { 402 return resources; 403 } 404 int indexSrcEnd = bodyString.indexOf(SRC_TAG_END, bodyIndex); 405 if (indexSrcEnd == -1) { 406 return resources; 407 } 408 resources.add(bodyString.substring(indexSrcStart + 5, indexSrcEnd).trim()); 409 bodyIndex = indexSrcEnd + 6; 410 } 411 return resources; 412 } 413 414 415 protected PackStrategy getPackStrategyDelegate() throws Exception { 416 return Boolean.TRUE.equals(isCompress()) ? getPackStrategy() : new DisabledPackStrategy(); 417 } 418 419 420 421 protected abstract void writeResouce(JspWriter writer, String path) throws Exception ; 422 423 424 425 protected abstract PackStrategy getPackStrategy() throws Exception ; 426 427 428 429 protected abstract String getResourceExtension(); 430 431 432 public String getSrc() { 433 return src; 434 } 435 436 437 public void setSrc(String src) { 438 if (isStandardTaglibAvailable()) { 439 this.src = (String )evaluate(ATTRIBUTE_SRC, src, String .class); 440 } 441 else { 442 this.src = src; 443 } 444 } 445 446 447 public Boolean isCompress() { 448 return compress; 449 } 450 451 452 public void setCompress(String compress) { 453 if (isStandardTaglibAvailable()) { 454 this.compress = new Boolean ((String )evaluate(ATTRIBUTE_COMPRESS, compress, String .class)); 455 } 456 else { 457 this.compress = new Boolean (compress); 458 } 459 } 460 461 462 public boolean isEnabled() { 463 return enabled && !isCachetypeDisabled(); 464 } 465 466 467 public void setEnabled(Boolean enabled) { 468 if (enabled != null) { 469 this.enabled = enabled.booleanValue(); 470 } 471 } 472 473 474 public void setEnabled(boolean enabled) { 475 this.enabled = enabled; 476 } 477 478 479 protected String getCacheFilePath() { 480 return ContextConfiguration.getCacheFilePath(pageContext.getServletContext()); 481 } 482 483 484 protected String getCacheServletPath() { 485 return ContextConfiguration.getCacheServletPath(pageContext.getServletContext()); 486 } 487 488 489 protected boolean isCachetypeDisabled() { 490 return ContextConfiguration.isCachetypeDisabled(pageContext.getServletContext()); 491 } 492 493 494 protected boolean isCachetypeServlet() { 495 return ContextConfiguration.isCachetypeServlet(pageContext.getServletContext()); 496 } 497 498 499 protected boolean isCachetypeFile() { 500 return ContextConfiguration.isCachetypeFile(pageContext.getServletContext()); 501 } 502 503 504 protected boolean isFileCheckTimestamps() { 505 return ContextConfiguration.isFileCheckTimestamps(pageContext.getServletContext()); 506 } 507 508 509 protected boolean isHideErros() { 510 return ContextConfiguration.isHideErros(pageContext.getServletContext()); 511 } 512 513 514 protected String getPackStrategyClassName(String resourceType) { 515 return ContextConfiguration.getPackStrategyClassName(pageContext.getServletContext(), resourceType); 516 } 517 518 protected Object evaluate(String attributeName, String expression, Class expectedType) { 519 Object result = null; 520 try { 521 result = org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager.evaluate(attributeName, expression, expectedType, this, pageContext); 525 } 526 catch (JspException je) { 527 try { 528 pageContext.getOut().write("<!-- "); 529 je.printStackTrace(new PrintWriter (pageContext.getOut())); 530 pageContext.getOut().write(" -->"); 531 } 532 catch (IOException e) { 533 e.printStackTrace(); 534 } 535 } 536 return result; 537 } 538 539 540 protected String getContextPath() { 541 String contextPath = null; 542 if (HttpServletRequest .class.isAssignableFrom(pageContext.getRequest().getClass())) { 543 contextPath = ((HttpServletRequest )pageContext.getRequest()).getContextPath(); 544 } 545 else { 546 contextPath = getContextPath(pageContext.getServletContext()); 547 } 548 return contextPath; 549 } 550 551 552 558 private static String getContextPath(final ServletContext context) { 559 String contextPath = EMPTY_STRING; 566 567 try { 568 String path = context.getResource(SLASH).getPath(); 572 573 contextPath = path.substring(0, path.lastIndexOf(SLASH)); 577 contextPath = contextPath.substring(contextPath.lastIndexOf(SLASH) + 1); 578 } 579 catch (Exception e) { 580 } 581 582 return SLASH + contextPath; 583 } 584 585 586 587 protected boolean isStandardTaglibAvailable() { 588 if (standardTaglibAvailable == null) { 589 synchronized (BaseTag.class) { 590 if (standardTaglibAvailable == null) { 591 try { 592 standardTaglibAvailable = new Boolean (Class.forName("org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager") != null); 593 } 594 catch (ClassNotFoundException e) { 595 standardTaglibAvailable = Boolean.FALSE; 596 } 597 } 598 } 599 } 600 return standardTaglibAvailable.booleanValue(); 601 } 602 603 } 604 | Popular Tags |