Coverage Report - org.apache.tapestry.services.impl.PrototypeResponseBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
PrototypeResponseBuilder
0%
0/153
0%
0/86
2.093
 
 1  
 package org.apache.tapestry.services.impl;
 2  
 
 3  
 import org.apache.hivemind.Resource;
 4  
 import org.apache.hivemind.util.Defense;
 5  
 import org.apache.tapestry.*;
 6  
 import org.apache.tapestry.asset.AssetFactory;
 7  
 import org.apache.tapestry.engine.NullWriter;
 8  
 import org.apache.tapestry.markup.MarkupWriterSource;
 9  
 import org.apache.tapestry.markup.NestedMarkupWriterImpl;
 10  
 import org.apache.tapestry.services.RequestLocaleManager;
 11  
 import org.apache.tapestry.services.ResponseBuilder;
 12  
 import org.apache.tapestry.services.ServiceConstants;
 13  
 import org.apache.tapestry.util.ContentType;
 14  
 import org.apache.tapestry.util.PageRenderSupportImpl;
 15  
 import org.apache.tapestry.web.WebResponse;
 16  
 
 17  
 import java.io.IOException;
 18  
 import java.io.PrintWriter;
 19  
 import java.util.*;
 20  
 
 21  
 /**
 22  
  * Implementation of response builder for prototype client side library initiated XHR requests.
 23  
  *
 24  
  */
 25  
 public class PrototypeResponseBuilder implements ResponseBuilder {
 26  
 
 27  
     public static final String CONTENT_TYPE = "text/html";
 28  
 
 29  
     private final AssetFactory _assetFactory;
 30  
 
 31  
     private final String _namespace;
 32  
 
 33  
     private PageRenderSupportImpl _prs;
 34  
 
 35  
     // used to create IMarkupWriter
 36  
     private RequestLocaleManager _localeManager;
 37  
     private MarkupWriterSource _markupWriterSource;
 38  
     private WebResponse _response;
 39  
 
 40  
     // our response writer
 41  
     private IMarkupWriter _writer;
 42  
 
 43  
     // Parts that will be updated.
 44  0
     private List _parts = new ArrayList();
 45  
 
 46  
     // Map of specialized writers, like scripts
 47  
 
 48  0
     private Map _writers = new HashMap();
 49  
     private IRequestCycle _cycle;
 50  
 
 51  
     /**
 52  
      * Used for unit testing only.
 53  
      *
 54  
      * @param cycle Request.
 55  
      * @param writer Markup writer.
 56  
      * @param parts Update parts list.
 57  
      */
 58  
     public PrototypeResponseBuilder(IRequestCycle cycle, IMarkupWriter writer, List parts)
 59  0
     {
 60  0
         _cycle = cycle;
 61  0
         _writer = writer;
 62  
 
 63  0
         if (parts != null)
 64  0
             _parts.addAll(parts);
 65  
 
 66  0
         _assetFactory = null;
 67  0
         _namespace = null;
 68  0
     }
 69  
 
 70  
     /**
 71  
      * Creates a new response builder with the required services it needs
 72  
      * to render the response when {@link #renderResponse(IRequestCycle)} is called.
 73  
      *
 74  
      * @param cycle
 75  
      *          Associated request.
 76  
      * @param localeManager
 77  
      *          Locale manager to use for response.
 78  
      * @param markupWriterSource
 79  
      *          Creates necessary {@link IMarkupWriter} instances.
 80  
      * @param webResponse
 81  
      *          The http response.
 82  
      * @param assetFactory
 83  
      *          Asset manager for script / other resource inclusion.
 84  
      * @param namespace
 85  
      *          Javascript namespace value - used in portlets.
 86  
      */
 87  
     public PrototypeResponseBuilder(IRequestCycle cycle,
 88  
                                     RequestLocaleManager localeManager,
 89  
                                     MarkupWriterSource markupWriterSource,
 90  
                                     WebResponse webResponse,
 91  
                                     AssetFactory assetFactory, String namespace)
 92  0
     {
 93  0
         Defense.notNull(cycle, "cycle");
 94  0
         Defense.notNull(assetFactory, "assetService");
 95  
 
 96  0
         _cycle = cycle;
 97  0
         _localeManager = localeManager;
 98  0
         _markupWriterSource = markupWriterSource;
 99  0
         _response = webResponse;
 100  
 
 101  
         // Used by PageRenderSupport
 102  
 
 103  0
         _assetFactory = assetFactory;
 104  0
         _namespace = namespace;
 105  
         
 106  0
         _prs = new PageRenderSupportImpl(_assetFactory, _namespace, this, cycle);
 107  0
     }
 108  
 
 109  
     /**
 110  
      *
 111  
      * {@inheritDoc}
 112  
      */
 113  
     public boolean isDynamic()
 114  
     {
 115  0
         return true;
 116  
     }
 117  
 
 118  
     /**
 119  
      * {@inheritDoc}
 120  
      */
 121  
     public void renderResponse(IRequestCycle cycle)
 122  
       throws IOException
 123  
     {
 124  0
         _localeManager.persistLocale();
 125  
 
 126  0
         ContentType contentType = new ContentType(CONTENT_TYPE + ";charset=" + cycle.getInfrastructure().getOutputEncoding());
 127  
 
 128  0
         String encoding = contentType.getParameter(ENCODING_KEY);
 129  
 
 130  0
         if (encoding == null)
 131  
         {
 132  0
             encoding = cycle.getEngine().getOutputEncoding();
 133  
 
 134  0
             contentType.setParameter(ENCODING_KEY, encoding);
 135  
         }
 136  
 
 137  0
         if (_writer == null)
 138  
         {
 139  0
             parseParameters(cycle);
 140  
 
 141  0
             PrintWriter printWriter = _response.getPrintWriter(contentType);
 142  
 
 143  0
             _writer = _markupWriterSource.newMarkupWriter(printWriter, contentType);
 144  
         }
 145  
 
 146  
         // render response
 147  
 
 148  0
         TapestryUtils.storePageRenderSupport(cycle, _prs);
 149  
 
 150  0
         cycle.renderPage(this);
 151  
 
 152  0
         TapestryUtils.removePageRenderSupport(cycle);
 153  
 
 154  0
         endResponse();
 155  
 
 156  0
         _writer.close();
 157  0
     }
 158  
 
 159  
     public void flush()
 160  
       throws IOException
 161  
     {
 162  0
         _writer.flush();
 163  0
     }
 164  
 
 165  
     /**
 166  
      * {@inheritDoc}
 167  
      */
 168  
     public void updateComponent(String id)
 169  
     {
 170  0
         if (!_parts.contains(id))
 171  0
             _parts.add(id);
 172  0
     }
 173  
 
 174  
     /**
 175  
      * {@inheritDoc}
 176  
      */
 177  
     public IMarkupWriter getWriter()
 178  
     {
 179  0
         return _writer;
 180  
     }
 181  
 
 182  
     void setWriter(IMarkupWriter writer)
 183  
     {
 184  0
         _writer = writer;
 185  0
     }
 186  
 
 187  
     /**
 188  
      * {@inheritDoc}
 189  
      */
 190  
     public boolean isBodyScriptAllowed(IComponent target)
 191  
     {
 192  0
         if (target != null
 193  0
             && IPage.class.isInstance(target)
 194  
             || (IForm.class.isInstance(target)
 195  
                 && ((IForm)target).isFormFieldUpdating()))
 196  0
             return true;
 197  
 
 198  0
         return contains(target);
 199  
     }
 200  
 
 201  
     /**
 202  
      * {@inheritDoc}
 203  
      */
 204  
     public boolean isExternalScriptAllowed(IComponent target)
 205  
     {
 206  0
         if (target != null
 207  
             && IPage.class.isInstance(target)
 208  
             || (IForm.class.isInstance(target)
 209  
                 && ((IForm)target).isFormFieldUpdating()))
 210  0
             return true;
 211  
 
 212  0
         return contains(target);
 213  
     }
 214  
 
 215  
     /**
 216  
      * {@inheritDoc}
 217  
      */
 218  
     public boolean isInitializationScriptAllowed(IComponent target)
 219  
     {
 220  0
         if (target != null
 221  
             && IPage.class.isInstance(target)
 222  
             || (IForm.class.isInstance(target)
 223  
                 && ((IForm)target).isFormFieldUpdating()))
 224  0
             return true;
 225  
 
 226  0
         return contains(target);
 227  
     }
 228  
 
 229  
     /**
 230  
      * {@inheritDoc}
 231  
      */
 232  
     public boolean isImageInitializationAllowed(IComponent target)
 233  
     {
 234  0
         if (target != null
 235  
             && IPage.class.isInstance(target)
 236  
             || (IForm.class.isInstance(target)
 237  
                 && ((IForm)target).isFormFieldUpdating()))
 238  0
             return true;
 239  
 
 240  0
         return contains(target);
 241  
     }
 242  
 
 243  
     /**
 244  
      * {@inheritDoc}
 245  
      */
 246  
     public String getPreloadedImageReference(IComponent target, IAsset source)
 247  
     {
 248  0
         return _prs.getPreloadedImageReference(target, source);
 249  
     }
 250  
 
 251  
     /**
 252  
      * {@inheritDoc}
 253  
      */
 254  
     public String getPreloadedImageReference(IComponent target, String url)
 255  
     {
 256  0
         return _prs.getPreloadedImageReference(target, url);
 257  
     }
 258  
 
 259  
     /**
 260  
      * {@inheritDoc}
 261  
      */
 262  
     public String getPreloadedImageReference(String url)
 263  
     {
 264  0
         return _prs.getPreloadedImageReference(url);
 265  
     }
 266  
 
 267  
     /**
 268  
      * {@inheritDoc}
 269  
      */
 270  
     public void addBodyScript(IComponent target, String script)
 271  
     {
 272  0
         _prs.addBodyScript(target, script);
 273  0
     }
 274  
 
 275  
     /**
 276  
      * {@inheritDoc}
 277  
      */
 278  
     public void addBodyScript(String script)
 279  
     {
 280  0
         _prs.addBodyScript(script);
 281  0
     }
 282  
 
 283  
     /**
 284  
      * {@inheritDoc}
 285  
      */
 286  
     public void addExternalScript(IComponent target, Resource resource)
 287  
     {
 288  0
         _prs.addExternalScript(target, resource);
 289  0
     }
 290  
 
 291  
     /**
 292  
      * {@inheritDoc}
 293  
      */
 294  
     public void addExternalScript(Resource resource)
 295  
     {
 296  0
         _prs.addExternalScript(resource);
 297  0
     }
 298  
 
 299  
     /**
 300  
      * {@inheritDoc}
 301  
      */
 302  
     public void addInitializationScript(IComponent target, String script)
 303  
     {
 304  0
         _prs.addInitializationScript(target, script);
 305  0
     }
 306  
 
 307  
     /**
 308  
      * {@inheritDoc}
 309  
      */
 310  
     public void addInitializationScript(String script)
 311  
     {
 312  0
         _prs.addInitializationScript(script);
 313  0
     }
 314  
 
 315  
     public void addScriptAfterInitialization(IComponent target, String script)
 316  
     {
 317  0
         _prs.addScriptAfterInitialization(target, script);
 318  0
     }
 319  
 
 320  
     /**
 321  
      * {@inheritDoc}
 322  
      */
 323  
     public String getUniqueString(String baseValue)
 324  
     {
 325  0
         return _prs.getUniqueString(baseValue);
 326  
     }
 327  
 
 328  
     /**
 329  
      * {@inheritDoc}
 330  
      */
 331  
     public void writeBodyScript(IMarkupWriter writer, IRequestCycle cycle)
 332  
     {
 333  0
         _prs.writeBodyScript(writer, cycle);
 334  0
     }
 335  
 
 336  
     /**
 337  
      * {@inheritDoc}
 338  
      */
 339  
     public void writeInitializationScript(IMarkupWriter writer)
 340  
     {
 341  0
         _prs.writeInitializationScript(writer);
 342  0
     }
 343  
 
 344  
     /**
 345  
      * {@inheritDoc}
 346  
      */
 347  
     public void beginBodyScript(IMarkupWriter normalWriter, IRequestCycle cycle)
 348  
     {
 349  0
         _writer.begin("script");
 350  0
         _writer.printRaw("\n//<![CDATA[\n");
 351  0
     }
 352  
 
 353  
     /**
 354  
      * {@inheritDoc}
 355  
      */
 356  
     public void endBodyScript(IMarkupWriter normalWriter, IRequestCycle cycle)
 357  
     {
 358  0
         _writer.printRaw("\n//]]>\n");
 359  0
         _writer.end();
 360  0
     }
 361  
 
 362  
     /**
 363  
      * {@inheritDoc}
 364  
      */
 365  
     public void writeBodyScript(IMarkupWriter normalWriter, String script, IRequestCycle cycle)
 366  
     {
 367  0
         _writer.printRaw(script);
 368  0
     }
 369  
 
 370  
     /**
 371  
      * {@inheritDoc}
 372  
      */
 373  
     public void writeExternalScript(IMarkupWriter normalWriter, String url, IRequestCycle cycle)
 374  
     {
 375  0
         _writer.begin("script");
 376  0
         _writer.attribute("type", "text/javascript");
 377  0
         _writer.attribute("src", url);
 378  0
         _writer.end();
 379  0
     }
 380  
 
 381  
     /**
 382  
      * {@inheritDoc}
 383  
      */
 384  
     public void writeImageInitializations(IMarkupWriter normalWriter, String script, String preloadName, IRequestCycle cycle)
 385  
     {
 386  0
     }
 387  
 
 388  
     /**
 389  
      * {@inheritDoc}
 390  
      */
 391  
     public void writeInitializationScript(IMarkupWriter normalWriter, String script)
 392  
     {
 393  0
         _writer.begin("script");
 394  
 
 395  
         // return is in XML so must escape any potentially non-xml compliant content
 396  0
         _writer.printRaw("\n//<![CDATA[\n");
 397  0
         _writer.printRaw(script);
 398  0
         _writer.printRaw("\n//]]>\n");
 399  0
         _writer.end();
 400  0
     }
 401  
 
 402  
     public void addStatus(IMarkupWriter normalWriter, String text)
 403  
     {
 404  0
         throw new UnsupportedOperationException("Can't return a status response with prototype based requests.");
 405  
     }
 406  
 
 407  
     public void addStatusMessage(IMarkupWriter normalWriter, String category, String text)
 408  
     {
 409  0
         throw new UnsupportedOperationException("Can't return a status response with prototype based requests.");
 410  
     }
 411  
 
 412  
     /**
 413  
      * {@inheritDoc}
 414  
      */
 415  
     public void render(IMarkupWriter writer, IRender render, IRequestCycle cycle)
 416  
     {
 417  
         // must be a valid writer already
 418  
 
 419  0
         if (NestedMarkupWriterImpl.class.isInstance(writer))
 420  
         {
 421  0
             render.render(writer, cycle);
 422  0
             return;
 423  
         }
 424  
 
 425  0
         if (IComponent.class.isInstance(render)
 426  
             && contains((IComponent)render, ((IComponent)render).peekClientId()))
 427  
         {
 428  0
             render.render(getComponentWriter( ((IComponent)render).peekClientId() ), cycle);
 429  0
             return;
 430  
         }
 431  
 
 432  
         // Nothing else found, throw out response
 433  
 
 434  0
         render.render(NullWriter.getSharedInstance(), cycle);
 435  0
     }
 436  
 
 437  
     IMarkupWriter getComponentWriter(String id)
 438  
     {
 439  0
         return getWriter(id, ELEMENT_TYPE);
 440  
     }
 441  
 
 442  
     /**
 443  
      *
 444  
      * {@inheritDoc}
 445  
      */
 446  
     public IMarkupWriter getWriter(String id, String type)
 447  
     {
 448  0
         Defense.notNull(id, "id can't be null");
 449  
 
 450  0
         IMarkupWriter w = (IMarkupWriter)_writers.get(id);
 451  0
         if (w != null)
 452  0
             return w;
 453  
 
 454  0
         IMarkupWriter nestedWriter = _writer.getNestedWriter();
 455  0
         _writers.put(id, nestedWriter);
 456  
 
 457  0
         return nestedWriter;
 458  
     }
 459  
 
 460  
     void beginResponse()
 461  
     {
 462  0
     }
 463  
 
 464  
     /**
 465  
      * Invoked to clear out tempoary partial writer buffers before rendering exception
 466  
      * page.
 467  
      */
 468  
     void clearPartialWriters()
 469  
     {
 470  0
         _writers.clear();
 471  0
     }
 472  
 
 473  
     /**
 474  
      * Called after the entire response has been captured. Causes
 475  
      * the writer buffer output captured to be segmented and written
 476  
      * out to the right response elements for the client libraries to parse.
 477  
      */
 478  
     void endResponse()
 479  
     {
 480  0
         Iterator keys = _writers.keySet().iterator();
 481  
 
 482  0
         while (keys.hasNext())
 483  
         {
 484  0
             String key = (String)keys.next();
 485  0
             NestedMarkupWriter nw = (NestedMarkupWriter)_writers.get(key);
 486  
 
 487  0
             nw.close();
 488  0
         }
 489  
 
 490  0
         _writer.flush();
 491  0
     }
 492  
 
 493  
     /**
 494  
      * Grabs the incoming parameters needed for json responses, most notable the
 495  
      * {@link ServiceConstants#UPDATE_PARTS} parameter.
 496  
      *
 497  
      * @param cycle
 498  
      *            The request cycle to parse from
 499  
      */
 500  
     void parseParameters(IRequestCycle cycle)
 501  
     {
 502  0
         Object[] updateParts = cycle.getParameters(ServiceConstants.UPDATE_PARTS);
 503  
 
 504  0
         if (updateParts == null)
 505  0
             return;
 506  
 
 507  0
         for(int i = 0; i < updateParts.length; i++)
 508  
         {
 509  0
             _parts.add(updateParts[i].toString());
 510  
         }
 511  0
     }
 512  
 
 513  
     /**
 514  
      * Determines if the specified component is contained in the
 515  
      * responses requested update parts.
 516  
      * @param target
 517  
      *          The component to check for.
 518  
      * @return True if the request should capture the components output.
 519  
      */
 520  
     public boolean contains(IComponent target)
 521  
     {
 522  0
         if (target == null)
 523  0
             return false;
 524  
 
 525  0
         String id = target.getClientId();
 526  
 
 527  0
         return contains(target, id);
 528  
     }
 529  
 
 530  
     boolean contains(IComponent target, String id)
 531  
     {
 532  0
         if (_parts.contains(id))
 533  0
             return true;
 534  
 
 535  0
         Iterator it = _cycle.renderStackIterator();
 536  0
         while (it.hasNext())
 537  
         {
 538  0
             IComponent comp = (IComponent)it.next();
 539  0
             String compId = comp.getClientId();
 540  
 
 541  0
             if (comp != target && _parts.contains(compId))
 542  0
                 return true;
 543  0
         }
 544  
 
 545  0
         return false;
 546  
     }
 547  
 
 548  
     /**
 549  
      * {@inheritDoc}
 550  
      */
 551  
     public boolean explicitlyContains(IComponent target)
 552  
     {
 553  0
         if (target == null)
 554  0
             return false;
 555  
 
 556  0
         return _parts.contains(target.getId());
 557  
     }
 558  
 }