/* * Copyright 2014 MovingBlocks * * 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.terasology.engine.module; import com.google.common.collect.Sets; import org.terasology.assets.Asset; import org.terasology.engine.TerasologyConstants; import org.terasology.engine.paths.PathManager; import org.terasology.module.ClasspathModule; import org.terasology.module.DependencyInfo; import org.terasology.module.Module; import org.terasology.module.ModuleEnvironment; import org.terasology.module.ModuleLoader; import org.terasology.module.ModuleMetadata; import org.terasology.module.ModuleMetadataJsonAdapter; import org.terasology.module.ModulePathScanner; import org.terasology.module.ModuleRegistry; import org.terasology.module.TableModuleRegistry; import org.terasology.module.sandbox.APIScanner; import org.terasology.module.sandbox.BytecodeInjector; import org.terasology.module.sandbox.ModuleSecurityManager; import org.terasology.module.sandbox.ModuleSecurityPolicy; import org.terasology.module.sandbox.StandardPermissionProviderFactory; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.lang.reflect.ReflectPermission; import java.net.URISyntaxException; import java.security.Policy; import java.util.Collections; import java.util.Set; import java.util.stream.Collectors; public class ModuleManagerImpl implements ModuleManager { private StandardPermissionProviderFactory permissionProviderFactory = new StandardPermissionProviderFactory(); private ModuleRegistry registry; private ModuleEnvironment environment; private ModuleMetadataJsonAdapter metadataReader; public ModuleManagerImpl() { metadataReader = new ModuleMetadataJsonAdapter(); for (ModuleExtension ext : StandardModuleExtension.values()) { metadataReader.registerExtension(ext.getKey(), ext.getValueType()); } Module engineModule; try (Reader reader = new InputStreamReader(getClass().getResourceAsStream("/engine-module.txt"), TerasologyConstants.CHARSET)) { ModuleMetadata metadata = metadataReader.read(reader); engineModule = ClasspathModule.create(metadata, getClass(), Module.class, Asset.class); } catch (IOException e) { throw new RuntimeException("Failed to read engine metadata", e); } catch (URISyntaxException e) { throw new RuntimeException("Failed to convert engine library location to path", e); } registry = new TableModuleRegistry(); registry.add(engineModule); ModulePathScanner scanner = new ModulePathScanner(new ModuleLoader(metadataReader)); scanner.getModuleLoader().setModuleInfoPath(TerasologyConstants.MODULE_INFO_FILENAME); scanner.scan(registry, PathManager.getInstance().getModulePaths()); DependencyInfo engineDep = new DependencyInfo(); engineDep.setId(engineModule.getId()); engineDep.setMinVersion(engineModule.getVersion()); engineDep.setMaxVersion(engineModule.getVersion().getNextPatchVersion()); registry.stream().filter(mod -> mod != engineModule).forEach(mod -> mod.getMetadata().getDependencies().add(engineDep)); setupSandbox(); loadEnvironment(Sets.newHashSet(engineModule), true); } private void setupSandbox() { ExternalApiWhitelist.CLASSES.stream().forEach(clazz -> permissionProviderFactory.getBasePermissionSet().addAPIClass(clazz)); ExternalApiWhitelist.PACKAGES.stream().forEach(packagee -> permissionProviderFactory.getBasePermissionSet().addAPIPackage(packagee)); APIScanner apiScanner = new APIScanner(permissionProviderFactory); registry.stream().filter(Module::isOnClasspath).forEach(apiScanner::scan); permissionProviderFactory.getBasePermissionSet().grantPermission("com.google.gson", ReflectPermission.class); permissionProviderFactory.getBasePermissionSet().grantPermission("com.google.gson.internal", ReflectPermission.class); Policy.setPolicy(new ModuleSecurityPolicy()); System.setSecurityManager(new ModuleSecurityManager()); } @Override public ModuleRegistry getRegistry() { return registry; } @Override public ModuleEnvironment getEnvironment() { return environment; } @Override public ModuleEnvironment loadEnvironment(Set<Module> modules, boolean asPrimary) { Set<Module> finalModules = Sets.newLinkedHashSet(modules); finalModules.addAll(registry.stream().filter(Module::isOnClasspath).collect(Collectors.toList())); ModuleEnvironment newEnvironment = new ModuleEnvironment(finalModules, permissionProviderFactory, Collections.<BytecodeInjector>emptyList()); if (asPrimary) { environment = newEnvironment; } return newEnvironment; } @Override public ModuleMetadataJsonAdapter getModuleMetadataReader() { return metadataReader; } }