/** * OLAT - Online Learning and Training
* http://www.olat.org *

* Licensed under the Apache 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.apache.org/licenses/LICENSE-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. *

* Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),
* University of Zurich, Switzerland. *

*/ package org.olat.ims.cp; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import org.dom4j.tree.DefaultDocument; import org.dom4j.tree.DefaultElement; import org.olat.core.id.OLATResourceable; import org.olat.core.logging.OLATRuntimeException; import org.olat.core.util.CodeHelper; import org.olat.core.util.FileUtils; import org.olat.core.util.ZipUtil; import org.olat.core.util.vfs.LocalFolderImpl; 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.xml.XMLParser; import org.olat.fileresource.FileResourceManager; import org.olat.ims.cp.objects.CPOrganization; import org.olat.ims.cp.objects.CPResource; import org.olat.ims.cp.ui.CPPage; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; /** * The CP manager implementation. *

* In many cases, method calls are delegated to the content package object. * *

* Initial Date: 04.07.2008
* * @author Sergio Trentini */ public class CPManagerImpl extends CPManager { /** * [spring] */ private CPManagerImpl() { INSTANCE = this; } /** * * @see org.olat.ims.cp.CPManager#load(org.olat.core.util.vfs.VFSContainer) */ public ContentPackage load(VFSContainer directory, OLATResourceable ores) { XMLParser parser = new XMLParser(); ContentPackage cp; VFSLeaf file = (VFSLeaf) directory.resolve("imsmanifest.xml"); if (file != null) { try { DefaultDocument doc = (DefaultDocument) parser.parse(file.getInputStream(), false); cp = new ContentPackage(doc, directory, ores); // If a wiki is imported or a new cp created, set a unique orga // identifier. if (cp.getLastError() == null) { if (cp.isOLATContentPackage() && CPCore.OLAT_ORGANIZATION_IDENTIFIER.equals(cp.getFirstOrganizationInManifest().getIdentifier())) { setUniqueOrgaIdentifier(cp); } } } catch (OLATRuntimeException e) { cp = new ContentPackage(null, directory, ores); logError("Reading imsmanifest failed. Dir: " + directory.getName() + ". Ores: " + ores.getResourceableId(), e); cp.setLastError("Exception reading XML for IMS CP: invalid xml-file ( " + directory.getName() + ")"); } } else { cp = new ContentPackage(null, directory, ores); cp.setLastError("Exception reading XML for IMS CP: IMS-Manifest not found in " + directory.getName()); logError("IMS manifiest xml couldn't be found in dir " + directory.getName() + ". Ores: " + ores.getResourceableId(), null); throw new OLATRuntimeException(CPManagerImpl.class, "The imsmanifest.xml file was not found.", new IOException()); } return cp; } /** * @see org.olat.ims.cp.CPManager#createNewCP(org.olat.core.id.OLATResourceable) */ public ContentPackage createNewCP(OLATResourceable ores, String initalPageTitle) { // copy template cp to new repo-location if (copyTemplCP(ores)) { File cpRoot = FileResourceManager.getInstance().unzipFileResource(ores); logDebug("createNewCP: cpRoot=" + cpRoot); logDebug("createNewCP: cpRoot.getAbsolutePath()=" + cpRoot.getAbsolutePath()); System.out.println("createNewCP: cpRoot.getAbsolutePath()=" + cpRoot.getAbsolutePath()); LocalFolderImpl vfsWrapper = new LocalFolderImpl(cpRoot); ContentPackage cp = load(vfsWrapper, ores); // Modify the copy of the template to get a unique identifier CPOrganization orga = setUniqueOrgaIdentifier(cp); setOrgaTitleToRepoEntryTitle(ores, orga); // Also set the translated title of the inital page. orga.getItems().get(0).setTitle(initalPageTitle); writeToFile(cp); return cp; } else { logError("CP couldn't be created. Error when copying template. Ores: " + ores.getResourceableId(), null); throw new OLATRuntimeException("ERROR while creating new empty cp. an error occured while trying to copy template CP", null); } } /** * Sets the organization title to the title of the repository entry. * * @param ores * @param orga */ private void setOrgaTitleToRepoEntryTitle(OLATResourceable ores, CPOrganization orga) { // Set the title of the organization to the title of the resource. RepositoryManager resMgr = RepositoryManager.getInstance(); RepositoryEntry cpEntry = resMgr.lookupRepositoryEntry(ores, false); if (cpEntry != null) { String title = cpEntry.getDisplayname(); orga.setTitle(title); } } /** * Assigns the organization a unique identifier in order to prevent any * caching issues in the extjs menu tree later. * * @param cp * @return The first organization of the content package. */ private CPOrganization setUniqueOrgaIdentifier(ContentPackage cp) { CPOrganization orga = cp.getFirstOrganizationInManifest(); String newOrgaIdentifier = "olatcp-" + CodeHelper.getForeverUniqueID(); orga.setIdentifier(newOrgaIdentifier); return orga; } public boolean isSingleUsedResource(CPResource res, ContentPackage cp) { return cp.isSingleUsedResource(res); } @Override public String addBlankPage(ContentPackage cp, String title) { return cp.addBlankPage(title); } @Override public String addBlankPage(ContentPackage cp, String title, String parentNodeID) { return cp.addBlankPage(parentNodeID, title); } @Override public void updatePage(ContentPackage cp, CPPage page) { cp.updatePage(page); } /** * @see org.olat.ims.cp.CPManager#addElement(org.olat.ims.cp.ContentPackage, * org.dom4j.tree.DefaultElement) */ public boolean addElement(ContentPackage cp, DefaultElement newElement) { return cp.addElement(newElement); } /** * @see org.olat.ims.cp.CPManager#addElement(org.olat.ims.cp.ContentPackage, * org.dom4j.tree.DefaultElement, java.lang.String) */ public boolean addElement(ContentPackage cp, DefaultElement newElement, String parentIdentifier, int position) { return cp.addElement(newElement, parentIdentifier, position); } /** * * @see org.olat.ims.cp.CPManager#addElementAfter(org.olat.ims.cp.ContentPackage, * org.dom4j.tree.DefaultElement, java.lang.String) */ public boolean addElementAfter(ContentPackage cp, DefaultElement newElement, String identifier) { return cp.addElementAfter(newElement, identifier); } /** * * @see org.olat.ims.cp.CPManager#removeElement(org.olat.ims.cp.ContentPackage, * java.lang.String) */ public void removeElement(ContentPackage cp, String identifier, boolean deleteResource) { cp.removeElement(identifier, deleteResource); } /** * @see org.olat.ims.cp.CPManager#moveElement(org.olat.ims.cp.ContentPackage, * java.lang.String, java.lang.String, int) */ public void moveElement(ContentPackage cp, String nodeID, String newParentID, int position) { cp.moveElement(nodeID, newParentID, position); } /** * * @see org.olat.ims.cp.CPManager#copyElement(org.olat.ims.cp.ContentPackage, * java.lang.String) */ public String copyElement(ContentPackage cp, String sourceID) { return cp.copyElement(sourceID, sourceID); } /** * @see org.olat.ims.cp.CPManager#getDocument(org.olat.ims.cp.ContentPackage) */ public DefaultDocument getDocument(ContentPackage cp) { return cp.getDocument(); } public String getItemTitle(ContentPackage cp, String itemID) { return cp.getItemTitle(itemID); } /** * @see org.olat.ims.cp.CPManager#getElementByIdentifier(org.olat.ims.cp.ContentPackage, * java.lang.String) */ public DefaultElement getElementByIdentifier(ContentPackage cp, String identifier) { return cp.getElementByIdentifier(identifier); } @Override public CPTreeDataModel getTreeDataModel(ContentPackage cp) { return cp.buildTreeDataModel(); } /** * * @see org.olat.ims.cp.CPManager#getFirstOrganizationInManifest(org.olat.ims.cp.ContentPackage) */ @Override public CPOrganization getFirstOrganizationInManifest(ContentPackage cp) { return cp.getFirstOrganizationInManifest(); } /** * * @see org.olat.ims.cp.CPManager#getFirstPageToDisplay(org.olat.ims.cp.ContentPackage) */ @Override public CPPage getFirstPageToDisplay(ContentPackage cp) { return cp.getFirstPageToDisplay(); } /** * @see org.olat.ims.cp.CPManager#WriteToFile(org.olat.ims.cp.ContentPackage) */ public void writeToFile(ContentPackage cp) { cp.writeToFile(); } /** * @see org.olat.ims.cp.CPManager#writeToZip(org.olat.ims.cp.ContentPackage) */ public VFSLeaf writeToZip(ContentPackage cp) { OLATResourceable ores = cp.getResourcable(); VFSContainer cpRoot = cp.getRootDir(); VFSContainer oresRoot = FileResourceManager.getInstance().getFileResourceRootImpl(ores); RepositoryEntry repoEntry = RepositoryManager.getInstance().lookupRepositoryEntry(ores, false); String zipFileName = "imscp.zip"; if (repoEntry != null) { String zipName = repoEntry.getResourcename(); if (zipName != null && zipName.endsWith(".zip")) { zipFileName = zipName; } } // delete old archive and create new one VFSItem oldArchive = oresRoot.resolve(zipFileName); if (oldArchive != null) { oldArchive.delete(); } ZipUtil.zip(cpRoot.getItems(), oresRoot.createChildLeaf(zipFileName)); VFSLeaf zip = (VFSLeaf) oresRoot.resolve(zipFileName); return zip; } /** * * @see org.olat.ims.cp.CPManager#getPageByItemId(org.olat.ims.cp.ContentPackage, * java.lang.String) */ @Override public String getPageByItemId(ContentPackage cp, String itemIdentifier) { return cp.getPageByItemId(itemIdentifier); } /** * copies the default,empty, cp template to the new ores-directory * * @param ores * @return */ private boolean copyTemplCP(OLATResourceable ores) { File root = FileResourceManager.getInstance().getFileResourceRoot(ores); String packageName = ContentPackage.class.getCanonicalName(); String path = packageName.replace('.', '/'); path = path.replace("/ContentPackage", "/_resources/imscp.zip"); path = VFSManager.sanitizePath(path); URL url = this.getClass().getResource(path); try { File f = new File(url.toURI()); if (f.exists() && root.exists()) { FileUtils.copyFileToDir(f, root); } else { logError("cp template was not copied. Source: " + url + " Target: " + root.getAbsolutePath(), null); } } catch (URISyntaxException e) { logError("Bad url syntax when copying cp template. url: " + url + " Ores:" + ores.getResourceableId(), null); return false; } return true; } }