1 30 31 34 package net.sf.jasperreports.engine.base; 35 36 import java.awt.Graphics2D ; 37 import java.awt.geom.Dimension2D ; 38 import java.awt.geom.Rectangle2D ; 39 import java.io.ByteArrayInputStream ; 40 import java.io.ByteArrayOutputStream ; 41 import java.io.IOException ; 42 import java.io.ObjectInputStream ; 43 import java.io.ObjectOutputStream ; 44 import java.io.Serializable ; 45 import java.util.ArrayList ; 46 import java.util.HashMap ; 47 import java.util.HashSet ; 48 import java.util.Iterator ; 49 import java.util.List ; 50 import java.util.Map ; 51 import java.util.Random ; 52 import java.util.Set ; 53 54 import org.apache.commons.logging.Log; 55 import org.apache.commons.logging.LogFactory; 56 57 import net.sf.jasperreports.engine.JRConstants; 58 import net.sf.jasperreports.engine.JRException; 59 import net.sf.jasperreports.engine.JRPrintElement; 60 import net.sf.jasperreports.engine.JRPrintFrame; 61 import net.sf.jasperreports.engine.JRPrintImage; 62 import net.sf.jasperreports.engine.JRPrintPage; 63 import net.sf.jasperreports.engine.JRRenderable; 64 import net.sf.jasperreports.engine.JRRuntimeException; 65 import net.sf.jasperreports.engine.JRVirtualizable; 66 import net.sf.jasperreports.engine.JRVirtualizationHelper; 67 import net.sf.jasperreports.engine.JRVirtualizer; 68 import net.sf.jasperreports.engine.JasperPrint; 69 import net.sf.jasperreports.engine.fill.JRTemplateElement; 70 import net.sf.jasperreports.engine.fill.JRTemplatePrintElement; 71 import net.sf.jasperreports.engine.fill.JRVirtualizationContext; 72 73 79 public class JRVirtualPrintPage implements JRPrintPage, JRVirtualizable, Serializable 80 { 81 protected static final Log log = LogFactory.getLog(JRVirtualPrintPage.class); 82 83 92 public static class ObjectIDPair implements Serializable { 93 96 private static final long serialVersionUID = JRConstants.SERIAL_VERSION_UID; 97 98 private final Object o; 99 100 private final int id; 101 102 public ObjectIDPair(Object o) { 103 this.o = o; 104 this.id = System.identityHashCode(o); 105 } 106 107 110 public Object getObject() { 111 return o; 112 } 113 114 120 public int getIdentity() { 121 return id; 122 } 123 } 124 125 129 public static interface IdentityDataProvider { 130 134 ObjectIDPair[] getIdentityData(JRVirtualPrintPage page); 135 136 139 void setIdentityData(JRVirtualPrintPage page, 140 ObjectIDPair[] identityData); 141 } 142 143 private static final long serialVersionUID = JRConstants.SERIAL_VERSION_UID; 144 145 private static final Random random = new Random (System.currentTimeMillis()); 146 147 private static short counter = 1; 148 149 150 protected List elements = new ArrayList (); 151 152 156 private String uid; 157 158 161 private transient JRVirtualizer virtualizer; 162 163 166 private transient IdentityDataProvider[] identityProviders; 167 168 protected JRVirtualizationContext virtualizationContext; 169 170 173 public JRVirtualPrintPage(JasperPrint printObject, JRVirtualizer virtualizer, JRVirtualizationContext virtualizationContext) { 174 super(); 175 176 this.virtualizationContext = virtualizationContext; 177 178 this.uid = makeUID(printObject); 179 this.virtualizer = virtualizer; 180 this.identityProviders = null; 181 if (virtualizer != null) { 182 virtualizer.registerObject(this); 183 } 184 } 185 186 187 190 private static String makeUID(JasperPrint printObject) { 191 synchronized (random) { 192 return Integer.toString(System.identityHashCode(printObject)) + "_" 193 + (printObject.getPages().size()) + "_" 194 + Integer.toString(counter++) + "_" 195 + Integer.toString(random.nextInt()); 196 } 197 } 198 199 public final String getUID() { 200 return this.uid; 201 } 202 203 public void setVirtualData(Object o) 204 { 205 elements = (List ) o; 206 } 207 208 public Object getVirtualData() 209 { 210 return elements; 211 } 212 213 public void removeVirtualData() { 214 elements = null; 215 } 216 217 public void setIdentityData(Object o) { 218 if (identityProviders != null) { 219 for (int i = 0; i < identityProviders.length; ++i) { 220 identityProviders[i].setIdentityData(this, (ObjectIDPair[]) o); 221 } 222 } 223 } 224 225 public Object getIdentityData() { 226 ObjectIDPair[] data; 227 if (identityProviders != null) { 228 if (identityProviders.length == 1) { 229 data = identityProviders[0].getIdentityData(this); 230 } else if (identityProviders.length > 1) { 231 Set list = new HashSet (); 232 for (int i = 0; i < identityProviders.length; ++i) { 233 ObjectIDPair[] pairs = identityProviders[i] 234 .getIdentityData(this); 235 if (pairs != null) { 236 for (int j = 0; j < pairs.length; ++j) { 237 list.add(pairs[j]); 238 } 239 } 240 } 241 data = (ObjectIDPair[]) list.toArray(new ObjectIDPair[list 242 .size()]); 243 } else { 244 data = null; 245 } 246 } else { 247 data = null; 248 } 249 250 return data; 251 } 252 253 public boolean isVirtualized() { 254 return elements == null; 255 } 256 257 260 public void setVirtualizer(JRVirtualizer virtualizer) { 261 this.virtualizer = virtualizer; 262 } 263 264 267 public JRVirtualizer getVirtualizer() { 268 return this.virtualizer; 269 } 270 271 public void addIdentityDataProvider(IdentityDataProvider p) { 272 if (identityProviders == null) { 273 identityProviders = new IdentityDataProvider[] { p }; 274 } else { 275 IdentityDataProvider[] newList = new IdentityDataProvider[identityProviders.length + 1]; 276 System.arraycopy(identityProviders, 0, newList, 0, 277 identityProviders.length); 278 newList[identityProviders.length] = p; 279 identityProviders = newList; 280 } 281 } 282 283 public void removeIdentityDataProvider(IdentityDataProvider p) { 284 if (identityProviders != null) { 285 int idx; 286 for (idx = 0; idx < identityProviders.length; ++idx) { 287 if (identityProviders[idx] == p) { 288 IdentityDataProvider[] newList = new IdentityDataProvider[identityProviders.length - 1]; 289 System.arraycopy(identityProviders, 0, newList, 0, idx); 290 int remaining = identityProviders.length - idx - 1; 291 if (remaining > 0) { 292 System.arraycopy(identityProviders, idx + 1, newList, 293 idx, remaining); 294 } 295 identityProviders = newList; 296 break; 297 } 298 } 299 } 300 } 301 302 public List getElements() 303 { 304 ensureVirtualData(); 305 return elements; 306 } 307 308 protected void ensureVirtualData() 309 { 310 if (this.virtualizer != null) 311 { 312 this.virtualizer.requestData(this); 313 } 314 } 315 316 public void setElements(List elements) { 317 cleanVirtualData(); 318 this.elements = elements; 319 cacheInContext(this.elements); 320 } 321 322 protected void cleanVirtualData() 323 { 324 if (this.virtualizer != null) 325 { 326 this.virtualizer.clearData(this); 327 } 328 } 329 330 331 public void addElement(JRPrintElement element) 332 { 333 ensureVirtualData(); 334 elements.add(element); 335 cacheInContext(element); 336 } 337 338 339 346 protected static class JRIdHolderRenderer implements JRRenderable, Serializable 347 { 348 private static final long serialVersionUID = JRConstants.SERIAL_VERSION_UID; 349 350 protected final String id; 351 352 protected JRIdHolderRenderer(JRRenderable renderer) 353 { 354 this.id = renderer.getId(); 355 } 356 357 public String getId() 358 { 359 return id; 360 } 361 362 public byte getType() 363 { 364 return TYPE_IMAGE; 365 } 366 367 public byte getImageType() 368 { 369 return IMAGE_TYPE_UNKNOWN; 370 } 371 372 public Dimension2D getDimension() throws JRException 373 { 374 return null; 375 } 376 377 public byte[] getImageData() throws JRException 378 { 379 return null; 380 } 381 382 public void render(Graphics2D grx, Rectangle2D rectanle) throws JRException 383 { 384 } 385 } 386 387 388 protected static class JRIdHolderTemplateElement extends JRTemplateElement 389 { 390 private static final long serialVersionUID = JRConstants.SERIAL_VERSION_UID; 391 392 protected JRIdHolderTemplateElement(String id) 393 { 394 super(id); 395 } 396 } 397 398 private void readObject(java.io.ObjectInputStream in) throws IOException , ClassNotFoundException 399 { 400 uid = (String ) in.readObject(); 401 virtualizationContext = (JRVirtualizationContext) in.readObject(); 402 403 int length = in.readInt(); 404 byte[] buffer = new byte[length]; 405 in.readFully(buffer); 406 ByteArrayInputStream inputStream = new ByteArrayInputStream (buffer, 0, buffer.length); 407 ObjectInputStream elementsStream = new ObjectInputStream (inputStream); 408 elements = (List ) elementsStream.readObject(); 409 afterInternalization(); 410 411 setThreadVirtualizer(); 412 } 413 414 415 private void writeObject(java.io.ObjectOutputStream out) throws IOException 416 { 417 ensureVirtualData(); 418 beforeExternalization(); 419 420 try 421 { 422 out.writeObject(uid); 423 out.writeObject(virtualizationContext); 424 425 ByteArrayOutputStream bout = new ByteArrayOutputStream (); 426 ObjectOutputStream stream = new ObjectOutputStream (bout); 427 stream.writeObject(elements); 428 stream.flush(); 429 430 byte[] bytes = bout.toByteArray(); 431 out.writeInt(bytes.length); 432 out.write(bytes); 433 } 434 finally 435 { 436 afterExternalization(); 437 } 438 } 439 440 441 private void setThreadVirtualizer() 442 { 443 JRVirtualizer threadVirtualizer = JRVirtualizationHelper.getThreadVirtualizer(); 444 if (threadVirtualizer != null) 445 { 446 virtualizer = threadVirtualizer; 447 virtualizer.registerObject(this); 448 } 449 } 450 451 452 protected void finalize() 453 { 454 if (virtualizer != null) 455 { 456 virtualizer.deregisterObject(this); 457 } 458 } 459 460 461 467 protected List getDeepElements() 468 { 469 List deepElements = new ArrayList (elements.size()); 470 collectDeepElements(elements, deepElements); 471 return deepElements; 472 } 473 474 protected void collectDeepElements(List elementsList, List deepElements) 475 { 476 for (Iterator it = elementsList.iterator(); it.hasNext();) 477 { 478 JRPrintElement element = (JRPrintElement) it.next(); 479 deepElements.add(element); 480 481 if (element instanceof JRPrintFrame) 482 { 483 JRPrintFrame frame = (JRPrintFrame) element; 484 collectDeepElements(frame.getElements(), deepElements); 485 } 486 } 487 } 488 489 490 public void beforeExternalization() 491 { 492 setElementsExternalData(); 493 } 494 495 496 protected void setElementsExternalData() 497 { 498 traverseDeepElements(new ExternalizationElementVisitor()); 499 } 500 501 502 protected void setExternalizationRenderer(JRPrintImage image) 503 { 504 JRRenderable renderer = image.getRenderer(); 505 if (renderer != null && virtualizationContext.hasCachedRenderer(renderer.getId())) 506 { 507 image.setRenderer(new JRIdHolderRenderer(renderer)); 508 } 509 } 510 511 512 protected void cacheInContext(List elementList) 513 { 514 if (elementList != null && !elementList.isEmpty()) 515 { 516 for (Iterator it = elementList.iterator(); it.hasNext();) 517 { 518 JRPrintElement element = (JRPrintElement) it.next(); 519 cacheInContext(element); 520 } 521 } 522 } 523 524 525 protected void cacheInContext(JRPrintElement element) 526 { 527 if (element instanceof JRTemplatePrintElement) 528 { 529 JRTemplatePrintElement templateElement = (JRTemplatePrintElement) element; 530 JRTemplateElement template = templateElement.getTemplate(); 531 if (template != null) 532 { 533 virtualizationContext.cacheTemplate(template); 534 } 535 } 536 537 if (element instanceof JRPrintFrame) 538 { 539 JRPrintFrame frame = (JRPrintFrame) element; 540 cacheInContext(frame.getElements()); 541 } 542 } 543 544 public void afterInternalization() 545 { 546 restoreElementsData(); 547 } 548 549 550 protected void restoreElementsData() 551 { 552 traverseDeepElements(new InternalizationElementVisitor()); 553 } 554 555 556 public JRVirtualizationContext getContext() 557 { 558 return virtualizationContext; 559 } 560 561 562 public void afterExternalization() 563 { 564 restoreElementsData(); 565 } 566 567 568 574 protected void traverseDeepElements(ElementVisitor visitor) 575 { 576 traverseDeepElements(visitor, elements); 577 } 578 579 protected void traverseDeepElements(ElementVisitor visitor, List elementsList) 580 { 581 for (Iterator it = elementsList.iterator(); it.hasNext();) 582 { 583 JRPrintElement element = (JRPrintElement) it.next(); 584 visitor.visitElement(element); 585 586 if (element instanceof JRPrintFrame) 587 { 588 JRPrintFrame frame = (JRPrintFrame) element; 589 traverseDeepElements(visitor, frame.getElements()); 590 } 591 } 592 } 593 594 protected static interface ElementVisitor 595 { 596 void visitElement(JRPrintElement element); 597 } 598 599 600 protected class ExternalizationElementVisitor implements ElementVisitor 601 { 602 private final Map idTemplates = new HashMap (); 603 604 public void visitElement(JRPrintElement element) 605 { 606 if (element instanceof JRTemplatePrintElement) 608 { 609 setExternalizationTemplate((JRTemplatePrintElement) element); 610 } 611 612 if (element instanceof JRPrintImage) 615 { 616 setExternalizationRenderer((JRPrintImage) element); 617 } 618 } 619 620 protected void setExternalizationTemplate(JRTemplatePrintElement templateElement) 621 { 622 JRTemplateElement template = templateElement.getTemplate(); 623 if (template != null) 624 { 625 if (virtualizationContext.hasCachedTemplate(template.getId())) 626 { 627 String templateId = template.getId(); 628 JRIdHolderTemplateElement idTemplate = (JRIdHolderTemplateElement) idTemplates.get(templateId); 629 if (idTemplate == null) 630 { 631 idTemplate = new JRIdHolderTemplateElement(templateId); 632 idTemplates.put(templateId, idTemplate); 633 } 634 templateElement.setTemplate(idTemplate); 635 } 636 else 637 { 638 if (log.isDebugEnabled()) 639 { 640 log.debug("Template " + template + " having id " + template.getId() + " not found in virtualization context cache"); 641 } 642 } 643 } 644 } 645 } 646 647 protected class InternalizationElementVisitor implements ElementVisitor 648 { 649 650 public void visitElement(JRPrintElement element) 651 { 652 if (element instanceof JRTemplatePrintElement) 653 { 654 restoreTemplate((JRTemplatePrintElement) element); 656 } 657 658 if (element instanceof JRPrintImage) 659 { 660 restoreRenderer((JRPrintImage) element); 662 } 663 } 664 665 protected void restoreTemplate(JRTemplatePrintElement element) 666 { 667 JRTemplateElement template = element.getTemplate(); 668 if (template != null && template instanceof JRIdHolderTemplateElement) 669 { 670 JRTemplateElement cachedTemplate = virtualizationContext.getCachedTemplate(template.getId()); 671 if (cachedTemplate == null) 672 { 673 throw new JRRuntimeException("Template " + template.getId() + " not found in virtualization context."); 674 } 675 676 element.setTemplate(cachedTemplate); 677 } 678 } 679 680 protected void restoreRenderer(JRPrintImage image) 681 { 682 JRRenderable renderer = image.getRenderer(); 683 if (renderer != null && renderer instanceof JRIdHolderRenderer) 684 { 685 JRRenderable cachedRenderer = virtualizationContext.getCachedRenderer(renderer.getId()); 686 if (cachedRenderer == null) 687 { 688 throw new JRRuntimeException("Renderer " + renderer.getId() + " not found in virtualization context."); 689 } 690 image.setRenderer(cachedRenderer); 691 } 692 } 693 } 694 } 695 | Popular Tags |