Package org.olat.core.util.servlets

Source Code of org.olat.core.util.servlets.VFSDirContext$StringManager

/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) 1999-2006 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/

package org.olat.core.util.servlets;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.OperationNotSupportedException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.apache.naming.resources.BaseDirContext;
import org.apache.naming.resources.Resource;
import org.apache.naming.resources.ResourceAttributes;
import org.olat.core.commons.modules.bc.meta.MetaInfo;
import org.olat.core.commons.modules.bc.meta.MetaInfoHelper;
import org.olat.core.commons.modules.bc.meta.tagged.MetaTagged;
import org.olat.core.id.Identity;
import org.olat.core.util.FileUtils;
import org.olat.core.util.UserSession;
import org.olat.core.util.vfs.Quota;
import org.olat.core.util.vfs.VFSConstants;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.core.util.vfs.VFSItem;
import org.olat.core.util.vfs.VFSLeaf;
import org.olat.core.util.vfs.VFSManager;
import org.olat.core.util.vfs.VFSStatus;
import org.olat.core.util.vfs.version.Versionable;
import org.olat.core.util.vfs.version.VersionsManager;


/**
* Filesystem Directory Context implementation helper class.
*
* @author Remy Maucherat
*/

public class VFSDirContext extends BaseDirContext {

  //private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(VFSDirContext.class);

  // -------------------------------------------------------------- Constants

  /**
   * The string manager for this package.
   */
  private StringManager smgr = new StringManager();

  /**
   * The descriptive information string for this implementation.
   */
  public static int bufferSize = 2048;
 
 
  private Identity identity;
  private UserSession userSession;

  // ----------------------------------------------------------- Constructors

  /**
   * Builds a file directory context using the given environment.
   */
  public VFSDirContext() {
    super();
  }

  /**
   * Builds a file directory context using the given environment.
   */
  public VFSDirContext(Hashtable env) {
    super(env);
  }

  // ----------------------------------------------------- Instance Variables

  /**
   * The document base directory.
   */
  protected VFSItem base = null;

  /**
   * Absolute normalized filename of the base.
   */
  protected String absoluteBase = null;

  /**
   * Case sensitivity.
   */
  protected boolean caseSensitive = true;

  /**
   * Allow linking.
   */
  protected boolean allowLinking = false;

  // ------------------------------------------------------------- Properties

 
 
  /**
   * Set the document root.
   *
   * @param vfsItem The new document root
   * @exception IllegalArgumentException if the specified value is not supported
   *              by this implementation
   */
  public void setVirtualDocBase(VFSItem vfsItem) {
      base = vfsItem;
  }

  public Identity getIdentity() {
    return identity;
  }

  public void setIdentity(Identity identity) {
    this.identity = identity;
  }

  public UserSession getUserSession() {
    return userSession;
  }

  public void setUserSession(UserSession userSession) {
    this.userSession = userSession;
  }

  public VFSItem getVirtualDocBase() {
    return base;
  }
 
  /**
   * Set the document root.
   *
   * @param docBase The new document root
   * @exception IllegalArgumentException if the specified value is not supported
   *              by this implementation
   * @exception IllegalArgumentException if this would create a malformed URL
   */
  public void setDocBase(String docBase) {

    // disabled for VFSDirContext implementation...
    throw new IllegalArgumentException("setDocBase(String) not supported by VFSDirCOntext.");
  }

  /**
   * Set case sensitivity.
   */
  public void setCaseSensitive(boolean caseSensitive) {
    this.caseSensitive = caseSensitive;
  }

  /**
   * Is case sensitive ?
   */
  public boolean isCaseSensitive() {
    return caseSensitive;
  }

  /**
   * Set allow linking.
   */
  public void setAllowLinking(boolean allowLinking) {
    this.allowLinking = allowLinking;
  }

  /**
   * Is linking allowed.
   */
  public boolean getAllowLinking() {
    return allowLinking;
  }

  public void setBuffer(int bytes) {
    bufferSize = bytes;
  }
  // --------------------------------------------------------- Public Methods

  /**
   * Release any resources allocated for this directory context.
   */
  public void release() {

    caseSensitive = true;
    allowLinking = false;
    absoluteBase = null;
    base = null;
    super.release();

  }

  // -------------------------------------------------------- Context Methods

  /**
   * Retrieves the named object.
   *
   * @param name the name of the object to look up
   * @return the object bound to name
   * @exception NamingException if a naming exception is encountered
   */
  public Object lookup(String name) throws NamingException {
   
    VFSItem item = resolveFile(name);
    if (item == null) throw new NamingException(smgr.getString("resources.notFound", name));

    if (item instanceof VFSContainer) {
      VFSDirContext tempContext = new VFSDirContext(env);
      tempContext.setVirtualDocBase(item);
      return tempContext;
    } else {
      return new VFSResource(item);
    }
  }

  /**
   * Check if resource can be copied (delegation to VFS item)
   * @param name
   * @return true: can copy; false: can not copy
   */
  public boolean canCopy(String name) {
    VFSItem item = resolveFile(name);
    if (item != null && VFSConstants.YES.equals(item.canCopy())) return true;
    else return false;
  }

  /**
   * Check if resource can be written (delegation to VFS item)
   * @param name
   * @return true: can write; false: can not write
   */
  public boolean canWrite(String name) {
    // resolve item if it already exists
    VFSItem item = resolveFile(name);
    if (item == null) {
      // try to resolve parent in case the item does not yet exist
      int lastSlash = name.lastIndexOf("/");
      if (lastSlash > 0) {
        String containerName = name.substring(0, lastSlash);
        item = resolveFile(containerName);
      }
    }
    if (item == null) return false;
   
    VFSStatus status;
    if (item instanceof VFSContainer) {
      status = item.canWrite();
    } else {
      // read/write is not defined on item level, only on directory level
      status = item.getParentContainer().canWrite();
    }
    return VFSConstants.YES.equals(status);
  }

  /**
   * Check if resource can be deleted (delegation to VFS item)
   * @param name
   * @return true: can delete; false: can not delete
   */
  public boolean canDelete(String name) {
    VFSItem item = resolveFile(name);
    if (item != null && VFSConstants.YES.equals(item.canDelete())) {
      return !MetaInfoHelper.isLocked(item, userSession);
    }
    else return false;
  }

  /**
   * Check if resource can be renamed (delegation to VFS item)
   * @param name
   * @return true: can rename; false: can not rename
   */
  public boolean canRename(String name) {
    VFSItem item = resolveFile(name);
    if (item != null && VFSConstants.YES.equals(item.canRename())) {
      return !MetaInfoHelper.isLocked(item, userSession);
    }
    else return false;
 
 
  /**
   * Unbinds the named object. Removes the terminal atomic name in name from the
   * target context--that named by all but the terminal atomic part of name.
   * <p>
   * This method is idempotent. It succeeds even if the terminal atomic name is
   * not bound in the target context, but throws NameNotFoundException if any of
   * the intermediate contexts do not exist.
   *
   * @param name the name to bind; may not be empty
   * @exception NameNotFoundException if an intermediate context does not exist
   * @exception NamingException if a naming exception is encountered
   */
  public void unbind(String name) throws NamingException {

    VFSItem file = resolveFile(name);
    if (file == null) throw new NamingException(smgr.getString("resources.notFound", name));

    VFSStatus status = file.delete();
    if (status == VFSConstants.NO)
      throw new NamingException(smgr.getString("resources.unbindFailed", name));
  }

  /**
   * Binds a new name to the object bound to an old name, and unbinds the old
   * name. Both names are relative to this context. Any attributes associated
   * with the old name become associated with the new name. Intermediate
   * contexts of the old name are not changed.
   *
   * @param oldName the name of the existing binding; may not be empty
   * @param newName the name of the new binding; may not be empty
   * @exception NameAlreadyBoundException if newName is already bound
   * @exception NamingException if a naming exception is encountered
   */
  public void rename(String oldName, String newName) throws NamingException {

    VFSItem oldFile = resolveFile(oldName);
    if (oldFile == null) throw new NamingException(smgr.getString("resources.notFound", oldName));

    VFSItem newFile = resolveFile(newName);
    if (newFile != null)
      throw new NameAlreadyBoundException();
   
    VFSStatus status = oldFile.rename(newName);
    if (status == VFSConstants.NO)
      throw new NameAlreadyBoundException();
  }

  /**
   * Enumerates the names bound in the named context, along with the class names
   * of objects bound to them. The contents of any subcontexts are not included.
   * <p>
   * If a binding is added to or removed from this context, its effect on an
   * enumeration previously returned is undefined.
   *
   * @param name the name of the context to list
   * @return an enumeration of the names and class names of the bindings in this
   *         context. Each element of the enumeration is of type NameClassPair.
   * @exception NamingException if a naming exception is encountered
   */
  public NamingEnumeration<NameClassPair> list(String name) throws NamingException {

    VFSItem file = resolveFile(name);
    if (file == null) throw new NamingException(smgr.getString("resources.notFound", name));
    return new NamingContextEnumeration(list(file).iterator());

  }

  /**
   * Enumerates the names bound in the named context, along with the objects
   * bound to them. The contents of any subcontexts are not included.
   * <p>
   * If a binding is added to or removed from this context, its effect on an
   * enumeration previously returned is undefined.
   *
   * @param name the name of the context to list
   * @return an enumeration of the bindings in this context. Each element of the
   *         enumeration is of type Binding.
   * @exception NamingException if a naming exception is encountered
   */
  public NamingEnumeration<Binding> listBindings(String name) throws NamingException {
    return new NamingContextEnumeration2(list(name));
  }

  /**
   * Destroys the named context and removes it from the namespace. Any
   * attributes associated with the name are also removed. Intermediate contexts
   * are not destroyed.
   * <p>
   * This method is idempotent. It succeeds even if the terminal atomic name is
   * not bound in the target context, but throws NameNotFoundException if any of
   * the intermediate contexts do not exist. In a federated naming system, a
   * context from one naming system may be bound to a name in another. One can
   * subsequently look up and perform operations on the foreign context using a
   * composite name. However, an attempt destroy the context using this
   * composite name will fail with NotContextException, because the foreign
   * context is not a "subcontext" of the context in which it is bound. Instead,
   * use unbind() to remove the binding of the foreign context. Destroying the
   * foreign context requires that the destroySubcontext() be performed on a
   * context from the foreign context's "native" naming system.
   *
   * @param name the name of the context to be destroyed; may not be empty
   * @exception NameNotFoundException if an intermediate context does not exist
   * @exception NotContextException if the name is bound but does not name a
   *              context, or does not name a context of the appropriate type
   */
  public void destroySubcontext(String name) throws NamingException {
    unbind(name);
  }

  /**
   * Retrieves the named object, following links except for the terminal atomic
   * component of the name. If the object bound to name is not a link, returns
   * the object itself.
   *
   * @param name the name of the object to look up
   * @return the object bound to name, not following the terminal link (if any).
   * @exception NamingException if a naming exception is encountered
   */
  public Object lookupLink(String name) throws NamingException {
    // Note : Links are not supported
    return lookup(name);
  }

  /**
   * Retrieves the full name of this context within its own namespace.
   * <p>
   * Many naming services have a notion of a "full name" for objects in their
   * respective namespaces. For example, an LDAP entry has a distinguished name,
   * and a DNS record has a fully qualified name. This method allows the client
   * application to retrieve this name. The string returned by this method is
   * not a JNDI composite name and should not be passed directly to context
   * methods. In naming systems for which the notion of full name does not make
   * sense, OperationNotSupportedException is thrown.
   *
   * @return this context's name in its own namespace; never null
   * @exception OperationNotSupportedException if the naming system does not
   *              have the notion of a full name
   * @exception NamingException if a naming exception is encountered
   */
  public String getNameInNamespace() {
    return docBase;
  }

  // ----------------------------------------------------- DirContext Methods

  /**
   * Retrieves selected attributes associated with a named object. See the class
   * description regarding attribute models, attribute type names, and
   * operational attributes.
   *
   * @return the requested attributes; never null
   * @param name the name of the object from which to retrieve attributes
   * @param attrIds the identifiers of the attributes to retrieve. null
   *          indicates that all attributes should be retrieved; an empty array
   *          indicates that none should be retrieved
   * @exception NamingException if a naming exception is encountered
   */
  public Attributes getAttributes(String name, String[] attrIds) throws NamingException {

    // Building attribute list
    VFSItem file = resolveFile(name);
    if (file == null) throw new NamingException(smgr.getString("resources.notFound", name));
    return new VFSResourceAttributes(file);

  }

  /**
   * Modifies the attributes associated with a named object. The order of the
   * modifications is not specified. Where possible, the modifications are
   * performed atomically.
   *
   * @param name the name of the object whose attributes will be updated
   * @param mod_op the modification operation, one of: ADD_ATTRIBUTE,
   *          REPLACE_ATTRIBUTE, REMOVE_ATTRIBUTE
   * @param attrs the attributes to be used for the modification; may not be
   *          null
   * @exception AttributeModificationException if the modification cannot be
   *              completed successfully
   * @exception NamingException if a naming exception is encountered
   */
  public void modifyAttributes(String name, int mod_op, Attributes attrs) {
    // not implemented
  }

  /**
   * Modifies the attributes associated with a named object using an an ordered
   * list of modifications. The modifications are performed in the order
   * specified. Each modification specifies a modification operation code and an
   * attribute on which to operate. Where possible, the modifications are
   * performed atomically.
   *
   * @param name the name of the object whose attributes will be updated
   * @param mods an ordered sequence of modifications to be performed; may not
   *          be null
   * @exception AttributeModificationException if the modification cannot be
   *              completed successfully
   * @exception NamingException if a naming exception is encountered
   */
  public void modifyAttributes(String name, ModificationItem[] mods) {
    // not implemented
  }

  /**
   * @see javax.naming.Context#bind(java.lang.String, java.lang.Object)
   */
  public void bind(String name, Object obj) throws NamingException {
    bind(name, obj, null);
  }
 
  /**
   * Binds a name to an object, along with associated attributes. If attrs is
   * null, the resulting binding will have the attributes associated with obj if
   * obj is a DirContext, and no attributes otherwise. If attrs is non-null, the
   * resulting binding will have attrs as its attributes; any attributes
   * associated with obj are ignored.
   *
   * @param name the name to bind; may not be empty
   * @param obj the object to bind; possibly null
   * @param attrs the attributes to associate with the binding
   * @exception NameAlreadyBoundException if name is already bound
   * @exception InvalidAttributesException if some "mandatory" attributes of the
   *              binding are not supplied
   * @exception NamingException if a naming exception is encountered
   */
  public void bind(String name, Object obj, Attributes attrs) throws NamingException {

    // Note: No custom attributes allowed
    VFSItem file = resolveFile(name);
    if (file != null) throw new NameAlreadyBoundException(smgr.getString("resources.alreadyBound", name));
   
    int lastSlash = name.lastIndexOf('/');
    if (lastSlash == -1) throw new NamingException();
    String parent = name.substring(0, lastSlash);
    VFSItem folder = resolveFile(parent);
    if (folder == null || (!(folder instanceof VFSContainer)))
      throw new NamingException(smgr.getString("resources.bindFailed", name));
    String newName = name.substring(lastSlash + 1);
    VFSLeaf childLeaf = ((VFSContainer)folder).createChildLeaf(newName);
    if (childLeaf == null)
      throw new NamingException(smgr.getString("resources.bindFailed", name));
    copyVFS(childLeaf, name, obj, attrs);
    if(childLeaf instanceof MetaTagged) {
      MetaInfo infos = ((MetaTagged)childLeaf).getMetaInfo();
      if(infos != null && infos.getAuthorIdentity() == null) {
        infos.setAuthor(userSession.getIdentity().getName());
        infos.write();
      }
    }
   
    //used by move operations
    if(obj instanceof VFSResource) {
      VFSResource vfsResource = (VFSResource)obj;
      if(vfsResource.vfsItem instanceof Versionable
          && ((Versionable)vfsResource.vfsItem).getVersions().isVersioned()) {
        Versionable currentVersion = (Versionable)vfsResource.vfsItem;
        VersionsManager.getInstance().move(currentVersion, childLeaf.getParentContainer());
      }
    }
  }

  /**
   * Binds a name to an object, along with associated attributes, overwriting
   * any existing binding. If attrs is null and obj is a DirContext, the
   * attributes from obj are used. If attrs is null and obj is not a DirContext,
   * any existing attributes associated with the object already bound in the
   * directory remain unchanged. If attrs is non-null, any existing attributes
   * associated with the object already bound in the directory are removed and
   * attrs is associated with the named object. If obj is a DirContext and attrs
   * is non-null, the attributes of obj are ignored.
   *
   * @param name the name to bind; may not be empty
   * @param obj the object to bind; possibly null
   * @param attrs the attributes to associate with the binding
   * @exception InvalidAttributesException if some "mandatory" attributes of the
   *              binding are not supplied
   * @exception NamingException if a naming exception is encountered
   */
  public void rebind(String name, Object obj, Attributes attrs) throws NamingException {

    // Note: No custom attributes allowed
    // Check obj type

    VFSItem vfsItem = resolveFile(name);
    if (vfsItem == null || (!(vfsItem instanceof VFSLeaf))) throw new NamingException(smgr.getString("resources.bindFailed", name));
    VFSLeaf file = (VFSLeaf)vfsItem;
   
    if(file instanceof Versionable && ((Versionable)file).getVersions().isVersioned()) {
      VersionsManager.getInstance().addToRevisions((Versionable)file, identity, "");
    }
   
    copyVFS(file, name, obj, attrs);
    if(file instanceof MetaTagged) {
      MetaInfo infos = ((MetaTagged)file).getMetaInfo();
      if(infos != null && infos.getAuthorIdentity() == null) {
        infos.setAuthor(userSession.getIdentity().getName());
        infos.write();
      }
    }
   
    //used by move operations
    if(obj instanceof VFSResource) {
      VFSResource vfsResource = (VFSResource)obj;
      if(vfsResource.vfsItem instanceof Versionable
          && ((Versionable)vfsResource.vfsItem).getVersions().isVersioned()) {
        Versionable currentVersion = (Versionable)vfsResource.vfsItem;
        VersionsManager.getInstance().move(currentVersion, file.getParentContainer());
      }
    }
  }
 
  private void copyVFS(VFSLeaf file, String name, Object obj, Attributes attrs) throws NamingException {
    InputStream is = null;
    if (obj instanceof Resource) {
      try {
        is = ((Resource) obj).streamContent();
      } catch (IOException e) {
        // ignore, check further
      }
    } else if (obj instanceof InputStream) {
      is = (InputStream) obj;
    } else if (obj instanceof DirContext) {
      createSubcontext(name, attrs);
      return;
    }
    if (is == null) throw new NamingException(smgr.getString("resources.bindFailed", name));

    // Try to get Quota
    long quotaLeft = -1;
    boolean withQuotaCheck = false;
    VFSContainer parentContainer = file.getParentContainer();
    if (parentContainer != null) {
      quotaLeft = VFSManager.getQuotaLeftKB(parentContainer);
      if (quotaLeft != Quota.UNLIMITED) {
        quotaLeft = quotaLeft * 1024; // convert from kB
        withQuotaCheck = true;
      } else {
        withQuotaCheck = false;
      }
    }
    // Open os
    OutputStream os = null;
    byte buffer[] = new byte[bufferSize];
    int len = -1;
    try {
      os = file.getOutputStream(false);
      while (true) {
        len = is.read(buffer);
        if (len == -1) break;
        if (withQuotaCheck) {
          // re-calculate quota and check
          quotaLeft = quotaLeft - len;
          if (quotaLeft < 0) throw new NamingException("Quota exceeded.");
        }
        os.write(buffer, 0, len);
      }
    } catch (Exception e) {
      FileUtils.closeSafely(os); // close first, in order to be able to delete any reamins of the file
      file.delete();
      if (e instanceof NamingException) throw (NamingException)e;
      throw new NamingException(smgr.getString("resources.bindFailed"));
    } finally {
      FileUtils.closeSafely(os);
      FileUtils.closeSafely(is);
    }
  }

  /**
   * @see javax.naming.Context#createSubcontext(java.lang.String)
   */
  public Context createSubcontext(String name) throws NamingException {
    return createSubcontext(name, null);
  }
 
  /**
   * Creates and binds a new context, along with associated attributes. This
   * method creates a new subcontext with the given name, binds it in the target
   * context (that named by all but terminal atomic component of the name), and
   * associates the supplied attributes with the newly created object. All
   * intermediate and target contexts must already exist. If attrs is null, this
   * method is equivalent to Context.createSubcontext().
   *
   * @param name the name of the context to create; may not be empty
   * @param attrs the attributes to associate with the newly created context
   * @return the newly created context
   * @exception NameAlreadyBoundException if the name is already bound
   * @exception InvalidAttributesException if attrs does not contain all the
   *              mandatory attributes required for creation
   * @exception NamingException if a naming exception is encountered
   */
  public DirContext createSubcontext(String name, Attributes attrs) throws NamingException {

    VFSItem file = resolveFile(name);
    if (file != null) throw new NameAlreadyBoundException(smgr.getString("resources.alreadyBound", name));
   
    int lastSlash = name.lastIndexOf('/');
    if (lastSlash == -1) throw new NamingException();
    String parent = name.substring(0, lastSlash);
    VFSItem folder = resolveFile(parent);
    if (folder == null || (!(folder instanceof VFSContainer)))
      throw new NamingException(smgr.getString("resources.bindFailed", name));
    String newName = name.substring(lastSlash + 1);
    VFSItem childContainer = ((VFSContainer)folder).createChildContainer(newName);
    if (childContainer == null)
      throw new NamingException(smgr.getString("resources.bindFailed", name));
    return (DirContext)lookup(name);

  }

  /**
   * Retrieves the schema associated with the named object. The schema describes
   * rules regarding the structure of the namespace and the attributes stored
   * within it. The schema specifies what types of objects can be added to the
   * directory and where they can be added; what mandatory and optional
   * attributes an object can have. The range of support for schemas is
   * directory-specific.
   *
   * @param name the name of the object whose schema is to be retrieved
   * @return the schema associated with the context; never null
   * @exception OperationNotSupportedException if schema not supported
   * @exception NamingException if a naming exception is encountered
   */
  public DirContext getSchema(String name) throws NamingException {
    throw new OperationNotSupportedException();
  }

  /**
   * Retrieves a context containing the schema objects of the named object's
   * class definitions.
   *
   * @param name the name of the object whose object class definition is to be
   *          retrieved
   * @return the DirContext containing the named object's class definitions;
   *         never null
   * @exception OperationNotSupportedException if schema not supported
   * @exception NamingException if a naming exception is encountered
   */
  public DirContext getSchemaClassDefinition(String name) throws NamingException {
    throw new OperationNotSupportedException();
  }

  /**
   * Searches in a single context for objects that contain a specified set of
   * attributes, and retrieves selected attributes. The search is performed
   * using the default SearchControls settings.
   *
   * @param name the name of the context to search
   * @param matchingAttributes the attributes to search for. If empty or null,
   *          all objects in the target context are returned.
   * @param attributesToReturn the attributes to return. null indicates that all
   *          attributes are to be returned; an empty array indicates that none
   *          are to be returned.
   * @return a non-null enumeration of SearchResult objects. Each SearchResult
   *         contains the attributes identified by attributesToReturn and the
   *         name of the corresponding object, named relative to the context
   *         named by name.
   * @exception NamingException if a naming exception is encountered
   */
  public NamingEnumeration<SearchResult> search(String name, Attributes matchingAttributes, String[] attributesToReturn) {
    return null;
  }

  /**
   * Searches in a single context for objects that contain a specified set of
   * attributes. This method returns all the attributes of such objects. It is
   * equivalent to supplying null as the atributesToReturn parameter to the
   * method search(Name, Attributes, String[]).
   *
   * @param name the name of the context to search
   * @param matchingAttributes the attributes to search for. If empty or null,
   *          all objects in the target context are returned.
   * @return a non-null enumeration of SearchResult objects. Each SearchResult
   *         contains the attributes identified by attributesToReturn and the
   *         name of the corresponding object, named relative to the context
   *         named by name.
   * @exception NamingException if a naming exception is encountered
   */
  public NamingEnumeration<SearchResult> search(String name, Attributes matchingAttributes) {
    return null;
  }

  /**
   * Searches in the named context or object for entries that satisfy the given
   * search filter. Performs the search as specified by the search controls.
   *
   * @param name the name of the context or object to search
   * @param filter the filter expression to use for the search; may not be null
   * @param cons the search controls that control the search. If null, the
   *          default search controls are used (equivalent to (new
   *          SearchControls())).
   * @return an enumeration of SearchResults of the objects that satisfy the
   *         filter; never null
   * @exception InvalidSearchFilterException if the search filter specified is
   *              not supported or understood by the underlying directory
   * @exception InvalidSearchControlsException if the search controls contain
   *              invalid settings
   * @exception NamingException if a naming exception is encountered
   */
  public NamingEnumeration<SearchResult> search(String name, String filter, SearchControls cons) {
    return null;
  }

  /**
   * Searches in the named context or object for entries that satisfy the given
   * search filter. Performs the search as specified by the search controls.
   *
   * @param name the name of the context or object to search
   * @param filterExpr the filter expression to use for the search. The
   *          expression may contain variables of the form "{i}" where i is a
   *          nonnegative integer. May not be null.
   * @param filterArgs the array of arguments to substitute for the variables in
   *          filterExpr. The value of filterArgs[i] will replace each
   *          occurrence of "{i}". If null, equivalent to an empty array.
   * @param cons the search controls that control the search. If null, the
   *          default search controls are used (equivalent to (new
   *          SearchControls())).
   * @return an enumeration of SearchResults of the objects that satisy the
   *         filter; never null
   * @exception ArrayIndexOutOfBoundsException if filterExpr contains {i}
   *              expressions where i is outside the bounds of the array
   *              filterArgs
   * @exception InvalidSearchControlsException if cons contains invalid settings
   * @exception InvalidSearchFilterException if filterExpr with filterArgs
   *              represents an invalid search filter
   * @exception NamingException if a naming exception is encountered
   */
  public NamingEnumeration<SearchResult> search(String name, String filterExpr, Object[] filterArgs, SearchControls cons) {
    return null;
  }

  // ------------------------------------------------------ Protected Methods

  /**
   * Resolve a file relative to this base.
   * Make sure, paths are relative
   */
  protected VFSItem resolveFile(String name) {
    if (name == null) name = "";
    if (name.length() > 0 && name.charAt(0) == '/') name = name.substring(1);
    return base.resolve(name);
  }
 
  /**
   * List the resources which are members of a collection.
   *
   * @param file Collection
   * @return Vector containg NamingEntry objects
   */
  protected List<NamingEntry> list(VFSItem file) {

    List<NamingEntry> entries = new ArrayList<NamingEntry>();

    if (!(file instanceof VFSContainer)) return entries;
    List<VFSItem> children = ((VFSContainer)file).getItems();

    NamingEntry entry = null;
    for (VFSItem currentFile:children) {
      Object object;
      if (currentFile instanceof VFSContainer) {
        VFSDirContext tempContext = new VFSDirContext(env);
        tempContext.setVirtualDocBase(currentFile);
        object = tempContext;
      } else {
        object = new VFSResource(currentFile);
      }
      entry = new NamingEntry(currentFile.getName(), object, NamingEntry.ENTRY);
      entries.add(entry);
    }
    return entries;
  }

  // ----------------------------------------------- FileResource Inner Class

  /**
   * This specialized resource implementation avoids opening the IputStream to
   * the file right away (which would put a lock on the file).
   */
  protected class VFSResource extends Resource {

    // -------------------------------------------------------- Constructor

    public VFSResource(VFSItem fileObject) {
      this.vfsItem = fileObject;
    }

    // --------------------------------------------------- Member Variables

    /**
     * Associated file object.
     */
    protected VFSItem vfsItem;

    /**
     * File length.
     */
    protected long length = -1L;

    // --------------------------------------------------- Resource Methods

    /**
     * Content accessor.
     *
     * @return InputStream
     */
    public InputStream streamContent() throws IOException {
      if (!(vfsItem instanceof VFSLeaf)) throw new IOException("Can't get stream for VFSItem.");
      VFSLeaf vfsLeaf = (VFSLeaf)vfsItem;
      return vfsLeaf.getInputStream();
    }

  }

  // ------------------------------------- FileResourceAttributes Inner Class

  /**
   * This specialized resource attribute implementation does some lazy reading
   * (to speed up simple checks, like checking the last modified date).
   */
  protected class VFSResourceAttributes extends ResourceAttributes {

    // -------------------------------------------------------- Constructor

    public VFSResourceAttributes(VFSItem vfsItem) {
      this.vfsItem = vfsItem;
    }

    // --------------------------------------------------- Member Variables

    protected VFSItem vfsItem;

    protected boolean accessed = false;
   
    protected String canonicalPath = null;

    // ----------------------------------------- ResourceAttributes Methods

    /**
     * Is collection.
     */
    public boolean isCollection() {
      if (!accessed) {
        collection = (vfsItem instanceof VFSContainer);
      }
      return collection;
    }

    /**
     * Get content length.
     *
     * @return content length value
     */
    public long getContentLength() {
      if (contentLength != -1L) return contentLength;
      if (isCollection()) contentLength = 0;
      else {
        VFSLeaf leaf = (VFSLeaf)vfsItem;
        contentLength = leaf.getSize();
      }
      return contentLength;
    }

    /**
     * Get creation time.
     *
     * @return creation time value
     */
    public long getCreation() {
      if (creation != -1L) return creation;
      if (isCollection()) creation = 0;
      else {
        creation = vfsItem.getLastModified();
      }
      return creation;
    }

    /**
     * Get creation date.
     *
     * @return Creation date value
     */
    public Date getCreationDate() {
      return new Date(getCreation());
    }

    /**
     * Get last modified time.
     *
     * @return lastModified time value
     */
    public long getLastModified() {
      if (lastModified != -1L) return lastModified;
      if (isCollection()) lastModified = 0;
      else {
        lastModified = vfsItem.getLastModified();
      }
      return lastModified;
    }

    /**
     * Get lastModified date.
     *
     * @return LastModified date value
     */
    public Date getLastModifiedDate() {
      return new Date(getLastModified());
    }

    /**
     * Get name.
     *
     * @return Name value
     */
    public String getName() {
      if (name == null) name = vfsItem.getName();
      return name;
    }

    /**
     * Get resource type.
     *
     * @return String resource type
     */
    public String getResourceType() {
      if (!accessed) isCollection(); // needed to initialize
      return super.getResourceType();
    }

  }

  protected class StringManager {

    public StringManager() {
      // dummy implementation
    }

    public String getString(String in) {
      return in;
    }

    public String getString(String in, String arg) {
      return in;
    }

  }

  /**
   * Represents a binding in a NamingContext.
   *
   * @author Remy Maucherat
   */

  public class NamingEntry {

    // --------------------------------------------------------------
    // Constants

    public static final int ENTRY = 0;
    public static final int LINK_REF = 1;
    public static final int REFERENCE = 2;

    public static final int CONTEXT = 10;

    // -----------------------------------------------------------
    // Constructors

    public NamingEntry(String name, Object value, int type) {
      this.name = name;
      this.value = value;
      this.type = type;
    }

    // ----------------------------------------------------- Instance Variables

    /**
     * The type instance variable is used to avoid unsing RTTI when doing
     * lookups.
     */
    public int type;
    public String name;
    public Object value;

    // --------------------------------------------------------- Object Methods

    public boolean equals(Object obj) {
      if ((obj != null) && (obj instanceof NamingEntry)) {
        return name.equals(((NamingEntry) obj).name);
      } else {
        return false;
      }
    }

    public int hashCode() {
      return name.hashCode();
    }

  }

  /**
   * Naming enumeration implementation.
   *
   * @author Remy Maucherat
   */

  public class NamingContextEnumeration implements NamingEnumeration<NameClassPair> {

    // ----------------------------------------------------------- Constructors

    public NamingContextEnumeration(Iterator<NamingEntry> entries) {
      iterator = entries;
    }

    // -------------------------------------------------------------- Variables

    /**
     * Underlying enumeration.
     */
    protected Iterator<NamingEntry> iterator;

    // --------------------------------------------------------- Public Methods

    /**
     * Retrieves the next element in the enumeration.
     */
    public NameClassPair next() {
      return nextElement();
    }

    /**
     * Determines whether there are any more elements in the enumeration.
     */
    public boolean hasMore() {
      return iterator.hasNext();
    }

    /**
     * Closes this enumeration.
     */
    public void close() {
      //nothing to do
    }

    public boolean hasMoreElements() {
      return iterator.hasNext();
    }

    public NameClassPair nextElement() {
      NamingEntry entry = iterator.next();
      return new NameClassPair(entry.name, entry.value.getClass().getName());
    }
  }
 
  public class NamingContextEnumeration2 implements NamingEnumeration<Binding> {

    private final NamingEnumeration<NameClassPair> entries;
   
    public NamingContextEnumeration2(NamingEnumeration<NameClassPair> entries) {
      this.entries = entries;
    }

    public void close() {
      //nothing to do
    }

    public boolean hasMore() throws NamingException {
      return entries.hasMore();
    }

    public Binding next() throws NamingException {
      NameClassPair pair = entries.next();
      return new Binding(pair.getName(), pair.getClassName(), null);
    }

    public boolean hasMoreElements() {
      return entries.hasMoreElements();
    }

    public Binding nextElement() {
      try {
        return next();
      } catch (NamingException e) {
        e.printStackTrace();
        return null;
      }
    }
  }
}
TOP

Related Classes of org.olat.core.util.servlets.VFSDirContext$StringManager

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.
alytics.com/analytics.js','ga'); ga('create', 'UA-20639858-1', 'auto'); ga('send', 'pageview');