Package er.extensions.appserver

Source Code of er.extensions.appserver.ERXWOContext$Observer

package er.extensions.appserver;

import java.net.MalformedURLException;
import java.net.URL;

import com.webobjects.appserver.WOApplication;
import com.webobjects.appserver.WOComponent;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WODirectAction;
import com.webobjects.appserver.WORequest;
import com.webobjects.appserver.WOResponse;
import com.webobjects.appserver.WOSession;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSMutableDictionary;
import com.webobjects.foundation.NSNotification;
import com.webobjects.foundation.NSNotificationCenter;

import er.extensions.appserver.ERXResponseRewriter.TagMissingBehavior;
import er.extensions.appserver.ajax.ERXAjaxContext;
import er.extensions.foundation.ERXMutableURL;
import er.extensions.foundation.ERXMutableUserInfoHolderInterface;
import er.extensions.foundation.ERXProperties;
import er.extensions.foundation.ERXRuntimeUtilities;
import er.extensions.foundation.ERXSelectorUtilities;
import er.extensions.foundation.ERXStringUtilities;
import er.extensions.foundation.ERXThreadStorage;

/**
* Replacement of WOContext. This subclass is installed when the frameworks
* loads.
*/
public class ERXWOContext extends ERXAjaxContext implements ERXMutableUserInfoHolderInterface {
  private static Observer observer;
  private boolean _generateCompleteURLs;
  private boolean _generateCompleteResourceURLs;
 
  private static final boolean IS_DEV = ERXApplication.isDevelopmentModeSafe();

  public static final String CONTEXT_KEY = "wocontext";
  public static final String CONTEXT_DICTIONARY_KEY = "ERXWOContext.dict";

  public static class Observer {
    public void applicationDidHandleRequest(NSNotification n) {
      ERXWOContext.setCurrentContext(null);
      ERXThreadStorage.removeValueForKey(ERXWOContext.CONTEXT_DICTIONARY_KEY);
    }
  }

  /**
   * Returns the existing session if any is given in the form values or URL.
   *
   * @return session for this request or <code>null</code>
   */
  public WOSession existingSession() {
    String sessionID = _requestSessionID();
    if (!super.hasSession() && sessionID != null)
      WOApplication.application().restoreSessionWithID(sessionID, this);
    return _session();
  }

  /**
   * Returns true if there is an existing session.
   */
  @Override
  public boolean hasSession() {
    if (super.hasSession()) {
      return true;
    }
    return existingSession() != null;
  }

  public static NSMutableDictionary contextDictionary() {
    if (observer == null) {
      synchronized (ERXWOContext.class) {
        if (observer == null) {
          observer = new Observer();

          NSNotificationCenter.defaultCenter().addObserver(observer, ERXSelectorUtilities.notificationSelector("applicationDidHandleRequest"), WOApplication.ApplicationDidDispatchRequestNotification, null);
        }
      }
    }
    NSMutableDictionary contextDictionary = ERXWOContext._contextDictionary();
    if (contextDictionary == null) {
      contextDictionary = new NSMutableDictionary();
      ERXThreadStorage.takeValueForKey(contextDictionary, ERXWOContext.CONTEXT_DICTIONARY_KEY);
    }
    return contextDictionary;
  }

  public static WOContext currentContext() {
    return (WOContext) ERXThreadStorage.valueForKey(CONTEXT_KEY);
  }

  public static void setCurrentContext(Object object) {
    ERXThreadStorage.takeValueForKey(object, CONTEXT_KEY);
  }

  protected static NSMutableDictionary _contextDictionary() {
    NSMutableDictionary contextDictionary = (NSMutableDictionary) ERXThreadStorage.valueForKey(ERXWOContext.CONTEXT_DICTIONARY_KEY);
    return contextDictionary;
  }

  public ERXWOContext(WORequest worequest) {
    super(worequest);
  }

  /**
   * Implemented so that the thread checks if it should get interrupted.
   *
   * @param component the current component
   */
  @Override
  public void _setCurrentComponent(WOComponent component) {
    ERXRuntimeUtilities.checkThreadInterrupt();
    super._setCurrentComponent(component);
  }
 
  @Override
  public Object clone() {
    ERXWOContext context = (ERXWOContext)super.clone();
    context._setGenerateCompleteResourceURLs(_generateCompleteResourceURLs);
    return context;
  }
 
  /**
   * Turn on complete resource URL generation.
   *
   * @param generateCompleteResourceURLs if true, resources will generate complete URLs.
   */
  public void _setGenerateCompleteResourceURLs(boolean generateCompleteResourceURLs) {
    _generateCompleteResourceURLs = generateCompleteResourceURLs;
  }

  /**
   * Returns whether or not resources generate complete URLs.
   *
   * @return whether or not resources generate complete URLs
   */
  public boolean _generatingCompleteResourceURLs() {
    return _generateCompleteResourceURLs;
  }
 
  @Override
  public void generateCompleteURLs() {
    super.generateCompleteURLs();
    _generateCompleteURLs = true;
  }

  @Override
  @Deprecated
  public void _generateCompleteURLs() {
    super._generateCompleteURLs();
    _generateCompleteURLs = true;
  }

  @Override
  public void generateRelativeURLs() {
    super.generateRelativeURLs();
    _generateCompleteURLs = false;
  }
 
  @Override
  @Deprecated
  public void _generateRelativeURLs() {
    super._generateRelativeURLs();
    _generateCompleteURLs = false;
  }
 
  @Override
  public boolean doesGenerateCompleteURLs() {
    return _generateCompleteURLs;
  }

  @Deprecated
  public boolean _generatingCompleteURLs() {
    return _generateCompleteURLs;
  }

  /**
   * Creates a WOContext using a dummy WORequest.
   * @return the new WOContext
   */
  public static WOContext newContext() {
    WOApplication app = WOApplication.application();
    // Try to create a URL with a relative path into the application to mimic a real request.
    // We must create a request with a relative URL, as using an absolute URL makes the new
    // WOContext's URL absolute, and it is then unable to render relative paths. (Long story short.)
    //
    // Note: If you configured the adaptor's WebObjectsAlias to something other than the default,
    // make sure to also set your WOAdaptorURL property to match.  Otherwise, asking the new context
    // the path to a direct action or component action URL will give an incorrect result.
    String requestUrl = app.cgiAdaptorURL() + "/" + app.name() + app.applicationExtension();
    try {
      URL url = new URL(requestUrl);
      requestUrl = url.getPath(); // Get just the part of the URL that is relative to the server root.
    } catch (MalformedURLException mue) {
      // The above should never fail.  As a last resort, using the empty string will
      // look funny in the request, but still allow the context to use a relative url.
      requestUrl = "";
    }
    return app.createContextForRequest(app.createRequest("GET", requestUrl, "HTTP/1.1", null, null, null));
  }

  public NSMutableDictionary mutableUserInfo() {
    return contextDictionary();
  }

  public void setMutableUserInfo(NSMutableDictionary userInfo) {
    ERXThreadStorage.takeValueForKey(userInfo, ERXWOContext.CONTEXT_DICTIONARY_KEY);
  }

  @Override
  public NSDictionary userInfo() {
    return mutableUserInfo();
  }

  /**
   * If er.extensions.ERXWOContext.forceRemoveApplicationNumber is true, then always remove the
   * application number from the generated URLs.  You have to be aware of how your app is written
   * to know if this is something you can do without causing problems.  For instance, you MUST be
   * using cookies, and you must not use WOImages with data bindings -- anything that requires a
   * per-instance cache has the potential to fail when this is enabled (if you have more than
   * one instance of your app deployed).
   */
  protected void _preprocessURL() {
    if (ERXProperties.booleanForKey("er.extensions.ERXWOContext.forceRemoveApplicationNumber")) {
      _url().setApplicationNumber(null);
    }
  }

  protected String _postprocessURL(String url) {
    if (WOApplication.application() instanceof ERXApplication) {
      return ERXApplication.erxApplication()._rewriteURL(url);
    }
    return url;
  }
 
  @Override
  public String _urlWithRequestHandlerKey(String requestHandlerKey, String requestHandlerPath, String queryString, boolean secure) {
    _preprocessURL();
    return super._urlWithRequestHandlerKey(requestHandlerKey, requestHandlerPath, queryString, secure);
  }
 
  @Override
  public String _urlWithRequestHandlerKey(String requestHandlerKey, String requestHandlerPath, String queryString, boolean isSecure, int somePort) {
    _preprocessURL();
    String url = super._urlWithRequestHandlerKey(requestHandlerKey, requestHandlerPath, queryString, isSecure, somePort);
    url = _postprocessURL(url);
    return url;
  }

  /**
   * Returns a complete URL for the specified action. Works like
   * {@link WOContext#directActionURLForActionNamed} but has one extra
   * parameter to specify whether or not to include the current session ID
   * in the URL. Convenient if you embed the link for the direct
   * action into an email message and don't want to keep the session ID in it.
   * <p>
   * <code>actionName</code> can be either an action -- "ActionName" -- or
   * an action on a class -- "ActionClass/ActionName". You can also specify
   * <code>queryDict</code> to be an NSDictionary which contains form values
   * as key/value pairs. <code>includeSessionID</code> indicates if you want
   * to include the session ID in the URL.
   *
   * @param actionName
   *            String action name
   * @param queryDict
   *            NSDictionary containing query key/value pairs
   * @param includeSessionID
   *            <code>true</code>: to include the session ID (if has one), <br>
   *            <code>false</code>: not to include the session ID
   * @return a String containing the URL for the specified action
   * @see WODirectAction
   */
  public String directActionURLForActionNamed(String actionName, NSDictionary queryDict, boolean includeSessionID) {
    String url = super.directActionURLForActionNamed(actionName, queryDict);
    if (!includeSessionID) {
      url = stripSessionIDFromURL(url);
    }
    return url;
  }

  /**
   * Removes session ID query key/value pair from the given URL
   * string.
   *
   * @param url
   *            String URL
   * @return a String with the session ID removed
   */
  public static String stripSessionIDFromURL(String url) {
    if (url == null)
      return null;
    String sessionIdKey = WOApplication.application().sessionIdKey();
    int len = 1;
    int startpos = url.indexOf("?" + sessionIdKey);
    if (startpos < 0) {
      startpos = url.indexOf("&" + sessionIdKey);
    }
    if (startpos < 0) {
      startpos = url.indexOf("&amp;" + sessionIdKey);
      len = 5;
    }

    if (startpos >= 0) {
      int endpos = url.indexOf('&', startpos + len);
      if (endpos < 0)
        url = url.substring(0, startpos);
      else {
        int endLen = len;
        if (len == 1 && url.indexOf("&amp;") >= 0) {
          endLen = 5;
        }
        url = url.substring(0, startpos + len) + url.substring(endpos + endLen);
      }
    }
    return url;
  }

  /**
   * Debugging help, returns the path to current component as a list of component names.
   *
   * @param context the current context
   * @return an array of component names
   */
  public static NSArray<String> componentPath(WOContext context) {
    NSMutableArray<String> result = new NSMutableArray<String>();
    if (context != null) {
      WOComponent component = context.component();
      while (component != null) {
        if (component.name() != null) {
          result.insertObjectAtIndex(component.name(), 0);
        }
        component = component.parent();
      }
    }
    return result;
  }

  /**
   * Debugging help, returns the path to current component as WOComponent objects.
   *
   * @param context the current context
   * @return an array of components
   */
  public static NSArray<WOComponent> _componentPath(WOContext context) {
    NSMutableArray<WOComponent> result = new NSMutableArray<WOComponent>();
    if (context != null) {
      WOComponent component = context.component();
      while (component != null) {
        if (component.name() != null) {
          result.insertObjectAtIndex(component, 0);
        }
        component = component.parent();
      }
    }
    return result;
  }
 
  /**
   *
   * @deprecated replaced by {@link er.extensions.appserver.ERXResponseRewriter}
   */
  @Deprecated
  public static String _htmlCloseHeadTag() {
    return ERXResponseRewriter._htmlCloseHeadTag();
  }
 
  /**
   * @deprecated replaced by {@link er.extensions.appserver.ERXResponseRewriter}
   */
  @Deprecated
  public static void insertInResponseBeforeTag(WOContext context, WOResponse response, String content, String tag, TagMissingBehavior tagMissingBehavior) {
    ERXResponseRewriter.insertInResponseBeforeTag(response, context, content, tag, tagMissingBehavior);
  }
 
  /**
   * @deprecated replaced by {@link er.extensions.appserver.ERXResponseRewriter}
   */
  @Deprecated
  public static void addScriptResourceInHead(WOContext context, WOResponse response, String framework, String fileName) {
    ERXResponseRewriter.addScriptResourceInHead(response, context, framework, fileName);
  }
 
  /**
   * @deprecated replaced by {@link er.extensions.appserver.ERXResponseRewriter}
   */
  @Deprecated
  public static void addStylesheetResourceInHead(WOContext context, WOResponse response, String framework, String fileName) {
    ERXResponseRewriter.addStylesheetResourceInHead(response, context, framework, fileName);
  }
 
  /**
   * @deprecated replaced by {@link er.extensions.appserver.ERXResponseRewriter}
   */
  @Deprecated
  public static void addScriptCodeInHead(WOContext context, WOResponse response, String script) {
    ERXResponseRewriter.addScriptCodeInHead(response, context, script);
  }
 
  /**
   * @deprecated replaced by {@link er.extensions.appserver.ERXResponseRewriter}
   */
  @Deprecated
  public static void addScriptCodeInHead(WOContext context, WOResponse response, String script, String scriptName) {
    ERXResponseRewriter.addScriptCodeInHead(response, context, script, scriptName);
  }
 
  /**
   * @deprecated replaced by {@link er.extensions.appserver.ERXResponseRewriter}
   */
  @Deprecated
  public static void addResourceInHead(WOContext context, WOResponse response, String framework, String fileName, String startTag, String endTag) {
    ERXResponseRewriter.addResourceInHead(response, context, framework, fileName, startTag, endTag);
  }
 
  /**
   * @deprecated replaced by {@link er.extensions.appserver.ERXResponseRewriter}
   */
  @Deprecated
  public static void addResourceInHead(WOContext context, WOResponse response, String framework, String fileName, String startTag, String endTag, TagMissingBehavior tagMissingBehavior) {
    ERXResponseRewriter.addResourceInHead(response, context, framework, fileName, startTag, endTag, tagMissingBehavior);
  }

  private static final String SAFE_IDENTIFIER_NAME_KEY = "ERXWOContext.safeIdentifierName";
  /**
   * Returns a safe identifier for the current component.  If willCache is true, your
   * component should cache the identifier name so that it does not change.  In this case,
   * your component will be given an incrementing counter value that is unique on the
   * current page.  If willCache is false (because you cannot cache the value), the
   * identifier returned will be based on the context.elementID().  While unique on the
   * page at any point in time, be aware that structural changes to the page can
   * cause the elementID of your component to change.
   *
   * @param context the WOContext
   * @param willCache if true, you should cache the resulting value in your component
   * @return a safe identifier name
   */
  public static String safeIdentifierName(WOContext context, boolean willCache) {
    String safeIdentifierName;
    if (willCache) {
      NSMutableDictionary<String, Object> pageUserInfo = ERXResponseRewriter.pageUserInfo(context);
      Integer counter = (Integer) pageUserInfo.objectForKey(ERXWOContext.SAFE_IDENTIFIER_NAME_KEY);
      if (counter == null) {
        counter = Integer.valueOf(0);
      }
      else {
        counter = Integer.valueOf(counter.intValue() + 1);
      }
      pageUserInfo.setObjectForKey(counter, ERXWOContext.SAFE_IDENTIFIER_NAME_KEY);
      safeIdentifierName = ERXStringUtilities.safeIdentifierName(counter.toString());
    }
    else {
      safeIdentifierName = ERXStringUtilities.safeIdentifierName("e_" + context.elementID())
    }
    return safeIdentifierName;
  }
 
  /**
   * Returns a javascript-safe version of the given element ID.
   *
   * @see er.extensions.foundation.ERXStringUtilities#safeIdentifierName(String)
   * @param elementID
   *            the element ID
   * @return a javascript-safe version (i.e. "_1_2_3_10")
   * @deprecated user {@link er.extensions.foundation.ERXStringUtilities#safeIdentifierName(String)}
   */
  @Deprecated
  public static String toSafeElementID(String elementID) {
    return ERXStringUtilities.safeIdentifierName(elementID);
  }

  /**
   * Call this anywhere you would have called _directActionURL in 5.3 if you
   * want to be 5.4 compatible.
   *
   * @param context
   *            the WOContext to operate on
   * @param actionName
   *            the name of the direct action to lookup
   * @param queryParams
   *            the query parameters to use
   * @param secure
   *            whether or not the URL should be HTTPS
   * @return the URL to the given direct action
   * @deprecated use non-static {@link #_directActionURL(String, NSDictionary, boolean, int, boolean)} instead
   */
  @Deprecated
  public static String _directActionURL(WOContext context, String actionName, NSDictionary queryParams, boolean secure) {
    return context._directActionURL(actionName, queryParams, secure, 0, false);
  }

  /**
   * Generates direct action URLs with support for various overrides.
   *
   * @param context
   *            the context to generate the URL within
   * @param directActionName
   *            the direct action name
   * @param secure
   *            <code>true</code> = https, <code>false</code> = http, <code>null</code> = same as request
   * @param includeSessionID
   *            if <code>false</code>, removes session ID from query parameters
   * @return the constructed direct action URL
   */
  public static String directActionUrl(WOContext context, String directActionName, Boolean secure, boolean includeSessionID) {
    return ERXWOContext.directActionUrl(context, null, null, null, directActionName, null, secure, includeSessionID);
  }

  /**
   * Generates direct action URLs with support for various overrides.
   *
   * @param context
   *            the context to generate the URL within
   * @param directActionName
   *            the direct action name
   * @param key
   *            the query parameter key to add (or <code>null</code> to skip)
   * @param value
   *            the query parameter value to add (or <code>null</code> to skip)
   * @param secure
   *            <code>true</code> = https, <code>false</code> = http, <code>null</code> = same as request
   * @param includeSessionID
   *            if <code>false</code>, removes session ID from query parameters
   * @return the constructed direct action URL
   */
  public static String directActionUrl(WOContext context, String directActionName, String key, String value, Boolean secure, boolean includeSessionID) {
    return ERXWOContext.directActionUrl(context, null, null, null, directActionName, key, value, secure, includeSessionID);
  }

  /**
   * Generates direct action URLs with support for various overrides.
   *
   * @param context
   *            the context to generate the URL within
   * @param directActionName
   *            the direct action name
   * @param queryParameters
   *            the query parameters to append (or <code>null</code>)
   * @param secure
   *            <code>true</code> = https, <code>false</code> = http, <code>null</code> = same as request
   * @param includeSessionID
   *            if <code>false</code>, removes session ID from query parameters
   * @return the constructed direct action URL
   */
  public static String directActionUrl(WOContext context, String directActionName, NSDictionary<String, Object> queryParameters, Boolean secure, boolean includeSessionID) {
    return ERXWOContext.directActionUrl(context, null, null, null, directActionName, queryParameters, secure, includeSessionID);
  }

  /**
   * Generates direct action URLs with support for various overrides.
   *
   * @param context
   *            the context to generate the URL within
   * @param host
   *            the host name for the URL (or <code>null</code> for default)
   * @param port
   *            the port number of the URL (or <code>null</code> for default)
   * @param path
   *            the custom path prefix (or <code>null</code> for none)
   * @param directActionName
   *            the direct action name
   * @param key
   *            the query parameter key to add (or <code>null</code> to skip)
   * @param value
   *            the query parameter value to add (or <code>null</code> to skip)
   * @param secure
   *            <code>true</code> = https, <code>false</code> = http, <code>null</code> = same as request
   * @param includeSessionID
   *            if <code>false</code>, removes session ID from query parameters
   * @return the constructed direct action URL
   */
  public static String directActionUrl(WOContext context, String host, Integer port, String path, String directActionName, String key, Object value, Boolean secure, boolean includeSessionID) {
    NSDictionary<String, Object> queryParameters = null;
    if (key != null && value != null) {
      queryParameters = new NSDictionary<String, Object>(value, key);
    }
    return ERXWOContext.directActionUrl(context, host, port, path, directActionName, queryParameters, secure, includeSessionID);
  }

  /**
   * Generates direct action URLs with support for various overrides.
   *
   * @param context
   *            the context to generate the URL within
   * @param host
   *            the host name for the URL (or <code>null</code> for default)
   * @param port
   *            the port number of the URL (or <code>null</code> for default)
   * @param path
   *            the custom path prefix (or <code>null</code> for none)
   * @param directActionName
   *            the direct action name
   * @param queryParameters
   *            the query parameters to append (or <code>null</code>)
   * @param secure
   *            <code>true</code> = https, <code>false</code> = http, <code>null</code> = same as request
   * @param includeSessionID
   *            if <code>false</code>, removes session ID from query parameters
   * @return the constructed direct action URL
   */
  public static String directActionUrl(WOContext context, String host, Integer port, String path, String directActionName, NSDictionary<String, Object> queryParameters, Boolean secure, boolean includeSessionID) {
    boolean completeUrls;

    boolean currentlySecure = ERXRequest.isRequestSecure(context.request());
    boolean secureBool = (secure == null) ? currentlySecure : secure.booleanValue();

    if (host == null && currentlySecure == secureBool && port == null) {
      completeUrls = true;
    }
    else {
      completeUrls = context.doesGenerateCompleteURLs();
    }

    if (!completeUrls) {
      context.generateCompleteURLs();
    }

    String url;
    try {
      ERXMutableURL mu = new ERXMutableURL();
      boolean customPath = (path != null && path.length() > 0);
      if (!customPath) {
        mu.setURL(context._directActionURL(directActionName, queryParameters, secureBool, 0, false));
        if (!includeSessionID) {
          mu.removeQueryParameter(WOApplication.application().sessionIdKey());
        }
      }
      else {
        if (secureBool) {
          mu.setProtocol("https");
        }
        else {
          mu.setProtocol("http");
        }
        mu.setHost(context.request()._serverName());
        mu.setPath(path + directActionName);
        mu.setQueryParameters(queryParameters);
        if (includeSessionID && context.session().storesIDsInURLs()) {
          mu.setQueryParameter(WOApplication.application().sessionIdKey(), context.session().sessionID());
        }
      }

      if (port != null) {
        mu.setPort(port);
      }

      if (host != null && host.length() > 0) {
        mu.setHost(host);
        if (mu.protocol() == null) {
          if (secureBool) {
            mu.setProtocol("https");
          }
          else {
            mu.setProtocol("http");
          }
        }
      }

      url = mu.toExternalForm();
    }
    catch (MalformedURLException e) {
      throw new RuntimeException("Failed to create url for direct action '" + directActionName + "'.", e);
    }
    finally {
      if (!completeUrls) {
        context.generateRelativeURLs();
      }
    }
    return url;
  }
 
  public String safeElementID() {
    return ERXStringUtilities.safeIdentifierName(elementID());
  }

  /**
   * Workaround for missing componentActionUrl(String) in 5.3.
   * @param context
   * @return ajax action URL
   * @deprecated use {@link #componentActionURL(String)} instead
   */
  @Deprecated
  public static String ajaxActionUrl(WOContext context) {
    String url = context.componentActionURL().replaceFirst( "/" + WOApplication.application().componentRequestHandlerKey() + "/", "/" +ERXApplication.erAjaxRequestHandlerKey() + "/");
    return url;
  }
 
  @Override
  protected String relativeURLWithRequestHandlerKey(String requestHandlerKey, String requestHandlerPath, String queryString) {
    String result = super.relativeURLWithRequestHandlerKey(requestHandlerKey, requestHandlerPath, queryString);
    if(IS_DEV && !WOApplication.application().isDirectConnectEnabled()) {
      String extension = "." + WOApplication.application().applicationExtension();
      String replace = extension + "/-" + WOApplication.application().port();
      if(!result.contains(replace) && result.contains(extension)) {
        result = result.replace(extension, replace);
      }
    }
    return result;
  }
}
TOP

Related Classes of er.extensions.appserver.ERXWOContext$Observer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.