Package org.olat.upgrade

Source Code of org.olat.upgrade.MigrationIdentity

/**
* 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.upgrade;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.hibernate.Hibernate;
import org.hibernate.type.Type;
import org.olat.admin.user.delete.service.UserDeletionManager;
import org.olat.admin.user.delete.service.UserFileDeletionManager;
import org.olat.basesecurity.Manager;
import org.olat.basesecurity.ManagerFactory;
import org.olat.commons.modules.bc.meta.MetaInfoFileImpl;
import org.olat.core.commons.modules.bc.FolderConfig;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.id.Identity;
import org.olat.core.id.Persistable;
import org.olat.core.id.User;
import org.olat.core.logging.AssertException;
import org.olat.core.util.xml.XMLParser;
import org.olat.core.util.xml.XStreamHelper;
import org.olat.modules.dialog.DialogElement;
import org.olat.modules.dialog.DialogElementsPropertyManager;
import org.olat.modules.dialog.DialogPropertyElements;
import org.olat.properties.Property;
import org.olat.properties.PropertyManager;

/**
* Description:<br>
* Automatic upgrade code for the OLAT 6.1.1 release
* Migrate deleted user data, delete user completly (deleted user name can used again).
*
* <P>
* Initial Date:  12.03.2009 <br>
* @author Christian Guretzki
*/
public class OLATUpgrade_6_1_1 extends OLATUpgrade {
  private static final String VERSION = "OLAT_6.1.1";
  private static final String TASK_RENAME_DELETED_USER = "Rename deleted username to <timestamp>_bks_<USRENAME>";
  private static final String TASK_REPLACE_AUTHOR_WITH_IDENTITY_KEY = "Replace author-name with identity-key in MetaData-files";
  private static final String TASK_CLEANUP_USERDATA_OF_DELETEDUSER = "Cleanup userdata of deleted user(dropbox, returnboxof task-node, meta data, qti-editor)";
  private static final String TASK_MIGRATE_ALL_DIALOG_ELEMENTS_PROPERTY = "Replace user-name with identity-key in file-dialog properties for all users";
 
  // migrate only one deleted-user for testing
  private boolean testMode = false;
  /**
   * @see org.olat.upgrade.OLATUpgrade#getVersion()
   */
  public String getVersion() {
    return VERSION;
  }

  /**
   * @see org.olat.upgrade.OLATUpgrade#doPreSystemInitUpgrade(org.olat.upgrade.UpgradeManager)
   */
  public boolean doPreSystemInitUpgrade(UpgradeManager upgradeManager) {
    return false;
  }

  /**
   * @see org.olat.upgrade.OLATUpgrade#doPostSystemInitUpgrade(org.olat.upgrade.UpgradeManager)
   */
  public boolean doPostSystemInitUpgrade(UpgradeManager upgradeManager) {
    UpgradeHistoryData uhd = upgradeManager.getUpgradesHistory(VERSION);
    if (uhd == null) {
      // has never been called, initialize
      uhd = new UpgradeHistoryData();
    } else {
      if (uhd.isInstallationComplete()) return false;
    }
    long startTime = 0 ;
    if (log.isDebug()) startTime = System.currentTimeMillis();
    renameDeletedUserNames(upgradeManager, uhd);
    if (log.isDebug()) {
      log.debug("OLATUpgrade_6_1_1: renameDeletedUserNames takes " + (System.currentTimeMillis() - startTime) + "ms");
      startTime = System.currentTimeMillis();
   
    replaceAuthorNameWithIdentityKeyInMetaData(upgradeManager, uhd);
    if (log.isDebug()) {
      log.debug("OLATUpgrade_6_1_1: replaceAuthorNameWithIdentityKeyInMetaData takes " + (System.currentTimeMillis() - startTime) + "ms");
      startTime = System.currentTimeMillis();
    }   
    cleanUpDeletedUserData(upgradeManager, uhd);
    if (log.isDebug()) {
      log.debug("OLATUpgrade_6_1_1: cleanUpDeletedUserData takes " + (System.currentTimeMillis() - startTime) + "ms");
      startTime = System.currentTimeMillis();
   
    migrateAllDialogElementsProperty(upgradeManager, uhd);
    if (log.isDebug()) {
      log.debug("OLATUpgrade_6_1_1: migrateAllDialogElementsProperty takes " + (System.currentTimeMillis() - startTime) + "ms");
      startTime = System.currentTimeMillis();
   
   
    // mark upgrade as finished, never run it again
    uhd.setInstallationComplete(true);
    upgradeManager.setUpgradesHistory(uhd, VERSION);
    return true;
  }

  /**
   * Deletes the guest users from 6.0 release, the guest users are now created
   * using other user names using an automated naming schema
   *
   * @param upgradeManager
   * @param uhd
   */
  private void renameDeletedUserNames(UpgradeManager upgradeManager, UpgradeHistoryData uhd) {
    if (!uhd.getBooleanDataValue(TASK_RENAME_DELETED_USER)) {
      log.audit("+---------------------------------------------------------------+");
      log.audit("+... Rename deleted username to <TIMESTAMP>_bks_<USRENAME>   ...+");
      log.audit("+---------------------------------------------------------------+");
      int counter = 0;
      //keep email only -> change login-name
      if (!UserDeletionManager.isKeepUserLoginAfterDeletion () ){
        // loop over all deleted-users
        Manager secMgr = ManagerFactory.getManager();
        List<Identity> identitiesList = secMgr.getIdentitiesByPowerSearch(null, null, true, null, null, null,
            null, null, Identity.STATUS_DELETED);
        for (Iterator<Identity> iterator = identitiesList.iterator(); iterator.hasNext();) {
          Identity identity = iterator.next();
          if (!identity.getName().contains(UserDeletionManager.DELETED_USER_DELIMITER)) {
            if (!(testMode && (counter > 0) ) ) {
              String oldName = identity.getName();
              String newName = UserDeletionManager.getInstance().getBackupStringWithDate(oldName);
              identity.setName(newName);
              DBFactory.getInstance().updateObject(identity);
              log.audit("Rename deleted username from '" + oldName + "' to '" + newName + "'");
              counter++;
            } else {
              log.info("TEST-MODE: Do not rename username '" + identity.getName() +"'");
            }
          }
          if (counter % 10 == 0) {
            DBFactory.getInstance().intermediateCommit();
          }
        }
      }
      // Final commit of all identity changes
      DBFactory.getInstance().intermediateCommit();
      log.audit("Rename " + counter +" deleted username to '<TIMESTAMP>_bks_<USRENAME>'");
      uhd.setBooleanDataValue(TASK_RENAME_DELETED_USER, true);
      upgradeManager.setUpgradesHistory(uhd, VERSION);
    }
  }
 
  private void replaceAuthorNameWithIdentityKeyInMetaData(UpgradeManager upgradeManager, UpgradeHistoryData uhd) {
    if (!uhd.getBooleanDataValue(TASK_REPLACE_AUTHOR_WITH_IDENTITY_KEY)) {
      log.audit("+-----------------------------------------------------------------------------+");
      log.audit("+... Replace author-name with identity-key in MetaData-files for all users ...+");
      log.audit("+-----------------------------------------------------------------------------+");
      String metaRootDirPath = FolderConfig.getCanonicalMetaRoot();
      File metaRootDir = new File(metaRootDirPath);
      if (log.isDebug()) log.debug("replaceAuthorNameWithIdentityKeyInMetaData: metaRootDir=" + metaRootDir.getAbsolutePath());
      long counter = replaceAuthorNameWithIdentityKeyInAllMetaData( metaRootDir, 0 /*subFolderNbr*/, 0 );
      log.info("replaceAuthorNameWithIdentityKeyInMetaData: replace #" + counter + " user-names in meta files");
      uhd.setBooleanDataValue(TASK_REPLACE_AUTHOR_WITH_IDENTITY_KEY, true);
      upgradeManager.setUpgradesHistory(uhd, VERSION);
    }
  }

 
  private void cleanUpDeletedUserData(UpgradeManager upgradeManager, UpgradeHistoryData uhd) {
    if (!uhd.getBooleanDataValue(TASK_CLEANUP_USERDATA_OF_DELETEDUSER)) {
      log.audit("+---------------------------------------------------------------------------------------------------------------+");
      log.audit("+... Cleanup userdata of deleted user (dropbox, returnbox of task-node, .meta/homes/<USER> data, qti-editor) ...+");
      log.audit("+---------------------------------------------------------------------------------------------------------------+");
      int counter = 0;
      int counterNotCleanup = 0;
      Manager secMgr = ManagerFactory.getManager();
      List<Identity> identitiesList = secMgr.getIdentitiesByPowerSearch(null, null, true, null, null, null,  null, null, Identity.STATUS_DELETED);
      if (log.isDebug()) log.debug("cleanUpDeletedUserData: found #" + identitiesList.size() + " deleted users");
      // loop over all deleted-users
      for (Iterator<Identity> iterator = identitiesList.iterator(); iterator.hasNext();) {
        Identity identity = iterator.next();
        if (log.isDebug()) log.debug("cleanUpDeletedUserData: process identity=" + identity);
        if (!(testMode && (counter > 0) ) ) {
          if (!UserDeletionManager.isKeepUserLoginAfterDeletion () ){
            // deleted username are like <TIMESTAMP>_bks_<USRENAME>
            // check if username is already in use again
            String orginalUserName = extractOrginalUserName(identity.getName());
            if (log.isDebug()) log.debug("cleanUpDeletedUserData: process orginalUserName=" + orginalUserName);
            Identity foundIdentity = secMgr.findIdentityByName(orginalUserName);
            if (foundIdentity == null) {
              MigrationIdentity migrationIdentity = new MigrationIdentity(orginalUserName);
              UserFileDeletionManager.getInstance().deleteUserData(migrationIdentity, migrationIdentity.getName())
              log.audit("Cleanup userdata of deleted user '" + identity.getName() + "' orginalUserName=" + orginalUserName);
              counter++;
            } else {
              log.audit("Could NOT cleanup userdata of deleted user '" + identity.getName() + "' because '" + orginalUserName + "' is already in use" );
              counterNotCleanup++;
            }
          } else {
            // deleted username are not renamed
            UserFileDeletionManager.getInstance().deleteUserData(identity, identity.getName())
            log.audit("KeepUserLoginAfterDeletion-Mode : Cleanup userdata of deleted user '" + identity.getName() + "'");
          }
        } else {
          log.info("TEST-MODE: Do not cleanup username '" + identity.getName() +"'");
        }
        DBFactory.getInstance(false).commitAndCloseSession();
        if (log.isDebug()) log.debug("cleanUpDeletedUserData: DONE migration of identity=" + identity);
      }
      log.audit("Cleanup userdata of " + counter +" users");
      if (counterNotCleanup > 0) {
        log.audit("Could not cleanup userdata of " + counterNotCleanup +" users because the username is already in use");
      }
      uhd.setBooleanDataValue(TASK_CLEANUP_USERDATA_OF_DELETEDUSER, true);
      upgradeManager.setUpgradesHistory(uhd, VERSION);
    }
  }

  private void migrateAllDialogElementsProperty(UpgradeManager upgradeManager, UpgradeHistoryData uhd) {
    if (!uhd.getBooleanDataValue(TASK_MIGRATE_ALL_DIALOG_ELEMENTS_PROPERTY)) {
      log.audit("+-----------------------------------------------------------------------------------+");
      log.audit("+... Replace user-name with identity-key in file-dialog properties for all users ...+");
      log.audit("+-----------------------------------------------------------------------------------+");

      migrateAllDialogElementsProperty();
     
      uhd.setBooleanDataValue(TASK_REPLACE_AUTHOR_WITH_IDENTITY_KEY, true);
      upgradeManager.setUpgradesHistory(uhd, VERSION);
    }
  }

  /**
   *
   * @param name deleted-username format like <TIMESTAMP>_bks_<USRENAME>
   * @return
   */
  private String extractOrginalUserName(String name) {
    if ( name.indexOf(UserDeletionManager.DELETED_USER_DELIMITER) == -1) throw new AssertException("Deleted user-name '" + name + "' without delimiter '" + UserDeletionManager.DELETED_USER_DELIMITER + "' ");
    String userName = name.substring(name.indexOf(UserDeletionManager.DELETED_USER_DELIMITER) + UserDeletionManager.DELETED_USER_DELIMITER.length(), name.length());
    return userName;
  }
 
 
  //////////////////////////////////////////////////////////
  // Replace author-name in MetaData files with identity-id.
  //////////////////////////////////////////////////////////
  private long replaceAuthorNameWithIdentityKeyInAllMetaData( File aFile, int deepness, long fileCounter) {
    int MAX_RECURSIV_DEEPNESS = 100;
    if (log.isDebug()) log.debug("replaceAuthorNameWithIdentityKeyInAllMetaData: process file=" + aFile.getAbsolutePath());
    if (deepness>MAX_RECURSIV_DEEPNESS) {
      log.error("replaceAuthorNameWithIdentityKeyInAllMetaData: Reach max_recursiv_deepness, metaDir=" + aFile );
      return 0;
    }
    if (aFile.isDirectory()) {
      File[] subFiles = aFile.listFiles();
      for (int j = 0; j < subFiles.length; j++) {
        fileCounter += replaceAuthorNameWithIdentityKeyInAllMetaData(subFiles[j], deepness+1, fileCounter);
       
      }
    } else {
      // it is File
      if (aFile.getName().endsWith(".xml")) {
        try {
          MetaInfoFileImpl metaInfoFile = new MetaInfoFileImpl(aFile);
          if (metaInfoFile.parseXMLdom(aFile) ) {
            // read author direct as XML value and not via getAuthor method because getAuthor is based on Identityreturns '-'
            String username = getAuthorFromXmlMetaData(aFile);
            Identity identity = ManagerFactory.getManager().findIdentityByName(username);
            if (identity == null) {
              // Could not found identity => try to find as deleted username <TIMESTAMP>_bkp_<USERNAME>
              identity = findDeletedIdentityByName(username);
              if (identity != null) {
                metaInfoFile.setAuthor(identity.getName());
              } else {
                // // Could not found identity as deleted-identity too, warn only when username is not empty
                if (username.trim().length() > 0) {
                  log.warn("Could not found identity with username=" + username + " file=" + aFile.getAbsolutePath());
                }
              }
            } else {
              // Set author again to force replacement of username with identity-key
              metaInfoFile.setAuthor(username);
            }
            if (!testMode) {
              metaInfoFile.write();
              if (log.isDebug()) log.debug("replaceAuthorNameWithIdentityKeyInAllMetaData setAuthor=" + username + " in meta file=" + aFile.getAbsolutePath() );
            } else {
              log.info("replaceAuthorNameWithIdentityKeyInAllMetaData: TEST-MODE !!! DO NOT WRITE setAuthor=" + username + " in meta file=" + aFile.getAbsolutePath());
            }
            fileCounter++;
          }
        } catch (Exception dex) {
          log.warn("Could not read meta file=" + aFile.getAbsolutePath() + " , DocumentException=", dex);
        }
      } else {
        log.warn("replaceAuthorNameWithIdentityKeyInAllMetaData: found non meta file=" + aFile.getAbsolutePath() );
      }
    }
    if (fileCounter % 10 == 0) {
      DBFactory.getInstance().intermediateCommit();
    }
    return fileCounter;
  }

  /**
   * Must be in sync with MetaInfo class.
   * @param fMeta
   * @return
   */
  public String getAuthorFromXmlMetaData(File fMeta) {
    if (fMeta == null) return null;
    FileInputStream in;
    try in = new FileInputStream(fMeta); }
    catch (FileNotFoundException e) {  return null}
    XMLParser xmlp = new XMLParser();
    Document doc = xmlp.parse(in, false);
    if (doc == null) return null;
   
    // extract data from XML
    Element root = doc.getRootElement();
    Element authorElement = root.element("author");
    if (authorElement != null) {
      return authorElement.getText();
    }
    return null;
  }

  /////////////////////////////////////////////////////////////////
  // Replace author-name in DialogElement entries with identity-id.
  /////////////////////////////////////////////////////////////////
  public void migrateAllDialogElementsProperty() {
    int counter = 0;
    int counterDialogElement = 0;
    int counterSetAuthor = 0;
    List properties = findAllProperty();
    // loop over all property
    for (Iterator iterator = properties.iterator(); iterator.hasNext();) {
      Property prop = (Property) iterator.next();
      DialogPropertyElements dialogPropertyElements = (DialogPropertyElements) XStreamHelper.fromXML(prop.getTextValue());
      // loop over all elements
      List list = dialogPropertyElements.getDialogPropertyElements();
      for (Iterator iterator2 = list.iterator(); iterator2.hasNext();) {
        DialogElement dialogElement = (DialogElement) iterator2.next();
        counterDialogElement++;
        try {
          String author = dialogElement.getAuthor();
          Identity identity = ManagerFactory.getManager().findIdentityByName(author);
          if (identity == null) {
            // Did not found username => try to find as deleted username <TIMESTAMP>_bks_<USERNAME>
            identity = findDeletedIdentityByName(author);
            if (identity != null) {
              log.audit("migrateAllDialogElementsProperty setIdentityId for author=" + author + " with IdentityId=" + identity.getKey());
              dialogElement.setAuthorIdentityId(identity.getKey().toString());
              counter++;
            } else {
              log.warn("migrateAllDialogElementsProperty: Could not found username=" + author);
            }
          } else {
            dialogElement.setAuthor(author);
            counterSetAuthor++;
          }
          if (counterDialogElement % 10 == 0) {
            DBFactory.getInstance().intermediateCommit();
          }
        } catch (Throwable th) {
          log.warn("migrateAllDialogElementsProperty: Exception in loop over dialog-elements, exception should be handled in DialogElement, " + dialogElement, th);
          DBFactory.getInstanceForClosing().rollbackAndCloseSession();
        }
      }
      String dialogElementsAsXML = XStreamHelper.toXML(dialogPropertyElements);
      prop.setTextValue(dialogElementsAsXML);
      if (!testMode) {
        PropertyManager.getInstance().updateProperty(prop);
      } else {
        log.warn("migrateAllDialogElementsProperty: TEST-MODE !!! DO NOT updateProperty");
      }
    }
    log.info("migrateAllDialogElementsProperty: replace #" + counter + " deleted user-names, call setAuthor #" + counterSetAuthor + " for existing user-names  in #" + counterDialogElement + " DialogElements");
  }
 
  private List findAllProperty() {
    PropertyManager propMrg = PropertyManager.getInstance();
    List elements = propMrg.listProperties(null, null, "CourseModule", null, null, DialogElementsPropertyManager.PROPERTY_NAME);
    return elements;
  }

  public Identity findDeletedIdentityByName(String identityName) {
    if (identityName == null) throw new AssertException("findIdentitybyName: name was null");
    identityName = "%" + UserDeletionManager.DELETED_USER_DELIMITER + identityName;
    List identities = DBFactory.getInstance().find(
        "select ident from org.olat.basesecurity.IdentityImpl as ident where ident.name like ? and ident.status = ?", new Object[] { identityName, Identity.STATUS_DELETED },
        new Type[] { Hibernate.STRING, Hibernate.INTEGER});
    int size = identities.size();
    if (size == 0) return null;
    if (size != 1) throw new AssertException("non unique name in identites: " + identityName);
    Identity identity = (Identity) identities.get(0);
    return identity;
  }

}

class MigrationIdentity implements Identity {
  private String name;
 
  public MigrationIdentity(String name) {
    this.name = name;
  }
 
  public Date getLastLogin() {
    // TODO Auto-generated method stub
    return null;
  }

  public String getName() {
    return name;
  }

  public Integer getStatus() {
    // TODO Auto-generated method stub
    return null;
  }

  public User getUser() {
    // TODO Auto-generated method stub
    return null;
  }

  public void setLastLogin(Date loginDate) {
    // TODO Auto-generated method stub
   
  }

  public void setName(String name) {
    // TODO Auto-generated method stub
   
  }

  public void setStatus(Integer newStatus) {
    // TODO Auto-generated method stub
   
  }

  public Date getCreationDate() {
    // TODO Auto-generated method stub
    return null;
  }

  public boolean equalsByPersistableKey(Persistable persistable) {
    // TODO Auto-generated method stub
    return false;
  }

  public Long getKey() {
    // TODO Auto-generated method stub
    return null;
  }
 
}
TOP

Related Classes of org.olat.upgrade.MigrationIdentity

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.