1 /*
2  * Copyright (C) 2007 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.adt.internal.project;
18 
19 import com.android.ide.eclipse.adt.AdtPlugin;
20 import com.android.ide.eclipse.adt.internal.launch.LaunchConfigDelegate;
21 
22 import org.eclipse.core.resources.IProject;
23 import org.eclipse.core.runtime.CoreException;
24 import org.eclipse.debug.core.DebugPlugin;
25 import org.eclipse.debug.core.ILaunchConfiguration;
26 import org.eclipse.debug.core.ILaunchConfigurationType;
27 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
28 import org.eclipse.debug.core.ILaunchManager;
29 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
30 
31 import java.util.ArrayList;
32 
33 /**
34  * Class to fix the launch configuration of a project if the java package
35  * defined in the manifest has been changed.<br>
36  * This fix can be done synchronously, or asynchronously.<br>
37  * <code>start()</code> will start a thread that will do the fix.<br>
38  * <code>run()</code> will do the fix in the current thread.<br><br>
39  * By default, the fix first display a dialog to the user asking if he/she wants to
40  * do the fix. This can be overriden by calling <code>setDisplayPrompt(false)</code>.
41  *
42  */
43 public class FixLaunchConfig extends Thread {
44 
45     private IProject mProject;
46     private String mOldPackage;
47     private String mNewPackage;
48 
49     private boolean mDisplayPrompt = true;
50 
FixLaunchConfig(IProject project, String oldPackage, String newPackage)51     public FixLaunchConfig(IProject project, String oldPackage, String newPackage) {
52         super();
53 
54         mProject = project;
55         mOldPackage = oldPackage;
56         mNewPackage = newPackage;
57     }
58 
59     /**
60      * Set the display prompt. If true run()/start() first ask the user if he/she wants
61      * to fix the Launch Config
62      * @param displayPrompt
63      */
setDisplayPrompt(boolean displayPrompt)64     public void setDisplayPrompt(boolean displayPrompt) {
65         mDisplayPrompt = displayPrompt;
66     }
67 
68     /**
69      * Fix the Launch configurations.
70      */
71     @Override
run()72     public void run() {
73 
74         if (mDisplayPrompt) {
75             // ask the user if he really wants to fix the launch config
76             boolean res = AdtPlugin.displayPrompt(
77                     "Launch Configuration Update",
78                     "The package definition in the manifest changed.\nDo you want to update your Launch Configuration(s)?");
79 
80             if (res == false) {
81                 return;
82             }
83         }
84 
85         // get the list of config for the project
86         String projectName = mProject.getName();
87         ILaunchConfiguration[] configs = findConfigs(mProject.getName());
88 
89         // loop through all the config and update the package
90         for (ILaunchConfiguration config : configs) {
91             try {
92                 // get the working copy so that we can make changes.
93                 ILaunchConfigurationWorkingCopy copy = config.getWorkingCopy();
94 
95                 // get the attributes for the activity
96                 String activity = config.getAttribute(LaunchConfigDelegate.ATTR_ACTIVITY,
97                         ""); //$NON-NLS-1$
98 
99                 // manifests can define activities that are not in the defined package,
100                 // so we need to make sure the activity is inside the old package.
101                 if (activity.startsWith(mOldPackage)) {
102                     // create the new activity
103                     activity = mNewPackage + activity.substring(mOldPackage.length());
104 
105                     // put it in the copy
106                     copy.setAttribute(LaunchConfigDelegate.ATTR_ACTIVITY, activity);
107 
108                     // save the config
109                     copy.doSave();
110                 }
111             } catch (CoreException e) {
112                 // couldn't get the working copy. we output the error in the console
113                 String msg = String.format("Failed to modify %1$s: %2$s", projectName,
114                         e.getMessage());
115                 AdtPlugin.printErrorToConsole(mProject, msg);
116             }
117         }
118 
119     }
120 
121     /**
122      * Looks for and returns all existing Launch Configuration object for a
123      * specified project.
124      * @param projectName The name of the project
125      * @return all the ILaunchConfiguration object. If none are present, an empty array is
126      * returned.
127      */
findConfigs(String projectName)128     private static ILaunchConfiguration[] findConfigs(String projectName) {
129         // get the launch manager
130         ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
131 
132         // now get the config type for our particular android type.
133         ILaunchConfigurationType configType = manager.
134                 getLaunchConfigurationType(LaunchConfigDelegate.ANDROID_LAUNCH_TYPE_ID);
135 
136         // create a temp list to hold all the valid configs
137         ArrayList<ILaunchConfiguration> list = new ArrayList<ILaunchConfiguration>();
138 
139         try {
140             ILaunchConfiguration[] configs = manager.getLaunchConfigurations(configType);
141 
142             for (ILaunchConfiguration config : configs) {
143                 if (config.getAttribute(
144                         IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME,
145                         "").equals(projectName)) {  //$NON-NLS-1$
146                     list.add(config);
147                 }
148             }
149         } catch (CoreException e) {
150         }
151 
152         return list.toArray(new ILaunchConfiguration[list.size()]);
153 
154     }
155 
156 }
157