/* * Copyright 2003-2017 JetBrains s.r.o. * * 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 jetbrains.mps.smodel.tempmodel; import jetbrains.mps.classloading.ClassLoaderManager; import jetbrains.mps.module.ReloadableModuleBase; import jetbrains.mps.project.ModuleId; import jetbrains.mps.project.facets.JavaModuleFacet; import jetbrains.mps.project.structure.model.ModelRootDescriptor; import jetbrains.mps.project.structure.modules.ModuleDescriptor; import jetbrains.mps.project.structure.modules.ModuleReference; import jetbrains.mps.smodel.MPSModuleOwner; import jetbrains.mps.vfs.IFile; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.module.SModule; import org.jetbrains.mps.openapi.module.SModuleFacet; import org.jetbrains.mps.openapi.module.SModuleId; import org.jetbrains.mps.openapi.module.SModuleReference; import org.jetbrains.mps.openapi.persistence.Memento; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Set; /** * TODO: rewrite class loading functional : it must not extend ReloadableModuleBase and be maintained by ClassLoaderManager. * TODO: it does not belong to any repository */ public class TempModule extends ReloadableModuleBase implements SModule, MPSModuleOwner { private final static Logger LOG = LogManager.getLogger(TempModule.class); private final ModuleDescriptor myDescriptor; private final JavaModuleFacet myJavaModuleFacet; public TempModule(Set<ModelRootDescriptor> modelRoots, boolean withSourceGen, boolean withJavaFacet) { if (withSourceGen && !withJavaFacet) { throw new IllegalArgumentException("Don't have GenerationTargetFacet implementation other than JavaModuleFacet handy, either write one or re-consider arguments"); } SModuleId id = ModuleId.regular(); SModuleReference reference = new ModuleReference("TempModule" + id, id); setModuleReference(reference); myDescriptor = new ModuleDescriptor(); myDescriptor.getModelRootDescriptors().addAll(modelRoots); dependenciesChanged(); if (withJavaFacet) { IFile sourcesGen = withSourceGen ? createTempDirectory("TempModule_source_gen") : null; IFile classesGen = createTempDirectory("TempModule_classes_gen"); myJavaModuleFacet = new TempModuleJavaFacet(sourcesGen, classesGen); } else { myJavaModuleFacet = null; } } @Override public void reload() { if (!willLoad()) return; LOG.debug("Reloading temporary module " + this); ClassLoaderManager.getInstance().reloadModule(this); } @Override public boolean willLoad() { return myJavaModuleFacet != null; } public boolean isHidden() { return true; } @Override public boolean isReadOnly() { return false; } @NotNull @Override public Iterable<SModuleFacet> getFacets() { return myJavaModuleFacet != null ? Collections.singleton(myJavaModuleFacet) : Collections.emptySet(); } public String toString() { return getModuleName() + " [temp module]"; } @Override public ModuleDescriptor getModuleDescriptor() { return myDescriptor; } private IFile createTempDirectory(String prefix) { try { final File temp; temp = File.createTempFile(prefix, ""); if (!(temp.delete())) { throw new IOException("Could not delete temp file: " + temp.getAbsolutePath()); } if (!(temp.mkdir())) { throw new IOException("Could not create temp directory: " + temp.getAbsolutePath()); } return getFileSystem().getFile(temp.getAbsolutePath()); } catch (IOException e) { LOG.error(e.toString(), e); return null; } } private class TempModuleJavaFacet implements JavaModuleFacet { private final IFile mySourceGen; private final IFile myClassesGen; @NotNull @Override public String getFacetType() { return FACET_TYPE; } public TempModuleJavaFacet(IFile sourceGen, IFile classesGen) { mySourceGen = sourceGen; myClassesGen = classesGen; } @Override public boolean isCompileInMps() { return true; } @Nullable @Override public IFile getOutputRoot() { return mySourceGen; } @NotNull @Override public IFile getClassesGen() { return myClassesGen; } @Override public Set<String> getLibraryClassPath() { return Collections.emptySet(); } @Override public Set<String> getClassPath() { return Collections.singleton(getClassesGen().getPath()); } @Override public Set<String> getAdditionalSourcePaths() { return Collections.emptySet(); } @NotNull @Override public SModule getModule() { return TempModule.this; } @Override public void save(Memento memento) { throw new UnsupportedOperationException(); } @Override public void load(Memento memento) { throw new UnsupportedOperationException(); } } }