Home | History | Annotate | Download | only in newproject
      1 /*
      2  * Copyright (C) 2012 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 package com.android.ide.eclipse.adt.internal.wizards.newproject;
     17 
     18 import static com.android.SdkConstants.ATTR_NAME;
     19 
     20 import com.android.annotations.NonNull;
     21 import com.android.annotations.Nullable;
     22 import com.android.ide.common.xml.AndroidManifestParser;
     23 import com.android.ide.common.xml.ManifestData;
     24 import com.android.ide.common.xml.ManifestData.Activity;
     25 import com.android.ide.eclipse.adt.AdtPlugin;
     26 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
     27 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
     28 import com.android.io.FolderWrapper;
     29 import com.android.sdklib.AndroidVersion;
     30 import com.android.sdklib.IAndroidTarget;
     31 import com.android.sdklib.internal.project.ProjectProperties;
     32 import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
     33 import com.google.common.base.Charsets;
     34 import com.google.common.io.Files;
     35 
     36 import org.eclipse.core.resources.IResource;
     37 import org.eclipse.core.resources.IWorkspace;
     38 import org.eclipse.core.resources.ResourcesPlugin;
     39 import org.eclipse.core.runtime.IPath;
     40 import org.eclipse.core.runtime.IStatus;
     41 import org.w3c.dom.Document;
     42 import org.w3c.dom.Node;
     43 import org.w3c.dom.NodeList;
     44 import org.xml.sax.SAXException;
     45 
     46 import java.io.File;
     47 import java.io.IOException;
     48 import java.util.regex.Matcher;
     49 import java.util.regex.Pattern;
     50 
     51 /** An Android project to be imported */
     52 class ImportedProject {
     53     private final File mLocation;
     54     private String mActivityName;
     55     private ManifestData mManifest;
     56     private String mProjectName;
     57     private String mRelativePath;
     58 
     59     ImportedProject(File location, String relativePath) {
     60         super();
     61         mLocation = location;
     62         mRelativePath = relativePath;
     63     }
     64 
     65     File getLocation() {
     66         return mLocation;
     67     }
     68 
     69     String getRelativePath() {
     70         return mRelativePath;
     71     }
     72 
     73     @Nullable
     74     ManifestData getManifest() {
     75         if (mManifest == null) {
     76             try {
     77                 mManifest = AndroidManifestParser.parse(new FolderWrapper(mLocation));
     78             } catch (SAXException e) {
     79                 // Some sort of error in the manifest file: report to the user in a better way?
     80                 AdtPlugin.log(e, null);
     81                 return null;
     82             } catch (Exception e) {
     83                 AdtPlugin.log(e, null);
     84                 return null;
     85             }
     86         }
     87 
     88         return mManifest;
     89     }
     90 
     91     @Nullable
     92     public String getActivityName() {
     93         if (mActivityName == null) {
     94             // Compute the project name and the package name from the manifest
     95             ManifestData manifest = getManifest();
     96             if (manifest != null) {
     97                 if (manifest.getLauncherActivity() != null) {
     98                     mActivityName = manifest.getLauncherActivity().getName();
     99                 }
    100                 if (mActivityName == null || mActivityName.isEmpty()) {
    101                     Activity[] activities = manifest.getActivities();
    102                     for (Activity activity : activities) {
    103                         mActivityName = activity.getName();
    104                         if (mActivityName != null && !mActivityName.isEmpty()) {
    105                             break;
    106                         }
    107                     }
    108                 }
    109                 if (mActivityName != null) {
    110                     int index = mActivityName.lastIndexOf('.');
    111                     mActivityName = mActivityName.substring(index + 1);
    112                 }
    113             }
    114         }
    115 
    116         return mActivityName;
    117     }
    118 
    119     @NonNull
    120     public String getProjectName() {
    121         if (mProjectName == null) {
    122             // Are we importing an Eclipse project? If so just use the existing project name
    123             mProjectName = findEclipseProjectName();
    124             if (mProjectName != null) {
    125                 return mProjectName;
    126             }
    127 
    128             String activityName = getActivityName();
    129             if (activityName == null || activityName.isEmpty()) {
    130                 // I could also look at the build files, say build.xml from ant, and
    131                 // try to glean the project name from there
    132                 mProjectName = mLocation.getName();
    133             } else {
    134                 // Try to derive it from the activity name:
    135                 IWorkspace workspace = ResourcesPlugin.getWorkspace();
    136                 IStatus nameStatus = workspace.validateName(activityName, IResource.PROJECT);
    137                 if (nameStatus.isOK()) {
    138                     mProjectName = activityName;
    139                 } else {
    140                     // Try to derive it by escaping characters
    141                     StringBuilder sb = new StringBuilder();
    142                     for (int i = 0, n = activityName.length(); i < n; i++) {
    143                         char c = activityName.charAt(i);
    144                         if (c != IPath.DEVICE_SEPARATOR && c != IPath.SEPARATOR && c != '\\') {
    145                             sb.append(c);
    146                         }
    147                     }
    148                     if (sb.length() == 0) {
    149                         mProjectName = mLocation.getName();
    150                     } else {
    151                         mProjectName = sb.toString();
    152                     }
    153                 }
    154             }
    155         }
    156 
    157         return mProjectName;
    158     }
    159 
    160     @Nullable
    161     private String findEclipseProjectName() {
    162         File projectFile = new File(mLocation, ".project"); //$NON-NLS-1$
    163         if (projectFile.exists()) {
    164             String xml;
    165             try {
    166                 xml = Files.toString(projectFile, Charsets.UTF_8);
    167                 Document doc = DomUtilities.parseDocument(xml, false);
    168                 if (doc != null) {
    169                     NodeList names = doc.getElementsByTagName(ATTR_NAME);
    170                     if (names.getLength() >= 1) {
    171                         Node nameElement = names.item(0);
    172                         String name = nameElement.getTextContent().trim();
    173                         if (!name.isEmpty()) {
    174                             return name;
    175                         }
    176                     }
    177                 }
    178             } catch (IOException e) {
    179                 // pass: don't attempt to read project name; must be some sort of unrelated
    180                 // file with the same name, perhaps from a different editor or IDE
    181             }
    182         }
    183 
    184         return null;
    185     }
    186 
    187     public void setProjectName(@NonNull String newName) {
    188         mProjectName = newName;
    189     }
    190 
    191     public IAndroidTarget getTarget() {
    192         // Pick a target:
    193         // First try to find the one requested by project.properties
    194         IAndroidTarget[] targets = Sdk.getCurrent().getTargets();
    195         ProjectProperties properties = ProjectProperties.load(mLocation.getPath(),
    196                 PropertyType.PROJECT);
    197         if (properties != null) {
    198             String targetProperty = properties.getProperty(ProjectProperties.PROPERTY_TARGET);
    199             if (targetProperty != null) {
    200                 Matcher m = Pattern.compile("android-(.+)").matcher( //$NON-NLS-1$
    201                         targetProperty.trim());
    202                 if (m.matches()) {
    203                     String targetName = m.group(1);
    204                     int targetLevel;
    205                     try {
    206                         targetLevel = Integer.parseInt(targetName);
    207                     } catch (NumberFormatException nufe) {
    208                         // pass
    209                         targetLevel = -1;
    210                     }
    211                     for (IAndroidTarget t : targets) {
    212                         AndroidVersion version = t.getVersion();
    213                         if (version.isPreview() && targetName.equals(version.getCodename())) {
    214                             return t;
    215                         } else if (targetLevel == version.getApiLevel()) {
    216                             return t;
    217                         }
    218                     }
    219                     if (targetLevel > 0) {
    220                         // If not found, pick the closest one that is higher than the
    221                         // api level
    222                         IAndroidTarget target = targets[targets.length - 1];
    223                         int targetDelta = target.getVersion().getApiLevel() - targetLevel;
    224                         for (IAndroidTarget t : targets) {
    225                             int newDelta = t.getVersion().getApiLevel() - targetLevel;
    226                             if (newDelta >= 0 && newDelta < targetDelta) {
    227                                 targetDelta = newDelta;
    228                                 target = t;
    229                             }
    230                         }
    231 
    232                         return target;
    233                     }
    234                 }
    235             }
    236         }
    237 
    238         // If not found, pick the closest one to the one requested by the
    239         // project (in project.properties) that is still >= the minSdk version
    240         IAndroidTarget target = targets[targets.length - 1];
    241         ManifestData manifest = getManifest();
    242         if (manifest != null) {
    243             int minSdkLevel = manifest.getMinSdkVersion();
    244             int targetDelta = target.getVersion().getApiLevel() - minSdkLevel;
    245             for (IAndroidTarget t : targets) {
    246                 int newDelta = t.getVersion().getApiLevel() - minSdkLevel;
    247                 if (newDelta >= 0 && newDelta < targetDelta) {
    248                     targetDelta = newDelta;
    249                     target = t;
    250                 }
    251             }
    252         }
    253 
    254         return target;
    255     }
    256 }