Package org.exist.xquery

Source Code of org.exist.xquery.ModuleContext

/*
* eXist Open Source Native XML Database
* Copyright (C) 2004-2007 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*  $Id$
*/
package org.exist.xquery;

import org.exist.debuggee.DebuggeeJoint;
import org.exist.dom.DocumentSet;
import org.exist.dom.QName;
import org.exist.memtree.MemTreeBuilder;
import org.exist.storage.UpdateListener;
import org.exist.util.FileUtils;
import org.exist.xmldb.XmldbURI;
import org.exist.xquery.functions.response.ResponseModule;
import org.exist.xquery.value.AnyURIValue;
import org.exist.xquery.value.BinaryValue;
import org.exist.xquery.value.Sequence;

import javax.xml.datatype.XMLGregorianCalendar;

import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.exist.xquery.value.StringValue;
import org.exist.xquery.value.ValueSequence;


/**
* Subclass of {@link org.exist.xquery.XQueryContext} for
* imported modules.
*
* @author wolf
*/
public class ModuleContext extends XQueryContext {

  private XQueryContext parentContext;
    private String modulePrefix;
    private String moduleNamespace;
    private final String location;

  /**
   * @param parentContext
   */
  public ModuleContext(XQueryContext parentContext, String modulePrefix, String moduleNamespace, String location) {
    super(parentContext.getAccessContext());
        this.moduleNamespace = moduleNamespace;
        this.modulePrefix = modulePrefix;
        this.location = location;
        setParentContext(parentContext);
    loadDefaults(getBroker().getConfiguration());
    this.profiler = new Profiler( getBroker().getBrokerPool() );
    }
 
  String getLocation() {
      return location;
  }
  
  String getModuleNamespace() {
    return moduleNamespace;
  }

    public void setModuleNamespace(String prefix, String namespaceURI) {
        this.modulePrefix = prefix;
        this.moduleNamespace = namespaceURI;
    }

  void setModulesChanged() {
    parentContext.setModulesChanged();
  }
 
  private void setParentContext(XQueryContext parentContext) {
        this.parentContext = parentContext;
        //XXX: raise error on null!
        if (parentContext != null) {
          this.db = parentContext.db;
        baseURI = parentContext.baseURI;
        try {
            if (location.startsWith(XmldbURI.XMLDB_URI_PREFIX) ||
                    (location.indexOf(':') < 0 &&
                     parentContext.getModuleLoadPath().startsWith(XmldbURI.XMLDB_URI_PREFIX))) {
                // use XmldbURI resolution - unfortunately these are not interpretable as URIs
                // because the scheme xmldb:exist: is not a valid URI scheme
                    final XmldbURI locationUri = XmldbURI.xmldbUriFor(FileUtils.dirname(location));
                    if (".".equals(parentContext.getModuleLoadPath()))
                        {setModuleLoadPath(locationUri.toString());}
                    else {
                      try {
                          final XmldbURI parentLoadUri = XmldbURI.xmldbUriFor(parentContext.getModuleLoadPath());
                          final XmldbURI moduleLoadUri = parentLoadUri.resolveCollectionPath(locationUri);
                          setModuleLoadPath(moduleLoadUri.toString());
                      } catch (final URISyntaxException e) {
                            setModuleLoadPath(locationUri.toString());
            }
                    }
            } else {
                    String dir = FileUtils.dirname(location);
                    if (dir.matches("^[a-z]+:.*")) {
                        moduleLoadPath = dir;
                    } else if (".".equals(parentContext.moduleLoadPath)) {
                    if (! ".".equals(dir)) {
                        if (dir.startsWith("/")) {
                            setModuleLoadPath("." + dir);
                                    } else {
                            setModuleLoadPath("./" + dir);
                                    }
                    }
                } else {
                    if (dir.startsWith("/")) {
                        setModuleLoadPath(dir);
                                } else {
                        setModuleLoadPath(FileUtils.addPaths(parentContext.getModuleLoadPath(), dir));
                                }
                }
            }
        } catch (final URISyntaxException e) {
                e.printStackTrace();
            }
        }
  }

    public void setModule(String namespaceURI, Module module) {
        if (module == null) {
            modules.remove(namespaceURI);   // unbind the module
        } else {
            modules.put(namespaceURI, module);
        }
        setRootModule(namespaceURI, module);
    }

    XQueryContext getParentContext() {
    return parentContext;
  }

    public boolean hasParent() {
        return true;
    }

    public XQueryContext getRootContext() {
        return parentContext.getRootContext();
    }

    public void updateContext(XQueryContext from) {
        if (from.hasParent()) {
            // TODO: shouldn't this call setParentContext ? - sokolov
            this.parentContext = ((ModuleContext)from).parentContext;
        }
       
        //workaround for shared context issue, remove after fix
        try {
          final Variable var = from.getRootContext().resolveVariable(ResponseModule.PREFIX + ":response");
          if (var != null)
            {declareVariable(
          ResponseModule.PREFIX + ":response",
          var.getValue()
        );}
    } catch (final Exception e) {
      //ignore if not set
    }

        setModule(
        ResponseModule.NAMESPACE_URI,
        from.getRootContext().getModule(ResponseModule.NAMESPACE_URI)
      );
    }

    public XQueryContext copyContext() {
        final ModuleContext ctx = new ModuleContext(parentContext, modulePrefix, moduleNamespace, location);
        copyFields(ctx);
        try {
            ctx.declareNamespace(modulePrefix, moduleNamespace);
        } catch (final XPathException e) {
            e.printStackTrace();
        }
        return ctx;
    }

  public void addDynamicOption(String qnameString, String contents) throws XPathException
  {
    parentContext.addDynamicOption(qnameString, contents);
  }

    /* (non-Javadoc)
   * @see org.exist.xquery.XQueryContext#getStaticallyKnownDocuments()
   */
  public DocumentSet getStaticallyKnownDocuments() throws XPathException {
    return parentContext.getStaticallyKnownDocuments();
  }
 
  /* (non-Javadoc)
   * @see org.exist.xquery.XQueryContext#getModule(java.lang.String)
   */
  public Module getModule(String namespaceURI) {
    Module module = super.getModule(namespaceURI);
    // TODO: I don't think modules should be able to access their parent context's modules,
    // since that breaks lexical scoping.  However, it seems that some eXist modules rely on
    // this so let's leave it for now.  (pkaminsk2)
    if(module == null)
      {module = parentContext.getModule(namespaceURI);}
    return module;
  }
 
  protected void setRootModule(String namespaceURI, Module module) {
    allModules.put(namespaceURI, module);
    parentContext.setRootModule(namespaceURI, module);
  }

  public Iterator<Module> getRootModules() {
    return parentContext.getRootModules();
  }
 
  public Iterator<Module> getAllModules() {
    return allModules.values().iterator();
  }
 
  public Module getRootModule(String namespaceURI) {
    return parentContext.getRootModule(namespaceURI);
  }
 
    /**
     * Overwritten method: the module will be loaded by the parent context, but
     * we need to declare its namespace in the module context.
     */
    public Module loadBuiltInModule(String namespaceURI, String moduleClass) {
        Module module = getModule(namespaceURI);
        if (module == null)
            {module = initBuiltInModule(namespaceURI, moduleClass);}
        if (module != null) {
            try {
              final String defaultPrefix = module.getDefaultPrefix();
              if (!"".equals(defaultPrefix))
                {declareNamespace(defaultPrefix, module.getNamespaceURI());}
            } catch (final XPathException e) {
                LOG.warn("error while loading builtin module class " + moduleClass, e);
            }
        }
        return module;
    }

    public void updateModuleRefs(XQueryContext rootContext) {
        HashMap<String, Module> newModules = new HashMap<String, Module>(modules.size());
        for (Module module : modules.values()) {
            if (module.isInternalModule()) {
                Module updated = rootContext.getModule(module.getNamespaceURI());
                if (updated == null)
                    {updated = module;}
                newModules.put(module.getNamespaceURI(), updated);
            } else
                {newModules.put(module.getNamespaceURI(), module);}
        }
        modules = newModules;
    }
   
    @Override
    final protected XPathException moduleLoadException(final String message, final String moduleLocation) throws XPathException {
       return moduleLoadException(message, moduleLocation, null);
    }
   
    @Override
    final protected XPathException moduleLoadException(final String message, final String moduleLocation, final Exception e) throws XPathException {
        //final String dependantModule = XmldbURI.create(moduleLoadPath).append(location).toString();
        String dependantModule;
        try {
            dependantModule = XmldbURI.create(getParentContext().getModuleLoadPath(), false).append(location).toString();
        } catch (final Exception ex) {
            dependantModule = location;
        }
       
        if(e == null) {
            return new XPathException(ErrorCodes.XQST0059, message, new ValueSequence(new StringValue(moduleLocation), new StringValue(dependantModule)));
        } else {
            return new XPathException(ErrorCodes.XQST0059, message, new ValueSequence(new StringValue(moduleLocation), new StringValue(dependantModule)), e);
        }
    }

  /* (non-Javadoc)
   * @see org.exist.xquery.XQueryContext#getWatchDog()
   */
  public XQueryWatchDog getWatchDog() {
    return parentContext.getWatchDog();
  }

    public Profiler getProfiler() {
        return parentContext.getProfiler();
    }

    /* (non-Javadoc)
   * @see org.exist.xquery.XQueryContext#getCalendar()
   */
    public XMLGregorianCalendar getCalendar(){
        return parentContext.getCalendar();
    }

    /* (non-Javadoc)
   * @see org.exist.xquery.XQueryContext#getBaseURI()
   */
  public AnyURIValue getBaseURI() throws XPathException {
    return parentContext.getBaseURI();
  }
   
    public void setBaseURI(AnyURIValue uri) {
        parentContext.setBaseURI(uri);
    }
   

    /**
     * Delegate to parent context
     *
     * @see org.exist.xquery.XQueryContext#setXQueryContextVar(String, Object)
     */
    public void setXQueryContextVar(String name, Object XQvar)
    {
      parentContext.setXQueryContextVar(name, XQvar);
    }

    /**
     * Delegate to parent context
     *
     * @see org.exist.xquery.XQueryContext#getXQueryContextVar(String)
     */
    public Object getXQueryContextVar(String name)
    {
      return(parentContext.getXQueryContextVar(name));
    }
   
//    /* (non-Javadoc)
//     * @see org.exist.xquery.XQueryContext#getBroker()
//     */
//    public DBBroker getBroker() {
//        return parentContext.getBroker();
//    }
   
    /* (non-Javadoc)
   * @see org.exist.xquery.XQueryContext#getDocumentBuilder()
   */
  public MemTreeBuilder getDocumentBuilder() {
    return parentContext.getDocumentBuilder();
  }

    public MemTreeBuilder getDocumentBuilder(boolean explicitCreation) {
        return parentContext.getDocumentBuilder(explicitCreation);
    }
   
    /* (non-Javadoc)
   * @see org.exist.xquery.XQueryContext#pushDocumentContext()
   */
  public void pushDocumentContext() {
    parentContext.pushDocumentContext();
  }

    public LocalVariable markLocalVariables(boolean newContext) {
        return parentContext.markLocalVariables(newContext);
    }

    public void popLocalVariables(LocalVariable var) {
        parentContext.popLocalVariables(var);
    }

    public void popLocalVariables(LocalVariable var, Sequence resultSequence) {
        parentContext.popLocalVariables(var, resultSequence);
    }

    public LocalVariable declareVariableBinding(LocalVariable var) throws XPathException {
        return parentContext.declareVariableBinding(var);
    }

    protected Variable resolveLocalVariable(QName qname) throws XPathException {
        return parentContext.resolveLocalVariable(qname);
    }

    /**
     * Try to resolve a variable.
     *
     * @param qname the qualified name of the variable
     * @return the declared Variable object
     * @throws XPathException if the variable is unknown
     */
    public Variable resolveVariable(QName qname) throws XPathException {
        Variable var;

        // check if the variable is declared local
        var = resolveLocalVariable(qname);

        // check if the variable is declared in a module
        if (var == null) {
            Module module;
            if (moduleNamespace.equals(qname.getNamespaceURI())) {
                module = getRootModule(moduleNamespace);
            } else {
                module = getModule(qname.getNamespaceURI());
            }
            if(module != null) {
                var = module.resolveVariable(qname);
            }
        }

        // check if the variable is declared global
        if (var == null)
            {var = globalVariables.get(qname);}
        //if (var == null)
        //  throw new XPathException("variable $" + qname + " is not bound");
        return var;
    }

    public Map<QName, Variable> getVariables() {
      return parentContext.getVariables();
    }

    public Map<QName, Variable> getLocalVariables() {
      return parentContext.getLocalVariables();
    }

    public List<Variable> getLocalStack() {
      return parentContext.getLocalStack();
    }
   
    public Map<QName, Variable> getGlobalVariables() {
      return parentContext.getGlobalVariables();
    }

    public void restoreStack(List<Variable> stack) throws XPathException {
      parentContext.restoreStack(stack);
    }
   
    public int getCurrentStackSize() {
        return parentContext.getCurrentStackSize();
    }

    /* (non-Javadoc)
   * @see org.exist.xquery.XQueryContext#popDocumentContext()
   */
  public void popDocumentContext() {
    parentContext.popDocumentContext();
  }

    /**
     * First checks the parent context for in-scope namespaces,
     * then the module's static context.
     *
     * @param prefix the prefix to look up
     * @return the namespace currently mapped to that prefix
     */
    public String getURIForPrefix(String prefix) {
        String uri = getInScopeNamespace(prefix);
        if (uri != null)
            {return uri;}
        //TODO : test NS inheritance
        uri = getInheritedNamespace(prefix);
        if (uri != null)
            {return uri;}
        // Check global declarations
        return staticNamespaces.get(prefix);
    }

    /**
     * First checks the parent context for in-scope namespaces,
     * then the module's static context.
     *
     * @param uri the URI to look up
     * @return a prefix for the URI
     */
    public String getPrefixForURI(String uri) {
        String prefix = getInScopePrefix(uri);
    if (prefix != null)
      {return prefix;}
    //TODO : test the NS inheritance
        prefix = getInheritedPrefix(uri);
    if (prefix != null)
      {return prefix;}
    return staticPrefixes.get(uri);
    }

    public String getInScopeNamespace(String prefix) {
        return parentContext.getInScopeNamespace(prefix);
    }

    public String getInScopePrefix(String uri) {
        return parentContext.getInScopePrefix(uri);
    }

    public String getInheritedNamespace(String prefix) {
        return parentContext.getInheritedNamespace(prefix);
    }

    public String getInheritedPrefix(String uri) {
        return parentContext.getInheritedPrefix(uri);
    }

    public void declareInScopeNamespace(String prefix, String uri) {
        parentContext.declareInScopeNamespace(prefix, uri);
    }

    public void pushInScopeNamespaces(boolean inherit) {
        parentContext.pushInScopeNamespaces(inherit);
    }

    public void pushInScopeNamespaces() {
        parentContext.pushInScopeNamespaces();
    }

    public void popInScopeNamespaces() {
        parentContext.popInScopeNamespaces();
    }

    public void registerUpdateListener(UpdateListener listener) {
    parentContext.registerUpdateListener(listener);
  }
 
  protected void clearUpdateListeners() {
    // will be cleared by the parent context
  }

  public DebuggeeJoint getDebuggeeJoint() {
    return parentContext.getDebuggeeJoint();
  }
 
  public boolean isDebugMode() {
    return parentContext.isDebugMode();
  }

    public void expressionStart(Expression expr) throws TerminatedException {
         parentContext.expressionStart(expr);
    }

    public void expressionEnd(Expression expr) {
         parentContext.expressionEnd(expr);
    }

    public void stackEnter(Expression expr) throws TerminatedException {
         parentContext.stackEnter(expr);
    }

    public void stackLeave(Expression expr) {
         parentContext.stackLeave(expr);
    }

    @Override
    public void registerBinaryValueInstance(BinaryValue binaryValue) {
        parentContext.registerBinaryValueInstance(binaryValue);
    }

    @Override
    public void saveState() {
        super.saveState();
        parentContext.saveState();
    }
}
TOP

Related Classes of org.exist.xquery.ModuleContext

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.