1b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera/* 2b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * Copyright (C) 2014 The Android Open Source Project 3b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * 4b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * Licensed under the Apache License, Version 2.0 (the "License"); 5b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * you may not use this file except in compliance with the License. 6b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * You may obtain a copy of the License at 7b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * 8b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * http://www.apache.org/licenses/LICENSE-2.0 9b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * 10b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * Unless required by applicable law or agreed to in writing, software 11b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * distributed under the License is distributed on an "AS IS" BASIS, 12b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * See the License for the specific language governing permissions and 14b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * limitations under the License. 15b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera */ 16b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 17b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talaverapackage com.android.commands.dpm; 18b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 196bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolovimport android.app.ActivityManagerNative; 206bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolovimport android.app.IActivityManager; 21afad8783699b1ba6f3c7ee5961d6ddc2bd771dc1Alan Treadwayimport android.app.admin.DevicePolicyManager; 22b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talaveraimport android.app.admin.IDevicePolicyManager; 239c17388cff98fba9679ce6457ac5003a660c6013Esteban Talaveraimport android.content.ComponentName; 24b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talaveraimport android.content.Context; 25b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talaveraimport android.os.RemoteException; 26b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talaveraimport android.os.ServiceManager; 279c17388cff98fba9679ce6457ac5003a660c6013Esteban Talaveraimport android.os.UserHandle; 28b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 29b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talaveraimport com.android.internal.os.BaseCommand; 30b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 31b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talaveraimport java.io.PrintStream; 32b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 33b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talaverapublic final class Dpm extends BaseCommand { 34b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 35b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera /** 36b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * Command-line entry point. 37b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * 38b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera * @param args The command-line arguments 39b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera */ 40b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera public static void main(String[] args) { 41b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera (new Dpm()).run(args); 42b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera } 43b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 44e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban private static final String COMMAND_SET_ACTIVE_ADMIN = "set-active-admin"; 45b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera private static final String COMMAND_SET_DEVICE_OWNER = "set-device-owner"; 4641de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera private static final String COMMAND_SET_PROFILE_OWNER = "set-profile-owner"; 4738dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy private static final String COMMAND_REMOVE_ACTIVE_ADMIN = "remove-active-admin"; 48b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 49b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera private IDevicePolicyManager mDevicePolicyManager; 50b52c7330d986e62812fd7c1b77020629e8ff7930Xiaohui Chen private int mUserId = UserHandle.USER_SYSTEM; 51a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki private String mName = ""; 52e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban private ComponentName mComponent = null; 53b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 54b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera @Override 55b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera public void onShowUsage(PrintStream out) { 569c17388cff98fba9679ce6457ac5003a660c6013Esteban Talavera out.println( 579c17388cff98fba9679ce6457ac5003a660c6013Esteban Talavera "usage: dpm [subcommand] [options]\n" + 586bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov "usage: dpm set-active-admin [ --user <USER_ID> | current ] <COMPONENT>\n" + 5958b684f1cdc52467b71c42cfae18433a19ce7d0bMakoto Onuki // STOPSHIP Finalize it 606bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov "usage: dpm set-device-owner [ --user <USER_ID> | current *EXPERIMENTAL* ] " + 616bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov "[ --name <NAME> ] <COMPONENT>\n" + 626bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov "usage: dpm set-profile-owner [ --user <USER_ID> | current ] [ --name <NAME> ] " + 636bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov "<COMPONENT>\n" + 6438dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy "usage: dpm remove-active-admin [ --user <USER_ID> | current ] [ --name <NAME> ] " + 6538dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy "<COMPONENT>\n" + 66b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera "\n" + 67e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban "dpm set-active-admin: Sets the given component as active admin" + 68e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban " for an existing user.\n" + 69e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban "\n" + 706bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov "dpm set-device-owner: Sets the given component as active admin, and its" + 716bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov " package as device owner.\n" + 7241de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera "\n" + 7341de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera "dpm set-profile-owner: Sets the given component as active admin and profile" + 7438dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy " owner for an existing user.\n" + 7538dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy "\n" + 7638dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy "dpm remove-active-admin: Disables an active admin, the admin must have declared" + 7738dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy " android:testOnly in the application in its manifest. This will also remove" + 7838dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy " device and profile owners\n"); 79b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera } 80b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 81b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera @Override 82b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera public void onRun() throws Exception { 83b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface( 84b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)); 85b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera if (mDevicePolicyManager == null) { 86b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera showError("Error: Could not access the Device Policy Manager. Is the system running?"); 87b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera return; 88b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera } 89b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 90b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera String command = nextArgRequired(); 91b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera switch (command) { 92e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban case COMMAND_SET_ACTIVE_ADMIN: 93e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban runSetActiveAdmin(); 94e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban break; 95b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera case COMMAND_SET_DEVICE_OWNER: 9641de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera runSetDeviceOwner(); 9741de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera break; 9841de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera case COMMAND_SET_PROFILE_OWNER: 9941de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera runSetProfileOwner(); 100b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera break; 10138dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy case COMMAND_REMOVE_ACTIVE_ADMIN: 10238dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy runRemoveActiveAdmin(); 10338dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy break; 104b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera default: 1059c17388cff98fba9679ce6457ac5003a660c6013Esteban Talavera throw new IllegalArgumentException ("unknown command '" + command + "'"); 106b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera } 107b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera } 108b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera 1096bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov private void parseArgs(boolean canHaveName) { 110a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki String opt; 111a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki while ((opt = nextOption()) != null) { 1126bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov if ("--user".equals(opt)) { 1136bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov String arg = nextArgRequired(); 1146bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov if ("current".equals(arg) || "cur".equals(arg)) { 1156bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov mUserId = UserHandle.USER_CURRENT; 1166bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov } else { 1176bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov mUserId = parseInt(arg); 1186bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov } 1196bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov if (mUserId == UserHandle.USER_CURRENT) { 1206bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov IActivityManager activityManager = ActivityManagerNative.getDefault(); 1216bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov try { 1226bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov mUserId = activityManager.getCurrentUser().id; 1236bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov } catch (RemoteException e) { 1246bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov e.rethrowAsRuntimeException(); 1256bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov } 1266bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov } 127a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki } else if (canHaveName && "--name".equals(opt)) { 128a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki mName = nextArgRequired(); 129a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki } else { 130a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki throw new IllegalArgumentException("Unknown option: " + opt); 131a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki } 132e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban } 133a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki mComponent = parseComponentName(nextArgRequired()); 134e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban } 135e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban 136e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban private void runSetActiveAdmin() throws RemoteException { 1376bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov parseArgs(/*canHaveName=*/ false); 138e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban mDevicePolicyManager.setActiveAdmin(mComponent, true /*refreshing*/, mUserId); 139e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban 140e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban System.out.println("Success: Active admin set to component " + mComponent.toShortString()); 141e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban } 142e9119876a21575ee7a7d058da85d04c4c4b8a971Zoltan Szatmary-Ban 14341de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera private void runSetDeviceOwner() throws RemoteException { 1446bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov parseArgs(/*canHaveName=*/ true); 14558b684f1cdc52467b71c42cfae18433a19ce7d0bMakoto Onuki mDevicePolicyManager.setActiveAdmin(mComponent, true /*refreshing*/, mUserId); 1469c17388cff98fba9679ce6457ac5003a660c6013Esteban Talavera 1479c17388cff98fba9679ce6457ac5003a660c6013Esteban Talavera try { 148a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki if (!mDevicePolicyManager.setDeviceOwner(mComponent, mName, mUserId)) { 14941de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera throw new RuntimeException( 150a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki "Can't set package " + mComponent + " as device owner."); 1519c17388cff98fba9679ce6457ac5003a660c6013Esteban Talavera } 1529c17388cff98fba9679ce6457ac5003a660c6013Esteban Talavera } catch (Exception e) { 1539c17388cff98fba9679ce6457ac5003a660c6013Esteban Talavera // Need to remove the admin that we just added. 15458b684f1cdc52467b71c42cfae18433a19ce7d0bMakoto Onuki mDevicePolicyManager.removeActiveAdmin(mComponent, UserHandle.USER_SYSTEM); 1559c17388cff98fba9679ce6457ac5003a660c6013Esteban Talavera throw e; 1569c17388cff98fba9679ce6457ac5003a660c6013Esteban Talavera } 157afad8783699b1ba6f3c7ee5961d6ddc2bd771dc1Alan Treadway 158afad8783699b1ba6f3c7ee5961d6ddc2bd771dc1Alan Treadway mDevicePolicyManager.setUserProvisioningState( 159afad8783699b1ba6f3c7ee5961d6ddc2bd771dc1Alan Treadway DevicePolicyManager.STATE_USER_SETUP_FINALIZED, mUserId); 160afad8783699b1ba6f3c7ee5961d6ddc2bd771dc1Alan Treadway 161a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki System.out.println("Success: Device owner set to package " + mComponent); 16258b684f1cdc52467b71c42cfae18433a19ce7d0bMakoto Onuki System.out.println("Active admin set to component " + mComponent.toShortString()); 163b5ef162129ced7e9636052af6b7f08d677a01f13Esteban Talavera } 16441de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera 16538dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy private void runRemoveActiveAdmin() throws RemoteException { 16638dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy parseArgs(/*canHaveName=*/ false); 16738dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy mDevicePolicyManager.forceRemoveActiveAdmin(mComponent, mUserId); 16838dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy System.out.println("Success: Admin removed " + mComponent); 16938dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy } 17038dcca51a739d3273b24e84ba5e89e505f45960cKenny Guy 17141de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera private void runSetProfileOwner() throws RemoteException { 1726bccb76a64ba74c2e0267db1d2ec14a4ffa96771Fyodor Kupolov parseArgs(/*canHaveName=*/ true); 173474c7aceae0c6a91049deb7db944cbe85b56bcc7Sudheer Shanka mDevicePolicyManager.setActiveAdmin(mComponent, true /*refreshing*/, mUserId); 17441de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera 17541de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera try { 176a52562ca9a4144cf30e6d5c6ffe856cc8e284464Makoto Onuki if (!mDevicePolicyManager.setProfileOwner(mComponent, mName, mUserId)) { 177474c7aceae0c6a91049deb7db944cbe85b56bcc7Sudheer Shanka throw new RuntimeException("Can't set component " + mComponent.toShortString() + 178474c7aceae0c6a91049deb7db944cbe85b56bcc7Sudheer Shanka " as profile owner for user " + mUserId); 17941de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera } 18041de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera } catch (Exception e) { 18141de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera // Need to remove the admin that we just added. 182474c7aceae0c6a91049deb7db944cbe85b56bcc7Sudheer Shanka mDevicePolicyManager.removeActiveAdmin(mComponent, mUserId); 18341de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera throw e; 18441de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera } 185afad8783699b1ba6f3c7ee5961d6ddc2bd771dc1Alan Treadway 186afad8783699b1ba6f3c7ee5961d6ddc2bd771dc1Alan Treadway mDevicePolicyManager.setUserProvisioningState( 187afad8783699b1ba6f3c7ee5961d6ddc2bd771dc1Alan Treadway DevicePolicyManager.STATE_USER_SETUP_FINALIZED, mUserId); 188afad8783699b1ba6f3c7ee5961d6ddc2bd771dc1Alan Treadway 189c48bca50fa64765d3019b0bf82511e030cabcc7aEsteban Talavera System.out.println("Success: Active admin and profile owner set to " 190474c7aceae0c6a91049deb7db944cbe85b56bcc7Sudheer Shanka + mComponent.toShortString() + " for user " + mUserId); 19141de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera } 19241de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera 19341de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera private ComponentName parseComponentName(String component) { 19441de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera ComponentName cn = ComponentName.unflattenFromString(component); 19541de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera if (cn == null) { 19641de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera throw new IllegalArgumentException ("Invalid component " + component); 19741de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera } 19841de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera return cn; 19941de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera } 20041de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera 20141de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera private int parseInt(String argument) { 20241de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera try { 20341de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera return Integer.parseInt(argument); 20441de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera } catch (NumberFormatException e) { 20541de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera throw new IllegalArgumentException ("Invalid integer argument '" + argument + "'", e); 20641de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera } 20741de9bb6fda113f7cfb8b7b8d64d07d3809f8f20Esteban Talavera } 208afad8783699b1ba6f3c7ee5961d6ddc2bd771dc1Alan Treadway} 209