Package org.olat.dispatcher

Source Code of org.olat.dispatcher.CatalogExportModuleDispatcher

/**
* 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) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/

package org.olat.dispatcher;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.olat.ControllerFactory;
import org.olat.basesecurity.Manager;
import org.olat.basesecurity.ManagerFactory;
import org.olat.basesecurity.SecurityGroup;
import org.olat.catalog.CatalogEntry;
import org.olat.catalog.CatalogManager;
import org.olat.core.configuration.OLATModule;
import org.olat.core.dispatcher.Dispatcher;
import org.olat.core.gui.media.FileMediaResource;
import org.olat.core.gui.media.NotFoundMediaResource;
import org.olat.core.gui.media.ServletUtil;
import org.olat.core.gui.render.StringOutput;
import org.olat.core.gui.translator.PackageTranslator;
import org.olat.core.gui.translator.Translator;
import org.olat.core.id.Identity;
import org.olat.core.logging.Tracing;
import org.olat.core.util.FileUtils;
import org.olat.core.util.Util;
import org.olat.core.util.WebappHelper;
import org.olat.core.util.i18n.I18nModule;
import org.olat.repository.RepoJumpInHandlerFactory;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryIconRenderer;
import org.olat.repository.controllers.RepositoryDetailsController;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.anthonyeden.lib.config.Configuration;

public class CatalogExportModuleDispatcher implements OLATModule, Dispatcher {

  public  static final String XML_FILE = "catalog.xml";
  private static final String SYSTEM_DIR = "system";

  private static final String CONFIG_UPDATE_INTERVAL = "interval";
 
  private static final String XML_CAT = "catalog";                    // catalog root tag
  private static final String XML_NODE = "node";                      // node element (catalog hierarchy structure)
  private static final String XML_LEAF = "leaf";                      // leaf element (catalog entries (courses, files, ...))
  private static final String XML_CHILDREN = "children";              // child elements of nodes
  private static final String XML_DESCR = "description";              // catalog(!) description of nodes and leaves
  private static final String XML_TYPE = "type";                      // catalog entry type (course, PDF, ...) -> translated to installations default language!
  private static final String XML_TYPE_CSS = "iconCSS";                // CSS class for catalog entry type icon
  private static final String XML_LINKS = "links";                    // links to entries container
  private static final String XML_LINK = "link";                      // link to the entry
  private static final String XML_LINKTYPE = "type";                  // type of the link to the entry (see following)
  private static final String XML_LINKTYPE_GUEST = "guest";            // -> link for guest access (only there if accessible by guests)
  private static final String XML_LINKTYPE_LOGIN = "login";            // -> link with login required
  private static final String XML_LINKTYPE_DETAIL = "detail";          // -> link to entry detail page
  private static final String XML_LINKTYPE_ENROLL = "cbb_enrollment"// -> link to enrollment course buildings blocks in entry (there may be many of this!!!)
  private static final String XML_ACC = "access";                      // entry access settings attribute name
  private static final String XML_OWN = "owners";                      // entry owners container element name
  private static final String XML_USR = "user";                        // entry owners user subelements
  private static final String XML_CUSTOM = "custom";                  // custom info (empty for now)
 
  // NLS:
 
  private static final String NLS_CIF_TYPE_NA = "cif.type.na";
  private static final String NLS_TABLE_HEADER_ACCESS_GUEST = "access.guest";
  private static final String NLS_TABLE_HEADER_ACCESS_USER = "access.user";
  private static final String NLS_TABLE_HEADER_ACCESS_AUTHOR = "access.author";
  private static final String NLS_TABLE_HEADER_ACCESS_OWNER = "access.owner";
 
  private static DocumentBuilderFactory domFactory = null;
  private static DocumentBuilder domBuilder = null;
  private static Manager securityManager = null;
 
  private static Translator repoTypeTranslator =null;
  private static Translator catalogExportTranslator = null;
 
  private static boolean inAccess = false;
 
  private TimerTask tt;

 
  private static boolean instance=false;
  private static Configuration moduleConfig=null;
 

 
  synchronized private boolean reInitialize(){//o_clusterOK by:fj
    boolean retVal=true;
    if(instance){
      return retVal;
    }
    repoTypeTranslator = new PackageTranslator(Util.getPackageName(RepositoryDetailsController.class), I18nModule.getDefaultLocale());
    catalogExportTranslator = new PackageTranslator(Util.getPackageName(CatalogExportModuleDispatcher.class), I18nModule.getDefaultLocale());
    securityManager = ManagerFactory.getManager();
    String updateInterval = moduleConfig.getChildValue(CONFIG_UPDATE_INTERVAL);
    long inter = 5 * 60 * 1000;                                                  // default is 5 min.
    if (updateInterval != null) {
      try {
        inter = Long.valueOf(updateInterval).longValue() * 60 * 1000;
        } catch (Exception e) {
          retVal=false;
      }
    }
    try {
      domFactory = DocumentBuilderFactory.newInstance();                        // init
      domBuilder = domFactory.newDocumentBuilder();
    } catch (Exception e) {
      retVal=false;
    }
    tt = new TimerTask() {
      public void run() {
        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);                // don't disturb other things going on
        createXML();
      }
    };
    Timer timer = new Timer();
    timer.schedule(tt, (new GregorianCalendar()).getTime(), inter);
    instance=true;
    return retVal;
  }
 
  protected void createXML() {
    Tracing.logDebug("Creating catalog export XML file...", CatalogExportModuleDispatcher.class);
    Document doc = domBuilder.newDocument();                                    // create new XML document
    Element cat = doc.createElement(XML_CAT);                                    // catalog element
    doc.appendChild(cat);
    cat.setAttribute("date", String.valueOf(System.currentTimeMillis()));        // set date in catalog element
    Element root = doc.createElement(XML_NODE);                                  // root node
    root.setAttribute("name", "root");
    cat.appendChild(root);
   
    CatalogManager cm = CatalogManager.getInstance();                            // instanciate catalog manager
    List ces = cm.getRootCatalogEntries();
    for (Iterator it = ces.iterator(); it.hasNext();) {                          // for every root entry (currently only one)
      CatalogEntry ce = (CatalogEntry) it.next();
      getCatalogSubStructure(doc, root, cm, ce);                                // scan this entry
    }
   
    TransformerFactory tranFac = TransformerFactory.newInstance();              // init transfromer to write XML to file
    Transformer t;
    try {
      t = tranFac.newTransformer();
      t.setOutputProperty(OutputKeys.INDENT, "yes");                            // insert newlines
      t.setOutputProperty(OutputKeys.METHOD, "xml");
      t.setOutputProperty(OutputKeys.VERSION, "1.0");
      t.setOutputProperty(OutputKeys.ENCODING, "utf-8");
      t.setOutputProperty(OutputKeys.STANDALONE, "yes");
      Source src  = new DOMSource(doc);
      File sysDir = new File(WebappHelper.getUserDataRoot(), SYSTEM_DIR);        // destination is .../olatdata/system/catalog.xml
      File f = new File(sysDir, XML_FILE);
      File o = new File(sysDir, XML_FILE + ".old");
      OutputStream os = new BufferedOutputStream(new FileOutputStream(o));
      try {
        InputStream  is = new BufferedInputStream(new FileInputStream(f));
        FileUtils.copy(is, os);                                                    // copy old version for access in the meantime
      } catch (Exception e) {
        // initial call of this method or fs error: catalog.xml not found, so don't copy it, that's ok
      }
      os = new BufferedOutputStream(new FileOutputStream(f));
      Result dest = new StreamResult(os);
      inAccess = true;
      t.transform(src, dest);                                                    // and that's it
      inAccess = false;
      Tracing.logDebug("                                ...done", CatalogExportModuleDispatcher.class);
    } catch (Exception e) {
      Tracing.logError("Error writing catalog export file.", e, CatalogExportModuleDispatcher.class);
    }
  }
 
  private void getCatalogSubStructure(Document doc, Element parent, CatalogManager cm, CatalogEntry ce) {
    Element cur = null;                                                          // tmp. element
    List l = cm.getChildrenOf(ce);                                              // get catalog children
    // all nodes
    for (Iterator it = l.iterator(); it.hasNext();) {                            // scan for node entries
      CatalogEntry c = (CatalogEntry) it.next();
      if (c.getType() == CatalogEntry.TYPE_NODE) {                              // it's a node
       
        Element node = doc.createElement(XML_NODE);                              // node element
        node.setAttribute("name", c.getName());
        parent.appendChild(node);
       
        cur = doc.createElement(XML_DESCR);                                      // description element
        cur.appendChild(doc.createTextNode(c.getDescription()));
        node.appendChild(cur);

        if (cm.getChildrenOf(c).size() > 0) {                                    // children element containing all subentries
          cur = doc.createElement(XML_CHILDREN);
          node.appendChild(cur);
          getCatalogSubStructure(doc, cur, cm, c);                              // recursive scan
        }
       
        cur = doc.createElement(XML_CUSTOM);
        /*
         * Insert custom info here!
         */
        node.appendChild(cur);
       
      }
    }
    // all leafes
    for (Iterator it = l.iterator(); it.hasNext();) {                            // scan for leaf entries
      CatalogEntry c = (CatalogEntry) it.next();
      if (c.getType() == CatalogEntry.TYPE_LEAF) {
        RepositoryEntry re = c.getRepositoryEntry();                            // get repo entry
        if (re.getAccess() > RepositoryEntry.ACC_OWNERS_AUTHORS) {              // just show entries visible for registered users
          Element leaf = doc.createElement(XML_LEAF);                            // leaf element
          leaf.setAttribute("name", c.getName());
          parent.appendChild(leaf);
         
          cur = doc.createElement(XML_DESCR);                                    // description element
          cur.appendChild(doc.createTextNode(c.getDescription()));
          leaf.appendChild(cur);
         
          cur = doc.createElement(XML_TYPE);
          String typeName = re.getOlatResource().getResourceableTypeName();      // add the resource type
          StringOutput typeDisplayText = new StringOutput(100);
          if (typeName != null) { // add typename code
            RepositoryEntryIconRenderer reir = new RepositoryEntryIconRenderer();
            cur.setAttribute(XML_TYPE_CSS, reir.getIconCssClass(re));
            String tName = ControllerFactory.translateResourceableTypeName(typeName, repoTypeTranslator.getLocale());
            typeDisplayText.append(tName);
          } else {
            typeDisplayText.append(repoTypeTranslator.translate(NLS_CIF_TYPE_NA));
          }
          cur.appendChild(doc.createTextNode(typeDisplayText.toString()));
          leaf.appendChild(cur);

         
          Element links = doc.createElement(XML_LINKS);                          // links container
          String tmp = "";
          switch (re.getAccess()) { // Attention! This uses the switch-case-fall-through mechanism!
            case RepositoryEntry.ACC_USERS_GUESTS:    tmp = catalogExportTranslator.translate(NLS_TABLE_HEADER_ACCESS_GUEST) + tmp;
                                                      appendLinkElement(doc, links, XML_LINKTYPE_GUEST, RepoJumpInHandlerFactory.buildRepositoryDispatchURI(re) + "&guest=true&amp;lang=" + I18nModule.getDefaultLocale().toString().toLowerCase());
            case RepositoryEntry.ACC_USERS:            tmp = catalogExportTranslator.translate(NLS_TABLE_HEADER_ACCESS_USER) + tmp;
            case RepositoryEntry.ACC_OWNERS_AUTHORS:  tmp = catalogExportTranslator.translate(NLS_TABLE_HEADER_ACCESS_AUTHOR) + tmp;
            case RepositoryEntry.ACC_OWNERS:          tmp = catalogExportTranslator.translate(NLS_TABLE_HEADER_ACCESS_OWNER) + tmp;
                                                      appendLinkElement(doc, links, XML_LINKTYPE_LOGIN, RepoJumpInHandlerFactory.buildRepositoryDispatchURI(re));
                                                      break;
            default:                                  tmp = catalogExportTranslator.translate(NLS_TABLE_HEADER_ACCESS_USER);
                                                      break;
          }

          // when implemented in OLAT, add link to detail page and enrollment entries here
          //appendLinkElement(doc, links, XML_LINKTYPE_DETAIL, RepoJumpInHandlerFactory.buildRepositoryDispatchURI2DeatilPage(re));
          //appendALotOfLinkElements4EnrollmentCBBsNeverthelessTheyAreVisibleAndOrAccessibleOrNot(doc, links, XML_LINKTYPE_ENROLL, re);
         
          leaf.setAttribute(XML_ACC, tmp);                                      // access rights as attribute
          leaf.appendChild(links);                                              // append links container
         
          Element owners = doc.createElement(XML_OWN);                          // owners node
          leaf.appendChild(owners);
          SecurityGroup sg = re.getOwnerGroup();
          List m = securityManager.getIdentitiesOfSecurityGroup(sg);
          for (Iterator iter = m.iterator(); iter.hasNext();) {
            Identity i = (Identity) iter.next();
            cur = doc.createElement(XML_USR);                                    // get all users
            cur.appendChild(doc.createTextNode(i.getName()));
            owners.appendChild(cur);
          }
         
          cur = doc.createElement(XML_CUSTOM);
          /*
           * Insert custom info here!
           */
          leaf.appendChild(cur);
         
        }
      }
    }
  }
 
  private void appendLinkElement(Document doc, Element parent, String type, String URL) {
    Element link = doc.createElement(XML_LINK);
    link.appendChild(doc.createTextNode(URL));
    link.setAttribute(XML_LINKTYPE, type);
    parent.appendChild(link);
  }
 
  /**
   * @return The catalog XML file
   */
  public static File getFile() throws FileNotFoundException {
    File f;
    if (inAccessf = new File(new File(WebappHelper.getUserDataRoot(), SYSTEM_DIR), XML_FILE + ".old");
    else          f = new File(new File(WebappHelper.getUserDataRoot(), SYSTEM_DIR), XML_FILE);
    if (!f.exists() || !f.canRead()) throw new FileNotFoundException("Catalog export file not found!");
    return f;
  }

  public void init(Configuration moduleConfig){
    CatalogExportModuleDispatcher.moduleConfig=moduleConfig;
  }

  public void destroy() {
    // nothing to dispose
  }

  public void execute(HttpServletRequest request, HttpServletResponse response, String uriPrefix) {
    if(!this.reInitialize())
      Tracing.logError("Some Failsaves in reInitialization needed !", CatalogExportModuleDispatcher.class);
      try {
        Tracing.logInfo("Catalog XML file requested by " + request.getRemoteAddr(), CatalogExportModuleDispatcher.class);
        ServletUtil.serveResource(request, response, new FileMediaResource(CatalogExportModuleDispatcher.getFile(), true));
      } catch (Exception e) {
        Tracing.logError("Error requesting catalog export file: ", e, CatalogExportModuleDispatcher.class);
        try {
          ServletUtil.serveResource(request, response, new NotFoundMediaResource(request.getRequestURI()));
        } catch (Exception e1) {
          // what now???
          Tracing.logError("What now ???", CatalogExportModuleDispatcher.class);
        }
      }
  }
}
TOP

Related Classes of org.olat.dispatcher.CatalogExportModuleDispatcher

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.