• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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.actions;
18 
19 import com.android.ide.eclipse.adt.AdtPlugin;
20 import com.android.ide.eclipse.adt.internal.build.DexWrapper;
21 import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog;
22 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
23 import com.android.sdklib.SdkConstants;
24 import com.android.sdklib.io.FileOp;
25 import com.android.sdklib.util.GrabProcessOutput;
26 import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
27 import com.android.sdklib.util.GrabProcessOutput.Wait;
28 import com.android.sdkuilib.repository.ISdkChangeListener;
29 import com.android.sdkuilib.repository.SdkUpdaterWindow;
30 import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext;
31 
32 import org.eclipse.jface.action.IAction;
33 import org.eclipse.jface.viewers.ISelection;
34 import org.eclipse.ui.IObjectActionDelegate;
35 import org.eclipse.ui.IWorkbenchPart;
36 import org.eclipse.ui.IWorkbenchWindow;
37 import org.eclipse.ui.IWorkbenchWindowActionDelegate;
38 
39 import java.io.File;
40 
41 /**
42  * Delegate for the toolbar/menu action "Android SDK Manager".
43  * It displays the Android SDK Manager.
44  */
45 public class SdkManagerAction implements IWorkbenchWindowActionDelegate, IObjectActionDelegate {
46 
47     @Override
dispose()48     public void dispose() {
49         // nothing to dispose.
50     }
51 
52     @Override
init(IWorkbenchWindow window)53     public void init(IWorkbenchWindow window) {
54         // no init
55     }
56 
57     @Override
run(IAction action)58     public void run(IAction action) {
59         if (!openAdtSdkManager()) {
60             AdtPlugin.displayError(
61                     "Android SDK",
62                     "Location of the Android SDK has not been setup in the preferences.");
63         }
64     }
65 
66     /**
67      * Opens the SDK Manager as an external application.
68      * This call is asynchronous, it doesn't wait for the manager to be closed.
69      *
70      * @return True if the application was found and executed. False if it could not
71      *   be located or could not be launched.
72      */
openExternalSdkManager()73     public static boolean openExternalSdkManager() {
74         final Sdk sdk = Sdk.getCurrent();
75         if (sdk == null) {
76             return false;
77         }
78 
79         File androidBat = FileOp.append(
80                 sdk.getSdkLocation(),
81                 SdkConstants.FD_TOOLS,
82                 SdkConstants.androidCmdName());
83 
84         if (!androidBat.exists()) {
85             return false;
86         }
87 
88         try {
89             final AdtConsoleSdkLog logger = new AdtConsoleSdkLog();
90 
91             String command[] = new String[] {
92                     androidBat.getAbsolutePath(),
93                     "sdk"   //$NON-NLS-1$
94             };
95             Process process = Runtime.getRuntime().exec(command);
96             GrabProcessOutput.grabProcessOutput(
97                     process,
98                     Wait.ASYNC,
99                     new IProcessOutput() {
100                         @Override
101                         public void out(String line) {
102                             // Ignore stdout
103                         }
104 
105                         @Override
106                         public void err(String line) {
107                             if (line != null) {
108                                 logger.printf("[SDK Manager] %s", line);
109                             }
110                         }
111                     });
112         } catch (Exception ignore) {
113         }
114 
115         return true;
116     }
117 
118     /**
119      * Opens the SDK Manager bundled within ADT.
120      * The call is blocking and does not return till the SD Manager window is closed.
121      *
122      * @return True if the SDK location is known and the SDK Manager was started.
123      *   False if the SDK location is not set and we can't open a SDK Manager to
124      *   manage files in an unknown location.
125      */
openAdtSdkManager()126     public static boolean openAdtSdkManager() {
127         final Sdk sdk = Sdk.getCurrent();
128         if (sdk == null) {
129             return false;
130         }
131 
132         // Runs the updater window, directing only warning/errors logs to the ADT console
133         // (normal log is just dropped, which is fine since the SDK Manager has its own
134         // log window now.)
135 
136         SdkUpdaterWindow window = new SdkUpdaterWindow(
137                 AdtPlugin.getDisplay().getActiveShell(),
138                 new AdtConsoleSdkLog() {
139                     @Override
140                     public void printf(String msgFormat, Object... args) {
141                         // Do not show non-error/warning log in Eclipse.
142                     };
143                 },
144                 sdk.getSdkLocation(),
145                 SdkInvocationContext.IDE);
146 
147         ISdkChangeListener listener = new ISdkChangeListener() {
148             @Override
149             public void onSdkLoaded() {
150                 // Ignore initial load of the SDK.
151             }
152 
153             /**
154              * Unload all we can from the SDK before new packages are installed.
155              * Typically we need to get rid of references to dx from platform-tools
156              * and to any platform resource data.
157              * <p/>
158              * {@inheritDoc}
159              */
160             @Override
161             public void preInstallHook() {
162 
163                 // TODO we need to unload as much of as SDK as possible. Otherwise
164                 // on Windows we end up with Eclipse locking some files and we can't
165                 // replace them.
166                 //
167                 // At this point, we know what the user wants to install so it would be
168                 // possible to pass in flags to know what needs to be unloaded. Typically
169                 // we need to:
170                 // - unload dex if platform-tools is going to be updated. There's a vague
171                 //   attempt below at removing any references to dex and GCing. Seems
172                 //   to do the trick.
173                 // - unload any target that is going to be updated since it may have
174                 //   resource data used by a current layout editor (e.g. data/*.ttf
175                 //   and various data/res/*.xml).
176                 //
177                 // Most important we need to make sure there isn't a build going on
178                 // and if there is one, either abort it or wait for it to complete and
179                 // then we want to make sure we don't get any attempt to use the SDK
180                 // before the postInstallHook is called.
181 
182                 if (sdk != null) {
183                     sdk.unloadTargetData(true /*preventReload*/);
184 
185                     DexWrapper dx = sdk.getDexWrapper();
186                     dx.unload();
187                 }
188             }
189 
190             /**
191              * Nothing to do. We'll reparse the SDK later in onSdkReload.
192              * <p/>
193              * {@inheritDoc}
194              */
195             @Override
196             public void postInstallHook() {
197             }
198 
199             /**
200              * Reparse the SDK in case anything was add/removed.
201              * <p/>
202              * {@inheritDoc}
203              */
204             @Override
205             public void onSdkReload() {
206                 AdtPlugin.getDefault().reparseSdk();
207             }
208         };
209 
210         window.addListener(listener);
211         window.open();
212 
213         return true;
214     }
215 
216     @Override
selectionChanged(IAction action, ISelection selection)217     public void selectionChanged(IAction action, ISelection selection) {
218         // nothing related to the current selection.
219     }
220 
221     @Override
setActivePart(IAction action, IWorkbenchPart targetPart)222     public void setActivePart(IAction action, IWorkbenchPart targetPart) {
223         // nothing to do.
224     }
225 }
226