Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: cb0a877bf7a8fecdf8911e2c8d8b403970faa647 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                                
                                                                


                                                                       
                                                           


                                         

                
                                                     
                                                                                 










                                              

                      
                               
                              




                                                     




                                                              
                                                                     




                                                                  
                                                     






                                                           

                                                         

                                 


                                                                           
                                                                                                                            


                                                                                             
                                                                                                              


                                                    
                                                 
                                        
 
                                                                                                        


                                             

                 
 

                                   

                                      
                                                           

                                                                                                                        

         
                 
                                              


                                                                                        

                                    
                     
                                                              

                                                              
                                                
                         
                                                  
                                                               
                                                         


                               

                                            
                 







                                                                                                            
 
                                                               

                                                                                           



                                                                                       






                                                                                                                                    
                                             


                                                                                  



                                         



                                                                                 

                                                  
                                                      
                           





                                                   
 



                                                                                                           
                                                               
                                         

                                                                                                                                        
                 
                                                                    
                                                                                             

         
                                                     
                                                                   

                                         
                                                                                                                
                                     
                                                                        
                                                                       
                                                                       
                                         
                                           

                                                      
                                               





                                                   
                                                                                                                           
                                                                              


                                                     

                                                       

                                       
                                                                               
                                                         

                                                                                                                                                


                                                                                             
                                                                                
                                                                        
                                                      
                                                                            
 

                                                           
 
                                                                             
                                                                       
                                                          


                                                                              


                                                                                                        
                                                                               




                                                                           
                                                                                                            
                                                                 
                                                                                                          



                                                       
                                                                                                   
                                                                
                                 



                                                                                                                            
                                                                                       
                           









                                                               
                                                                                                                  

                                                                                         
                                                             
                     
                                                                        

                                                              
                                                              
                                 
                         
                                                                     
                                                      

                                                                    
                                                   
                                                                             




                                                                                         
                           
                                                                     

                 



                                                                                             




                                                               
                 
 
                                                                 
                                                         
                                              

                                                       
                                         
                                                                  

                                                       
                                                                                    
                                                                    
                                                                                               
                                                                                                                                 
                                                                                                                      


                                                                                                            
                                                         
                                                 
                                                                                 
                                                                   
                                                               



                                         
                              

         
/*******************************************************************************
 * Copyright (c) 2007, 2014 Wind River Systems, Inc. and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Markus Schorn - initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMIndexerTask;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
import org.eclipse.cdt.internal.core.pdom.indexer.PDOMIndexerTask;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.osgi.util.NLS;

public class TeamPDOMImportOperation implements IWorkspaceRunnable {
	static final String CHECKSUMS_NAME = "checksums.dat"; //$NON-NLS-1$
	static final String INDEX_NAME = "cdt-index.pdom"; //$NON-NLS-1$
	private static final Pattern PROJECT_VAR_PATTERN = Pattern.compile("\\$\\{(project_[a-zA-Z0-9]*)\\}"); //$NON-NLS-1$
	private static final String PROJECT_VAR_REPLACEMENT_BEGIN = "\\${$1:"; //$NON-NLS-1$
	private static final String PROJECT_VAR_REPLACEMENT_END = "}"; //$NON-NLS-1$
	private static final String DOLLAR_OR_BACKSLASH_REPLACEMENT = "\\\\$0"; //$NON-NLS-1$
	private static final Pattern DOLLAR_OR_BACKSLASH_PATTERN = Pattern.compile("[\\$\\\\]"); //$NON-NLS-1$

	private static final class FileAndChecksum {
		public ITranslationUnit fFile;
		public IIndexFragmentFile fIFile;
		public byte[] fChecksum;

		public FileAndChecksum(ITranslationUnit tu, IIndexFragmentFile ifile, byte[] checksum) {
			fFile = tu;
			fIFile = ifile;
			fChecksum = checksum;
		}
	}

	private ICProject fProject;
	private boolean fSuccess;
	private boolean fShowActivity;

	public TeamPDOMImportOperation(ICProject project) {
		fProject = project;
		fShowActivity = PDOMIndexerTask.checkDebugOption(IPDOMIndexerTask.TRACE_ACTIVITY, "true"); //$NON-NLS-1$
	}

	@Override
	public void run(IProgressMonitor pm) {
		if (fShowActivity) {
			System.out.println("Indexer: PDOMImporter start"); //$NON-NLS-1$
		}
		fSuccess = false;
		Exception ex = null;
		try {
			File importFile = getImportLocation();
			if (importFile.exists()) {
				doImportIndex(importFile, pm);
				fSuccess = true;
			}
		} catch (InterruptedException e) {
			throw new OperationCanceledException();
		} catch (IOException | CoreException e) {
			ex = e;
		}

		if (ex != null) {
			CCorePlugin.log(ex);
		}
		if (fShowActivity) {
			System.out.println("Indexer: PDOMImporter completed, ok=" + fSuccess); //$NON-NLS-1$
		}
	}

	public boolean wasSuccessful() {
		return fSuccess;
	}

	private File getImportLocation() throws CoreException {
		IProject project = fProject.getProject();
		String locationString = IndexerPreferences.getIndexImportLocation(project);
		return expandLocation(project, locationString);
	}

	static File expandLocation(IProject project, String loc) throws CoreException {
		String replacement = PROJECT_VAR_REPLACEMENT_BEGIN
				+ DOLLAR_OR_BACKSLASH_PATTERN.matcher(project.getName()).replaceAll(DOLLAR_OR_BACKSLASH_REPLACEMENT)
				+ PROJECT_VAR_REPLACEMENT_END;

		loc = PROJECT_VAR_PATTERN.matcher(loc).replaceAll(replacement);
		IStringVariableManager varManager = VariablesPlugin.getDefault().getStringVariableManager();
		IPath location = new Path(varManager.performStringSubstitution(loc));
		if (!location.isAbsolute()) {

			if (project.getLocation() != null)
				location = project.getLocation().append(location);
		}
		return location.toFile();
	}

	private void doImportIndex(File importFile, IProgressMonitor monitor)
			throws CoreException, InterruptedException, IOException {
		ZipFile zip = new ZipFile(importFile);
		Map<?, ?> checksums = null;
		try {
			importIndex(zip, monitor);
			checksums = getChecksums(zip);
		} finally {
			try {
				zip.close();
			} catch (IOException e) {
				CCorePlugin.log(e);
			}
		}

		checkIndex(checksums, monitor);
	}

	private void importIndex(ZipFile zip, IProgressMonitor monitor) throws CoreException, IOException {
		ZipEntry indexEntry = zip.getEntry(INDEX_NAME);
		if (indexEntry == null) {
			throw new CoreException(
					CCorePlugin.createStatus(NLS.bind(Messages.PDOMImportTask_errorInvalidArchive, zip.getName())));
		}
		InputStream stream = zip.getInputStream(indexEntry);
		CCoreInternals.getPDOMManager().importProjectPDOM(fProject, stream, monitor);
	}

	private Map<?, ?> getChecksums(ZipFile zip) {
		ZipEntry indexEntry = zip.getEntry(CHECKSUMS_NAME);
		if (indexEntry != null) {
			try {
				ObjectInputStream input = new ObjectInputStream(zip.getInputStream(indexEntry));
				try {
					Object obj = input.readObject();
					if (obj instanceof Map<?, ?>) {
						return (Map<?, ?>) obj;
					}
				} finally {
					input.close();
				}
			} catch (Exception e) {
				CCorePlugin.log(e);
			}
		}
		return Collections.EMPTY_MAP;
	}

	private void checkIndex(Map<?, ?> checksums, IProgressMonitor monitor) throws CoreException, InterruptedException {
		IPDOM obj = CCoreInternals.getPDOMManager().getPDOM(fProject);
		if (!(obj instanceof WritablePDOM)) {
			return;
		}

		WritablePDOM pdom = (WritablePDOM) obj;
		pdom.acquireReadLock();
		try {
			List<FileAndChecksum> filesToCheck = new ArrayList<>();
			if (!pdom.isSupportedVersion()) {
				throw new CoreException(CCorePlugin.createStatus(NLS
						.bind(Messages.PDOMImportTask_errorInvalidPDOMVersion, INDEX_NAME, fProject.getElementName())));
			}

			final IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
			IIndexFragmentFile[] filesToDelete = pdom.getAllFiles();
			for (int i = 0; i < filesToDelete.length; i++) {
				checkMonitor(monitor);
				IIndexFragmentFile ifile = filesToDelete[i];

				byte[] checksum = null;
				ITranslationUnit tu = null;

				IIndexFileLocation ifl = ifile.getLocation();
				String fullPathStr = ifl.getFullPath();
				if (fullPathStr != null) {
					Path fullPath = new Path(fullPathStr);
					IFile file = root.getFile(fullPath);
					boolean exists = file.exists();
					if (!exists) {
						try {
							file.refreshLocal(0, new NullProgressMonitor());
							exists = file.exists();
						} catch (CoreException e) {
							CCorePlugin.log(e);
						}
					}
					if (exists) {
						tu = (ITranslationUnit) CoreModel.getDefault().create(file);
						if (tu != null) {
							checksum = Checksums.getChecksum(checksums, file);
						}
					}
				}
				if (checksum != null) {
					filesToCheck.add(new FileAndChecksum(tu, ifile, checksum));
					filesToDelete[i] = null;
				}
			}

			List<FileAndChecksum> updateTimestamps = getUnchangedWithDifferentTimestamp(checksums, filesToCheck,
					monitor);
			updateIndex(pdom, 1, filesToDelete, updateTimestamps, monitor);
		} finally {
			pdom.releaseReadLock();
		}
	}

	private void checkMonitor(IProgressMonitor monitor) {
		if (monitor.isCanceled()) {
			throw new OperationCanceledException();
		}
	}

	private void updateIndex(WritablePDOM pdom, final int giveupReadlocks, IIndexFragmentFile[] filesToDelete,
			List<FileAndChecksum> updateTimestamps, IProgressMonitor monitor)
			throws InterruptedException, CoreException {
		pdom.acquireWriteLock(giveupReadlocks, null);
		try {
			for (IIndexFragmentFile ifile : filesToDelete) {
				if (ifile != null) {
					checkMonitor(monitor);
					pdom.clearFile(ifile);
				}
			}
			for (FileAndChecksum fc : updateTimestamps) {
				checkMonitor(monitor);

				IIndexFragmentFile file = fc.fIFile;
				if (file != null) {
					IResource r = fc.fFile.getResource();
					if (r != null) {
						file.setTimestamp(r.getLocalTimeStamp());
					}
				}
			}
		} finally {
			pdom.releaseWriteLock(giveupReadlocks, true);
		}
	}

	private List<FileAndChecksum> getUnchangedWithDifferentTimestamp(Map<?, ?> checksums,
			List<FileAndChecksum> filesToCheck, IProgressMonitor monitor) {
		MessageDigest md;
		try {
			md = Checksums.getAlgorithm(checksums);
		} catch (NoSuchAlgorithmException e) {
			CCorePlugin.log(e);
			return Collections.emptyList();
		}

		List<FileAndChecksum> result = new ArrayList<>();
		for (FileAndChecksum cs : filesToCheck) {
			checkMonitor(monitor);

			ITranslationUnit tu = cs.fFile;
			if (tu != null) {
				IPath location = tu.getLocation();
				if (location != null) {
					try {
						final File file = location.toFile();
						if (file.isFile()) {
							IResource res = cs.fFile.getResource();
							if (res == null || res.getLocalTimeStamp() != cs.fIFile.getTimestamp()) {
								byte[] checksum = Checksums.computeChecksum(md, file);
								if (Arrays.equals(checksum, cs.fChecksum)) {
									result.add(cs);
								}
							}
						}
					} catch (IOException | CoreException e) {
						CCorePlugin.log(e);
						result.add(cs);
					}
				}
			}
		}
		return result;
	}
}

Back to the top