gt:         path = rootDirectory.lookup(realPath);
context: /*
   * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
   *
   * This file is part of Resin(R) Open Source
   *
   * Each copy or derived work must preserve the copyright notice and this
   * notice unmodified.
   *
   * Resin Open Source is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * Resin Open Source is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
   * of NON-INFRINGEMENT.  See the GNU General Public License for more
   * details.
   *
   * You should have received a copy of the GNU General Public License
   * along with Resin Open Source; if not, write to the
   *
   *   Free Software Foundation, Inc.
   *   59 Temple Place, Suite 330
   *   Boston, MA 02111-1307  USA
   *
   * @author Scott Ferguson
   */
  
  package com.caucho.server.webapp;
  
  import com.caucho.VersionFactory;
  import com.caucho.config.Configurable;
  import com.caucho.util.L10N;
  import com.caucho.vfs.Path;
  
  import javax.servlet.*;
  import javax.servlet.descriptor.JspConfigDescriptor;
  import java.io.*;
  import java.net.URL;
  import java.net.URLConnection;
  import java.util.*;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  
  /**
   * Bare-bones servlet context implementation.
   */
  public class ServletContextImpl extends ServletContextCompat
    implements ServletContext
  {
    static final Logger log
      = Logger.getLogger(ServletContextImpl.class.getName());
    static final L10N L = new L10N(ServletContextImpl.class);
  
    private String _name;
    
    private HashMap<String,Object> _attributes = new HashMap<String,Object>();
  
    private ArrayList<ServletContextAttributeListener>
      _applicationAttributeListeners;
  
    private HashMap<String,String> _initParams = new HashMap<String,String>();
  
    public Path getRootDirectory()
    {
      throw new UnsupportedOperationException();
    }
    
    /**
     * Sets the servlet context name
     */
    public void setDisplayName(String name)
    {
      _name = name;
    }
  
    /**
     * Gets the servlet context name
     */
    public String getServletContextName()
    {
      return _name;
    }
  
    /**
     * Gets the servlet context name
     */
    public String getContextPath()
    {
      return _name;
    }
  
    /**
     * Adds the listener.
     */
    protected void addAttributeListener(ServletContextAttributeListener listener)
    {
      if (_applicationAttributeListeners == null)
        _applicationAttributeListeners = new ArrayList<ServletContextAttributeListener>();
      
      _applicationAttributeListeners.add(listener);
    }
  
    /**
     * Returns the server information
     */
    public String getServerInfo()
    {
      return "Resin/" + VersionFactory.getVersion();
    }
  
    /**
     * Returns the servlet major version
     */
    public int getMajorVersion()
    {
      return 3;
    }
  
    public int getEffectiveMajorVersion()
    {
      return 3;
    }
  
    /**
     * Returns the servlet minor version
     */
    public int getMinorVersion()
    {
      return 0;
    }
  
    public int getEffectiveMinorVersion()
    {
      return 0;
    }
  
    /**
     * Sets an init param
     */
    public boolean setInitParameter(String name, String value)
    {
  
      if (isActive())
        throw new IllegalStateException(L.l("setInitParameter must be called before the web-app has been initialized, because it's required by the servlet spec."));
  
      // server/1h12
      if (_initParams.containsKey(name))
        return false;
  
      _initParams.put(name, value);
  
      return true;
    }
  
    /**
     * Sets an init param
     */
    protected void setInitParam(String name, String value)
    {
      _initParams.put(name, value);
    }
  
    /**
     * Gets the init params
     */
    public String getInitParameter(String name)
    {
      return _initParams.get(name);
    }
  
    /**
     * Gets the init params
     */
    public Enumeration<String> getInitParameterNames()
    {
      return Collections.enumeration(_initParams.keySet());
    }
  
    /**
     * Returns the named attribute.
     */
    public Object getAttribute(String name)
    {
      synchronized (_attributes) {
        Object value = _attributes.get(name);
  
        return value;
      }
    }
  
    /**
     * Returns an enumeration of the attribute names.
     */
    public Enumeration<String> getAttributeNames()
    {
      synchronized (_attributes) {
        return Collections.enumeration(_attributes.keySet());
      }
    }
  
    /**
     * Sets an application attribute.
     *
     * @param name the name of the attribute
     * @param value the value of the attribute
     */
    public void setAttribute(String name, Object value)
    {
      Object oldValue;
      
      synchronized (_attributes) {
        if (value != null)
          oldValue = _attributes.put(name, value);
        else
          oldValue = _attributes.remove(name);
      }
      
      // Call any listeners
      if (_applicationAttributeListeners != null) {
        ServletContextAttributeEvent event;
  
        if (oldValue != null)
          event = new ServletContextAttributeEvent(this, name, oldValue);
        else
          event = new ServletContextAttributeEvent(this, name, value);
          
        for (int i = 0; i < _applicationAttributeListeners.size(); i++) {
          ServletContextAttributeListener listener;
  
          Object objListener = _applicationAttributeListeners.get(i);
          listener = (ServletContextAttributeListener) objListener;
  
          try {
            if (oldValue != null)
              listener.attributeReplaced(event);
            else
              listener.attributeAdded(event);
          } catch (Exception e) {
            log.log(Level.FINE, e.toString(), e);
          }
        }
      }
    }
  
    /**
     * Removes an attribute from the servlet context.
     *
     * @param name the name of the attribute to remove.
     */
    public void removeAttribute(String name)
    {
      Object oldValue;
      
      synchronized (_attributes) {
        oldValue = _attributes.remove(name);
      }
  
      // Call any listeners
      if (_applicationAttributeListeners != null) {
        ServletContextAttributeEvent event;
  
        event = new ServletContextAttributeEvent(this, name, oldValue);
          
        for (int i = 0; i < _applicationAttributeListeners.size(); i++) {
          ServletContextAttributeListener listener;
  
          Object objListener = _applicationAttributeListeners.get(i);
          listener = (ServletContextAttributeListener) objListener;
  
          try {
            listener.attributeRemoved(event);
          } catch (Throwable e) {
            log.log(Level.FINE, e.toString(), e);
          }
        }
      }
    }
  
    /**
     * Maps from a URI to a real path.
     */
    public String getRealPath(String uri)
    {
      return getRootDirectory().lookup("./" + uri).getNativePath();
    }
  
    /**
     * Returns a resource for the given uri.
     *
     * <p>XXX: jdk 1.1.x doesn't appear to allow creation of private
     * URL streams.
     */
    @Override
    public URL getResource(String name)
      throws java.net.MalformedURLException
    {
      if (! name.startsWith("/"))
        throw new java.net.MalformedURLException(name);
      
      String realPath = getRealPath(name);
  
      Path rootDirectory = getRootDirectory();
      Path path = rootDirectory.lookupNative(realPath);
  
      URL url = new URL("jndi:/server" + getContextPath() + name);
  
      if (path.exists() && name.startsWith("/resources/")) {
        return url;
      }
      else if (path.isFile()) {
        return url;
      }
      else if (getClassLoader().getResource("META-INF/resources/" + realPath) != null) {
        return url;
      }
      else if (path.exists()) {
        return new URL(path.getURL());
      }
  
      return null;
    }
  
    public URLConnection getResource(URL url)
      throws IOException
    {
      if (! "jndi".equals(url.getProtocol()))
        return null;
  
      //handle jndi:/server (single slash) parsing (gf)
      String file = url.getFile();
  
      if ("".equals(url.getHost()) && file.startsWith("/server")) {
        file = file.substring(7, file.length());
        
        if (file.startsWith(getContextPath()))
          file = file.substring(getContextPath().length());
        else {
          // server/102p
          int p = file.indexOf('/', 1);
          
          if (p > 0) {
            String contextPath = file.substring(0, p);
            WebApp webApp = (WebApp) getContext(contextPath);
            
            if (webApp != null)
              return webApp.getResource(url);
          }
        }
      }
  
      String realPath = getRealPath(file);
      Path rootDirectory = getRootDirectory();
      Path path = rootDirectory.lookup(realPath);
  
      if (path.exists())
        return new URL(path.getURL()).openConnection();
  
      int fileIdx;
  
      URLConnection connection = null;
  
      if (file.length() > 1 && (fileIdx = file.indexOf("/", 1)) > -1) {
        String context = file.substring(0, file.indexOf("/", 1));
  
        if (context.equals(getContextPath())) {// disable cross-context lookup
  
          file = file.substring(fileIdx, file.length());
          realPath = getRealPath(file);
  