/** * Copyright 2012 Universitat Pompeu Fabra. * * 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. * * */ package org.onexus.resource.manager.internal; import org.onexus.resource.api.IAuthorizationManager; import static org.onexus.resource.api.IAuthorizationManager.READ; import static org.onexus.resource.api.IAuthorizationManager.WRITE; import org.onexus.resource.api.IResourceListener; import org.onexus.resource.api.IResourceManager; import org.onexus.resource.api.IResourceSerializer; import org.onexus.resource.api.Loader; import org.onexus.resource.api.ORI; import org.onexus.resource.api.Plugin; import org.onexus.resource.api.Project; import org.onexus.resource.api.Resource; import org.onexus.resource.manager.internal.providers.AbstractProjectProvider; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleEvent; import org.osgi.framework.BundleListener; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.service.blueprint.container.BlueprintEvent; import org.osgi.service.blueprint.container.BlueprintListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.List; public class ResourceManager implements IResourceManager, BlueprintListener, BundleListener { private static final Logger LOGGER = LoggerFactory.getLogger(ResourceManager.class); // Injected OSGi services private IResourceSerializer serializer; private IAuthorizationManager authorizationManager; private BundleContext context; // Loaders and managers private PluginLoader pluginLoader; private ProjectsContainer projectsContainer; public ResourceManager() { super(); } @Override public Project getProject(String projectUrl) { if (!authorizationManager.check(READ, new ORI(projectUrl))) { throw new SecurityException("Unauthorized READ access to project '" + projectUrl + "'"); } AbstractProjectProvider projectManager = getProjectProvider(projectUrl); if (projectManager == null) { return null; } return projectManager.getProject(); } @Override public List<Project> getProjects() { List<Project> projects = new ArrayList<Project>(); for (String projectUrl : projectsContainer.getProjectUrls()) { try { AbstractProjectProvider provider = projectsContainer.getProjectProvider(projectUrl); Project project = provider.getProject(); if (authorizationManager.check(READ, project.getORI())) { projects.add(project); } } catch (Exception e) { LOGGER.error("Loading project '" + projectUrl + "'", e); } } return projects; } @Override public <T extends Resource> T load(Class<T> resourceType, ORI resourceURI) { assert resourceType != null; if (resourceURI == null) { return null; } if (!authorizationManager.check(READ, resourceURI)) { throw new SecurityException("Unauthorized READ access to '" + resourceURI.toString() + "'"); } AbstractProjectProvider provider = getProjectProvider(resourceURI.getProjectUrl()); T output = (T) provider.getResource(resourceURI); if (output == null) { throw new RuntimeException("Resource '" + resourceURI + "' not found."); } if (!resourceType.isAssignableFrom(output.getClass())) { throw new RuntimeException("The resource '" + resourceURI + "' is not a '" + resourceType.getSimpleName() + "' is a '" + output.getClass().getSimpleName() + "'"); } return output; } @Override public <T extends Resource> List<T> loadChildren(Class<T> resourceType, ORI parentURI) { if (!authorizationManager.check(READ, parentURI)) { throw new SecurityException("Unauthorized READ access to '" + parentURI.toString() + "'"); } AbstractProjectProvider provider = getProjectProvider(parentURI.getProjectUrl()); return provider.getResourceChildren(authorizationManager, resourceType, parentURI); } @Override public void save(Resource resource) { if (resource == null) { return; } if (!authorizationManager.check(WRITE, resource.getORI())) { throw new SecurityException("Unauthorized WRITE access to '" + resource.getORI().toString() + "'"); } AbstractProjectProvider provider = getProjectProvider(resource.getORI().getProjectUrl()); provider.save(resource); } @Override public <T> T getLoader(Class<T> serviceClass, Plugin plugin, Loader loader) { if (plugin == null || plugin.getLocation() == null) { String msg = "Plugin '" + loader.getPlugin() + "' not defined in project. "; throw new RuntimeException(msg); } String pluginLocation = plugin.getLocation(); try { for (ServiceReference service : context.getServiceReferences(serviceClass.getName(), null)) { Bundle bundle = service.getBundle(); if (bundle == null) { continue; } if (pluginLocation.startsWith(bundle.getLocation())) { return (T) context.getService(service); } } } catch (InvalidSyntaxException e) { LOGGER.error("On context.getServiceReferences()", e); } // TODO Auto-install tool String msg = "Plugin for '" + loader + "' not found."; LOGGER.error(msg); throw new RuntimeException(msg); } @Override public void addResourceListener(IResourceListener resourceListener) { projectsContainer.addResourceListener(resourceListener); } @Override public void importProject(String projectName, String projectUri) { projectsContainer.importProject(projectName, projectUri); } @Override public void syncProject(String projectURI) { if (!authorizationManager.check(READ, new ORI(projectURI, null))) { throw new SecurityException("Unauthorized READ access to '" + projectURI + "'"); } AbstractProjectProvider provider = getProjectProvider(projectURI); provider.syncProject(); } @Override public void updateProject(String projectUrl) { if (!authorizationManager.check(WRITE, new ORI(projectUrl, null))) { throw new SecurityException("Unauthorized WRITE access to '" + projectUrl + "'"); } AbstractProjectProvider provider = getProjectProvider(projectUrl); provider.updateProject(); } public void init() { // Projects container this.pluginLoader = new PluginLoader(context); this.projectsContainer = new ProjectsContainer(serializer, pluginLoader); } public void destroy() { this.projectsContainer.destroy(); } private AbstractProjectProvider getProjectProvider(String projectUrl) { AbstractProjectProvider provider = projectsContainer.getProjectProvider(projectUrl); if (provider == null) { throw new InvalidParameterException("Project '" + projectUrl + "' is not imported"); } return provider; } public IResourceSerializer getSerializer() { return serializer; } public void setSerializer(IResourceSerializer serializer) { this.serializer = serializer; } public BundleContext getContext() { return context; } public void setContext(BundleContext context) { this.context = context; } public IAuthorizationManager getAuthorizationManager() { return authorizationManager; } public void setAuthorizationManager(IAuthorizationManager authorizationManager) { this.authorizationManager = authorizationManager; } public ProjectsContainer getProjectsContainer() { return projectsContainer; } public void setProjectsContainer(ProjectsContainer projectsContainer) { this.projectsContainer = projectsContainer; } @Override public void blueprintEvent(BlueprintEvent blueprintEvent) { if (blueprintEvent.getType() == BlueprintEvent.CREATED) { this.projectsContainer.bundleCreated(blueprintEvent.getBundle().getBundleId()); } } @Override public void bundleChanged(BundleEvent bundleEvent) { if (bundleEvent.getType() == BundleEvent.UNINSTALLED) { this.projectsContainer.bundleUninstalled(bundleEvent.getBundle().getBundleId()); } } }