migration.RepositoryUpgrader.java Source code

Java tutorial

Introduction

Here is the source code for migration.RepositoryUpgrader.java

Source

/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/osp/trunk/jsf/example/src/java/migration/RepositoryUpgrader.java $
* $Id: RepositoryUpgrader.java 105079 2012-02-24 23:08:11Z ottenhoff@longsight.com $
***********************************************************************************
 *
 * Copyright (c) 2006, 2008 The Sakai Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
**********************************************************************************/

package migration;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.content.api.ContentCollectionEdit;
import org.sakaiproject.content.api.ContentHostingService;
import org.sakaiproject.content.api.ContentResourceEdit;
import org.sakaiproject.db.api.SqlReader;
import org.sakaiproject.db.cover.SqlService;
import org.sakaiproject.entity.api.Entity;
import org.sakaiproject.entity.api.ResourceProperties;
import org.sakaiproject.entity.api.ResourcePropertiesEdit;
import org.sakaiproject.exception.IdInvalidException;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.exception.IdUsedException;
import org.sakaiproject.exception.InconsistentException;
import org.sakaiproject.exception.OverQuotaException;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.exception.ServerOverloadException;
import org.sakaiproject.exception.TypeException;
import org.sakaiproject.time.api.Time;
import org.sakaiproject.time.cover.TimeService;
import org.sakaiproject.tool.api.Session;
import org.sakaiproject.tool.cover.SessionManager;

/**
    
 * "/files" is the base of the repository.
    
 * Resources doesn't have a base.
    
 * 
    
 * "/files/users/*" => "/user/*"
    
 * "/files/worksites/*" => "/group/*"
    
 * respository worksites are ids without dashes and resources worksites have dashes
    
 *    how is that being converted from 1.5=>2.1 in sakai?
    
 * 
    
 * When deleting a folder, it doesn't actually remove the record.  It just adds 2000 years to the modification date.
    
 * This is how we can retain all the info and add our "processed" tag without changing the database.
    
 * 
    
 * @author andersjb
    
 *
    
 */

public class RepositoryUpgrader {

    private final static Log logger = org.apache.commons.logging.LogFactory.getLog(RepositoryUpgrader.class);

    private ContentHostingService contentHostingService;

    /**
        
     * This moves the files from repository to resources.  The process is interruptible.
        
     * This method builds the tree structure
        
     *
        
     */

    public void upgrade()

    {

        contentHostingService = (ContentHostingService) ComponentManager.get(ContentHostingService.APPLICATION_ID);

        // move the folder tree over to the resources

        try {

            moveTree();

        } catch (Exception e) {

            logger.fatal(e);

        }

    }

    /**
        
     * all artifacts have a parent directory
        
     *
        
     */

    protected void moveTree() throws SQLException,

            InconsistentException, PermissionException, IdUsedException, IdInvalidException, TypeException

    {

        moveFolder(null, false);

    }

    /**
        
     * get all the children folders and create them, then recurse those children.
        
     * @param parentId String
        
     */

    protected void moveFolder(ReFolder parentFolder, boolean move) throws SQLException,

            InconsistentException, PermissionException, IdUsedException, IdInvalidException

    {

        List children = getChildren(parentFolder);

        upgradeEntityPaths(children);

        for (Iterator i = children.iterator(); i.hasNext();) {

            RepositoryEntity ent = (RepositoryEntity) i.next();

            ent.transition(move);

        }

    }

    /**
        
     * this pulls in the file from the old location and places it in the resources
        
     * @param parentId String
        
     */

    protected void moveFile(ReFile file) throws SQLException,

            InconsistentException, PermissionException, IdUsedException, IdInvalidException

    {

        //    set the user information into the current session

        Session sakaiSession = SessionManager.getCurrentSession();

        String uid, eid;

        uid = sakaiSession.getUserId();

        eid = sakaiSession.getUserEid();

        sakaiSession.setUserId(file.getOwnerId());

        sakaiSession.setUserEid(file.getOwnerId());

        ResourcePropertiesEdit resourceProperties = contentHostingService.newResourceProperties();

        resourceProperties.addProperty(ResourceProperties.PROP_DISPLAY_NAME, file.getTitle());

        resourceProperties.addProperty(ResourceProperties.PROP_DESCRIPTION, file.getTitle());

        resourceProperties.addProperty(ResourceProperties.PROP_CREATION_DATE,

                dateToTime(file.getCreationDate()).toString());

        resourceProperties.addProperty(ResourceProperties.PROP_MODIFIED_DATE,

                dateToTime(file.getLastModifiedDate()).toString());

        resourceProperties.addProperty(ResourceProperties.PROP_CREATOR, file.getOwnerId());

        resourceProperties.addProperty(ResourceProperties.PROP_MODIFIED_BY, file.getOwnerId());

        try {

            //We can't just add a collection the normal way because we want to override the live properties

            ContentResourceEdit cc = contentHostingService.addResource(file.getUri());

            addProperties(cc.getPropertiesEdit(), resourceProperties);

            cc.setContent("".getBytes());

            cc.setContentType("");

            contentHostingService.commitResource(cc);

            contentHostingService.setUuid(file.getUri(), file.getArtifactId());

        } catch (ServerOverloadException e) {

            throw new RuntimeException(e);

        } catch (OverQuotaException e) {

            throw new RuntimeException(e);

        }

        sakaiSession.setUserId(uid);

        sakaiSession.setUserEid(eid);

    }

    /**
        
     * This should be ordered by uri, always.  the folder always comes first
        
     * @param parentId String of the parent folder structure id
        
     * @return List of class Folder
        
     * @throws SQLException
        
     */

    protected List getChildren(ReFolder parentFolder) //throws SQLException

    {

        Connection connection = null;
        boolean wasCommit = false;
        try {
            connection = SqlService.borrowConnection();

            wasCommit = connection.getAutoCommit();

            connection.setAutoCommit(false);

            String sql = "select row_id, parent,  osp_tree_node.id, osp_tree_node.name, uri, " +

                    "creation, last_modified, owner_id, worksiteId, typeId " +

                    "from osp_tree_node join osp_node_metadata on osp_tree_node.id=osp_node_metadata.id " +

                    "where parent ";

            Object[] fields = null;

            if (parentFolder != null) {

                sql += "=? ";

                fields = new Object[1];

                fields[0] = parentFolder.getFolderStructureId();

            } else

                sql += "is null ";

            sql += "order by uri";

            List children = SqlService.dbRead(connection, sql, fields, new SqlReader() {

                public Object readSqlResultRecord(ResultSet result)

                {

                    try

                    {

                        RepositoryEntity ent = null;

                        String type = result.getString(10);

                        if (type.equals("folder")) {

                            ent = new ReFolder();

                        } else if (type.equals("fileArtifact")) {

                            ent = new ReFile();

                        } else {

                            ent = new ReForm(type);

                        }

                        ent.setFolderStructureId(result.getString(1));

                        ent.setParentFolderId(result.getString(2));

                        ent.setArtifactId(result.getString(3));

                        ent.setTitle(result.getString(4));

                        ent.setUri(result.getString(5));

                        ent.setCreationDate(result.getDate(6));

                        ent.setLastModifiedDate(result.getDate(7));

                        ent.setOwnerId(result.getString(8));

                        ent.setWorksiteId(result.getString(9));

                        return ent;

                    } catch (SQLException ignore) {

                        return null;

                    }

                }

            });

            for (Iterator i = children.iterator(); i.hasNext();) {

                RepositoryEntity ent = (RepositoryEntity) i.next();

                ent.setParentFolder(parentFolder);

            }

            return children;
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                connection.commit();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            try {
                connection.setAutoCommit(wasCommit);
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            SqlService.returnConnection(connection);
        }
        return null;
    }

    protected Time dateToTime(Date in)

    {

        GregorianCalendar gc = new GregorianCalendar();

        gc.setTime(in);

        return TimeService.newTime(gc);

    }

    protected String idToGuid(String str) throws java.lang.IllegalArgumentException

    {

        if (str == null)
            return null;

        int length = str.length();

        if (length == 36 || length == 0)

            return str;

        if (length == 32)

            return str.substring(0, 8) + "-" + str.substring(8, 12) + "-" + str.substring(12, 16)

                    + "-" + str.substring(16, 20) + "-" + str.substring(20, 32);

        throw new IllegalArgumentException("");

    }

    /**
        
     * This method will create a folder in resources if it doesn't exist.
        
     * @param folder
        
     * @throws InconsistentException
        
     * @throws PermissionException
        
     * @throws IdUsedException
        
     * @throws IdInvalidException
        
     * @throws TypeException
        
     */

    protected void createNewResourceFolder(ReFolder folder)

            throws InconsistentException, PermissionException, IdUsedException, IdInvalidException {

        try {

            contentHostingService.getCollection(folder.getUri());

        } catch (PermissionException e) {

            logger.error(e);

        } catch (TypeException e) {

            logger.error(e);

        } catch (IdUnusedException e) {

            // wasn't found, so we need to create it

            //         set the user information into the current session

            Session sakaiSession = SessionManager.getCurrentSession();

            String uid, eid;

            uid = sakaiSession.getUserId();

            eid = sakaiSession.getUserEid();

            sakaiSession.setUserId(folder.getOwnerId());

            sakaiSession.setUserEid(folder.getOwnerId());

            ResourcePropertiesEdit resourceProperties = contentHostingService.newResourceProperties();

            resourceProperties.addProperty(ResourceProperties.PROP_DISPLAY_NAME, folder.getTitle());

            resourceProperties.addProperty(ResourceProperties.PROP_DESCRIPTION, folder.getTitle());

            resourceProperties.addProperty(ResourceProperties.PROP_CREATION_DATE,

                    dateToTime(folder.getCreationDate()).toString());

            resourceProperties.addProperty(ResourceProperties.PROP_MODIFIED_DATE,

                    dateToTime(folder.getLastModifiedDate()).toString());

            resourceProperties.addProperty(ResourceProperties.PROP_CREATOR, folder.getOwnerId());

            resourceProperties.addProperty(ResourceProperties.PROP_MODIFIED_BY, folder.getOwnerId());

            //We can't just add a collection the normal way because we want to override the live properties

            ContentCollectionEdit cc = contentHostingService.addCollection(folder.getUri());

            addProperties(cc.getPropertiesEdit(), resourceProperties);

            contentHostingService.commitCollection(cc);

            sakaiSession.setUserId(uid);

            sakaiSession.setUserEid(eid);

        }

    }

    /**
        
     * strips "/files", transitions "/users" => "/user"
        
     * @param folders
        
     */

    protected void upgradeEntityPaths(List folders)

    {

        for (Iterator i = folders.iterator(); i.hasNext();) {

            RepositoryEntity ent = (RepositoryEntity) i.next();

            String uri = ent.getUri();

            if (uri.startsWith(Entity.SEPARATOR + "files"))

                uri = uri.substring((Entity.SEPARATOR + "files").length());

            if (uri.startsWith(Entity.SEPARATOR + "users")) {

                uri = uri.substring((Entity.SEPARATOR + "users").length());

                if (uri.length() == 0)

                    ent.setTitle("user");

                uri = Entity.SEPARATOR + "user" + uri;

            } else if (uri.startsWith(Entity.SEPARATOR + "worksites")) {

                uri = uri.substring((Entity.SEPARATOR + "worksites").length());

                if (uri.length() == 0)

                    ent.setTitle("group");

                uri = Entity.SEPARATOR + "group" + uri;

            }

            // all folders need to have an end separator

            if (ent.isFolder() && !uri.endsWith(Entity.SEPARATOR))

                uri += Entity.SEPARATOR;

            ent.setUri(uri);

            ent.setArtifactId(idToGuid(ent.getArtifactId()));

        }

    }

    /**
        
     * Add properties for a resource.
        
     * 
        
     * @param r
        
     *        The resource.
        
     * @param props
        
     *        The properties.
        
     */

    protected void addProperties(ResourcePropertiesEdit p, ResourceProperties props)

    {

        if (props == null)
            return;

        Iterator it = props.getPropertyNames();

        while (it.hasNext())

        {

            String name = (String) it.next();

            p.addProperty(name, props.getProperty(name));

        }

    } // addProperties

    public ContentHostingService getContentHostingService() {

        return contentHostingService;

    }

    public void setContentHostingService(ContentHostingService contentHostingService) {

        this.contentHostingService = contentHostingService;

    }

    private abstract class RepositoryEntity {

        protected String folderStructureId, parentFolderId, artifactId, title, uri, ownerId, worksiteId, type;

        protected ReFolder parentFolder;

        protected Date creationDate, lastModifiedDate;

        public String getArtifactId() {
            return artifactId;
        }

        public void setArtifactId(String artifactId) {
            this.artifactId = artifactId;
        }

        public String getFolderStructureId() {
            return folderStructureId;
        }

        public void setFolderStructureId(String folderStructureId) {

            this.folderStructureId = folderStructureId;
        }

        public String getParentFolderId() {
            return parentFolderId;
        }

        public void setParentFolderId(String parentFolderId) {

            this.parentFolderId = parentFolderId;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public ReFolder getParentFolder() {
            return parentFolder;
        }

        public void setParentFolder(ReFolder parentFolder) {
            this.parentFolder = parentFolder;
        }

        public String getUri() {
            return uri;
        }

        public void setUri(String uri) {
            this.uri = uri;
        }

        public Date getCreationDate() {
            return creationDate;
        }

        public void setCreationDate(Date creationDate) {
            this.creationDate = creationDate;
        }

        public Date getLastModifiedDate() {
            return lastModifiedDate;
        }

        public void setLastModifiedDate(Date lastModifiedDate) {
            this.lastModifiedDate = lastModifiedDate;
        }

        public String getOwnerId() {
            return ownerId;
        }

        public void setOwnerId(String ownerId) {
            this.ownerId = ownerId;
        }

        public String getWorksiteId() {
            return worksiteId;
        }

        public void setWorksiteId(String worksiteId) {
            this.worksiteId = worksiteId;
        }

        public String getType() {
            return type;
        }

        //public void setType(String type) {this.type = type;}

        public abstract void transition(boolean move) throws SQLException,

                InconsistentException, PermissionException, IdUsedException, IdInvalidException;

        public boolean isFolder() {
            return false;
        }

        public boolean isFile() {
            return false;
        }

        public boolean isForm() {
            return false;
        }

    }

    private class ReFolder extends RepositoryEntity {

        public ReFolder() {
            type = "folder";
        }

        public boolean isFolder() {
            return true;
        }

        public void transition(boolean move) throws SQLException,

                InconsistentException, PermissionException, IdUsedException, IdInvalidException

        {

            // create the folder

            if (move)

                createNewResourceFolder(this);

            // move all the children nodes

            moveFolder(this, true);

            // delete this folder

            //        markEntityProcessed(this);

        }

    }

    private class ReFile extends RepositoryEntity {

        public ReFile() {
            type = "fileArtifact";
        }

        public boolean isFile() {
            return true;
        }

        public void transition(boolean move) throws SQLException,

                InconsistentException, PermissionException, IdUsedException, IdInvalidException

        {

            moveFile(this);

            // delete this file

            //         markEntityProcessed(this);

        }

    }

    private class ReForm extends RepositoryEntity {

        public ReForm(String type) {
            this.type = type;
        }

        public boolean isForm() {
            return true;
        }

        public void transition(boolean move) throws SQLException,

                InconsistentException, PermissionException, IdUsedException, IdInvalidException

        {

            //        moveForm(this);

            // delete this file

            //        markEntityProcessed(this);

        }

    }

}