Home | History | Annotate | Download | only in discovery
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.ide.eclipse.ndk.internal.discovery;
     18 
     19 import com.android.ide.eclipse.ndk.internal.Activator;
     20 
     21 import org.eclipse.cdt.core.CCorePlugin;
     22 import org.eclipse.cdt.core.model.CoreModel;
     23 import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo;
     24 import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredScannerInfoSerializable;
     25 import org.eclipse.core.resources.IFile;
     26 import org.eclipse.core.resources.IProject;
     27 import org.eclipse.core.runtime.CoreException;
     28 import org.eclipse.core.runtime.IPath;
     29 import org.eclipse.core.runtime.IProgressMonitor;
     30 import org.eclipse.core.runtime.Path;
     31 
     32 import java.io.BufferedReader;
     33 import java.io.File;
     34 import java.io.FileReader;
     35 import java.io.IOException;
     36 import java.io.PrintStream;
     37 import java.util.ArrayList;
     38 import java.util.HashMap;
     39 import java.util.List;
     40 import java.util.Map;
     41 import java.util.Map.Entry;
     42 
     43 public class NdkDiscoveredPathInfo implements IDiscoveredPathInfo {
     44 
     45     private final IProject mProject;
     46     private long mLastUpdate = IFile.NULL_STAMP;
     47     private IPath[] mIncludePaths;
     48     private Map<String, String> mSymbols;
     49     private boolean mNeedReindexing = false;
     50     private static final IPath ANDROID_MK = new Path("jni/Android.mk");
     51 
     52     // Keys for preferences
     53     public static final String LAST_UPDATE = "lastUpdate"; //$NON-NLS-1$
     54 
     55     public NdkDiscoveredPathInfo(IProject project) {
     56         this.mProject = project;
     57         load();
     58     }
     59 
     60     @Override
     61     public IProject getProject() {
     62         return mProject;
     63     }
     64 
     65     @Override
     66     public IPath[] getIncludePaths() {
     67         if (mNeedReindexing) {
     68             // Call for a reindex
     69             // TODO this is probably a bug. a new include path should trigger
     70             // reindexing anyway, no?
     71             // BTW, can't do this in the update since the indexer runs before
     72             // this gets called
     73             CCorePlugin.getIndexManager().reindex(CoreModel.getDefault().create(mProject));
     74             mNeedReindexing = false;
     75         }
     76         return mIncludePaths;
     77     }
     78 
     79     void setIncludePaths(List<String> pathStrings) {
     80         mIncludePaths = new IPath[pathStrings.size()];
     81         int i = 0;
     82         for (String path : pathStrings)
     83             mIncludePaths[i++] = new Path(path);
     84         mNeedReindexing = true;
     85     }
     86 
     87     @Override
     88     public Map<String, String> getSymbols() {
     89         if (mSymbols == null)
     90             mSymbols = new HashMap<String, String>();
     91         return mSymbols;
     92     }
     93 
     94     void setSymbols(Map<String, String> symbols) {
     95         this.mSymbols = symbols;
     96     }
     97 
     98     @Override
     99     public IDiscoveredScannerInfoSerializable getSerializable() {
    100         return null;
    101     }
    102 
    103     public void update(IProgressMonitor monitor) throws CoreException {
    104         if (!needUpdating())
    105             return;
    106 
    107         new NdkDiscoveryUpdater(this).runUpdate(monitor);
    108 
    109         if (mIncludePaths != null && mSymbols != null) {
    110             recordUpdate();
    111             save();
    112         }
    113     }
    114 
    115     private boolean needUpdating() {
    116         if (mLastUpdate == IFile.NULL_STAMP)
    117             return true;
    118         return mProject.getFile(ANDROID_MK).getLocalTimeStamp() > mLastUpdate;
    119     }
    120 
    121     private void recordUpdate() {
    122         mLastUpdate = mProject.getFile(ANDROID_MK).getLocalTimeStamp();
    123     }
    124 
    125     public void delete() {
    126         mLastUpdate = IFile.NULL_STAMP;
    127     }
    128 
    129     private File getInfoFile() {
    130         File stateLoc = Activator.getDefault().getStateLocation().toFile();
    131         return new File(stateLoc, mProject.getName() + ".pathInfo"); //$NON-NLS-1$
    132     }
    133 
    134     private void save() {
    135         try {
    136             File infoFile = getInfoFile();
    137             infoFile.getParentFile().mkdirs();
    138             PrintStream out = new PrintStream(infoFile);
    139 
    140             // timestamp
    141             out.print("t,"); //$NON-NLS-1$
    142             out.print(mLastUpdate);
    143             out.println();
    144 
    145             for (IPath include : mIncludePaths) {
    146                 out.print("i,"); //$NON-NLS-1$
    147                 out.print(include.toPortableString());
    148                 out.println();
    149             }
    150 
    151             for (Entry<String, String> symbol : mSymbols.entrySet()) {
    152                 out.print("d,"); //$NON-NLS-1$
    153                 out.print(symbol.getKey());
    154                 out.print(","); //$NON-NLS-1$
    155                 out.print(symbol.getValue());
    156                 out.println();
    157             }
    158 
    159             out.close();
    160         } catch (IOException e) {
    161             Activator.log(e);
    162         }
    163 
    164     }
    165 
    166     private void load() {
    167         try {
    168             File infoFile = getInfoFile();
    169             if (!infoFile.exists())
    170                 return;
    171 
    172             long timestamp = IFile.NULL_STAMP;
    173             List<IPath> includes = new ArrayList<IPath>();
    174             Map<String, String> defines = new HashMap<String, String>();
    175 
    176             BufferedReader reader = new BufferedReader(new FileReader(infoFile));
    177             for (String line = reader.readLine(); line != null; line = reader.readLine()) {
    178                 switch (line.charAt(0)) {
    179                     case 't':
    180                         timestamp = Long.valueOf(line.substring(2));
    181                         break;
    182                     case 'i':
    183                         includes.add(Path.fromPortableString(line.substring(2)));
    184                         break;
    185                     case 'd':
    186                         int n = line.indexOf(',', 2);
    187                         if (n == -1)
    188                             defines.put(line.substring(2), ""); //$NON-NLS-1$
    189                         else
    190                             defines.put(line.substring(2, n), line.substring(n + 1));
    191                         break;
    192                 }
    193             }
    194             reader.close();
    195 
    196             mLastUpdate = timestamp;
    197             mIncludePaths = includes.toArray(new IPath[includes.size()]);
    198             mSymbols = defines;
    199         } catch (IOException e) {
    200             Activator.log(e);
    201         }
    202     }
    203 }
    204