/**
* 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.extensions;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.olat.core.defaults.dispatcher.StaticMediaDispatcher;
import org.olat.core.gui.render.StringOutput;
import org.olat.core.logging.StartupException;
import org.olat.core.logging.Tracing;
import org.olat.core.util.FileUtils;
import org.olat.core.util.WebappHelper;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
/**
*
* Description:<br>
* Handles extension points for extending OLAT. See olat_extensions.xml for enabling or disabling:
* <ul>
* <li>Top navaigation -> olatsites</li>
* <li>Course building blocks -> bbfactory</li>
* <li>Home portal, and portlets -> olat_portals.xml</li>
* <li>Webdav mount points -> webdavfactory</li>
* </ul>
* Generic extensions are handled in @see org.olat.core.extensions.ExtManager
*
* @author guido
*/
public class ExtensionManager {
private static final ExtensionManager INSTANCE = new ExtensionManager();
private static final String EXTENSIONS_FILE = "olat_extensions.xml";
private static final String EXTENSIONS_CSS = "extensions.css";
private static final String EXTENSIONS_SUBDIR = "extensions";
private XmlBeanFactory pluginFactory;
private static List extensions;
private static File fExtensionsDeploymentDir;
private static List extensionCSSFiles;
private ExtensionManager() {
// singleton
// initialize extension resource deployment directory
fExtensionsDeploymentDir = new File(WebappHelper.getContextRoot() + "/static/" + EXTENSIONS_SUBDIR);
if (fExtensionsDeploymentDir.exists()) FileUtils.deleteDirsAndFiles(fExtensionsDeploymentDir, true, true);
fExtensionsDeploymentDir.mkdirs();
extensionCSSFiles = new ArrayList();
extensions = new ArrayList();
}
public static ExtensionManager getInstance() { return INSTANCE; }
public void init() {
//TODO:fj:cleanup ExtManager and ExtensionManager
FileSystemResource pluginConfigFile = new FileSystemResource(WebappHelper.getContextRoot() + "/WEB-INF/" + EXTENSIONS_FILE);
pluginFactory = new XmlBeanFactory(pluginConfigFile);
// get all configured beand and load them to initialize the classes properly
String[] beanFactories = pluginFactory.getBeanDefinitionNames();
int i = 0;
try {
for(/*i already declared*/; i < beanFactories.length; i++){
pluginFactory.getBean(beanFactories[i]);
Tracing.logInfo("Initializing OLATExtension::" + beanFactories[i]
+ " from plugin factory::"
+ pluginConfigFile.getFile().getAbsolutePath(),
ExtensionManager.class);
}
} catch (BeansException e) {
throw new StartupException("Error deploying extensions! ["+beanFactories[i]+"] Make sure your application server has write access to your olat installation: ", e);
}
}
/**
* @param beanName
* @return the bean
*/
public Object getBean(String beanName) {
return pluginFactory.getBean(beanName);
}
public void doPostStartupTasks() {
deployExtensionCSS();
OLATExtension ext = null;
for (Iterator iter = extensions.iterator(); iter.hasNext();) {
try {
ext = (OLATExtension)iter.next();
ext.setup();
} catch (Exception e) {
throw new StartupException("Extension '" + ext.getName() + "' threw exception during setup()",e);
}
}
}
public void doPreShutdownTasks() {
OLATExtension ext = null;
for (Iterator iter = extensions.iterator(); iter.hasNext();) {
try {
ext = (OLATExtension)iter.next();
ext.tearDown();
} catch (Exception e) {
Tracing.logError("Extension '" + ext.getName() + "' threw exception during setup()",e, ExtensionManager.class);
}
}
}
/**
* @param extension
* @throws IOException
*/
public void deployExtension(OLATExtension extension) throws IOException {
Tracing.logInfo("Deploying extension '" + extension.getName() + "'.",ExtensionManager.class);
copyExtensionResources(extension);
installExtensionCSS(extension);
//setExtensionURLBuilder(extension);
}
private void deployExtensionCSS() {
File f = new File(WebappHelper.getContextRoot() + "/static/" + EXTENSIONS_SUBDIR + "/" + EXTENSIONS_CSS);
StringOutput so = new StringOutput();
for (Iterator iter = extensionCSSFiles.iterator(); iter.hasNext();) {
String extensionCSS = (String) iter.next();
so.append("@import url(");
StaticMediaDispatcher.renderStaticURI(so, EXTENSIONS_SUBDIR + "/" + extensionCSS);
so.append(");\n");
}
FileUtils.save(f , so.toString(), "utf-8");
}
private void copyExtensionResources(OLATExtension extension) throws IOException {
List res = extension.getExtensionResources();
if (res == null) return;
for (Iterator iterator = res.iterator(); iterator.hasNext();) {
ExtensionResource extRes = (ExtensionResource)iterator.next();
copyExtensionResource(extension, extRes);
}
}
private void copyExtensionResource(OLATExtension extension, ExtensionResource extRes) throws IOException {
// create extension base path
File fExtBasepath = getExtensionBasePath(extension);
if (!fExtBasepath.exists()) fExtBasepath.mkdirs();
InputStream is = null;
OutputStream os = null;
try {
File fExtSubpath = new File(fExtBasepath, extRes.getTargetSubpath());
if (!fExtSubpath.exists())
if (!fExtSubpath.mkdirs()) throw new IOException("Unable to create targetpath for extension '" + extension.getName() + "' at " + fExtSubpath.getCanonicalPath());
is = extRes.getContent();
os = new FileOutputStream(new File(fExtSubpath, extRes.getTargetName()));
FileUtils.copy(is, os);
} catch (IOException e) {
throw new StartupException("Failed to deploy extension '" + extension.getName() + "'.",e);
} finally {
FileUtils.closeSafely(is);
FileUtils.closeSafely(os);
}
}
@SuppressWarnings("unchecked")
private void installExtensionCSS(OLATExtension extension) throws IOException {
ExtensionResource extRes = extension.getExtensionCSS();
if (extRes == null) return;
copyExtensionResource(extension, extRes);
String cssTarget = extension.getName() + extRes.getTargetSubpath() + "/" + extRes.getTargetName();
extensionCSSFiles.add(cssTarget);
}
//private void setExtensionURLBuilder(OLATExtension extension) {
// extension.setExtensionResourcesBaseURI(OLATContext.getContextPath() + "/raw/" + EXTENSIONS_SUBDIR + "/" + extension.getName() + "/");
//}
private File getExtensionBasePath(OLATExtension extension) {
return new File(fExtensionsDeploymentDir, extension.getName());
}
}