/* license-start
*
* Copyright (C) 2008 - 2013 Crispico, <http://www.crispico.com/>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, at <http://www.gnu.org/licenses/>.
*
* Contributors:
* Crispico - Initial API and implementation
*
* license-end
*/
package org.flowerplatform.web;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServlet;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.flowerplatform.common.CommonPlugin;
import org.flowerplatform.common.plugin.AbstractFlowerJavaPlugin;
import org.flowerplatform.communication.CommunicationPlugin;
import org.flowerplatform.communication.tree.remote.GenericTreeStatefulService;
import org.flowerplatform.editor.EditorPlugin;
import org.flowerplatform.editor.model.EditorModelPlugin;
import org.flowerplatform.web.database.DatabaseManager;
import org.flowerplatform.web.projects.WebProjectAccessController;
import org.flowerplatform.web.projects.remote.ProjectsService;
import org.flowerplatform.web.security.mail.SendMailService;
import org.flowerplatform.web.security.service.GroupService;
import org.flowerplatform.web.security.service.OrganizationService;
import org.flowerplatform.web.security.service.PermissionService;
import org.flowerplatform.web.security.service.UserService;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.crispico.flower.mp.codesync.base.CodeSyncPlugin;
import com.crispico.flower.mp.codesync.code.CodeSyncCodePlugin;
/**
* @author Cristi
* @author Mariana
*/
public class WebPlugin extends AbstractFlowerJavaPlugin {
protected static WebPlugin INSTANCE;
private final static Logger logger = LoggerFactory.getLogger(WebPlugin.class);
private List<GenericTreeStatefulService>treeStatefulServicesDisplayingWorkingDirectoryContent = new ArrayList<GenericTreeStatefulService>();
public static WebPlugin getInstance() {
return INSTANCE;
}
/**
* @author Razvan Tache
*/
public static final String TREE_NODE_FILE_SYSTEM_IS_DIRECTORY = "isDirectory";
/**
* Only set by plugin test project activator, to avoid {@link ClassNotFoundException}
* for <code>BridgeServlet</code>.
*
* @author Mariana
*/
private String TESTING_FLAG = "testing";
private EclipseDispatcherServlet eclipseDispatcherServlet;
private DatabaseManager databaseManager;
private Map<String, List<String>> nodeTypeCategoryToNodeTypesMap = new HashMap<String, List<String>>();
public Map<String, List<String>> getNodeTypeCategoryToNodeTypesMap() {
return nodeTypeCategoryToNodeTypesMap;
}
public WebPlugin() {
super();
INSTANCE = this;
CommonPlugin.getInstance().initializeFlowerProperties(
this.getClass().getClassLoader().getResourceAsStream("META-INF/flower-web.properties"));
// Initially, this initialization was in the attribute initializer. But this lead to an issue:
// .communication was loaded, which processed the extension points, including services,
// which forced the initialization of .web.git plugin, which wanted to use the properties, which
// are initialized in the line above. Maybe in the future we'll solve this kind of issues
eclipseDispatcherServlet = new EclipseDispatcherServlet();
databaseManager = new DatabaseManager();
}
/**
* We use reflection because there is no compile time dependency,
* which would generate a circular project dependency (or would imply
* exotic projects setup.
*
*/
private void invokeBridgeServletMethod(String methodName, Object parameter) {
try {
@SuppressWarnings("rawtypes")
Class bridgeServletClass = Class.forName("org.eclipse.equinox.servletbridge.BridgeServlet");
@SuppressWarnings("unchecked")
Method registerServletDelegateMethod = bridgeServletClass.getDeclaredMethod(methodName, new Class[] {HttpServlet.class});
registerServletDelegateMethod.invoke(null, parameter);
} catch (Exception e) {
throw new RuntimeException("Error registering/unregistering to webapp bridge servlet.", e);
}
}
/**
* @author Mariana
*/
public DatabaseManager getDatabaseManager() {
return databaseManager;
}
public void start(final BundleContext bundleContext) throws Exception {
super.start(bundleContext);
if (bundleContext.getProperty(TESTING_FLAG) == null) {
invokeBridgeServletMethod("registerServletDelegate", eclipseDispatcherServlet);
}
initExtensionPoint_nodeTypeToCategoriesMapping();
// do these initializations here, after the services have been instantiated
CommunicationPlugin.getInstance().getAllServicesStartedListeners().add(new Runnable() {
@Override
public void run() {
UserService.getInstance().getObservable().addObserver(PermissionService.getInstance().getSecurityEntityObserver());
GroupService.getInstance().getObservable().addObserver(PermissionService.getInstance().getSecurityEntityObserver());
OrganizationService.getInstance().getObservable().addObserver(PermissionService.getInstance().getSecurityEntityObserver());
OrganizationService.getInstance().getObservable().addObserver(OrganizationService.getInstance().getOrganizationObserver());
// TODO CS: see GH211
databaseManager.initialize();
SendMailService.getInstance().initializeProperties();
try {
// TODO CS: see GH211
CommunicationPlugin.getInstance().getServiceRegistry().registerService(ProjectsService.SERVICE_ID, new ProjectsService());
} catch (Exception e) {
throw new RuntimeException(e);
}
EditorPlugin.getInstance().setFileAccessController(new WebFileAccessController());
EditorModelPlugin.getInstance().setModelAccessController(new WebModelAccessController());
CodeSyncPlugin.getInstance().setProjectsProvider(new WebProjectAccessController());
}
});
}
private void initExtensionPoint_nodeTypeToCategoriesMapping() {
// nodeTypeToCategoriesMapping
IConfigurationElement[] configurationElements = Platform.getExtensionRegistry().getConfigurationElementsFor("org.flowerplatform.web.nodeTypeToCategoriesMapping");
for (IConfigurationElement configurationElement : configurationElements) {
String nodeType = configurationElement.getAttribute("nodeType");
for (IConfigurationElement nodeTypeConfigurationElement : configurationElement.getChildren()) {
String nodeTypeCategory = nodeTypeConfigurationElement.getAttribute("nodeTypeCategory");
List<String> nodesTypesForCurrentCategoryNodeType = nodeTypeCategoryToNodeTypesMap.get(nodeTypeCategory);
if (nodesTypesForCurrentCategoryNodeType == null) {
nodesTypesForCurrentCategoryNodeType = new ArrayList<String>();
nodeTypeCategoryToNodeTypesMap.put(nodeTypeCategory, nodesTypesForCurrentCategoryNodeType);
}
nodesTypesForCurrentCategoryNodeType.add(nodeType);
}
}
if (logger.isDebugEnabled()) {
for (Map.Entry<String, List<String>> entry : nodeTypeCategoryToNodeTypesMap.entrySet()) {
logger.debug("ExplorerTreeStatefulService: for nodeCategoryType = {}, these are the nodeTypes that have subscribed = {}", entry.getKey(), entry.getValue());
}
}
}
public void stop(BundleContext bundleContext) throws Exception {
super.stop(bundleContext);
if (bundleContext.getProperty(TESTING_FLAG) == null) {
invokeBridgeServletMethod("unregisterServletDelegate", eclipseDispatcherServlet);
}
INSTANCE = null;
}
public List<GenericTreeStatefulService> getTreeStatefulServicesDisplayingWorkingDirectoryContent() {
return treeStatefulServicesDisplayingWorkingDirectoryContent;
}
}