/******************************************************************************* * Copyright (c) 2004, 2010 Intel Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Intel Corporation - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.managedbuilder.projectconverter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; import org.eclipse.cdt.managedbuilder.internal.core.ManagedBuildInfo; import org.eclipse.cdt.managedbuilder.internal.dataprovider.ProjectConverter; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.osgi.framework.Version; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.ui.dialogs.IOverwriteQuery; /** * @noextend This class is not intended to be subclassed by clients. * @noinstantiate This class is not intended to be instantiated by clients. */ public class UpdateManagedProjectManager { static private ThreadLocal<Map<String, UpdateManagedProjectManager>> fThreadInfo = new ThreadLocal<Map<String, UpdateManagedProjectManager>>(); static private IOverwriteQuery fBackupFileOverwriteQuery = null; static private IOverwriteQuery fOpenQuestionQuery = null; static private IOverwriteQuery fUpdateProjectQuery = null; private ManagedBuildInfo fConvertedInfo= null; private boolean fIsInfoReadOnly = false; final private IProject fProject; private UpdateManagedProjectManager(IProject project){ fProject = project; } public static void setBackupFileOverwriteQuery(IOverwriteQuery backupFileOverwriteQuery){ fBackupFileOverwriteQuery = backupFileOverwriteQuery; } /* public static void setOpenQuestionQuery(IOverwriteQuery openQuestionQuery){ fOpenQuestionQuery = openQuestionQuery; } */ public static void setUpdateProjectQuery(IOverwriteQuery updateProjectQuery){ fUpdateProjectQuery = updateProjectQuery; } synchronized static private UpdateManagedProjectManager getUpdateManager(IProject project){ UpdateManagedProjectManager mngr = getExistingUpdateManager(project); if(mngr == null) mngr = createUpdateManager(project); return mngr; } static private UpdateManagedProjectManager getExistingUpdateManager(IProject project){ Map<String, UpdateManagedProjectManager> map = getManagerMap(false); return map != null ? (UpdateManagedProjectManager)map.get(project.getName()) : null; } static private UpdateManagedProjectManager createUpdateManager(IProject project){ UpdateManagedProjectManager mngr = new UpdateManagedProjectManager(project); getManagerMap(true).put(project.getName(),mngr); return mngr; } static public void addInfo(final IProject project, ManagedBuildInfo info) { getUpdateManager(project).setBuildInfo(info); } static public void delInfo(final IProject project) { removeUpdateManager(project); } static private void removeUpdateManager(IProject project){ UpdateManagedProjectManager mngr = getExistingUpdateManager(project); if(mngr == null) return; getManagerMap(false).remove(project.getName()); } static private Map<String, UpdateManagedProjectManager> getManagerMap(boolean create){ Map<String, UpdateManagedProjectManager> map = fThreadInfo.get(); if(map == null && create){ map = new HashMap<String, UpdateManagedProjectManager>(); fThreadInfo.set(map); } return map; } /** * @since 8.0 */ static protected Version getManagedBuildInfoVersion(String version){ if(version == null) version = "1.2"; //$NON-NLS-1$ return new Version(version); } static public boolean isCompatibleProject(IManagedBuildInfo info) { if(info == null) return false; Version projVersion = getManagedBuildInfoVersion(info.getVersion()); Version compVersion = ManagedBuildManager.getBuildInfoVersion(); if(compVersion.equals(projVersion)) return true; return false; } /* (non-Javadoc) * Create a back-up file * * @param settingsFile * @param suffix * @param monitor * @param project */ static void backupFile(IFile settingsFile, String suffix, IProgressMonitor monitor, IProject project){ UpdateManagedProjectManager mngr = getExistingUpdateManager(project); if(mngr == null || mngr.fIsInfoReadOnly) return; IContainer destFolder = project; IFile dstFile = destFolder.getFile(new Path(settingsFile.getName()+suffix)); mngr.backupFile(settingsFile, dstFile, monitor, project, fBackupFileOverwriteQuery); } /* * Creates a back-up file. This method is useful for the vendor who wants * to create a backup of '.cdtbuild' file before project conversion. * @param settingsFile * @param suffix * @param monitor * @param project */ public static void backupSettingsFile(IFile settingsFile, String suffix, IProgressMonitor monitor, IProject project){ UpdateManagedProjectManager mngr = getUpdateManager(project); if(mngr == null || mngr.fIsInfoReadOnly) return; IContainer destFolder = project; IFile dstFile = destFolder.getFile(new Path(settingsFile.getName()+suffix)); mngr.backupFile(settingsFile, dstFile, monitor, project, fBackupFileOverwriteQuery); } /* (non-Javadoc) * Create a back-up file * * @param srcFile * @param dstFile * @param monitor * @param project * @param query */ private void backupFile(IFile srcFile, IFile dstFile, IProgressMonitor monitor, IProject project, IOverwriteQuery query){ File src = srcFile.getLocation().toFile(); File dst = dstFile.getLocation().toFile(); backupFile(src, dst, monitor, project, query); } private void backupFile(File srcFile, File dstFile, IProgressMonitor monitor, IProject project, IOverwriteQuery query){ try { if (dstFile.exists()) { boolean shouldUpdate; if(query != null) shouldUpdate = ProjectConverter.getBooleanFromQueryAnswer(query.queryOverwrite(dstFile.getName())); else shouldUpdate = ProjectConverter.openQuestion(fProject, "UpdateManagedProjectManager.0", ConverterMessages.getResourceString("UpdateManagedProjectManager.0"), //$NON-NLS-1$ //$NON-NLS-2$ ConverterMessages.getFormattedString("UpdateManagedProjectManager.1", new String[] {dstFile.getName(),project.getName()}), fOpenQuestionQuery, false); //$NON-NLS-1$ if (shouldUpdate) { dstFile.delete(); } else { throw new OperationCanceledException(ConverterMessages.getFormattedString("UpdateManagedProjectManager.2", project.getName())); //$NON-NLS-1$ } } copyFile(srcFile, dstFile); } catch(Exception e){ fIsInfoReadOnly = true; } } void copyFile(File src, File dst) throws IOException { FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream(src); fos = new FileOutputStream(dst); final int BUFSIZ = 1024; byte buf[] = new byte[BUFSIZ]; int len = 0; while ((len = fis.read(buf)) > 0) { fos.write(buf, 0, len); } } finally { if (fis != null) { fis.close(); } if (fos != null) { fos.close(); } } } private void restoreFile(String backupFileName, String restoreFileName, IProgressMonitor monitor, IProject project){ IContainer destFolder = project; File restoreFile = destFolder.getFile(new Path(restoreFileName)).getLocation().toFile(); File backupFile = destFolder.getFile(new Path(backupFileName)).getLocation().toFile(); try{ if (restoreFile.exists()) { restoreFile.delete(); } copyFile(backupFile, restoreFile); } catch(Exception e){ fIsInfoReadOnly = true; } } // static private boolean openQuestion(IResource rc, final String title, final String message){ // return ProjectConverter.openQuestion(rc, message, title, message, fOpenQuestionQuery, false); // } // static public void openInformation(final String title, final String message){ // if(fOpenQuestionQuery != null) // return;// getBooleanFromQueryAnswer(fOpenQuestionQuery.queryOverwrite(message)); // // IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); // if(window == null){ // IWorkbenchWindow windows[] = PlatformUI.getWorkbench().getWorkbenchWindows(); // window = windows[0]; // } // // final Shell shell = window.getShell(); // shell.getDisplay().syncExec(new Runnable() { // public void run() { // MessageDialog.openInformation(shell,title,message); // } // }); // } /** * returns ManagedBuildInfo for the current project * if converter is currently running * @param project project for which ManagedBuildInfo is needed * @return the pointer to the project ManagedBuildInfo or null * if converter is no running */ static public ManagedBuildInfo getConvertedManagedBuildInfo(IProject project){ UpdateManagedProjectManager mngr = getExistingUpdateManager(project); if(mngr == null) return null; return mngr.getConvertedManagedBuildInfo(); } private ManagedBuildInfo getConvertedManagedBuildInfo(){ return fConvertedInfo; } private void setBuildInfo(ManagedBuildInfo info) { fConvertedInfo = info; } private void doProjectUpdate(ManagedBuildInfo info) throws CoreException { fConvertedInfo = info; NullProgressMonitor monitor = new NullProgressMonitor(); IFile settingsFile = fProject.getFile(ManagedBuildManager.SETTINGS_FILE_NAME); IFile backupFile = fProject.getFile(ManagedBuildManager.SETTINGS_FILE_NAME + "_initial"); //$NON-NLS-1$ if(isCompatibleProject(info)) return; try { if (!settingsFile.getLocation().toFile().exists()) throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1, ConverterMessages.getResourceString("UpdateManagedProjectManager.6"),null)); //$NON-NLS-1$ backupFile(settingsFile, backupFile, monitor, fProject, new IOverwriteQuery(){ public String queryOverwrite(String file) { return ALL; } }); Version version = getManagedBuildInfoVersion(info.getVersion()); boolean shouldUpdate; if(fUpdateProjectQuery != null) shouldUpdate = ProjectConverter.getBooleanFromQueryAnswer(fUpdateProjectQuery.queryOverwrite(fProject.getFullPath().toString())); else shouldUpdate = ProjectConverter.openQuestion(fProject, "UpdateManagedProjectManager.3", ConverterMessages.getResourceString("UpdateManagedProjectManager.3"), //$NON-NLS-1$ //$NON-NLS-2$ ConverterMessages.getFormattedString("UpdateManagedProjectManager.4", new String[]{fProject.getName(),version.toString(),ManagedBuildManager.getBuildInfoVersion().toString()}), //$NON-NLS-1$ fOpenQuestionQuery, false); if (!shouldUpdate){ fIsInfoReadOnly = true; throw new CoreException(new Status(IStatus.CANCEL, ManagedBuilderCorePlugin.getUniqueIdentifier(), ConverterMessages.getResourceString("UpdateManagedProjectManager.7"))); //$NON-NLS-1$ } IFile projectFile = fProject.getFile(".project"); //$NON-NLS-1$ if(projectFile.exists()) backupFile(projectFile, "_initial", monitor, fProject); //$NON-NLS-1$ if(version.equals(new Version(1,2,0))){ UpdateManagedProject12.doProjectUpdate(monitor, fProject); version = getManagedBuildInfoVersion(info.getVersion()); } if(version.equals(new Version(2,0,0))){ UpdateManagedProject20.doProjectUpdate(monitor, fProject); version = getManagedBuildInfoVersion(info.getVersion()); } if(version.equals(new Version(2,1,0))){ UpdateManagedProject21.doProjectUpdate(monitor, fProject); version = getManagedBuildInfoVersion(info.getVersion()); } if(version.equals(new Version(3,0,0))){ UpdateManagedProject30.doProjectUpdate(monitor, fProject); version = getManagedBuildInfoVersion(info.getVersion()); } if (new Version(4,0,0).compareTo(version)>0){ UpdateManagedProject31.doProjectUpdate(monitor, fProject); version = getManagedBuildInfoVersion(info.getVersion()); } if(!isCompatibleProject(info)){ throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1, ConverterMessages.getFormattedString("UpdateManagedProjectManager.5", //$NON-NLS-1$ new String [] { ManagedBuildManager.getBuildInfoVersion().toString(), version.toString(), info.getManagedProject().getId() } ),null)); } } catch (CoreException e) { fIsInfoReadOnly = true; throw e; } finally{ if(fIsInfoReadOnly){ restoreFile(backupFile.getName(), settingsFile.getName(), monitor, fProject); info.setReadOnly(true); } } } /** * updates the managed project * * @param project the project to be updated * @param info the ManagedBuildInfo for the current project * @throws CoreException if conversion failed */ static public void updateProject(final IProject project, ManagedBuildInfo info) throws CoreException{ try { getUpdateManager(project).doProjectUpdate(info); } finally { removeUpdateManager(project); // We have to this here since we use java.io.File to handle the update. IWorkspace workspace = project.getWorkspace(); ISchedulingRule rule = workspace.getRuleFactory().refreshRule(project); WorkspaceJob job = new WorkspaceJob("Refresh Project") { //$NON-NLS-1$ @Override public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { project.refreshLocal(IResource.DEPTH_ONE, null); return Status.OK_STATUS; } }; job.setRule(rule); job.schedule(); } } }