/* * Copyright 2003-2011 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.build; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.RoamingType; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.BuildNumber; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.io.ZipUtil; import jetbrains.mps.InternalFlag; import jetbrains.mps.RuntimeFlags; import jetbrains.mps.build.SamplesExtractor.MyState; import jetbrains.mps.samples.SamplesInfo; import jetbrains.mps.util.PathManager; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; @State( name = "LastBuildNumber", storages = { @Storage(value = "sampleProjects.xml", roamingType = RoamingType.DISABLED), @Storage(value = "other.xml", deprecated = true) } ) public class SamplesExtractor implements ApplicationComponent, PersistentStateComponent<MyState>, SamplesInfo { private static final Logger LOG = LogManager.getLogger(SamplesExtractor.class); private static final String SAMPLES_IN_MPS_HOME_DIR = "samples"; public static SamplesExtractor getInstance() { return ((SamplesExtractor) ApplicationManager.getApplication().getComponent(SamplesInfo.class)); } private MyState myState; private final ApplicationInfo myApplicationInfo; private boolean myIsSamplesInMPSHome; public SamplesExtractor(ApplicationInfo applicationInfo) { myApplicationInfo = applicationInfo; } @NotNull public String getComponentName() { return "Samples Extractor"; } public void initComponent() { if (myState == null) { myState = new MyState(); } updateSamplesLocation(); if (RuntimeFlags.isTestMode()) { return; } checkSamplesAndUpdateIfNeeded(); } private void checkSamplesAndUpdateIfNeeded() { int currentBuildNumber = currentBuildNumberString(); if (myState.myLastBuildNumber < currentBuildNumber) { if (!myIsSamplesInMPSHome) { extractSamples(); } } } private int currentBuildNumberString() { BuildNumber buildNumber = myApplicationInfo.getBuild(); String currentBuildNumberString = buildNumber.asString(); if (!currentBuildNumberString.matches("MPS[-\\.\\d]*.*") || InternalFlag.isInternalMode()) { // "Normal" build number starts with MPS, then goes some actual build number with numbers and dots and dashes, then goes some suffix like M1. // If build number looks like "11.snapshot", we consider it developers build and do not to extract samples. return MyState.DEFAULT; } return buildNumber.getBuildNumber(); } private void updateSamplesLocation() { File samplesDirectory = new File(getSamplesPathInMPSHome()); myIsSamplesInMPSHome = samplesDirectory.exists() && samplesDirectory.isDirectory(); } public void disposeComponent() { } public MyState getState() { return myState; } public void loadState(MyState state) { myState = state; } public String getSamplesPath() { return myIsSamplesInMPSHome ? getSamplesPathInMPSHome() : getSamplesPathInUserHome(); } private String getSamplesPathInUserHome() { return System.getProperty("user.home") + File.separator + SAMPLES_IN_USER_HOME_DIR + "." + getSuffix(); } private String getSuffix() { String majorVersion = myApplicationInfo.getMajorVersion(); assert majorVersion != null; String minorVersion = myApplicationInfo.getMinorVersion(); assert minorVersion != null; return majorVersion + "." + minorVersion; } private String getSamplesPathInMPSHome() { return PathManager.getHomePath() + File.separator + SAMPLES_IN_MPS_HOME_DIR; } public void extractSamples() { final File samplesZipFile = new File(PathManager.getHomePath() + File.separator + SAMPLES_IN_MPS_HOME_ZIP); if (samplesZipFile.exists()) { final File samplesDir = new File(getSamplesPathInUserHome()); if (samplesDir.exists()) { ApplicationManager.getApplication().invokeLater(() -> { int answer = Messages.showYesNoDialog( "Do you want to replace directory\n" + samplesDir + "\n with version " + myApplicationInfo.getBuild().asString() + " (old directory contents will be deleted)?", "Replace MPS Samples?", Messages.getQuestionIcon()); if (answer == Messages.YES) { FileUtil.delete(samplesDir); actuallyExtractSamples(samplesZipFile); } }); } else { actuallyExtractSamples(samplesZipFile); } } myState.myLastBuildNumber = currentBuildNumberString(); } private void actuallyExtractSamples(File samplesZipFile) { try { File tmpDir = FileUtil.createTempDirectory("MPSSamples", ""); ZipUtil.extract(samplesZipFile, tmpDir, null); File from = new File(tmpDir + File.separator + SAMPLES_IN_USER_HOME_DIR); File to = new File(getSamplesPathInUserHome()); if (!FileUtil.moveDirWithContent(from, to) && !to.exists()) { FileUtil.copyDir(from, to); } FileUtil.delete(tmpDir); } catch (IOException e) { LOG.error(null, e); } } public static class MyState { public int myLastBuildNumber = DEFAULT; private static final int DEFAULT = -1; } }