/**
   * Return a <code>MarinerURL</code> (or null) for any non-cacheable urls.
   *
   * @param requestContext the mariner request context
   * @param assetGroup the assetgroup
   * @param asset the asset
   * @return a mariner url or null if none can be computed.
   * @throws RepositoryException if a repository exception occurs.
   */
  protected MarinerURL computeNoncacheableURL(
      MarinerRequestContext requestContext, AssetGroup assetGroup, Asset asset)
      throws RepositoryException {

    // If the asset is a DynamicVisualAsset and the encoding is TV then the
    // asset url consists of the device specific tv channel prefix and the
    // value appended if it is set. If the tv channel prefix is not valid in
    // a url then we have problems.
    if (asset.getClass() == DynamicVisualAsset.class) {
      DynamicVisualAsset dynamicVisualAsset = (DynamicVisualAsset) asset;
      if (dynamicVisualAsset.getEncoding() == DynamicVisualAsset.TV) {
        MarinerPageContext marinerPageContext =
            ContextInternals.getMarinerPageContext(requestContext);
        InternalDevice device = marinerPageContext.getDevice();

        String tvChannelPrefix = device.getTVChannelPrefix();
        String url = tvChannelPrefix;
        String value = dynamicVisualAsset.getValue();
        if (value != null) {
          url += value;
        }
        return new MarinerURL(url);
      }
    }
    return null;
  }
  /**
   * Creates a MarinerUrl
   *
   * @param requestContext
   * @param asset
   * @param assetGroup
   * @param marinerURL
   * @return
   * @throws RepositoryException
   */
  public static MarinerURL createMarinerURL(
      MarinerRequestContext requestContext,
      Asset asset,
      AssetGroup assetGroup,
      MarinerURL marinerURL)
      throws RepositoryException {

    MarinerURL urlResult = computeURL(requestContext, asset, assetGroup, marinerURL);

    if (asset instanceof ConvertibleImageAsset) {
      String url = urlResult.getExternalForm();

      // Construct the url for the convertible image asset.
      ConvertibleImageAsset convertible = (ConvertibleImageAsset) asset;
      PreservedArea area =
          PreservedArea.get(convertible.getPreserveLeft(), convertible.getPreserveRight(), true);
      String value = ContextInternals.constructImageURL(requestContext, url, area);

      urlResult = new MarinerURL(value);
    }

    // Complete the URL
    urlResult = completeURL(requestContext, asset, assetGroup, urlResult);

    // Make sure that the url cannot be modified (even if it is a
    // convertible image asset).
    urlResult.makeReadOnly();

    return urlResult;
  }
 /**
  * Method to return the Volantis bean
  *
  * @param requestContext the MarinerRequestContext
  * @return the Volantis bean
  */
 private Volantis getVolantisBean(MarinerRequestContext requestContext) {
   if (volantisBean == null) {
     MarinerPageContext marinerPageContext =
         ContextInternals.getMarinerPageContext(requestContext);
     volantisBean = marinerPageContext.getVolantisBean();
   }
   return volantisBean;
 }
  // javadoc inherited
  public void process(
      final Object content,
      final XDIMEContextInternal context,
      final String id,
      final String propertyName)
      throws XDIMEException {

    // Perform default property processing.
    super.process(content, context, id, propertyName);

    // Enable caching
    final EnvironmentContext environmentContext =
        ContextInternals.getEnvironmentContext(context.getInitialRequestContext());
    final ResponseCachingDirectives cachingDirectives = environmentContext.getCachingDirectives();
    if (cachingDirectives != null) {
      cachingDirectives.enable();
    }
  }
  /**
   * Method that completes a computed URL
   *
   * @param requestContext the mariner request context
   * @param asset the Asset whose URL we are completing
   * @param assetGroup the AssetGroup associated with the Asset
   * @param marinerURL the URL that is being completed
   * @return the completed URL
   */
  public static MarinerURL completeURL(
      MarinerRequestContext requestContext,
      Asset asset,
      AssetGroup assetGroup,
      MarinerURL marinerURL) {

    // Get the project that owns the resource. If an asset group is
    // provided then it is the asset group's project, otherwise it is the
    // asset's project.
    RuntimeProject assetProject = (RuntimeProject) asset.getProject();
    RuntimeProject project = null;
    if (assetGroup == null) {
      project = assetProject;
    } else {
      project = (RuntimeProject) assetGroup.getProject();
    }
    if (project == null) {
      throw new IllegalStateException("Project not set");
    }

    MarinerURL assetsBaseURL = project.getAssetsBaseURL();
    if (isClientSideURL(asset, assetGroup)) {
      // Client side URLs are not affected by the project's base URL.
    } else if (project.getContainsOrphans() && project.isRemote()) {
      // Asset URLs from remote policies that are not in a remote project
      // should already be fully qualified.
      if (!marinerURL.isAbsolute()) {
        synchronized (DefaultAssetURLRewriter.class) {
          if (!vikingCasualtyChipWOWFlag) {
            vikingCasualtyChipWOWFlag = true;
            logger.warn("url-not-absolute", marinerURL.getExternalForm());
          }
        }
      }
    } else if (marinerURL.containsDocumentRelativePath()) {

      // Document relative assets should only be resolved if the project
      // is portable, otherwise leave them as they are.
      // todo Always resolve these and then provide a way later to optimise URLs in the page to try
      // and make them relative if possible.
      if (project.isPortable()) {

        // If the project is portable then get the project relative path to the
        // policy so that it can be used to resolve relative asset references
        // against.
        MarinerURL projectRelativePath;
        String name = asset.getName();
        if (name.startsWith("/")) {
          projectRelativePath = new MarinerURL(name);
        } else {
          projectRelativePath = new MarinerURL(assetProject.makeProjectRelativePath(name, true));
        }

        // Resolve relative asset references against the project
        // relative path and then make sure that it can be resolved
        // against the assets base URL by removing leading /.
        marinerURL = new MarinerURL(projectRelativePath, marinerURL);
        marinerURL =
            new MarinerURL(
                URLNormalizer.convertHostRelativeToDocumentRelative(marinerURL.getExternalForm()));

        // Resolve the document relative asset URL against the assets
        // base URL.
        marinerURL = new MarinerURL(assetsBaseURL, marinerURL);

        // The result must be absolute, or host relative.
        if (marinerURL.isAbsolute()) {
          // Nothing more to do.
        } else if (marinerURL.containsHostRelativePath()) {
          // May need to make it relative to the context.
          EnvironmentContext environmentContext =
              ContextInternals.getEnvironmentContext(requestContext);
          MarinerURL contextPath = environmentContext.getContextPathURL();
          marinerURL =
              new MarinerURL(
                  contextPath,
                  URLNormalizer.convertHostRelativeToDocumentRelative(
                      marinerURL.getExternalForm()));
        } else {
          throw new IllegalStateException(
              "The rewritten URL "
                  + marinerURL
                  + " for remote asset "
                  + asset
                  + " "
                  + "must be absolute or host relative but is not");
        }
      }

    } else if (marinerURL.containsHostRelativePath()) {

      // Host relative paths are treated as being relative to the
      // project's asset base URL. This is because otherwise assets
      // and asset groups would need to know the host relative path to
      // the assets including the web application context (if any).

      // NOTE: I have the feeling this should be dealt with when the url
      // is computed but there is no description for the intermediate form
      // of the url so I am not prepared to change that. This class needs
      // rewriting/clarifying. Until then we are left with the following
      // bodge...
      // todo: later: deal with document relative urls which are from
      // asset groups which are host relative.
      //
      // If the url was computed from an asset group which was relative
      // to the host, then we should leave this as host relative.
      if (assetGroup != null && assetGroup.getLocationType() == AssetGroup.HOST) {
        // Leave the url as host relative. This will mean than when
        // resolved against the context the context is ignored.
        if (logger.isDebugEnabled()) {
          logger.debug(
              "leaving existing host relative url computed "
                  + "from host relative asset group url as host "
                  + "relative");
        }
      } else {
        // Either it was not from an asset group or the asset group was
        // context relative. In either case we should...

        // Strip the / off the front of the host relative URL to make it
        // a document relative URL so it will resolve against the base
        // URL properly.
        String url =
            URLNormalizer.convertHostRelativeToDocumentRelative(marinerURL.getExternalForm());
        marinerURL = new MarinerURL(assetsBaseURL, url);
      }

      // The resulting URL must be either a host relative path or an
      // absolute URL. If it is not then it is a fatal error as it could
      // only have arisen due to invalid configuration which should have
      // been detected during init.
      if (marinerURL.isRelative() && marinerURL.containsDocumentRelativePath()) {
        throw new RuntimeException(
            "The rewritten URL "
                + marinerURL
                + " for Asset "
                + asset
                + " is not host relative or "
                + "absolute.  The configuration is probably wrong.");
      }
    }
    return marinerURL;
  }
  // Javadoc inherited.
  protected int exprElementEnd(MarinerRequestContext context, PAPIAttributes papiAttributes)
      throws PAPIException {
    IncludeAttributes attributes = (IncludeAttributes) papiAttributes;

    if (attributes.getHref() == null) {
      throw new PAPIException(exceptionLocalizer.format("include-href-missing"));
    } else {
      // @todo this is a bit duff since it relies on markup naming not to change; do this a
      // different way
      // Set up the markup that will be sent down the pipeline
      StringBuffer markup = new StringBuffer();
      InputSource inputSource;

      markup.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
      markup
          .append("<urid:fetch xmlns:urid=\"")
          .append(Namespace.URID.getURI())
          .append("\" href=\"")
          .append(attributes.getHref())
          .append("\"");

      if (attributes.getParse() != null) {
        markup.append(" parse=\"").append(attributes.getParse()).append("\"");
      }

      if (attributes.getEncoding() != null) {
        markup.append(" encoding=\"").append(attributes.getEncoding()).append("\"");
      }

      markup.append("/>");

      if (logger.isDebugEnabled()) {
        logger.debug("Set up inclusion command as: " + markup.toString());
      }

      inputSource = new InputSource(new StringReader(markup.toString()));

      // Set up and execute the pipeline to perform the required
      // inclusion
      MarinerPageContext pageContext = ContextInternals.getMarinerPageContext(context);
      XMLReader reader = MarlinSAXHelper.getXMLReader(context);
      reader.setContentHandler(MarlinSAXHelper.getContentHandler(context));
      // @todo this is nasty: we assume that the reader is actually an XMLPipelineFilter
      XMLPipelineFilter filter = (XMLPipelineFilter) reader;
      XMLPipelineContext pipelineContext = filter.getPipelineContext();

      // set the Base URI in the pipeline's context
      try {
        URL baseURI = pageContext.getAbsoluteURL(pageContext.getRequestURL(false));

        if (logger.isDebugEnabled()) {
          logger.debug("Setting Base URI " + baseURI);
        }

        pipelineContext.pushBaseURI(baseURI.toExternalForm());
      } catch (MalformedURLException e) {
        throw new PAPIException(e);
      }

      PipelineIntegrationUtilities.setUpIntegration(
          filter, pageContext.getCurrentElement(), context, pageContext.getCurrentOutputBuffer());

      if (logger.isDebugEnabled()) {
        logger.debug("Executing inclusion");
      }

      // Execute the inclusion
      try {
        reader.parse(inputSource);
      } catch (IOException e) {
        throw new PAPIException(e);
      } catch (SAXException e) {
        throw new PAPIException(e);
      } finally {
        PipelineIntegrationUtilities.tearDownIntegration(filter);
      }
    }

    if (logger.isDebugEnabled()) {
      logger.debug("Successful execution of inclusion");
    }

    return CONTINUE_PROCESSING;
  }