uidesigner/com.nokia.sdt.sourcegen/src/com/nokia/sdt/sourcegen/core/SourceGenContext.java
changeset 0 fb279309251b
equal deleted inserted replaced
-1:000000000000 0:fb279309251b
       
     1 /*
       
     2 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 package com.nokia.sdt.sourcegen.core;
       
    19 
       
    20 import com.nokia.cpp.internal.api.utils.core.Check;
       
    21 import com.nokia.cpp.internal.api.utils.core.FileUtils;
       
    22 import com.nokia.cpp.internal.api.utils.core.IDisposable;
       
    23 import com.nokia.cpp.internal.api.utils.core.Logging;
       
    24 import com.nokia.cpp.internal.api.utils.core.Message;
       
    25 import com.nokia.cpp.internal.api.utils.core.TrackedResource;
       
    26 import com.nokia.sdt.datamodel.IDesignerDataModel;
       
    27 import com.nokia.sdt.datamodel.adapter.IComponentInstance;
       
    28 import com.nokia.sdt.datamodel.util.MessageLocators;
       
    29 import com.nokia.sdt.sourcegen.*;
       
    30 import com.nokia.sdt.sourcegen.contributions.ComponentSourceGenGatherer;
       
    31 import com.nokia.sdt.sourcegen.contributions.IContributionGatherer;
       
    32 import com.nokia.sdt.sourcegen.contributions.domains.cpp.*;
       
    33 import com.nokia.sdt.utils.*;
       
    34 import com.nokia.sdt.workspace.IProjectContext;
       
    35 import com.nokia.sdt.workspace.WorkspaceContext;
       
    36 
       
    37 import org.eclipse.cdt.core.dom.ICodeReaderFactory;
       
    38 import org.eclipse.core.resources.*;
       
    39 import org.eclipse.core.runtime.*;
       
    40 
       
    41 import java.io.*;
       
    42 import java.text.MessageFormat;
       
    43 import java.util.*;
       
    44 
       
    45 /**
       
    46  * This context holds the modified file state while
       
    47  * generating C/C++ source.
       
    48  * 
       
    49  *
       
    50  */
       
    51 public class SourceGenContext implements IDisposable, ISourceManipulatorProvider {
       
    52     /** Moveable reference to the project */
       
    53     TrackedResource trackedProject;
       
    54     /** Base directory: set to non-null for testing outside project,
       
    55      * otherwise the project's base is used */
       
    56     private File baseDir;
       
    57 
       
    58     /** Map of IPath to ISourceManipulator */
       
    59     private Map pathsToSources;
       
    60     
       
    61     /** Set of IPath of sources created without ISourceManipulator */
       
    62     private Set<IPath> pathsToExtraFiles;
       
    63     
       
    64     //private WorkInProgressCodeReaderFactory codeReaderFactory;
       
    65     private ICodeReaderFactory codeReaderFactory;
       
    66 	ISourceGenProvider provider;
       
    67     
       
    68 	IContributionGatherer gatherer;
       
    69 	
       
    70     /**
       
    71      * 
       
    72      */
       
    73     public SourceGenContext(ISourceGenProvider provider) {
       
    74     	this.provider = provider;
       
    75         this.pathsToSources = new HashMap();
       
    76         pathsToExtraFiles = new HashSet<IPath>();
       
    77         
       
    78         //codeReaderFactory = new MemoryBufferCodeReaderFactory(this);
       
    79         codeReaderFactory = new WorkInProgressCodeReaderFactory();
       
    80         this.gatherer = new ComponentSourceGenGatherer();
       
    81     }
       
    82     
       
    83     /**
       
    84      * NOTE: This form is only to be used by CppDomain
       
    85      * @param project
       
    86      */
       
    87     public SourceGenContext(IProject project) {
       
    88     	this((ISourceGenProvider)null);
       
    89     	setProject(project);
       
    90     }
       
    91 
       
    92 	/* (non-Javadoc)
       
    93      * @see com.nokia.sdt.utils.IDisposable#dispose()
       
    94      */
       
    95     public void dispose() {
       
    96     }
       
    97 
       
    98     public IContributionGatherer getContributionGatherer() {
       
    99     	return gatherer;
       
   100     }
       
   101     
       
   102     public void setProject(IProject project) {
       
   103         if (trackedProject != null) {
       
   104             trackedProject.dispose();
       
   105             trackedProject = null;
       
   106         }
       
   107         if (project != null) {
       
   108         	trackedProject = new TrackedResource(project);
       
   109         	setBaseDir(null);
       
   110         }
       
   111     }
       
   112     
       
   113     public IProject getProject() {
       
   114         if (trackedProject == null)
       
   115             return null;
       
   116         return trackedProject.getProject();
       
   117     }
       
   118     
       
   119     /**
       
   120      * Revert changed sources
       
   121      */
       
   122     public void revert() {
       
   123        	for (Iterator iter = pathsToSources.values().iterator(); iter.hasNext();) {
       
   124 			ISourceManipulator manip = (ISourceManipulator) iter.next();
       
   125 			try {
       
   126 				if (manip.changed())
       
   127 					manip.revert();
       
   128 			} catch (CoreException e) {
       
   129 				SourceGenPlugin.getDefault().log(e);
       
   130 			}
       
   131 		}
       
   132     }
       
   133     
       
   134     /**
       
   135      * Reset the context for a new round of generation
       
   136      * <p>
       
   137      * Clears known source files
       
   138      */
       
   139     public void reset() {
       
   140     	for (Iterator iter = pathsToSources.values().iterator(); iter.hasNext();) {
       
   141 			ISourceManipulator manip = (ISourceManipulator) iter.next();
       
   142 			try {
       
   143 				if (manip.changed())
       
   144 					manip.unload();
       
   145 			} catch (CoreException e) {
       
   146 				SourceGenPlugin.getDefault().log(e);
       
   147 			}
       
   148 		}
       
   149         pathsToSources.clear();
       
   150         gatherer.getDeadLocations().clear();
       
   151         pathsToExtraFiles.clear();
       
   152     }
       
   153 
       
   154     /* copied from Eclipse and fixed to work... */
       
   155     /*
       
   156     private int matchingFirstSegments(IPath my, IPath anotherPath) {
       
   157         int anotherPathLen = anotherPath.segmentCount();
       
   158         int max = Math.min(my.segmentCount(), anotherPathLen);
       
   159         int count = 0;
       
   160         for (int i = 0; i < max; i++) {
       
   161             if (!my.segment(i).equalsIgnoreCase(anotherPath.segment(i))) {
       
   162                 return count;
       
   163             }
       
   164             count++;
       
   165         }
       
   166         return count;
       
   167     }*/
       
   168 
       
   169     /**
       
   170      * Map the given file to a path in the current workspace.
       
   171      * @param fullPath
       
   172      * @return the IFile for the file
       
   173      */
       
   174     private IFile fullPathToWorkspace(String fullPath) {
       
   175     	return FileUtils.convertFileToIFile(new File(fullPath));
       
   176     	/*
       
   177         if (getProject() == null)
       
   178             return null;
       
   179         
       
   180         IPath path = new Path(fullPath);
       
   181         IPath rootPath;
       
   182         rootPath = trackedProject.getProject().getLocation();
       
   183         
       
   184         // this is BUGGY!  Case sensitive for some dumb reason
       
   185         //int match = path.matchingFirstSegments(rootPath);
       
   186         int match = matchingFirstSegments(path, rootPath);
       
   187         
       
   188         if (match == 0)
       
   189             return null;
       
   190         
       
   191         path = path.removeFirstSegments(match);
       
   192         IFile wsFile = FileUtils.convertFileToIFile(getEffectiveBaseDir()) 
       
   193         	getProject().getFile(path);
       
   194         return wsFile;
       
   195         */
       
   196     }
       
   197 
       
   198     /**
       
   199      * Get a manipulator allowing modification of source file
       
   200      * @param path project-relative path
       
   201      */
       
   202     public ISourceManipulator getSourceManipulator(IPath path) {
       
   203         if (trackedProject != null) {
       
   204             if (trackedProject.getProject().getFile(path) == null)
       
   205                 return null;
       
   206         }
       
   207         
       
   208         ISourceManipulator sfi = (ISourceManipulator) pathsToSources.get(path); 
       
   209         if (sfi == null) {
       
   210             if (trackedProject != null)
       
   211                 sfi = new WorkspaceSourceManipulator(this, path);
       
   212             else
       
   213                 sfi = new StandaloneSourceManipulator(this, path);
       
   214             //System.out.println("working with file: " + path);
       
   215             pathsToSources.put(path, sfi);
       
   216         }
       
   217         return sfi;
       
   218     }
       
   219     
       
   220     public ISourceManipulator getSourceManipulator(String fullPath) {
       
   221         if (getProject() != null) {
       
   222             IFile workspaceFile = fullPathToWorkspace(fullPath);
       
   223             if (workspaceFile != null)
       
   224                 return getSourceManipulator(workspaceFile.getProjectRelativePath());
       
   225             else
       
   226                 return null; //return getSourceManipulator(new Path(fullPath));
       
   227         }
       
   228         else if (baseDir != null)
       
   229             return getSourceManipulator(new Path(fullPath.substring(baseDir.getAbsolutePath().length()+1))); 
       
   230         else
       
   231             return null;
       
   232     }
       
   233 
       
   234     /**
       
   235      * @param monitor 
       
   236      * 
       
   237      */
       
   238     public void saveGeneratedSources(IProgressMonitor monitor) throws CoreException {
       
   239         monitor.beginTask(Messages.getString("SourceGenSession.SavingSourceFiles"), //$NON-NLS-1$ 
       
   240                 pathsToSources.values().size());
       
   241         Check.checkState(provider != null);
       
   242         try {
       
   243         	writeFiles(provider.getFileTracker(), monitor);
       
   244         } finally {
       
   245             monitor.done();
       
   246         }
       
   247     }
       
   248 
       
   249     public List<IPath> getGeneratedSources() {
       
   250     	List<IPath> files = new ArrayList<IPath>();
       
   251     	for (Iterator iter = pathsToSources.values().iterator(); iter.hasNext();) {
       
   252 			ISourceManipulator manip = (ISourceManipulator) iter.next();
       
   253 			files.add(manip.getPath());
       
   254 		}
       
   255     	files.addAll(pathsToExtraFiles);
       
   256     	return files;
       
   257     }
       
   258     
       
   259     /**
       
   260 	 *	Write the modified files to disk 
       
   261      * @param fileSaver 
       
   262 	 */
       
   263 	private void writeFiles(IFileSaver fileSaver, IProgressMonitor monitor) throws CoreException {
       
   264         // write all the one-way files
       
   265         for (Iterator iter = pathsToSources.values().iterator(); iter.hasNext();) {
       
   266             ISourceManipulator sfi = (ISourceManipulator) iter.next();
       
   267             if (sfi.changed()) {
       
   268             	//System.out.println("saving new version of " + sfi.getPath());
       
   269             	sfi.save(fileSaver, new SubProgressMonitor(monitor, 1));
       
   270             } else {
       
   271             	sfi.unload();
       
   272                 monitor.worked(1);
       
   273             }
       
   274         }
       
   275 	}
       
   276 
       
   277 	/**
       
   278      * Find or create the file at the given path in the project
       
   279      * @param path project-relative path
       
   280      * @return true: created file
       
   281      * @throws CoreException
       
   282      */
       
   283     public boolean resolveOrCreateFile(IPath path) throws CoreException {
       
   284         resolveOrCreatePath(path.removeLastSegments(1));
       
   285 
       
   286         if (getProject() != null) {
       
   287             IFile file = getProject().getFile(path);
       
   288             if (file.exists())
       
   289                 return false;
       
   290             
       
   291             file.create(new ByteArrayInputStream(new byte[0]),
       
   292             		false, new NullProgressMonitor());
       
   293             return true;
       
   294         } else if (baseDir != null ){
       
   295             File nf = new File(baseDir, path.toString());
       
   296 
       
   297             try {
       
   298             	return nf.createNewFile();
       
   299             } catch (IOException e) {
       
   300                 throw new CoreException(Logging.newStatus(SourceGenPlugin.getDefault(), 
       
   301                         e));
       
   302             }
       
   303         } else
       
   304             return false;
       
   305     }
       
   306 
       
   307 	/**
       
   308      * Set contents of the given file, which must exist already.
       
   309      * @param path project-relative path
       
   310      * @param is stream to initial contents
       
   311      * @throws CoreException
       
   312      */
       
   313     public void setFileContents(IPath path, InputStream is) throws CoreException {
       
   314         if (getProject() != null) {
       
   315             IFile file = getProject().getFile(path);
       
   316             file.setContents(is, false, true, new NullProgressMonitor());
       
   317         } else if (baseDir != null ){
       
   318             File nf = new File(baseDir, path.toString());
       
   319             
       
   320             try {
       
   321                 FileOutputStream fos = new FileOutputStream(nf);
       
   322                 byte[] buffer = new byte[4096];
       
   323                 int len;
       
   324                 while ((len = is.read(buffer)) > 0)
       
   325                 	fos.write(buffer, 0, len);
       
   326                 fos.close();
       
   327             } catch (IOException e) {
       
   328                 throw new CoreException(Logging.newStatus(SourceGenPlugin.getDefault(), 
       
   329                         e));
       
   330             }
       
   331         }
       
   332     }
       
   333 
       
   334     /**
       
   335      * Find or create the directory at the given path in the project
       
   336      * @param path
       
   337      */
       
   338     protected void resolveOrCreatePath(IPath path) throws CoreException {
       
   339         if (getProject() != null) {
       
   340             
       
   341             IFolder folder = getProject().getFolder(path);
       
   342             if (folder.exists())
       
   343                 return;
       
   344             
       
   345             folder.create(false, true, new NullProgressMonitor());
       
   346         } else if (baseDir != null) {
       
   347             File nf = new File(baseDir, path.toString());
       
   348             if (nf.exists())
       
   349                 return;
       
   350             
       
   351             nf.mkdirs();
       
   352         }
       
   353     }
       
   354 
       
   355     /**
       
   356      * Set the base directory for writing files
       
   357      * @param baseDir if null, use the project base, else
       
   358      * use this directory 
       
   359      */
       
   360     public void setBaseDir(File baseDir) {
       
   361         if (baseDir != null) {
       
   362             this.baseDir = baseDir;
       
   363             this.baseDir.mkdirs();
       
   364         } else
       
   365             this.baseDir = null;
       
   366         
       
   367     }
       
   368 
       
   369     /**
       
   370      * Get the effective base directory (either the overridden
       
   371      * one or one based on the project)
       
   372      * @return directory
       
   373      */
       
   374     public File getEffectiveBaseDir() {
       
   375         if (baseDir != null)
       
   376             return baseDir;
       
   377         IProject project = getProject();
       
   378         if (project != null && project.getLocation() != null)
       
   379             return project.getLocation().toFile();
       
   380         else
       
   381             return null;
       
   382     }
       
   383 
       
   384     /**
       
   385      */
       
   386     public ICodeReaderFactory getCodeReaderFactory() {
       
   387         return codeReaderFactory;
       
   388     }
       
   389 
       
   390  
       
   391     public static void emit(IComponentInstance instance, int severity, String msgKey, Object[] args) {
       
   392 		MessageReporting.emitMessage(
       
   393 				new Message(
       
   394 						severity,
       
   395 						MessageLocators.getComponentOrInstanceLocation(instance),
       
   396 						msgKey,
       
   397 						MessageFormat.format(Messages.getString(msgKey), args)));
       
   398 	}
       
   399 
       
   400     public IProjectContext getProjectContext(IDesignerDataModel model) {
       
   401     	IProject project = getProject();
       
   402 		if (project != null) {
       
   403 			return WorkspaceContext.getContext().getContextForProject(project);
       
   404 		}
       
   405 		return null;
       
   406     }
       
   407     
       
   408     public ISourceFormatting getSourceFormatting() {
       
   409     	if (provider.getSourceFormatter() != null)
       
   410     		return provider.getSourceFormatter().getSourceFormatting();
       
   411     	else
       
   412     		return null;
       
   413     }
       
   414    
       
   415     public void addExtraSourcePath(IPath extraSourcePath) {
       
   416     	pathsToExtraFiles.add(extraSourcePath);
       
   417     }
       
   418 }