You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by is...@apache.org on 2013/07/23 14:04:18 UTC

[2/4] Renaming Stratos CLI Component. org.apache.stratos.adc.mgt.cli to org.apache.stratos.cli

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/CommandLineApplication.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/CommandLineApplication.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/CommandLineApplication.java
new file mode 100644
index 0000000..010948f
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/CommandLineApplication.java
@@ -0,0 +1,190 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli;
+
+import java.io.File;
+import java.io.IOException;
+
+import jline.console.ConsoleReader;
+import jline.console.history.FileHistory;
+
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class CommandLineApplication<T extends CommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(CommandLineApplication.class);
+
+	protected final ConsoleReader reader;
+	protected FileHistory history;
+
+	public CommandLineApplication() {
+		reader = createConsoleReader();
+	}
+
+	/**
+	 * Creates new jline ConsoleReader.
+	 * 
+	 * @return a jline ConsoleReader instance
+	 */
+	protected ConsoleReader createConsoleReader() {
+		ConsoleReader consoleReader = null;
+		try {
+			consoleReader = new ConsoleReader();
+			consoleReader.setPrompt(getPrompt());
+			history = new FileHistory(getHistoryFile());
+			consoleReader.setHistory(history);
+		} catch (IOException e) {
+			throw new IllegalStateException("Cannot create jline console reader", e);
+		}
+		return consoleReader;
+	}
+
+	public ConsoleReader getConsoleReader() {
+		return reader;
+	}
+
+	protected abstract String getPrompt();
+
+	/**
+	 * Get the history file for the Console Reader.
+	 * 
+	 * @return File for storing history
+	 */
+	protected abstract File getHistoryFile();
+
+	public final void start(String[] args) {
+		Thread shutdownHookThread = new Thread("CLI Shutdown Hook") {
+			@Override
+			public void run() {
+				performDestroy();
+			}
+		};
+		Runtime.getRuntime().addShutdownHook(shutdownHookThread);
+		int returnCode = run(args);
+		if (logger.isDebugEnabled()) {
+			logger.debug("Exiting with error code {}", returnCode);
+		}
+		System.exit(returnCode);
+	}
+
+	protected abstract int run(String[] args);
+
+	protected void promptLoop() {
+		String line = null;
+		boolean exit = false;
+
+		try {
+			while (!exit && (reader != null && ((line = reader.readLine()) != null))) {
+				if ("".equals(line)) {
+					continue;
+				}
+				if (StringUtils.isNotBlank(line)) {
+					execute(line);
+					exit = CliConstants.EXIT_ACTION.equals(line.trim());
+				}
+			}
+		} catch (IOException e) {
+			throw new IllegalStateException("Error in reading line", e);
+		}
+	}
+
+	private int execute(String line) {
+		try {
+			if (logger.isDebugEnabled()) {
+				logger.debug("Executing command line: \"{}\"", line);
+			}
+			int returnCode = executeCommand(line);
+			if (logger.isDebugEnabled()) {
+				logger.debug("Command line executed \"{}\". Return code: {}", line, returnCode);
+			}
+			return returnCode;
+		} catch (RuntimeException e) {
+			if (logger.isErrorEnabled()) {
+				logger.error("Error executing command line: " + line, e);
+			}
+			return 1;
+		}
+	}
+
+	protected abstract int executeCommand(String line);
+
+	private void performDestroy() {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Shutting down application... Invoking destroy methods");
+		}
+		if (history != null) {
+			try {
+				history.flush();
+			} catch (IOException e) {
+				if (logger.isErrorEnabled()) {
+					logger.error("Error flushing history.", e);
+				}
+			}
+		}
+		destroy();
+	}
+
+	/**
+	 * May override to perform action before destroying
+	 */
+	protected void destroy() {
+	};
+
+	public String getInput(String prompt) {
+		return getInput(prompt, null);
+	}
+
+	public String getInput(String prompt, Character mask) {
+		String line = null;
+		try {
+			reader.setPrompt(prompt + ": ");
+			while ((line = reader.readLine(mask)) != null) {
+				if ("".equals(line)) {
+					continue;
+				}
+				return line;
+			}
+		} catch (IOException e) {
+			throw new IllegalStateException("Error in reading line", e);
+		} finally {
+			reader.setPrompt(CliConstants.STRATOS_SHELL_PROMPT);
+		}
+		return line;
+	}
+	
+	/**
+	 * @return {@code true if user confirmed}
+	 */
+	public boolean getConfirmation(String prompt) {
+		prompt = prompt + " [yes/no]";
+
+		String input = "";
+		int tries = 0;
+		do {
+			tries++;
+			input = getInput(prompt);
+		} while (!"y".equals(input) && !"yes".equals(input) && !"n".equals(input) && !"no".equals(input) && tries < 3);
+
+		return "y".equals(input) || "yes".equals(input);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/CommandLineService.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/CommandLineService.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/CommandLineService.java
new file mode 100644
index 0000000..2aa9f2b
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/CommandLineService.java
@@ -0,0 +1,556 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli;
+
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.client.Options;
+import org.apache.axis2.client.ServiceClient;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.axis2.context.ConfigurationContextFactory;
+import org.apache.axis2.description.TransportOutDescription;
+import org.apache.axis2.transport.http.HttpTransportProperties;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.stratos.adc.mgt.cli.utils.CommandLineUtils;
+import org.apache.stratos.adc.mgt.cli.utils.RowMapper;
+import org.apache.stratos.adc.mgt.dto.xsd.Cartridge;
+import org.apache.stratos.adc.mgt.dto.xsd.PolicyDefinition;
+import org.apache.stratos.adc.mgt.dto.xsd.SubscriptionInfo;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceADCExceptionException;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceAlreadySubscribedExceptionException;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceDomainMappingExistsExceptionException;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceDuplicateCartridgeAliasExceptionException;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceInvalidCartridgeAliasExceptionException;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceInvalidRepositoryExceptionException;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceNotSubscribedExceptionException;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServicePolicyExceptionException;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceRepositoryCredentialsRequiredExceptionException;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceRepositoryRequiredExceptionException;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceRepositoryTransportExceptionException;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceStub;
+import org.apache.stratos.adc.mgt.stub.ApplicationManagementServiceUnregisteredCartridgeExceptionException;
+
+import com.google.gson.Gson;
+
+public class CommandLineService {
+
+	private static final Logger logger = LoggerFactory.getLogger(CommandLineService.class);
+
+	private ApplicationManagementServiceStub stub;
+
+	private CommandLineService() {
+	}
+
+	private static class SingletonHolder {
+		private final static CommandLineService INSTANCE = new CommandLineService();
+	}
+
+	public static CommandLineService getInstance() {
+		return SingletonHolder.INSTANCE;
+	}
+	
+	private void initializeApplicationManagementStub(String serverURL, String username, String password) throws AxisFault {
+		HttpTransportProperties.Authenticator authenticator = new HttpTransportProperties.Authenticator();
+        authenticator.setUsername(username);
+        authenticator.setPassword(password);
+        authenticator.setPreemptiveAuthentication(true);
+		
+        ApplicationManagementServiceStub stub;
+        ConfigurationContext configurationContext = null;
+        try {
+            configurationContext = ConfigurationContextFactory.createDefaultConfigurationContext();
+        } catch (Exception e) {
+            String msg = "Backend error occurred. Please contact the service admins!";
+            throw new AxisFault(msg, e);
+        }
+        HashMap<String, TransportOutDescription> transportsOut = configurationContext
+                .getAxisConfiguration().getTransportsOut();
+        for (TransportOutDescription transportOutDescription : transportsOut.values()) {
+            transportOutDescription.getSender().init(configurationContext, transportOutDescription);
+        }
+        stub = new ApplicationManagementServiceStub(configurationContext, serverURL + "/services/ApplicationManagementService");
+        ServiceClient client = stub._getServiceClient();
+        Options option = client.getOptions();
+        option.setManageSession(true);
+        option.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, authenticator);
+        option.setTimeOutInMilliSeconds(300000);
+        this.stub = stub;
+    }
+
+	public boolean login(String serverURL, String username, String password, boolean validateLogin) throws CommandException {
+		try {
+			// Following code will avoid validating certificate
+			SSLContext sc;
+			// Get SSL context
+			sc = SSLContext.getInstance("SSL");
+			// Create empty HostnameVerifier
+			HostnameVerifier hv = new HostnameVerifier() {
+				public boolean verify(String urlHostName, SSLSession session) {
+					return true;
+				}
+			};
+			// Create a trust manager that does not validate certificate
+			// chains
+			TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+				public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+					return null;
+				}
+
+				public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
+				}
+
+				public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
+				}
+			} };
+			sc.init(null, trustAllCerts, new java.security.SecureRandom());
+			SSLContext.setDefault(sc);
+			HttpsURLConnection.setDefaultHostnameVerifier(hv);
+		} catch (Exception e) {
+			throw new RuntimeException("Error while authentication process!", e);
+		}
+
+		// Initialize Service Stub
+		try {
+			initializeApplicationManagementStub(serverURL, username, password);
+		} catch (AxisFault e) {
+			System.out.println("Error connecting to the back-end");
+			throw new CommandException(e);
+		}
+		
+		try {
+			if (validateLogin) {
+				String tenantDomain = stub.getTenantDomain();
+				if (logger.isDebugEnabled()) {
+					logger.debug("Tenant Domain {}", tenantDomain);
+				}
+				return (tenantDomain != null);
+			} else {
+				// Just return true as we don't need to validate
+				return true;
+			}
+		} catch (RemoteException e) {
+			System.out.println("Authentication failed!");
+			throw new CommandException(e);
+		}
+	}
+
+	public void listSubscribedCartridges(final boolean full) throws CommandException {
+		try {
+			Cartridge[] cartridges = stub.getSubscribedCartridges();
+
+			if (cartridges == null) {
+				if (logger.isDebugEnabled()) {
+					logger.debug("No subscribed cartridges found");
+				}
+				System.out.println("There are no subscribed cartridges");
+				return;
+			}
+
+			RowMapper<Cartridge> cartridgeMapper = new RowMapper<Cartridge>() {
+
+				@Override
+				public String[] getData(Cartridge cartridge) {
+					String[] data = full ? new String[9] : new String[7];
+					data[0] = cartridge.getCartridgeType();
+					data[1] = cartridge.getDisplayName();
+					data[2] = cartridge.getVersion();
+					data[3] = cartridge.getMultiTenant() ? "Multi-Tenant" : "Single-Tenant";
+					data[4] = cartridge.getCartridgeAlias();
+					data[5] = cartridge.getStatus();
+					data[6] = cartridge.getMultiTenant() ? "N/A" : String.valueOf(cartridge.getActiveInstances());
+					if (full) {
+						data[7] = getAccessURLs(cartridge);
+						data[8] = cartridge.getRepoURL() != null ? cartridge.getRepoURL() : "";
+					}
+					return data;
+				}
+			};
+			
+			List<String> headers = new ArrayList<String>();
+			headers.add("Type");
+			headers.add("Name");
+			headers.add("Version");
+			headers.add("Tenancy Model");
+			headers.add("Alias");
+			headers.add("Status");
+			headers.add("Running Instances");
+			if (full) {
+				headers.add("Access URL(s)");
+				headers.add("Repo URL");
+			}
+
+			System.out.println("Subscribed Cartridges:");
+			CommandLineUtils.printTable(cartridges, cartridgeMapper, headers.toArray(new String[headers.size()]));
+
+			System.out.println();
+
+		} catch (ApplicationManagementServiceADCExceptionException e) {
+			handleException("cannot.list.subscribed.cartridges", e);
+		} catch (RemoteException e) {
+			handleException(e);
+		}
+	}
+
+	public void listAvailableCartridges() throws CommandException {
+		try {
+			Cartridge[] multiTenantCatridges = stub.getAvailableCartridges(true);
+
+			if (multiTenantCatridges == null) {
+				if (logger.isDebugEnabled()) {
+					logger.debug("No multi-tenant cartridges available");
+				}
+				System.out.println("There are no multi-tenant cartridges available");
+			}
+
+			RowMapper<Cartridge> cartridgeMapper = new RowMapper<Cartridge>() {
+
+				@Override
+				public String[] getData(Cartridge cartridge) {
+					String[] data = new String[3];
+					data[0] = cartridge.getCartridgeType();
+					data[1] = cartridge.getDisplayName();
+					data[2] = cartridge.getVersion();
+					return data;
+				}
+			};
+
+			System.out.println("Available Multi-Tenant Cartridges:");
+			CommandLineUtils.printTable(multiTenantCatridges, cartridgeMapper, "Type", "Name", "Version");
+			System.out.println();
+			
+			Cartridge[] singleTenantCatridges = stub.getAvailableCartridges(false);
+
+			if (multiTenantCatridges == null) {
+				if (logger.isDebugEnabled()) {
+					logger.debug("No single-tenant cartridges available");
+				}
+				System.out.println("There are no single-tenant cartridges available");
+			}
+			
+			System.out.println("Available Single-Tenant Cartridges:");
+			CommandLineUtils.printTable(singleTenantCatridges, cartridgeMapper, "Type", "Name", "Version");
+			System.out.println();
+		} catch (ApplicationManagementServiceADCExceptionException e) {
+			handleException("cannot.list.available.cartridges", e);
+		} catch (RemoteException e) {
+			handleException(e);
+		}
+	}
+	
+	public void listAvailablePolicies() throws CommandException {
+		try {
+			PolicyDefinition[] policies = stub.getPolicyDefinitions();
+
+			if (policies == null) {
+				if (logger.isDebugEnabled()) {
+					logger.debug("No policies available");
+				}
+				System.out.println("There are no policies available");
+			}
+
+			RowMapper<PolicyDefinition> policyMapper = new RowMapper<PolicyDefinition>() {
+
+				@Override
+				public String[] getData(PolicyDefinition policyDefinition) {
+					String[] data = new String[3];
+					data[0] = policyDefinition.getName();
+					data[1] = policyDefinition.getDescription();
+					data[2] = policyDefinition.getDefaultPolicy() ? "Yes" : "No";
+					return data;
+				}
+			};
+
+			CommandLineUtils.printTable(policies, policyMapper, "Policy Name", "Description", "Default");
+			System.out.println();
+		} catch (RemoteException e) {
+			handleException(e);
+		}
+	}
+
+	public void info(String alias) throws CommandException {
+		try {
+            Cartridge cartridge = null;
+            try {
+                cartridge = stub.getCartridgeInfo(alias);
+            } catch (ApplicationManagementServiceADCExceptionException e) {
+            	handleException(e);
+                return;
+            } catch (ApplicationManagementServiceNotSubscribedExceptionException e) {
+            	handleException("notsubscribed.error", e, alias);
+			}
+			if (logger.isDebugEnabled()) {
+				logger.debug("Cartridge Info: {}", new Gson().toJson(cartridge));
+			}
+			final String FORMAT = "%-20s: %s%n";
+			System.out.println();
+			System.out.println("Cartridge Information");
+			System.out.println("---------------------");
+			System.out.format(FORMAT, "Cartridge", cartridge.getCartridgeType());
+			System.out.format(FORMAT, "Name", cartridge.getDisplayName());
+			System.out.format(FORMAT, "Description", cartridge.getDescription());
+			System.out.format(FORMAT, "Version", cartridge.getVersion());
+			System.out.format(FORMAT, "Tenancy Model", cartridge.getMultiTenant() ? "Multi-Tenant" : "Single-Tenant");
+			System.out.format(FORMAT, "Alias", cartridge.getCartridgeAlias());
+			if (StringUtils.isNotBlank(cartridge.getPolicyDescription())) {
+				System.out.format(FORMAT, "Policy", cartridge.getPolicyDescription());
+			}
+			System.out.format(FORMAT, "Access URL(s)", getAccessURLs(cartridge));
+			if (StringUtils.isNotBlank(cartridge.getIp())) {
+				System.out.format(FORMAT, "Host", cartridge.getIp());
+			}
+			if (StringUtils.isNotBlank(cartridge.getDbUserName())) {
+				System.out.format(FORMAT, "Database Username", cartridge.getDbUserName());
+			}
+			if (StringUtils.isNotBlank(cartridge.getPassword())) {
+				System.out.format(FORMAT, "Password", cartridge.getPassword());
+			}
+			if (StringUtils.isNotBlank(cartridge.getRepoURL())) {
+				System.out.format(FORMAT, "Repository URL", cartridge.getRepoURL());
+			}
+			System.out.format(FORMAT, "Status", cartridge.getStatus());
+			System.out.format(FORMAT, "Running Instances",
+					cartridge.getMultiTenant() ? "N/A" : String.valueOf(cartridge.getActiveInstances()));
+			System.out.println();
+
+        } catch (RemoteException e) {
+        	handleException(e);
+        }
+	}
+
+	public void unsubscribe(String alias) throws CommandException {
+		try {
+			stub.unsubscribe(alias);
+			System.out.println("You have successfully unsubscribed " + alias);
+        } catch (ApplicationManagementServiceADCExceptionException e) {
+        	handleException("cannot.unsubscribe", e);
+        } catch (ApplicationManagementServiceNotSubscribedExceptionException e) {
+			handleException("notsubscribed.error", e, alias);
+        } catch (RemoteException e) {
+        	handleException(e);
+        }
+	}
+
+	public void sync(String alias) throws CommandException {
+		try {
+			System.out.format("Synchronizing repository for alias: %s%n", alias);
+			stub.synchronizeRepository(alias);
+		} catch (ApplicationManagementServiceADCExceptionException e) {
+			handleException("cannot.syncrepo", e);
+		} catch (RemoteException e) {
+			handleException(e);
+		} catch (ApplicationManagementServiceNotSubscribedExceptionException e) {
+			handleException("notsubscribed.error", e, alias);
+		}
+	}
+
+	public String addDomainMapping(String domain, String alias) throws CommandException {
+		try {
+			return stub.addDomainMapping(domain, alias);
+		} catch (ApplicationManagementServiceADCExceptionException e) {
+			handleException("cannot.mapdomain", e);
+		} catch (RemoteException e) {
+			handleException(e);
+		} catch (ApplicationManagementServiceNotSubscribedExceptionException e) {
+			handleException("notsubscribed.error", e, alias);
+		} catch (ApplicationManagementServiceDomainMappingExistsExceptionException e) {
+			handleException("domainmapping.exists.error", e, domain, alias);
+		}
+		return null;
+	}
+
+	public void removeDomainMapping(String alias) throws CommandException {
+		try {
+			stub.removeDomainMapping(alias);
+			System.out.format("Domain mapping removed for alias: %s.%n", alias);
+		} catch (ApplicationManagementServiceADCExceptionException e) {
+			handleException("cannot.removedomain", e);
+		} catch (RemoteException e) {
+			handleException(e);
+		} catch (ApplicationManagementServiceNotSubscribedExceptionException e) {
+			handleException("notsubscribed.error", e, alias);
+		}
+	}
+
+	public void subscribe(String cartridgeType, String alias, String policy, String externalRepoURL,
+			boolean privateRepo, String username, String password, String dataCartridgeType, String dataCartridgeAlias)
+			throws CommandException {
+		
+		SubscriptionInfo subcriptionConnectInfo = null;
+		if (StringUtils.isNotBlank(dataCartridgeType) && StringUtils.isNotBlank(dataCartridgeAlias)) {
+			System.out.format("Subscribing to data cartridge %s with alias %s.%n", dataCartridgeType,
+					dataCartridgeAlias);
+			try {
+				subcriptionConnectInfo = stub.subscribe(dataCartridgeType, dataCartridgeAlias, null, null, false, null,
+						null, null, null);
+				System.out.format("You have successfully subscribed to %s cartridge with alias %s.%n",
+						dataCartridgeType, dataCartridgeAlias);
+				System.out.format("%nSubscribing to %s cartridge and connecting with %s data cartridge.%n", alias,
+						dataCartridgeAlias);
+			} catch (RemoteException e) {
+				handleException(e);
+			} catch (ApplicationManagementServiceADCExceptionException e) {
+				handleException("cannot.subscribe", e);
+			} catch (ApplicationManagementServiceRepositoryRequiredExceptionException e) {
+				handleException("repository.required", e);
+			} catch (ApplicationManagementServiceUnregisteredCartridgeExceptionException e) {
+				handleException("cartridge.notregistered", e, dataCartridgeType);
+			} catch (ApplicationManagementServiceInvalidCartridgeAliasExceptionException e) {
+				handleException("cartridge.invalid.alias", e);
+			} catch (ApplicationManagementServiceAlreadySubscribedExceptionException e) {
+				handleException("cartridge.already.subscribed", e, e.getFaultMessage().getAlreadySubscribedException()
+						.getCartridgeType());
+			} catch (ApplicationManagementServiceDuplicateCartridgeAliasExceptionException e) {
+				handleException("cartridge.alias.duplicate", e, dataCartridgeAlias);
+			} catch (ApplicationManagementServicePolicyExceptionException e) {
+				handleException("policy.error", e);
+			} catch (ApplicationManagementServiceRepositoryTransportExceptionException e) {
+				handleException("repository.transport.error", e, externalRepoURL);
+			} catch (ApplicationManagementServiceRepositoryCredentialsRequiredExceptionException e) {
+				handleException("repository.credentials.required", e, externalRepoURL);
+			} catch (ApplicationManagementServiceInvalidRepositoryExceptionException e) {
+				handleException("repository.invalid.error", e, externalRepoURL);
+			}
+		}
+		
+		
+		try {
+			SubscriptionInfo subcriptionInfo = stub.subscribe(cartridgeType, alias, policy, externalRepoURL,
+					privateRepo, username, password, dataCartridgeType, dataCartridgeAlias);
+
+			System.out
+					.format("You have successfully subscribed to %s cartridge with alias %s.%n", cartridgeType, alias);
+
+			String repoURL = null;
+			String hostnames = null;
+			String hostnamesLabel = null;
+			if (subcriptionInfo != null) {
+				repoURL = subcriptionInfo.getRepositoryURL();
+				hostnames = subcriptionInfo.getHostname();
+				hostnamesLabel = "host name";
+
+				if (repoURL != null) {
+					System.out.println("GIT Repository URL: " + repoURL);
+				}
+
+				Cartridge cart = stub.getCartridgeInfo(alias);
+				System.out.format("Your application is being published here. %s%n", getAccessURLs(cart));
+			}
+			if (subcriptionConnectInfo != null) {
+				hostnames += ", " + subcriptionConnectInfo.getHostname();
+				hostnamesLabel = "host names";
+
+				Cartridge cart = stub.getCartridgeInfo(alias);
+				System.out.format("Your data application is being published here. %s%n", getAccessURLs(cart));
+			}
+			if (externalRepoURL != null) {
+				String takeTimeMsg = "(this might take few minutes... depending on repo size)\n";
+				System.out.println(takeTimeMsg);
+			}
+
+			System.out.format("Please map the %s \"%s\" to ELB IP%n", hostnamesLabel, hostnames);
+		} catch (RemoteException e) {
+			handleException(e);
+		} catch (ApplicationManagementServiceADCExceptionException e) {
+			handleException("cannot.subscribe", e);
+		} catch (ApplicationManagementServiceRepositoryRequiredExceptionException e) {
+			handleException("repository.required", e);
+		} catch (ApplicationManagementServiceUnregisteredCartridgeExceptionException e) {
+			handleException("cartridge.notregistered", e, cartridgeType);
+		} catch (ApplicationManagementServiceInvalidCartridgeAliasExceptionException e) {
+			handleException("cartridge.invalid.alias", e);
+		} catch (ApplicationManagementServiceAlreadySubscribedExceptionException e) {
+			handleException("cartridge.already.subscribed", e, e.getFaultMessage().getAlreadySubscribedException()
+					.getCartridgeType());
+		} catch (ApplicationManagementServiceDuplicateCartridgeAliasExceptionException e) {
+			handleException("cartridge.alias.duplicate", e, alias);
+		} catch (ApplicationManagementServicePolicyExceptionException e) {
+			handleException("policy.error", e);
+		} catch (ApplicationManagementServiceRepositoryTransportExceptionException e) {
+			handleException("repository.transport.error", e, externalRepoURL);
+		} catch (ApplicationManagementServiceRepositoryCredentialsRequiredExceptionException e) {
+			handleException("repository.credentials.required", e, externalRepoURL);
+		} catch (ApplicationManagementServiceInvalidRepositoryExceptionException e) {
+			handleException("repository.invalid.error", e, externalRepoURL);
+		} catch (ApplicationManagementServiceNotSubscribedExceptionException e) {
+			handleException("notsubscribed.error", e, alias);
+		}
+	}
+
+	private String getAccessURLs(Cartridge cartridge) {
+		String[] accessURLs = cartridge.getAccessURLs();
+		StringBuilder urlBuilder = new StringBuilder();
+		if (accessURLs != null) {
+			for (int i = 0; i < accessURLs.length; i++) {
+				String url = accessURLs[i];
+				if (url != null) {
+					if (i > 0) {
+						urlBuilder.append(", ");
+					}
+					urlBuilder.append(url);
+				}
+			}
+		}
+		return urlBuilder.toString();
+	}
+
+	private void handleException(Exception e) throws CommandException {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Displaying message from Exception {}\n{}", e.getClass(), e.getMessage());
+		}
+		// TODO: Fix handling error message.
+		// Sometimes the Axis2 stub throws only the RemoteException (an
+		// AxisFault)
+		// So, other exceptions won't come here.
+		String message = e.getMessage();
+		if (message == null || (message != null && message.contains("Exception"))) {
+			message = "Error executing command!";
+		}
+		if (logger.isErrorEnabled()) {
+			logger.error(message);
+		}
+		System.out.println(message);
+		throw new CommandException(message, e);
+	}
+    
+    private void handleException(String key, Exception e, Object... args) throws CommandException {
+    	if (logger.isDebugEnabled()) {
+    		logger.debug("Displaying message for {}. Exception thrown is {}", key, e.getClass());
+    	}
+    	String message = CommandLineUtils.getMessage(key, args);
+        if (logger.isErrorEnabled()) {
+        	logger.error(message);
+        }
+        System.out.println(message);
+        throw new CommandException(message, e);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/StratosApplication.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/StratosApplication.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/StratosApplication.java
new file mode 100644
index 0000000..74caf39
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/StratosApplication.java
@@ -0,0 +1,504 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli;
+
+import static org.apache.stratos.adc.mgt.cli.utils.CliConstants.STRATOS_DIR;
+import static org.apache.stratos.adc.mgt.cli.utils.CliConstants.STRATOS_HISTORY_DIR;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.stratos.adc.mgt.cli.completer.CommandCompleter;
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.text.StrTokenizer;
+import org.apache.commons.validator.routines.UrlValidator;
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.stratos.adc.mgt.cli.commands.AddDomainMappingCommand;
+import org.apache.stratos.adc.mgt.cli.commands.CartridgesCommand;
+import org.apache.stratos.adc.mgt.cli.commands.ExitCommand;
+import org.apache.stratos.adc.mgt.cli.commands.HelpCommand;
+import org.apache.stratos.adc.mgt.cli.commands.InfoCommand;
+import org.apache.stratos.adc.mgt.cli.commands.ListCommand;
+import org.apache.stratos.adc.mgt.cli.commands.PoliciesCommand;
+import org.apache.stratos.adc.mgt.cli.commands.RemoveDomainMappingCommand;
+import org.apache.stratos.adc.mgt.cli.commands.SubscribeCommand;
+import org.apache.stratos.adc.mgt.cli.commands.SyncCommand;
+import org.apache.stratos.adc.mgt.cli.commands.UnsubscribeCommand;
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+
+public class StratosApplication extends CommandLineApplication<StratosCommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(StratosApplication.class);
+
+	private final Map<String, Command<StratosCommandContext>> commands;
+	private final StratosCommandContext context;
+
+	private final Options options;
+
+	public StratosApplication() {
+		commands = new HashMap<String, Command<StratosCommandContext>>();
+		context = new StratosCommandContext(this);
+
+		options = constructOptions();
+
+		createCommands();
+		createAutocomplete();
+	}
+
+	/**
+	 * Construct Options.
+	 * 
+	 * @return Options expected from command-line.
+	 */
+	private Options constructOptions() {
+		final Options options = new Options();
+		Option usernameOption = new Option(CliConstants.USERNAME_OPTION, CliConstants.USERNAME_LONG_OPTION, true,
+				"Username");
+		usernameOption.setArgName("username");
+		options.addOption(usernameOption);
+
+		Option passwordOption = new Option(CliConstants.PASSWORD_OPTION, CliConstants.PASSWORD_LONG_OPTION, true,
+				"Password");
+		passwordOption.setArgName("password");
+		passwordOption.setOptionalArg(true);
+		options.addOption(passwordOption);
+		options.addOption(CliConstants.HELP_OPTION, CliConstants.HELP_LONG_OPTION, false, "Display this help");
+		options.addOption(CliConstants.TRACE_OPTION, false, "Enable trace logging");
+		options.addOption(CliConstants.DEBUG_OPTION, false, "Enable debug logging");
+		return options;
+	}
+
+	private void createCommands() {
+		Command<StratosCommandContext> command = new HelpCommand();
+		commands.put(command.getName(), command);
+
+		command = new ExitCommand();
+		commands.put(command.getName(), command);
+
+		command = new SubscribeCommand();
+		commands.put(command.getName(), command);
+
+		command = new UnsubscribeCommand();
+		commands.put(command.getName(), command);
+		
+		command = new CartridgesCommand();
+		commands.put(command.getName(), command);
+		
+		command = new ListCommand();
+		commands.put(command.getName(), command);
+		
+		command = new InfoCommand();
+		commands.put(command.getName(), command);
+		
+		command = new AddDomainMappingCommand();
+		commands.put(command.getName(), command);
+		
+		command = new RemoveDomainMappingCommand();
+		commands.put(command.getName(), command);
+		
+		command = new SyncCommand();
+		commands.put(command.getName(), command);
+		
+		command = new PoliciesCommand();
+		commands.put(command.getName(), command);
+
+		if (logger.isDebugEnabled()) {
+			logger.debug("Created {} commands for the application. {}", commands.size(), commands.keySet());
+		}
+	}
+
+	private void createAutocomplete() {
+		reader.addCompleter(new CommandCompleter(commands));
+	}
+
+	@Override
+	protected String getPrompt() {
+		return CliConstants.STRATOS_SHELL_PROMPT;
+	}
+
+	@Override
+	protected File getHistoryFile() {
+		File stratosFile = new File(System.getProperty("user.home"), STRATOS_DIR);
+		File historyFile = new File(stratosFile, STRATOS_HISTORY_DIR);
+		return historyFile;
+	}
+
+	@Override
+	public int run(String[] args) {
+		boolean loaded = loadRequiredProperties();
+		if (!loaded) {
+			return CliConstants.ERROR_CODE;
+		}
+
+		// To get the command action from arguments
+		String[] remainingArgs = null;
+
+		// Command action
+		String action = null;
+
+		String usernameInput = null;
+		String passwordInput = null;
+
+		if (args != null && args.length > 0) {
+			// Arguments are passed.
+			if (logger.isDebugEnabled()) {
+				logger.debug("Arguments:");
+				for (String arg : args) {
+					logger.debug(arg);
+				}
+			}
+
+			final CommandLineParser parser = new GnuParser();
+			CommandLine commandLine;
+			try {
+				// Must add all options. Otherwise actions cannot be performed directly by command line.
+				Options allCommandOptions = new Options();
+				for (Command<StratosCommandContext> command : commands.values()) {
+					Options commandOptions = command.getOptions();
+					if (commandOptions != null) {
+						Collection<?> allOptions = commandOptions.getOptions();
+						for (Object o : allOptions) {
+							allCommandOptions.addOption((Option) o);
+						}
+					}
+				}
+				// Add options in this application
+				Collection<?> allOptions = options.getOptions();
+				for (Object o : allOptions) {
+					allCommandOptions.addOption((Option) o);
+				}
+				
+				commandLine = parser.parse(allCommandOptions, args);
+				remainingArgs = commandLine.getArgs();
+				if (remainingArgs != null && remainingArgs.length > 0) {
+					// Get command action
+					action = remainingArgs[0];
+				}
+
+				// Set logger levels from this point onwards
+				setLoggerLevel(commandLine.hasOption(CliConstants.TRACE_OPTION),
+						commandLine.hasOption(CliConstants.DEBUG_OPTION));
+
+				if (commandLine.hasOption(CliConstants.USERNAME_OPTION)) {
+					if (logger.isTraceEnabled()) {
+						logger.trace("Username option is passed");
+					}
+					usernameInput = commandLine.getOptionValue(CliConstants.USERNAME_OPTION);
+				}
+				if (commandLine.hasOption(CliConstants.PASSWORD_OPTION)) {
+					if (logger.isTraceEnabled()) {
+						logger.trace("Password option is passed");
+					}
+					passwordInput = commandLine.getOptionValue(CliConstants.PASSWORD_OPTION);
+				}
+				if (commandLine.hasOption(CliConstants.HELP_ACTION)) {
+					printHelp();
+					return CliConstants.SUCCESSFUL_CODE;
+				}
+			} catch (ParseException e) {
+				if (logger.isErrorEnabled()) {
+					logger.error("Error parsing arguments when trying to login", e);
+				}
+				System.out.println(e.getMessage());
+				return CliConstants.BAD_ARGS_CODE; 
+			}
+
+		}
+
+		if (StringUtils.isNotBlank(action)) {
+			// User is executing an action
+			if (logger.isDebugEnabled()) {
+				logger.debug("Action: {}", action);
+			}
+			Command<StratosCommandContext> command = commands.get(action);
+			if (command == null) {
+				printHelp();
+				return CliConstants.BAD_ARGS_CODE;
+			}
+
+			boolean loginRequired = !CliConstants.HELP_ACTION.equals(action);
+			
+			if (loginRequired && logger.isDebugEnabled()) {
+				logger.debug("Trying to login...");
+			}
+
+			if (loginRequired && !login(usernameInput, passwordInput, false)) {
+				if (logger.isDebugEnabled()) {
+					logger.debug("Exiting from CLI. Login required but login might have failed: {}", action);
+				}
+				// Exit
+				return CliConstants.ERROR_CODE;
+			}
+
+			try {
+				String[] actionArgs = Arrays.copyOfRange(remainingArgs, 1, remainingArgs.length);
+				if (logger.isDebugEnabled()) {
+					logger.debug("Executing Action: {} {}", action, Arrays.asList(actionArgs));
+				}
+				int returnCode = command.execute(context, actionArgs);
+				if (logger.isDebugEnabled()) {
+					logger.debug("Exiting with error code {} after executing action {}", returnCode, action);
+				}
+				System.exit(returnCode);
+			} catch (CommandException e) {
+				if (logger.isErrorEnabled()) {
+					logger.error("Error executing command: " + action, e);
+				}
+				return CliConstants.ERROR_CODE;
+			}
+		} else {
+			if (login(usernameInput, passwordInput, true)) {
+				System.out.println("Successfully Authenticated.");
+			} else {
+				// Exit
+				return CliConstants.ERROR_CODE;
+			}
+
+			promptLoop();
+		}
+		return CliConstants.SUCCESSFUL_CODE;
+	}
+
+	private boolean login(String usernameInput, String passwordInput, boolean validateLogin) {
+		// TODO Previous CLI version uses a keystore. Here we are not using it.
+		// Check whether user has passed username and password
+		if (StringUtils.isBlank(usernameInput) && StringUtils.isBlank(passwordInput)) {
+			// User has not passed any arguments.
+			// Try authenticating from the values found
+			usernameInput = context.getString(CliConstants.STRATOS_USERNAME_ENV_PROPERTY);
+			passwordInput = context.getString(CliConstants.STRATOS_PASSWORD_ENV_PROPERTY);
+
+			if (logger.isDebugEnabled()) {
+				if (StringUtils.isNotBlank(usernameInput) && StringUtils.isNotBlank(passwordInput)) {
+					logger.debug("Found authentication details for {} from context", usernameInput);
+				}
+			}
+
+		}
+		// Get user input if not passed as args
+		if (StringUtils.isBlank(usernameInput)) {
+			usernameInput = getInput("Username");
+		} else {
+			System.out.format("Username: %s%n", usernameInput);
+		}
+		if (StringUtils.isBlank(passwordInput)) {
+			passwordInput = getInput("Password", '*');
+		}
+
+		boolean success = false;
+		String stratosURL = null;
+		stratosURL = context.getString(CliConstants.STRATOS_URL_ENV_PROPERTY);
+
+		try {
+			success = CommandLineService.getInstance().login(stratosURL, usernameInput, passwordInput, validateLogin);
+		} catch (Exception e) {
+			if (logger.isErrorEnabled()) {
+				logger.error("Error when trying to login", e);
+			}
+		}
+		if (success) {
+			if (logger.isDebugEnabled()) {
+				logger.debug("Successfully Authenticated.");
+			}
+		} else {
+			if (logger.isDebugEnabled()) {
+				logger.debug("Authentication failed.");
+			}
+		}
+		return success;
+	}
+
+	@Override
+	protected int executeCommand(String line) {
+		String[] tokens = new StrTokenizer(line).getTokenArray();
+		String action = tokens[0];
+		String[] actionArgs = Arrays.copyOfRange(tokens, 1, tokens.length);
+		if (logger.isDebugEnabled()) {
+			logger.debug("Executing command action: {}, Tokens: {}", action, tokens.length);
+		}
+		Command<StratosCommandContext> command = commands.get(action);
+		if (command == null) {
+			System.out.println(action + ": command not found.");
+			return CliConstants.BAD_ARGS_CODE;
+		}
+		try {
+			return command.execute(context, actionArgs);
+		} catch (CommandException e) {
+			if (logger.isErrorEnabled()) {
+				logger.error("Error executing command: " + action, e);
+			}
+			return CliConstants.ERROR_CODE;
+		}
+	}
+
+	/**
+	 * @return {@code true} if required properties are loaded
+	 */
+	private boolean loadRequiredProperties() {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Loading properties...");
+		}
+		// Load properties
+		String stratosURL = null;
+		String username = null;
+		String password = null;
+
+		stratosURL = System.getenv(CliConstants.STRATOS_URL_ENV_PROPERTY);
+		username = System.getenv(CliConstants.STRATOS_USERNAME_ENV_PROPERTY);
+		password = System.getenv(CliConstants.STRATOS_PASSWORD_ENV_PROPERTY);
+
+		if (StringUtils.isBlank(stratosURL)) {
+			if (logger.isDebugEnabled()) {
+				logger.debug("Required configuration not found.");
+			}
+			// Stratos Controller details are not set.
+			System.out.format("Could not find required \"%s\" variable in your environment.%n",
+					CliConstants.STRATOS_URL_ENV_PROPERTY);
+			return false;
+		} else {
+			if (logger.isDebugEnabled()) {
+				logger.debug("Required configuration found. Validating {}", stratosURL);
+			}
+			UrlValidator urlValidator = new UrlValidator(new String[] { "https" });
+			if (!urlValidator.isValid(stratosURL)) {
+				if (logger.isDebugEnabled()) {
+					logger.debug("Stratos Controller URL {} is not valid", stratosURL);
+				}
+				System.out.format(
+						"The \"%s\" variable in your environment is not a valid URL. You have provided \"%s\".%n"
+								+ "Please provide the Stratos Controller URL as follows%nhttps://<host>:<port>%n",
+						CliConstants.STRATOS_URL_ENV_PROPERTY, stratosURL);
+				return false;
+			}
+			if (logger.isDebugEnabled()) {
+				logger.debug("Stratos Controller URL {} is valid.", stratosURL);
+				logger.debug("Adding the values to context.");
+			}
+			context.put(CliConstants.STRATOS_URL_ENV_PROPERTY, stratosURL);
+			context.put(CliConstants.STRATOS_USERNAME_ENV_PROPERTY, username);
+			context.put(CliConstants.STRATOS_PASSWORD_ENV_PROPERTY, password);
+			return true;
+		}
+	}
+	
+	private void setLoggerLevel(boolean trace, boolean debug) {
+		// We are using Log4j. So, get the logger and set log levels.
+		org.apache.log4j.Logger logger = LogManager.getLogger(StratosApplication.class.getPackage().getName());
+		if (logger != null && trace) {
+			logger.setLevel(Level.TRACE);
+			LogManager.getRootLogger().setLevel(Level.TRACE);
+		} else if (logger != null && debug) {
+			logger.setLevel(Level.DEBUG);
+			LogManager.getRootLogger().setLevel(Level.DEBUG);
+		}
+	}
+
+	public void printHelp(final String action) {
+		Command<StratosCommandContext> command = commands.get(action);
+		if (command == null) {
+			System.out.println(action + ": command not found. Help not available.");
+			return;
+		}
+		System.out.println(command.getDescription());
+		Options options = command.getOptions();
+		if (options != null) {
+			if (StringUtils.isNotBlank(command.getArgumentSyntax())) {
+				printHelp(command.getName() + " " + command.getArgumentSyntax(), options);
+			} else {
+				printHelp(command.getName(), options);
+			}
+		} else {
+			// No options. Just print the usage.
+			printUsage(command);
+		}
+	}
+
+	public void printHelp() {
+		printHelp(CliConstants.STRATOS_APPLICATION_NAME, options);
+		System.out.println("\n\nAvailable Commands: ");
+		for (String action : commands.keySet()) {
+			Command<StratosCommandContext> command = commands.get(action);
+			if (command != null) {
+				System.out.format("%-25s %s%n", command.getName(), command.getDescription());
+			}
+		}
+
+		System.out.println("\nFor help on a specific command type:\nhelp [command]");
+	}
+
+	/**
+	 * Print "help" with usage
+	 */
+	private void printHelp(final String commandLineSyntax, final Options options) {
+		final HelpFormatter helpFormatter = new HelpFormatter();
+		helpFormatter.printHelp(commandLineSyntax, options, true);
+	}
+	
+	public void printUsage(final String action) {
+		Command<StratosCommandContext> command = commands.get(action);
+		if (command == null) {
+			return;
+		}
+		printUsage(command);
+	}
+	
+	private void printUsage(Command<StratosCommandContext> command) {
+		Options options = command.getOptions();
+		if (options != null) {
+			if (StringUtils.isNotBlank(command.getArgumentSyntax())) {
+				printUsage(command.getName() + " " + command.getArgumentSyntax(), options);
+			} else {
+				printUsage(command.getName(), options);
+			}
+		} else {
+			System.out.print("usage: ");
+			if (StringUtils.isNotBlank(command.getArgumentSyntax())) {
+				System.out.println(command.getName() + " " + command.getArgumentSyntax());
+			} else {
+				System.out.println(command.getName());
+			}
+		}
+	}
+	
+	/**
+	 * Print "usage"
+	 */
+	private void printUsage(final String commandLineSyntax, final Options options) {
+		final PrintWriter writer = new PrintWriter(System.out);
+		final HelpFormatter usageFormatter = new HelpFormatter();
+		usageFormatter.printUsage(writer, 80, commandLineSyntax, options);
+		writer.flush();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/StratosCommandContext.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/StratosCommandContext.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/StratosCommandContext.java
new file mode 100644
index 0000000..e4f7652
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/StratosCommandContext.java
@@ -0,0 +1,31 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli;
+
+public class StratosCommandContext extends CommandContext {
+
+	public StratosCommandContext(StratosApplication application) {
+		super(application);
+	}
+
+	public StratosApplication getStratosApplication() {
+		return (StratosApplication) getApplication();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/AddDomainMappingCommand.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/AddDomainMappingCommand.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/AddDomainMappingCommand.java
new file mode 100644
index 0000000..fe25f02
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/AddDomainMappingCommand.java
@@ -0,0 +1,87 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli.commands;
+
+import org.apache.stratos.adc.mgt.cli.Command;
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.commons.cli.Options;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.stratos.adc.mgt.cli.CommandLineService;
+import org.apache.stratos.adc.mgt.cli.StratosCommandContext;
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+
+public class AddDomainMappingCommand implements Command<StratosCommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(AddDomainMappingCommand.class);
+
+	public AddDomainMappingCommand() {
+	}
+
+	@Override
+	public String getName() {
+		return CliConstants.ADD_DOMAIN_MAPPING_ACTION;
+	}
+
+	@Override
+	public String getDescription() {
+		return "Map domain for the subscribed cartridge";
+	}
+
+	@Override
+	public String getArgumentSyntax() {
+		return "[Cartridge alias] [Domain]";
+	}
+
+	@Override
+	public int execute(StratosCommandContext context, String[] args) throws CommandException {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Executing {} command...", getName());
+		}
+		if (args != null && args.length == 2) {
+			String alias = args[0];
+			String domain = args[1];
+			if (logger.isDebugEnabled()) {
+				logger.debug("Adding domain mapping {} for alias {}", domain, alias);
+			}
+
+			String domainToDisplay = null;
+
+			domainToDisplay = CommandLineService.getInstance().addDomainMapping(domain, alias);
+
+			if (StringUtils.isBlank(domainToDisplay)) {
+				System.out.println("Error adding domain mapping.");
+				return CliConstants.BAD_ARGS_CODE;
+			} else {
+				System.out.format("Your own domain is added. Please CNAME it to systems domain %s.%n", domainToDisplay);
+				return CliConstants.SUCCESSFUL_CODE;
+			}
+		} else {
+			context.getStratosApplication().printUsage(getName());
+			return CliConstants.BAD_ARGS_CODE;
+		}
+	}
+
+	@Override
+	public Options getOptions() {
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/CartridgesCommand.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/CartridgesCommand.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/CartridgesCommand.java
new file mode 100644
index 0000000..fc7461f
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/CartridgesCommand.java
@@ -0,0 +1,71 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli.commands;
+
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.commons.cli.Options;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.stratos.adc.mgt.cli.Command;
+import org.apache.stratos.adc.mgt.cli.CommandLineService;
+import org.apache.stratos.adc.mgt.cli.StratosCommandContext;
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+
+public class CartridgesCommand implements Command<StratosCommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(CartridgesCommand.class);
+
+	public CartridgesCommand() {
+	}
+
+	@Override
+	public String getName() {
+		return CliConstants.CARTRIDGES_ACTION;
+	}
+
+	@Override
+	public String getDescription() {
+		return "List available cartridges";
+	}
+
+	@Override
+	public String getArgumentSyntax() {
+		return null;
+	}
+
+	@Override
+	public int execute(StratosCommandContext context, String[] args) throws CommandException {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Executing {} command...", getName());
+		}
+		if (args == null || args.length == 0) {
+			CommandLineService.getInstance().listAvailableCartridges();
+			return CliConstants.SUCCESSFUL_CODE;
+		} else {
+			context.getStratosApplication().printUsage(getName());
+			return CliConstants.BAD_ARGS_CODE;
+		}
+	}
+
+	@Override
+	public Options getOptions() {
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/ExitCommand.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/ExitCommand.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/ExitCommand.java
new file mode 100644
index 0000000..e0ff8c3
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/ExitCommand.java
@@ -0,0 +1,70 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli.commands;
+
+import org.apache.commons.cli.Options;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.stratos.adc.mgt.cli.Command;
+import org.apache.stratos.adc.mgt.cli.StratosCommandContext;
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+
+public class ExitCommand implements Command<StratosCommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(ExitCommand.class);
+
+	public ExitCommand() {
+	}
+
+	@Override
+	public String getName() {
+		return CliConstants.EXIT_ACTION;
+	}
+
+	@Override
+	public String getDescription() {
+		return "Exit from Stratos Client Tool";
+	}
+
+	@Override
+	public String getArgumentSyntax() {
+		return null;
+	}
+
+	@Override
+	public int execute(StratosCommandContext context, String[] args) throws CommandException {
+		// Nothing to execute here. This is a special command.
+		if (logger.isDebugEnabled()) {
+			logger.debug("Executing {} command...", getName());
+		}
+		if (args == null || args.length == 0) {
+			return CliConstants.SUCCESSFUL_CODE;
+		} else {
+			context.getStratosApplication().printUsage(getName());
+			return CliConstants.BAD_ARGS_CODE;
+		}
+	}
+
+	@Override
+	public Options getOptions() {
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/HelpCommand.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/HelpCommand.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/HelpCommand.java
new file mode 100644
index 0000000..ca74687
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/HelpCommand.java
@@ -0,0 +1,73 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli.commands;
+
+import org.apache.commons.cli.Options;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.stratos.adc.mgt.cli.Command;
+import org.apache.stratos.adc.mgt.cli.StratosCommandContext;
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+
+public class HelpCommand implements Command<StratosCommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(HelpCommand.class);
+
+	public HelpCommand() {
+	}
+
+	@Override
+	public String getName() {
+		return CliConstants.HELP_ACTION;
+	}
+
+	@Override
+	public String getDescription() {
+		return "Help for commands";
+	}
+
+	@Override
+	public String getArgumentSyntax() {
+		return "[command]";
+	}
+
+	@Override
+	public int execute(StratosCommandContext context, String[] args) throws CommandException {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Executing {} command...", getName());
+		}
+		if (args == null || args.length == 0) {
+			context.getStratosApplication().printHelp();
+			return CliConstants.SUCCESSFUL_CODE;
+		} else if (args != null && args.length == 1) {
+			context.getStratosApplication().printHelp(args[0]);
+			return CliConstants.SUCCESSFUL_CODE;
+		} else {
+			context.getStratosApplication().printUsage(getName());
+			return CliConstants.BAD_ARGS_CODE;
+		}
+	}
+
+	@Override
+	public Options getOptions() {
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/InfoCommand.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/InfoCommand.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/InfoCommand.java
new file mode 100644
index 0000000..a4ac08e
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/InfoCommand.java
@@ -0,0 +1,75 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli.commands;
+
+import org.apache.stratos.adc.mgt.cli.Command;
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.commons.cli.Options;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.stratos.adc.mgt.cli.CommandLineService;
+import org.apache.stratos.adc.mgt.cli.StratosCommandContext;
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+
+public class InfoCommand implements Command<StratosCommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(InfoCommand.class);
+
+	public InfoCommand() {
+	}
+
+	@Override
+	public String getName() {
+		return CliConstants.INFO_ACTION;
+	}
+
+	@Override
+	public String getDescription() {
+		return "Get information about a subscribed cartridge";
+	}
+
+	@Override
+	public String getArgumentSyntax() {
+		return "[Cartridge alias]";
+	}
+
+	@Override
+	public int execute(StratosCommandContext context, String[] args) throws CommandException {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Executing {} command...", getName());
+		}
+		if (args != null && args.length == 1) {
+			String alias = args[0];
+			if (logger.isDebugEnabled()) {
+				logger.debug("Getting info {}", alias);
+			}
+			CommandLineService.getInstance().info(alias);
+			return CliConstants.SUCCESSFUL_CODE;
+		} else {
+			context.getStratosApplication().printUsage(getName());
+			return CliConstants.BAD_ARGS_CODE;
+		}
+	}
+
+	@Override
+	public Options getOptions() {
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/ListCommand.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/ListCommand.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/ListCommand.java
new file mode 100644
index 0000000..1b96182
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/ListCommand.java
@@ -0,0 +1,123 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli.commands;
+
+import org.apache.stratos.adc.mgt.cli.Command;
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.stratos.adc.mgt.cli.CommandLineService;
+import org.apache.stratos.adc.mgt.cli.StratosCommandContext;
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+
+public class ListCommand implements Command<StratosCommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(ListCommand.class);
+	
+	private final Options options;
+
+	public ListCommand() {
+		options = constructOptions();
+	}
+	
+	/**
+	 * Construct Options.
+	 * 
+	 * @return Options expected from command-line.
+	 */
+	private Options constructOptions() {
+		final Options options = new Options();
+		Option fullOption = new Option(CliConstants.FULL_OPTION, CliConstants.FULL_LONG_OPTION, false,
+				"Display extra details");
+		options.addOption(fullOption);
+		return options;
+	}
+
+	@Override
+	public String getName() {
+		return CliConstants.LIST_ACTION;
+	}
+
+	@Override
+	public String getDescription() {
+		return "List subscribed cartridges with details";
+	}
+
+	@Override
+	public String getArgumentSyntax() {
+		return null;
+	}
+
+	@Override
+	public int execute(StratosCommandContext context, String[] args) throws CommandException {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Executing {} command...", getName());
+		}
+		if (args == null || args.length == 0) {
+			CommandLineService.getInstance().listSubscribedCartridges(false);
+			return CliConstants.SUCCESSFUL_CODE;
+		} else if (args != null && args.length > 0) {
+			String[] remainingArgs = null;
+			boolean full = false;
+			final CommandLineParser parser = new GnuParser();
+			CommandLine commandLine;
+			try {
+				commandLine = parser.parse(options, args);
+				remainingArgs = commandLine.getArgs();
+				if (!(remainingArgs == null || remainingArgs.length == 0)) {
+					context.getStratosApplication().printUsage(getName());
+					return CliConstants.BAD_ARGS_CODE;
+				}
+
+				if (commandLine.hasOption(CliConstants.FULL_OPTION)) {
+					if (logger.isTraceEnabled()) {
+						logger.trace("Full option is passed");
+					}
+					full = true;
+				}
+				if (logger.isDebugEnabled()) {
+					logger.debug("Listing subscribed cartridges, Full Option: {}", full);
+				}
+				CommandLineService.getInstance().listSubscribedCartridges(full);
+				return CliConstants.SUCCESSFUL_CODE;
+			} catch (ParseException e) {
+				if (logger.isErrorEnabled()) {
+					logger.error("Error parsing arguments", e);
+				}
+				System.out.println(e.getMessage());
+				return CliConstants.BAD_ARGS_CODE;
+			}
+		} else {
+			context.getStratosApplication().printUsage(getName());
+			return CliConstants.BAD_ARGS_CODE;
+		}
+	}
+
+	@Override
+	public Options getOptions() {
+		return options;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/PoliciesCommand.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/PoliciesCommand.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/PoliciesCommand.java
new file mode 100644
index 0000000..4811efd
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/PoliciesCommand.java
@@ -0,0 +1,71 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli.commands;
+
+import org.apache.commons.cli.Options;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.stratos.adc.mgt.cli.Command;
+import org.apache.stratos.adc.mgt.cli.CommandLineService;
+import org.apache.stratos.adc.mgt.cli.StratosCommandContext;
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+
+public class PoliciesCommand implements Command<StratosCommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(PoliciesCommand.class);
+
+	public PoliciesCommand() {
+	}
+
+	@Override
+	public String getName() {
+		return CliConstants.POLICIES_ACTION;
+	}
+
+	@Override
+	public String getDescription() {
+		return "List available policies";
+	}
+
+	@Override
+	public String getArgumentSyntax() {
+		return null;
+	}
+
+	@Override
+	public int execute(StratosCommandContext context, String[] args) throws CommandException {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Executing {} command...", getName());
+		}
+		if (args == null || args.length == 0) {
+			CommandLineService.getInstance().listAvailablePolicies();
+			return CliConstants.SUCCESSFUL_CODE;
+		} else {
+			context.getStratosApplication().printUsage(getName());
+			return CliConstants.BAD_ARGS_CODE;
+		}
+	}
+
+	@Override
+	public Options getOptions() {
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/RemoveDomainMappingCommand.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/RemoveDomainMappingCommand.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/RemoveDomainMappingCommand.java
new file mode 100644
index 0000000..a3b4cc0
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/RemoveDomainMappingCommand.java
@@ -0,0 +1,75 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli.commands;
+
+import org.apache.stratos.adc.mgt.cli.Command;
+import org.apache.stratos.adc.mgt.cli.CommandLineService;
+import org.apache.stratos.adc.mgt.cli.StratosCommandContext;
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+import org.apache.commons.cli.Options;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RemoveDomainMappingCommand implements Command<StratosCommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(RemoveDomainMappingCommand.class);
+
+	public RemoveDomainMappingCommand() {
+	}
+
+	@Override
+	public String getName() {
+		return CliConstants.REMOVE_DOMAIN_MAPPING_ACTION;
+	}
+
+	@Override
+	public String getDescription() {
+		return "Remove domain mapping for the subscribed cartridge";
+	}
+
+	@Override
+	public String getArgumentSyntax() {
+		return "[Cartridge alias]";
+	}
+
+	@Override
+	public int execute(StratosCommandContext context, String[] args) throws CommandException {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Executing {} command...", getName());
+		}
+		if (args != null && args.length == 1) {
+			String alias = args[0];
+			if (logger.isDebugEnabled()) {
+				logger.debug("Removing domain mapping for {}", alias);
+			}
+			CommandLineService.getInstance().removeDomainMapping(alias);
+			return CliConstants.SUCCESSFUL_CODE;
+		} else {
+			context.getStratosApplication().printUsage(getName());
+			return CliConstants.BAD_ARGS_CODE;
+		}
+	}
+
+	@Override
+	public Options getOptions() {
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SubscribeCommand.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SubscribeCommand.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SubscribeCommand.java
new file mode 100644
index 0000000..90908e9
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SubscribeCommand.java
@@ -0,0 +1,208 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli.commands;
+
+import org.apache.stratos.adc.mgt.cli.Command;
+import org.apache.stratos.adc.mgt.cli.CommandLineService;
+import org.apache.stratos.adc.mgt.cli.StratosCommandContext;
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+
+public class SubscribeCommand implements Command<StratosCommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(ListCommand.class);
+
+	private final Options options;;
+
+	public SubscribeCommand() {
+		options = constructOptions();
+	}
+
+	/**
+	 * Construct Options.
+	 * 
+	 * @return Options expected from command-line.
+	 */
+	private Options constructOptions() {
+		final Options options = new Options();
+		Option policyOption = new Option(CliConstants.POLICY_OPTION, CliConstants.POLICY_LONG_OPTION, true,
+				"Auto-scaling policy.\nPlease use \"" + CliConstants.POLICIES_ACTION
+						+ "\" command to view the available policies.");
+		policyOption.setArgName("policy name");
+		options.addOption(policyOption);
+
+		Option connectOption = new Option(CliConstants.CONNECT_OPTION, CliConstants.CONNECT_LONG_OPTION, true,
+				"Data cartridge type");
+		connectOption.setArgName("data cartridge type");
+		options.addOption(connectOption);
+
+		Option aliasOption = new Option(CliConstants.DATA_ALIAS_OPTION, CliConstants.DATA_ALIAS_LONG_OPTION, true,
+				"Data cartridge alias");
+		aliasOption.setArgName("alias");
+		options.addOption(aliasOption);
+
+		Option urlOption = new Option(CliConstants.REPO_URL_OPTION, CliConstants.REPO_URL_LONG_OPTION, true,
+				"GIT repository URL");
+		urlOption.setArgName("url");
+		options.addOption(urlOption);
+
+		options.addOption(CliConstants.PRIVATE_REPO_OPTION, CliConstants.PRIVATE_REPO_LONG_OPTION, false,
+				"Private repository");
+
+		Option usernameOption = new Option(CliConstants.USERNAME_OPTION, CliConstants.USERNAME_LONG_OPTION, true,
+				"GIT repository username");
+		usernameOption.setArgName("username");
+		options.addOption(usernameOption);
+
+		Option passwordOption = new Option(CliConstants.PASSWORD_OPTION, CliConstants.PASSWORD_LONG_OPTION, true,
+				"GIT repository password");
+		passwordOption.setArgName("password");
+		passwordOption.setOptionalArg(true);
+		options.addOption(passwordOption);
+		return options;
+	}
+
+	@Override
+	public String getName() {
+		return CliConstants.SUBSCRIBE_ACTION;
+	}
+
+	@Override
+	public String getDescription() {
+		return "Subscribe to a cartridge";
+	}
+
+	@Override
+	public String getArgumentSyntax() {
+		return "[Cartridge type] [Cartridge alias]";
+	}
+
+	@Override
+	public int execute(StratosCommandContext context, String[] args) throws CommandException {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Executing {} command...", getName());
+		}
+		if (args != null && args.length > 0) {
+			String[] remainingArgs = null;
+			String type = null;
+			String alias = null;
+			String policy = null;
+			String repoURL = null, dataCartridgeType = null, dataCartridgeAlias = null, username = "", password = "";
+			boolean privateRepo = false;
+			final CommandLineParser parser = new GnuParser();
+			CommandLine commandLine;
+			try {
+				commandLine = parser.parse(options, args);
+				remainingArgs = commandLine.getArgs();
+				if (remainingArgs != null && remainingArgs.length == 2) {
+					// Get type
+					type = remainingArgs[0];
+					alias = remainingArgs[1];
+				} else {
+					context.getStratosApplication().printUsage(getName());
+					return CliConstants.BAD_ARGS_CODE;
+				}
+
+				if (logger.isDebugEnabled()) {
+					logger.debug("Subscribing to {} cartridge with alias {}", type, alias);
+				}
+
+				if (commandLine.hasOption(CliConstants.POLICY_OPTION)) {
+					if (logger.isTraceEnabled()) {
+						logger.trace("Policy option is passed");
+					}
+					policy = commandLine.getOptionValue(CliConstants.POLICY_OPTION);
+				}
+				if (commandLine.hasOption(CliConstants.REPO_URL_OPTION)) {
+					if (logger.isTraceEnabled()) {
+						logger.trace("RepoURL option is passed");
+					}
+					repoURL = commandLine.getOptionValue(CliConstants.REPO_URL_OPTION);
+				}
+				if (commandLine.hasOption(CliConstants.PRIVATE_REPO_OPTION)) {
+					if (logger.isTraceEnabled()) {
+						logger.trace("privateRepo option is passed");
+					}
+					privateRepo = true;
+				}
+				if (commandLine.hasOption(CliConstants.USERNAME_OPTION)) {
+					if (logger.isTraceEnabled()) {
+						logger.trace("Username option is passed");
+					}
+					username = commandLine.getOptionValue(CliConstants.USERNAME_OPTION);
+				}
+				if (commandLine.hasOption(CliConstants.PASSWORD_OPTION)) {
+					if (logger.isTraceEnabled()) {
+						logger.trace("Password option is passed");
+					}
+					password = commandLine.getOptionValue(CliConstants.PASSWORD_OPTION);
+				}
+				if (commandLine.hasOption(CliConstants.CONNECT_OPTION)) {
+					if (logger.isTraceEnabled()) {
+						logger.trace("Connect option is passed");
+					}
+					dataCartridgeType = commandLine.getOptionValue(CliConstants.CONNECT_OPTION);
+				}
+				if (commandLine.hasOption(CliConstants.DATA_ALIAS_OPTION)) {
+					if (logger.isTraceEnabled()) {
+						logger.trace("Data alias option is passed");
+					}
+					dataCartridgeAlias = commandLine.getOptionValue(CliConstants.DATA_ALIAS_OPTION);
+				}
+				
+				if (StringUtils.isNotBlank(username) && StringUtils.isBlank(password)) {
+					password = context.getApplication().getInput("GIT Repository Password", '*');
+				}
+
+				if (StringUtils.isNotBlank(dataCartridgeType) && !StringUtils.isNotBlank(dataCartridgeAlias)) {
+					System.out.println("Data cartridge alias is required.");
+					context.getStratosApplication().printUsage(getName());
+					return CliConstants.BAD_ARGS_CODE;
+				}
+				CommandLineService.getInstance().subscribe(type, alias, policy, repoURL, privateRepo, username,
+						password, dataCartridgeType, dataCartridgeAlias);
+				return CliConstants.SUCCESSFUL_CODE;
+			} catch (ParseException e) {
+				if (logger.isErrorEnabled()) {
+					logger.error("Error parsing arguments", e);
+				}
+				System.out.println(e.getMessage());
+				return CliConstants.BAD_ARGS_CODE;
+			}
+		} else {
+			context.getStratosApplication().printUsage(getName());
+			return CliConstants.BAD_ARGS_CODE;
+		}
+	}
+
+	@Override
+	public Options getOptions() {
+		return options;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/4f790fe5/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SyncCommand.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SyncCommand.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SyncCommand.java
new file mode 100644
index 0000000..6e21a4d
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SyncCommand.java
@@ -0,0 +1,76 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.stratos.adc.mgt.cli.commands;
+
+import org.apache.stratos.adc.mgt.cli.exception.CommandException;
+import org.apache.commons.cli.Options;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.stratos.adc.mgt.cli.Command;
+import org.apache.stratos.adc.mgt.cli.CommandLineService;
+import org.apache.stratos.adc.mgt.cli.StratosCommandContext;
+import org.apache.stratos.adc.mgt.cli.utils.CliConstants;
+
+public class SyncCommand implements Command<StratosCommandContext> {
+
+	private static final Logger logger = LoggerFactory.getLogger(SyncCommand.class);
+
+	public SyncCommand() {
+	}
+
+	@Override
+	public String getName() {
+		return CliConstants.SYNC_ACTION;
+	}
+
+	@Override
+	public String getDescription() {
+		return "Synchronize GIT repository for the subscribed cartridge";
+	}
+
+	@Override
+	public String getArgumentSyntax() {
+		return "[Cartridge alias]";
+	}
+
+	@Override
+	public int execute(StratosCommandContext context, String[] args) throws CommandException {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Executing {} command...", getName());
+		}
+		if (args != null && args.length == 1) {
+			String alias = args[0];
+			if (logger.isDebugEnabled()) {
+				logger.debug("Synchronizing repository for alias {}", alias);
+			}
+
+			CommandLineService.getInstance().sync(alias);
+			return CliConstants.SUCCESSFUL_CODE;
+		} else {
+			context.getStratosApplication().printUsage(getName());
+			return CliConstants.BAD_ARGS_CODE;
+		}
+	}
+
+	@Override
+	public Options getOptions() {
+		return null;
+	}
+
+}