You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by da...@apache.org on 2014/02/04 13:38:32 UTC

[1/6] CLOUDSTACK-6003 fixing plus refactoring dispatcher

Updated Branches:
  refs/heads/master ca1b340ce -> 447430c3d


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
index 3159059..23ae50c 100644
--- a/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotSchedulerImpl.java
@@ -83,6 +83,8 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
     protected VolumeDao _volsDao;
     @Inject
     protected ConfigurationDao _configDao;
+    @Inject
+    protected ApiDispatcher _dispatcher;
 
     protected AsyncJobDispatcher _asyncDispatcher;
 
@@ -96,21 +98,21 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
         return _asyncDispatcher;
     }
 
-    public void setAsyncJobDispatcher(AsyncJobDispatcher dispatcher) {
+    public void setAsyncJobDispatcher(final AsyncJobDispatcher dispatcher) {
         _asyncDispatcher = dispatcher;
     }
 
-    private Date getNextScheduledTime(long policyId, Date currentTimestamp) {
-        SnapshotPolicyVO policy = _snapshotPolicyDao.findById(policyId);
+    private Date getNextScheduledTime(final long policyId, final Date currentTimestamp) {
+        final SnapshotPolicyVO policy = _snapshotPolicyDao.findById(policyId);
         Date nextTimestamp = null;
         if (policy != null) {
-            short intervalType = policy.getInterval();
-            IntervalType type = DateUtil.getIntervalType(intervalType);
-            String schedule = policy.getSchedule();
-            String timezone = policy.getTimezone();
+            final short intervalType = policy.getInterval();
+            final IntervalType type = DateUtil.getIntervalType(intervalType);
+            final String schedule = policy.getSchedule();
+            final String timezone = policy.getTimezone();
             nextTimestamp = DateUtil.getNextRunTime(type, schedule, timezone, currentTimestamp);
-            String currentTime = DateUtil.displayDateInTimezone(DateUtil.GMT_TIMEZONE, currentTimestamp);
-            String nextScheduledTime = DateUtil.displayDateInTimezone(DateUtil.GMT_TIMEZONE, nextTimestamp);
+            final String currentTime = DateUtil.displayDateInTimezone(DateUtil.GMT_TIMEZONE, currentTimestamp);
+            final String nextScheduledTime = DateUtil.displayDateInTimezone(DateUtil.GMT_TIMEZONE, nextTimestamp);
             s_logger.debug("Current time is " + currentTime + ". NextScheduledTime of policyId " + policyId + " is " + nextScheduledTime);
         }
         return nextTimestamp;
@@ -120,7 +122,7 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
      * {@inheritDoc}
      */
     @Override
-    public void poll(Date currentTimestamp) {
+    public void poll(final Date currentTimestamp) {
         // We don't maintain the time. The timer task does.
         _currentTimestamp = currentTimestamp;
 
@@ -152,12 +154,12 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
     }
 
     private void checkStatusOfCurrentlyExecutingSnapshots() {
-        SearchCriteria<SnapshotScheduleVO> sc = _snapshotScheduleDao.createSearchCriteria();
+        final SearchCriteria<SnapshotScheduleVO> sc = _snapshotScheduleDao.createSearchCriteria();
         sc.addAnd("asyncJobId", SearchCriteria.Op.NNULL);
-        List<SnapshotScheduleVO> snapshotSchedules = _snapshotScheduleDao.search(sc, null);
-        for (SnapshotScheduleVO snapshotSchedule : snapshotSchedules) {
-            Long asyncJobId = snapshotSchedule.getAsyncJobId();
-            AsyncJobVO asyncJob = _asyncJobDao.findById(asyncJobId);
+        final List<SnapshotScheduleVO> snapshotSchedules = _snapshotScheduleDao.search(sc, null);
+        for (final SnapshotScheduleVO snapshotSchedule : snapshotSchedules) {
+            final Long asyncJobId = snapshotSchedule.getAsyncJobId();
+            final AsyncJobVO asyncJob = _asyncJobDao.findById(asyncJobId);
             switch (asyncJob.getStatus()) {
                 case SUCCEEDED:
                     // The snapshot has been successfully backed up.
@@ -168,7 +170,7 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
                     break;
                 case FAILED:
                     // Check the snapshot status.
-                    Long snapshotId = snapshotSchedule.getSnapshotId();
+                    final Long snapshotId = snapshotSchedule.getSnapshotId();
                     if (snapshotId == null) {
                         // createSnapshotAsync exited, successfully or unsuccessfully,
                         // even before creating a snapshot record
@@ -176,7 +178,7 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
                         // Schedule the next snapshot.
                         scheduleNextSnapshotJob(snapshotSchedule);
                     } else {
-                        SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
+                        final SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
                         if (snapshot == null || snapshot.getRemoved() != null) {
                             // This snapshot has been deleted successfully from the primary storage
                             // Again no cleanup needs to be done.
@@ -220,16 +222,16 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
         String displayTime = DateUtil.displayDateInTimezone(DateUtil.GMT_TIMEZONE, _currentTimestamp);
         s_logger.debug("Snapshot scheduler.poll is being called at " + displayTime);
 
-        List<SnapshotScheduleVO> snapshotsToBeExecuted = _snapshotScheduleDao.getSchedulesToExecute(_currentTimestamp);
+        final List<SnapshotScheduleVO> snapshotsToBeExecuted = _snapshotScheduleDao.getSchedulesToExecute(_currentTimestamp);
         s_logger.debug("Got " + snapshotsToBeExecuted.size() + " snapshots to be executed at " + displayTime);
 
-        for (SnapshotScheduleVO snapshotToBeExecuted : snapshotsToBeExecuted) {
+        for (final SnapshotScheduleVO snapshotToBeExecuted : snapshotsToBeExecuted) {
             SnapshotScheduleVO tmpSnapshotScheduleVO = null;
-            long snapshotScheId = snapshotToBeExecuted.getId();
-            long policyId = snapshotToBeExecuted.getPolicyId();
-            long volumeId = snapshotToBeExecuted.getVolumeId();
+            final long snapshotScheId = snapshotToBeExecuted.getId();
+            final long policyId = snapshotToBeExecuted.getPolicyId();
+            final long volumeId = snapshotToBeExecuted.getVolumeId();
             try {
-                VolumeVO volume = _volsDao.findById(volumeId);
+                final VolumeVO volume = _volsDao.findById(volumeId);
                 if (volume.getPoolId() == null) {
                     // this volume is not attached
                     continue;
@@ -238,40 +240,41 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
                     _snapshotScheduleDao.remove(snapshotToBeExecuted.getId());
                 }
                 if (s_logger.isDebugEnabled()) {
-                    Date scheduledTimestamp = snapshotToBeExecuted.getScheduledTimestamp();
+                    final Date scheduledTimestamp = snapshotToBeExecuted.getScheduledTimestamp();
                     displayTime = DateUtil.displayDateInTimezone(DateUtil.GMT_TIMEZONE, scheduledTimestamp);
                     s_logger.debug("Scheduling 1 snapshot for volume " + volumeId + " for schedule id: " + snapshotToBeExecuted.getId() + " at " + displayTime);
                 }
 
                 tmpSnapshotScheduleVO = _snapshotScheduleDao.acquireInLockTable(snapshotScheId);
-                Long eventId =
+                final Long eventId =
                     ActionEventUtils.onScheduledActionEvent(User.UID_SYSTEM, volume.getAccountId(), EventTypes.EVENT_SNAPSHOT_CREATE, "creating snapshot for volume Id:" +
                         volumeId, 0);
 
-                Map<String, String> params = new HashMap<String, String>();
+                final Map<String, Object> params = new HashMap<String, Object>();
                 params.put(ApiConstants.VOLUME_ID, "" + volumeId);
                 params.put(ApiConstants.POLICY_ID, "" + policyId);
                 params.put("ctxUserId", "1");
                 params.put("ctxAccountId", "" + volume.getAccountId());
                 params.put("ctxStartEventId", String.valueOf(eventId));
 
-                CreateSnapshotCmd cmd = new CreateSnapshotCmd();
+                final CreateSnapshotCmd cmd = new CreateSnapshotCmd();
                 ComponentContext.inject(cmd);
-                ApiDispatcher.getInstance().dispatchCreateCmd(cmd, params);
+                _dispatcher.dispatchCreateCmd(cmd, params);
                 params.put("id", "" + cmd.getEntityId());
                 params.put("ctxStartEventId", "1");
 
-                AsyncJobVO job =
+                final AsyncJobVO job =
                     new AsyncJobVO(UUID.randomUUID().toString(), User.UID_SYSTEM, volume.getAccountId(), CreateSnapshotCmd.class.getName(), ApiGsonHelper.getBuilder()
                         .create()
                         .toJson(params), cmd.getEntityId(), cmd.getInstanceType() != null ? cmd.getInstanceType().toString() : null);
                 job.setDispatcher(_asyncDispatcher.getName());
 
-                long jobId = _asyncMgr.submitAsyncJob(job);
+                final long jobId = _asyncMgr.submitAsyncJob(job);
 
                 tmpSnapshotScheduleVO.setAsyncJobId(jobId);
                 _snapshotScheduleDao.update(snapshotScheId, tmpSnapshotScheduleVO);
-            } catch (Exception e) {
+            } catch (final Exception e) {
+                // TODO Logging this exception is enough?
                 s_logger.warn("Scheduling snapshot failed due to " + e.toString());
             } finally {
                 if (tmpSnapshotScheduleVO != null) {
@@ -281,16 +284,16 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
         }
     }
 
-    private Date scheduleNextSnapshotJob(SnapshotScheduleVO snapshotSchedule) {
+    private Date scheduleNextSnapshotJob(final SnapshotScheduleVO snapshotSchedule) {
         if (snapshotSchedule == null) {
             return null;
         }
-        Long policyId = snapshotSchedule.getPolicyId();
+        final Long policyId = snapshotSchedule.getPolicyId();
         if (policyId.longValue() == Snapshot.MANUAL_POLICY_ID) {
             // Don't need to schedule the next job for this.
             return null;
         }
-        SnapshotPolicyVO snapshotPolicy = _snapshotPolicyDao.findById(policyId);
+        final SnapshotPolicyVO snapshotPolicy = _snapshotPolicyDao.findById(policyId);
         if (snapshotPolicy == null) {
             _snapshotScheduleDao.expunge(snapshotSchedule.getId());
         }
@@ -299,15 +302,15 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
 
     @Override
     @DB
-    public Date scheduleNextSnapshotJob(SnapshotPolicyVO policy) {
+    public Date scheduleNextSnapshotJob(final SnapshotPolicyVO policy) {
         if (policy == null) {
             return null;
         }
-        long policyId = policy.getId();
+        final long policyId = policy.getId();
         if (policyId == Snapshot.MANUAL_POLICY_ID) {
             return null;
         }
-        Date nextSnapshotTimestamp = getNextScheduledTime(policyId, _currentTimestamp);
+        final Date nextSnapshotTimestamp = getNextScheduledTime(policyId, _currentTimestamp);
         SnapshotScheduleVO spstSchedVO = _snapshotScheduleDao.findOneByVolumePolicy(policy.getVolumeId(), policy.getId());
         if (spstSchedVO == null) {
             spstSchedVO = new SnapshotScheduleVO(policy.getVolumeId(), policyId, nextSnapshotTimestamp);
@@ -331,9 +334,9 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
 
     @Override
     @DB
-    public boolean removeSchedule(Long volumeId, Long policyId) {
+    public boolean removeSchedule(final Long volumeId, final Long policyId) {
         // We can only remove schedules which are in the future. Not which are already executed in the past.
-        SnapshotScheduleVO schedule = _snapshotScheduleDao.getCurrentSchedule(volumeId, policyId, false);
+        final SnapshotScheduleVO schedule = _snapshotScheduleDao.getCurrentSchedule(volumeId, policyId, false);
         boolean success = true;
         if (schedule != null) {
             success = _snapshotScheduleDao.remove(schedule.getId());
@@ -345,18 +348,18 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
     }
 
     @Override
-    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+    public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
 
         _snapshotPollInterval = NumbersUtil.parseInt(_configDao.getValue("snapshot.poll.interval"), 300);
-        boolean snapshotsRecurringTest = Boolean.parseBoolean(_configDao.getValue("snapshot.recurring.test"));
+        final boolean snapshotsRecurringTest = Boolean.parseBoolean(_configDao.getValue("snapshot.recurring.test"));
         if (snapshotsRecurringTest) {
             // look for some test values in the configuration table so that snapshots can be taken more frequently (QA test code)
-            int minutesPerHour = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.minutes.per.hour"), 60);
-            int hoursPerDay = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.hours.per.day"), 24);
-            int daysPerWeek = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.days.per.week"), 7);
-            int daysPerMonth = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.days.per.month"), 30);
-            int weeksPerMonth = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.weeks.per.month"), 4);
-            int monthsPerYear = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.months.per.year"), 12);
+            final int minutesPerHour = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.minutes.per.hour"), 60);
+            final int hoursPerDay = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.hours.per.day"), 24);
+            final int daysPerWeek = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.days.per.week"), 7);
+            final int daysPerMonth = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.days.per.month"), 30);
+            final int weeksPerMonth = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.weeks.per.month"), 4);
+            final int monthsPerYear = NumbersUtil.parseInt(_configDao.getValue("snapshot.test.months.per.year"), 12);
 
             _testTimerTask = new TestClock(this, minutesPerHour, hoursPerDay, daysPerWeek, daysPerMonth, weeksPerMonth, monthsPerYear);
         }
@@ -371,8 +374,8 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
     @DB
     public boolean start() {
         // reschedule all policies after management restart
-        List<SnapshotPolicyVO> policyInstances = _snapshotPolicyDao.listAll();
-        for (SnapshotPolicyVO policyInstance : policyInstances) {
+        final List<SnapshotPolicyVO> policyInstances = _snapshotPolicyDao.listAll();
+        for (final SnapshotPolicyVO policyInstance : policyInstances) {
             if (policyInstance.getId() != Snapshot.MANUAL_POLICY_ID) {
                 scheduleNextSnapshotJob(policyInstance);
             }
@@ -383,13 +386,13 @@ public class SnapshotSchedulerImpl extends ManagerBase implements SnapshotSchedu
             // Else it becomes too confusing.
             _testClockTimer.schedule(_testTimerTask, 100 * 1000L, 60 * 1000L);
         } else {
-            TimerTask timerTask = new ManagedContextTimerTask() {
+            final TimerTask timerTask = new ManagedContextTimerTask() {
                 @Override
                 protected void runInContext() {
                     try {
-                        Date currentTimestamp = new Date();
+                        final Date currentTimestamp = new Date();
                         poll(currentTimestamp);
-                    } catch (Throwable t) {
+                    } catch (final Throwable t) {
                         s_logger.warn("Catch throwable in snapshot scheduler ", t);
                     }
                 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/test/com/cloud/api/ApiDispatcherTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/ApiDispatcherTest.java b/server/test/com/cloud/api/ApiDispatcherTest.java
deleted file mode 100644
index 7314a57..0000000
--- a/server/test/com/cloud/api/ApiDispatcherTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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 com.cloud.api;
-
-import java.util.HashMap;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.runners.MockitoJUnitRunner;
-
-import org.apache.cloudstack.api.BaseCmd;
-import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
-import org.apache.cloudstack.context.CallContext;
-
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.exception.InsufficientCapacityException;
-import com.cloud.exception.NetworkRuleConflictException;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.user.Account;
-import com.cloud.user.AccountManager;
-import com.cloud.user.User;
-
-@RunWith(MockitoJUnitRunner.class)
-public class ApiDispatcherTest {
-
-    @Mock
-    AccountManager accountManager;
-
-    public static class TestCmd extends BaseCmd {
-
-        @Parameter(name = "strparam1")
-        String strparam1;
-
-        @Parameter(name = "intparam1", type = CommandType.INTEGER)
-        int intparam1;
-
-        @Parameter(name = "boolparam1", type = CommandType.BOOLEAN)
-        boolean boolparam1;
-
-        @Override
-        public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
-            ResourceAllocationException, NetworkRuleConflictException {
-            // well documented nothing
-        }
-
-        @Override
-        public String getCommandName() {
-            return "test";
-        }
-
-        @Override
-        public long getEntityOwnerId() {
-            return 0;
-        }
-
-    }
-
-    @Before
-    public void setup() {
-        CallContext.register(Mockito.mock(User.class), Mockito.mock(Account.class));
-        new ApiDispatcher().init();
-        ApiDispatcher.getInstance()._accountMgr = accountManager;
-    }
-
-    @After
-    public void cleanup() {
-        CallContext.unregister();
-    }
-
-    @Test
-    public void processParameters() {
-        HashMap<String, String> params = new HashMap<String, String>();
-        params.put("strparam1", "foo");
-        params.put("intparam1", "100");
-        params.put("boolparam1", "true");
-        TestCmd cmd = new TestCmd();
-        //how lucky that field is not protected, this test would be impossible
-        ApiDispatcher.processParameters(cmd, params);
-        Assert.assertEquals("foo", cmd.strparam1);
-        Assert.assertEquals(100, cmd.intparam1);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/test/com/cloud/api/dispatch/CommandCreationWorkerTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/dispatch/CommandCreationWorkerTest.java b/server/test/com/cloud/api/dispatch/CommandCreationWorkerTest.java
new file mode 100644
index 0000000..775fd6a
--- /dev/null
+++ b/server/test/com/cloud/api/dispatch/CommandCreationWorkerTest.java
@@ -0,0 +1,48 @@
+// 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 com.cloud.api.dispatch;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import org.apache.cloudstack.api.BaseAsyncCreateCmd;
+
+import com.cloud.exception.ResourceAllocationException;
+
+public class CommandCreationWorkerTest {
+
+    @Test
+    public void testHandle() throws ResourceAllocationException {
+        // Prepare
+        final BaseAsyncCreateCmd asyncCreateCmd = mock(BaseAsyncCreateCmd.class);
+        final Map<String, Object> params = new HashMap<String, Object>();
+
+        // Execute
+        final CommandCreationWorker creationWorker = new CommandCreationWorker();
+
+        creationWorker.handle(asyncCreateCmd, params);
+
+        // Assert
+        verify(asyncCreateCmd, times(1)).create();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/test/com/cloud/api/dispatch/DispatchChainFactoryTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/dispatch/DispatchChainFactoryTest.java b/server/test/com/cloud/api/dispatch/DispatchChainFactoryTest.java
new file mode 100644
index 0000000..0d743d4
--- /dev/null
+++ b/server/test/com/cloud/api/dispatch/DispatchChainFactoryTest.java
@@ -0,0 +1,54 @@
+// 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 com.cloud.api.dispatch;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+public class DispatchChainFactoryTest {
+
+    protected static final String STANDARD_CHAIN_ERROR = "Expecting worker of class %s at index %s of StandardChain";
+    protected static final String ASYNC_CHAIN_ERROR = "Expecting worker of class %s at index %s of StandardChain";
+
+    @Test
+    public void testAllChainCreation() {
+        // Prepare
+        final DispatchChainFactory dispatchChainFactory = new DispatchChainFactory();
+        dispatchChainFactory.paramGenericValidationWorker = new ParamGenericValidationWorker();
+        dispatchChainFactory.paramSemanticValidationWorker = new ParamSemanticValidationWorker();
+        dispatchChainFactory.paramProcessWorker = new ParamProcessWorker();
+        dispatchChainFactory.commandCreationWorker = new CommandCreationWorker();
+
+        final Class<?>[] standardClasses = {ParamGenericValidationWorker.class, ParamProcessWorker.class,
+                ParamSemanticValidationWorker.class};
+        final Class<?>[] asyncClasses = {ParamGenericValidationWorker.class, ParamProcessWorker.class,
+                ParamSemanticValidationWorker.class, CommandCreationWorker.class};
+
+        // Execute
+        dispatchChainFactory.setup();
+        final DispatchChain standardChain = dispatchChainFactory.getStandardDispatchChain();
+        final DispatchChain asyncChain = dispatchChainFactory.getAsyncCreationDispatchChain();
+        for (int i = 0; i < standardClasses.length; i++) {
+            assertEquals(String.format(STANDARD_CHAIN_ERROR, standardClasses[i], i),
+                    standardClasses[i], standardChain.workers.get(i).getClass());
+        }
+        for (int i = 0; i < asyncClasses.length; i++) {
+            assertEquals(String.format(ASYNC_CHAIN_ERROR, asyncClasses[i], i),
+                    asyncClasses[i], asyncChain.workers.get(i).getClass());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java b/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java
new file mode 100644
index 0000000..3fd37cc
--- /dev/null
+++ b/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java
@@ -0,0 +1,163 @@
+// 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 com.cloud.api.dispatch;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+
+import org.apache.log4j.Logger;
+
+public class ParamGenericValidationWorkerTest {
+
+    protected String loggerOutput = null;
+
+    protected void driveTest(final BaseCmd cmd, final Map<String, Object> params) {
+        final ParamGenericValidationWorker genValidationWorker = new ParamGenericValidationWorker();
+
+        // We create a mock logger to verify the result
+        ParamGenericValidationWorker.s_logger = new Logger(""){
+            @Override
+            public void warn(final Object msg){
+                loggerOutput = msg.toString();
+            }
+        };
+
+        // Execute
+        genValidationWorker.handle(cmd, params);
+    }
+
+    @Test
+    public void testHandle() throws ResourceAllocationException {
+        // Prepare
+        final BaseCmd cmd = new FakeCmd();
+        final Map<String, Object> params = new HashMap<String, Object>();
+        params.put(ApiConstants.COMMAND, "");
+        params.put("addedParam", "");
+
+        // Execute
+        driveTest(cmd, params);
+
+        // Assert
+        assertEquals("There should be no errors since there are no unknown parameters for this command class", null, loggerOutput);
+    }
+
+    @Test
+    public void testHandleWithUnknownParams() throws ResourceAllocationException {
+        // Prepare
+        final String unknownParamKey = "unknownParam";
+        final BaseCmd cmd = new FakeCmd();
+        final Map<String, Object> params = new HashMap<String, Object>();
+        params.put(ApiConstants.COMMAND, "");
+        params.put("addedParam", "");
+        params.put(unknownParamKey, "");
+
+        // Execute
+        driveTest(cmd, params);
+
+        // Assert
+        assertTrue("There should be error msg, since there is one unknown parameter", loggerOutput.contains(unknownParamKey));
+    }
+
+    @Test
+    public void testHandleWithoutAuthorization() throws ResourceAllocationException {
+        final short type = 2;
+        driveAuthTest(type);
+
+        // Assert
+        assertTrue("There should be error msg, since there is one unauthorized parameter", loggerOutput.contains("paramWithRole"));
+    }
+
+    @Test
+    public void testHandleWithAuthorization() throws ResourceAllocationException {
+        final short type = 1;
+        driveAuthTest(type);
+
+        // Assert
+        assertEquals("There should be no errors since parameters have authorization", null, loggerOutput);
+    }
+
+    protected void driveAuthTest(final short type) {
+        // Prepare
+        final BaseCmd cmd = new FakeCmdWithRoleAdmin();
+        final Account account = mock(Account.class);
+        ((FakeCmdWithRoleAdmin)cmd).account = account;
+        when(account.getType()).thenReturn(type);
+        final Map<String, Object> params = new HashMap<String, Object>();
+        params.put(ApiConstants.COMMAND, "");
+        params.put("addedParam", "");
+        params.put("paramWithRole", "");
+
+        // Execute
+        driveTest(cmd, params);
+    }
+}
+
+class FakeCmd extends BaseCmd {
+
+    @Parameter(name = "addedParam")
+    private String addedParam;
+
+    public Account account;
+
+    @Override
+    protected Account getCurrentContextAccount() {
+        return account;
+    }
+
+    //
+    // Dummy methods for mere correct compilation
+    //
+    @Override
+    public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException,
+            NetworkRuleConflictException {
+    }
+    @Override
+    public String getCommandName() {
+        return null;
+    }
+    @Override
+    public long getEntityOwnerId() {
+        return 0;
+    }
+}
+
+class FakeCmdWithRoleAdmin extends FakeCmd {
+
+    @Parameter(name = "paramWithRole", authorized = {RoleType.Admin})
+    private String paramWithRole;
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/test/com/cloud/api/dispatch/ParamProcessWorkerTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/dispatch/ParamProcessWorkerTest.java b/server/test/com/cloud/api/dispatch/ParamProcessWorkerTest.java
new file mode 100644
index 0000000..1259713
--- /dev/null
+++ b/server/test/com/cloud/api/dispatch/ParamProcessWorkerTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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 com.cloud.api.dispatch;
+
+import java.util.HashMap;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.user.User;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ParamProcessWorkerTest {
+
+    @Mock
+    protected AccountManager accountManager;
+
+    protected ParamProcessWorker paramProcessWorker;
+
+    public static class TestCmd extends BaseCmd {
+
+        @Parameter(name = "strparam1")
+        String strparam1;
+
+        @Parameter(name = "intparam1", type = CommandType.INTEGER)
+        int intparam1;
+
+        @Parameter(name = "boolparam1", type = CommandType.BOOLEAN)
+        boolean boolparam1;
+
+        @Override
+        public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
+            ResourceAllocationException, NetworkRuleConflictException {
+            // well documented nothing
+        }
+
+        @Override
+        public String getCommandName() {
+            return "test";
+        }
+
+        @Override
+        public long getEntityOwnerId() {
+            return 0;
+        }
+
+    }
+
+    @Before
+    public void setup() {
+        CallContext.register(Mockito.mock(User.class), Mockito.mock(Account.class));
+        paramProcessWorker = new ParamProcessWorker();
+        paramProcessWorker._accountMgr = accountManager;
+    }
+
+    @After
+    public void cleanup() {
+        CallContext.unregister();
+    }
+
+    @Test
+    public void processParameters() {
+        final HashMap<String, Object> params = new HashMap<String, Object>();
+        params.put("strparam1", "foo");
+        params.put("intparam1", "100");
+        params.put("boolparam1", "true");
+        final TestCmd cmd = new TestCmd();
+        paramProcessWorker.processParameters(cmd, params);
+        Assert.assertEquals("foo", cmd.strparam1);
+        Assert.assertEquals(100, cmd.intparam1);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/test/com/cloud/api/dispatch/ParamSemanticValidationWorkerTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/dispatch/ParamSemanticValidationWorkerTest.java b/server/test/com/cloud/api/dispatch/ParamSemanticValidationWorkerTest.java
new file mode 100644
index 0000000..920654e
--- /dev/null
+++ b/server/test/com/cloud/api/dispatch/ParamSemanticValidationWorkerTest.java
@@ -0,0 +1,48 @@
+// 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 com.cloud.api.dispatch;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import org.apache.cloudstack.api.BaseCmd;
+
+import com.cloud.exception.ResourceAllocationException;
+
+public class ParamSemanticValidationWorkerTest {
+
+    @Test
+    public void testHandle() throws ResourceAllocationException {
+        // Prepare
+        final BaseCmd cmd = mock(BaseCmd.class);
+        final Map<String, Object> params = new HashMap<String, Object>();
+
+        // Execute
+        final ParamSemanticValidationWorker semanticValWorker = new ParamSemanticValidationWorker();
+
+        semanticValWorker.handle(cmd, params);
+
+        // Assert
+        verify(cmd, times(1)).validateSpecificParameters(params);
+    }
+}


[2/6] CLOUDSTACK-6003 fixing plus refactoring dispatcher

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index bf2516a..589b50c 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -105,7 +105,6 @@ import com.cloud.agent.api.to.StaticNatRuleTO;
 import com.cloud.agent.manager.Commands;
 import com.cloud.alert.AlertManager;
 import com.cloud.api.ApiAsyncJobDispatcher;
-import com.cloud.api.ApiDispatcher;
 import com.cloud.api.ApiGsonHelper;
 import com.cloud.cluster.ManagementServerHostVO;
 import com.cloud.cluster.dao.ManagementServerHostDao;
@@ -427,8 +426,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     BlockingQueue<Long> _vrUpdateQueue = null;
 
     @Override
-    public boolean sendSshKeysToHost(Long hostId, String pubKey, String prvKey) {
-        ModifySshKeysCommand cmd = new ModifySshKeysCommand(pubKey, prvKey);
+    public boolean sendSshKeysToHost(final Long hostId, final String pubKey, final String prvKey) {
+        final ModifySshKeysCommand cmd = new ModifySshKeysCommand(pubKey, prvKey);
         final Answer answer = _agentMgr.easySend(hostId, cmd);
 
         if (answer != null) {
@@ -439,13 +438,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     @Override
-    public VirtualRouter destroyRouter(final long routerId, Account caller, Long callerUserId) throws ResourceUnavailableException, ConcurrentOperationException {
+    public VirtualRouter destroyRouter(final long routerId, final Account caller, final Long callerUserId) throws ResourceUnavailableException, ConcurrentOperationException {
 
         if (s_logger.isDebugEnabled()) {
             s_logger.debug("Attempting to destroy router " + routerId);
         }
 
-        DomainRouterVO router = _routerDao.findById(routerId);
+        final DomainRouterVO router = _routerDao.findById(routerId);
         if (router == null) {
             return null;
         }
@@ -459,12 +458,12 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
     @Override
     @DB
-    public VirtualRouter upgradeRouter(UpgradeRouterCmd cmd) {
-        Long routerId = cmd.getId();
-        Long serviceOfferingId = cmd.getServiceOfferingId();
-        Account caller = CallContext.current().getCallingAccount();
+    public VirtualRouter upgradeRouter(final UpgradeRouterCmd cmd) {
+        final Long routerId = cmd.getId();
+        final Long serviceOfferingId = cmd.getServiceOfferingId();
+        final Account caller = CallContext.current().getCallingAccount();
 
-        DomainRouterVO router = _routerDao.findById(routerId);
+        final DomainRouterVO router = _routerDao.findById(routerId);
         if (router == null) {
             throw new InvalidParameterValueException("Unable to find router with id " + routerId);
         }
@@ -476,7 +475,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             return _routerDao.findById(routerId);
         }
 
-        ServiceOffering newServiceOffering = _entityMgr.findById(ServiceOffering.class, serviceOfferingId);
+        final ServiceOffering newServiceOffering = _entityMgr.findById(ServiceOffering.class, serviceOfferingId);
         if (newServiceOffering == null) {
             throw new InvalidParameterValueException("Unable to find service offering with id " + serviceOfferingId);
         }
@@ -493,7 +492,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                 "; make sure the router is stopped and not in an error state before upgrading.");
         }
 
-        ServiceOfferingVO currentServiceOffering = _serviceOfferingDao.findById(router.getServiceOfferingId());
+        final ServiceOfferingVO currentServiceOffering = _serviceOfferingDao.findById(router.getServiceOfferingId());
 
         // Check that the service offering being upgraded to has the same storage pool preference as the VM's current service
         // offering
@@ -512,7 +511,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     @Override
-    public boolean savePasswordToRouter(Network network, final NicProfile nic, VirtualMachineProfile profile, List<? extends VirtualRouter> routers)
+    public boolean savePasswordToRouter(final Network network, final NicProfile nic, final VirtualMachineProfile profile, final List<? extends VirtualRouter> routers)
         throws ResourceUnavailableException {
         _userVmDao.loadDetails((UserVmVO)profile.getVirtualMachine());
 
@@ -520,10 +519,10 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
         return applyRules(network, routers, "save password entry", false, null, false, new RuleApplier() {
             @Override
-            public boolean execute(Network network, VirtualRouter router) throws ResourceUnavailableException {
+            public boolean execute(final Network network, final VirtualRouter router) throws ResourceUnavailableException {
                 // for basic zone, send vm data/password information only to the router in the same pod
-                Commands cmds = new Commands(Command.OnError.Stop);
-                NicVO nicVo = _nicDao.findById(nic.getId());
+                final Commands cmds = new Commands(Command.OnError.Stop);
+                final NicVO nicVo = _nicDao.findById(nic.getId());
                 createPasswordCommand(router, updatedProfile, nicVo, cmds);
                 return sendCommandsToRouter(router, cmds);
             }
@@ -531,7 +530,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     @Override
-    public boolean saveSSHPublicKeyToRouter(Network network, final NicProfile nic, VirtualMachineProfile profile, List<? extends VirtualRouter> routers,
+    public boolean saveSSHPublicKeyToRouter(final Network network, final NicProfile nic, final VirtualMachineProfile profile, final List<? extends VirtualRouter> routers,
         final String sshPublicKey) throws ResourceUnavailableException {
         final UserVmVO vm = _userVmDao.findById(profile.getVirtualMachine().getId());
         _userVmDao.loadDetails(vm);
@@ -540,11 +539,11 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
         return applyRules(network, routers, "save SSHkey entry", false, null, false, new RuleApplier() {
             @Override
-            public boolean execute(Network network, VirtualRouter router) throws ResourceUnavailableException {
+            public boolean execute(final Network network, final VirtualRouter router) throws ResourceUnavailableException {
                 // for basic zone, send vm data/password information only to the router in the same pod
-                Commands cmds = new Commands(Command.OnError.Stop);
-                NicVO nicVo = _nicDao.findById(nic.getId());
-                VMTemplateVO template = _templateDao.findByIdIncludingRemoved(updatedProfile.getTemplateId());
+                final Commands cmds = new Commands(Command.OnError.Stop);
+                final NicVO nicVo = _nicDao.findById(nic.getId());
+                final VMTemplateVO template = _templateDao.findByIdIncludingRemoved(updatedProfile.getTemplateId());
                 if (template != null && template.getEnablePassword()) {
                     createPasswordCommand(router, updatedProfile, nicVo, cmds);
                 }
@@ -555,17 +554,17 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     @Override
-    public boolean saveUserDataToRouter(Network network, final NicProfile nic, VirtualMachineProfile profile, List<? extends VirtualRouter> routers)
+    public boolean saveUserDataToRouter(final Network network, final NicProfile nic, final VirtualMachineProfile profile, final List<? extends VirtualRouter> routers)
         throws ResourceUnavailableException {
         final UserVmVO vm = _userVmDao.findById(profile.getVirtualMachine().getId());
         _userVmDao.loadDetails(vm);
 
         return applyRules(network, routers, "save userdata entry", false, null, false, new RuleApplier() {
             @Override
-            public boolean execute(Network network, VirtualRouter router) throws ResourceUnavailableException {
+            public boolean execute(final Network network, final VirtualRouter router) throws ResourceUnavailableException {
                 // for basic zone, send vm data/password information only to the router in the same pod
-                Commands cmds = new Commands(Command.OnError.Stop);
-                NicVO nicVo = _nicDao.findById(nic.getId());
+                final Commands cmds = new Commands(Command.OnError.Stop);
+                final NicVO nicVo = _nicDao.findById(nic.getId());
                 createVmDataCommand(router, vm, nicVo, null, cmds);
                 return sendCommandsToRouter(router, cmds);
             }
@@ -574,9 +573,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_ROUTER_STOP, eventDescription = "stopping router Vm", async = true)
-    public VirtualRouter stopRouter(long routerId, boolean forced) throws ResourceUnavailableException, ConcurrentOperationException {
-        CallContext context = CallContext.current();
-        Account account = context.getCallingAccount();
+    public VirtualRouter stopRouter(final long routerId, final boolean forced) throws ResourceUnavailableException, ConcurrentOperationException {
+        final CallContext context = CallContext.current();
+        final Account account = context.getCallingAccount();
 
         // verify parameters
         DomainRouterVO router = _routerDao.findById(routerId);
@@ -586,9 +585,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
         _accountMgr.checkAccess(account, null, true, router);
 
-        UserVO user = _userDao.findById(CallContext.current().getCallingUserId());
+        final UserVO user = _userDao.findById(CallContext.current().getCallingUserId());
 
-        VirtualRouter virtualRouter = stop(router, forced, user, account);
+        final VirtualRouter virtualRouter = stop(router, forced, user, account);
         if (virtualRouter == null) {
             throw new CloudRuntimeException("Failed to stop router with id " + routerId);
         }
@@ -604,13 +603,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     @DB
-    public void processStopOrRebootAnswer(final DomainRouterVO router, Answer answer) {
+    public void processStopOrRebootAnswer(final DomainRouterVO router, final Answer answer) {
         Transaction.execute(new TransactionCallbackNoReturn() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public void doInTransactionWithoutResult(final TransactionStatus status) {
                 //FIXME!!! - UserStats command should grab bytesSent/Received for all guest interfaces of the VR
-                List<Long> routerGuestNtwkIds = _routerDao.getRouterNetworks(router.getId());
-                for (Long guestNtwkId : routerGuestNtwkIds) {
+                final List<Long> routerGuestNtwkIds = _routerDao.getRouterNetworks(router.getId());
+                for (final Long guestNtwkId : routerGuestNtwkIds) {
                     final UserStatisticsVO userStats =
                         _userStatsDao.lock(router.getAccountId(), router.getDataCenterId(), guestNtwkId, null, router.getId(), router.getType().toString());
                     if (userStats != null) {
@@ -633,12 +632,12 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_ROUTER_REBOOT, eventDescription = "rebooting router Vm", async = true)
-    public VirtualRouter rebootRouter(long routerId, boolean reprogramNetwork) throws ConcurrentOperationException, ResourceUnavailableException,
+    public VirtualRouter rebootRouter(final long routerId, final boolean reprogramNetwork) throws ConcurrentOperationException, ResourceUnavailableException,
         InsufficientCapacityException {
-        Account caller = CallContext.current().getCallingAccount();
+        final Account caller = CallContext.current().getCallingAccount();
 
         // verify parameters
-        DomainRouterVO router = _routerDao.findById(routerId);
+        final DomainRouterVO router = _routerDao.findById(routerId);
         if (router == null) {
             throw new InvalidParameterValueException("Unable to find domain router with id " + routerId + ".");
         }
@@ -651,7 +650,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             throw new ResourceUnavailableException("Unable to reboot domR, it is not in right state " + router.getState(), DataCenter.class, router.getDataCenterId());
         }
 
-        UserVO user = _userDao.findById(CallContext.current().getCallingUserId());
+        final UserVO user = _userDao.findById(CallContext.current().getCallingUserId());
         s_logger.debug("Stopping and starting router " + router + " as a part of router reboot");
 
         if (stop(router, false, user, caller) != null) {
@@ -682,10 +681,10 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
         _routerExtraPublicNics = NumbersUtil.parseInt(_configDao.getValue(Config.RouterExtraPublicNics.key()), 2);
 
-        String guestOSString = configs.get("network.dhcp.nondefaultnetwork.setgateway.guestos");
+        final String guestOSString = configs.get("network.dhcp.nondefaultnetwork.setgateway.guestos");
         if (guestOSString != null) {
-            String[] guestOSList = guestOSString.split(",");
-            for (String os : guestOSList) {
+            final String[] guestOSList = guestOSString.split(",");
+            for (final String os : guestOSList) {
                 _guestOSNeedGatewayOnNonDefaultNetwork.add(os);
             }
         }
@@ -715,7 +714,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             _instance = "DEFAULT";
         }
 
-        String rpValue = configs.get("network.disable.rpfilter");
+        final String rpValue = configs.get("network.disable.rpfilter");
         if (rpValue != null && rpValue.equalsIgnoreCase("true")) {
             _disableRpFilter = true;
         }
@@ -726,7 +725,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
         _agentMgr.registerForHostEvents(new SshKeysDistriMonitor(_agentMgr, _hostDao, _configDao), true, false, false);
 
-        boolean useLocalStorage = Boolean.parseBoolean(configs.get(Config.SystemVMUseLocalStorage.key()));
+        final boolean useLocalStorage = Boolean.parseBoolean(configs.get(Config.SystemVMUseLocalStorage.key()));
         _offering =
             new ServiceOfferingVO("System Offering For Software Router", 1, _routerRamSize, _routerCpuMHz, null, null, true, null, useLocalStorage, true, null, true,
                 VirtualMachine.Type.DomainRouter, true);
@@ -735,14 +734,14 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
         // this can sometimes happen, if DB is manually or programmatically manipulated
         if (_offering == null) {
-            String msg = "Data integrity problem : System Offering For Software router VM has been removed?";
+            final String msg = "Data integrity problem : System Offering For Software router VM has been removed?";
             s_logger.error(msg);
             throw new ConfigurationException(msg);
         }
 
         _systemAcct = _accountMgr.getSystemAccount();
 
-        String aggregationRange = configs.get("usage.stats.job.aggregation.range");
+        final String aggregationRange = configs.get("usage.stats.job.aggregation.range");
         _usageAggregationRange = NumbersUtil.parseInt(aggregationRange, 1440);
         _usageTimeZone = configs.get("usage.aggregation.timezone");
         if (_usageTimeZone == null) {
@@ -765,11 +764,11 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         }
 
         //Schedule Network stats update task
-        TimeZone usageTimezone = TimeZone.getTimeZone(_usageTimeZone);
-        Calendar cal = Calendar.getInstance(usageTimezone);
+        final TimeZone usageTimezone = TimeZone.getTimeZone(_usageTimeZone);
+        final Calendar cal = Calendar.getInstance(usageTimezone);
         cal.setTime(new Date());
         long endDate = 0;
-        int HOURLY_TIME = 60;
+        final int HOURLY_TIME = 60;
         final int DAILY_TIME = 60 * 24;
         if (_usageAggregationRange == DAILY_TIME) {
             cal.roll(Calendar.DAY_OF_YEAR, false);
@@ -823,15 +822,15 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     protected VirtualNetworkApplianceManagerImpl() {
     }
 
-    private VmDataCommand generateVmDataCommand(VirtualRouter router, String vmPrivateIpAddress, String userData, String serviceOffering, String zoneName,
-        String guestIpAddress, String vmName, String vmInstanceName, long vmId, String vmUuid, String publicKey, long guestNetworkId) {
-        VmDataCommand cmd = new VmDataCommand(vmPrivateIpAddress, vmName, _networkModel.getExecuteInSeqNtwkElmtCmd());
+    private VmDataCommand generateVmDataCommand(final VirtualRouter router, final String vmPrivateIpAddress, final String userData, final String serviceOffering, final String zoneName,
+        final String guestIpAddress, final String vmName, final String vmInstanceName, final long vmId, final String vmUuid, final String publicKey, final long guestNetworkId) {
+        final VmDataCommand cmd = new VmDataCommand(vmPrivateIpAddress, vmName, _networkModel.getExecuteInSeqNtwkElmtCmd());
 
         cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId()));
         cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, getRouterIpInNetwork(guestNetworkId, router.getId()));
         cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName());
 
-        DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId());
+        final DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId());
         cmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString());
 
         cmd.addVmData("userdata", "user-data", userData);
@@ -868,12 +867,12 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         return cmd;
     }
 
-    private void setVmInstanceId(String vmUuid, VmDataCommand cmd) {
+    private void setVmInstanceId(final String vmUuid, final VmDataCommand cmd) {
         cmd.addVmData("metadata", "instance-id", vmUuid);
         cmd.addVmData("metadata", "vm-id", vmUuid);
     }
 
-    private void setVmInstanceId(String vmInstanceName, long vmId, VmDataCommand cmd) {
+    private void setVmInstanceId(final String vmInstanceName, final long vmId, final VmDataCommand cmd) {
         cmd.addVmData("metadata", "instance-id", vmInstanceName);
         cmd.addVmData("metadata", "vm-id", String.valueOf(vmId));
     }
@@ -890,11 +889,11 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                 s_logger.debug("Found " + routers.size() + " running routers. ");
 
                 for (final DomainRouterVO router : routers) {
-                    String privateIP = router.getPrivateIpAddress();
+                    final String privateIP = router.getPrivateIpAddress();
 
                     if (privateIP != null) {
                         final boolean forVpc = router.getVpcId() != null;
-                        List<? extends Nic> routerNics = _nicDao.listByVmId(router.getId());
+                        final List<? extends Nic> routerNics = _nicDao.listByVmId(router.getId());
                         for (final Nic routerNic : routerNics) {
                             final Network network = _networkModel.getNetwork(routerNic.getNetworkId());
                             //Send network usage command for public nic in VPC VR
@@ -909,7 +908,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                                 NetworkUsageAnswer answer = null;
                                 try {
                                     answer = (NetworkUsageAnswer)_agentMgr.easySend(router.getHostId(), usageCmd);
-                                } catch (Exception e) {
+                                } catch (final Exception e) {
                                     s_logger.warn("Error while collecting network stats from router: " + router.getInstanceName() + " from host: " + router.getHostId(),
                                         e);
                                     continue;
@@ -929,8 +928,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                                         final NetworkUsageAnswer answerFinal = answer;
                                         Transaction.execute(new TransactionCallbackNoReturn() {
                                             @Override
-                                            public void doInTransactionWithoutResult(TransactionStatus status) {
-                                                UserStatisticsVO stats =
+                                            public void doInTransactionWithoutResult(final TransactionStatus status) {
+                                                final UserStatisticsVO stats =
                                                     _userStatsDao.lock(router.getAccountId(), router.getDataCenterId(), network.getId(),
                                                         (forVpc ? routerNic.getIp4Address() : null), router.getId(), routerType);
                                                 if (stats == null) {
@@ -973,7 +972,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                                             }
                                         });
 
-                                    } catch (Exception e) {
+                                    } catch (final Exception e) {
                                         s_logger.warn("Unable to update user statistics for account: " + router.getAccountId() + " Rx: " + answer.getBytesReceived() +
                                             "; Tx: " + answer.getBytesSent());
                                     }
@@ -982,7 +981,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                         }
                     }
                 }
-            } catch (Exception e) {
+            } catch (final Exception e) {
                 s_logger.warn("Error while collecting network stats", e);
             }
         }
@@ -995,12 +994,12 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
         @Override
         protected void runInContext() {
-            GlobalLock scanLock = GlobalLock.getInternLock("network.stats");
+            final GlobalLock scanLock = GlobalLock.getInternLock("network.stats");
             try {
                 if (scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) {
                     //Check for ownership
                     //msHost in UP state with min id should run the job
-                    ManagementServerHostVO msHost = _msHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
+                    final ManagementServerHostVO msHost = _msHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
                     if (msHost == null || (msHost.getMsid() != mgmtSrvrId)) {
                         s_logger.debug("Skipping aggregate network stats update");
                         scanLock.unlock();
@@ -1009,17 +1008,17 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                     try {
                         Transaction.execute(new TransactionCallbackNoReturn() {
                             @Override
-                            public void doInTransactionWithoutResult(TransactionStatus status) {
+                            public void doInTransactionWithoutResult(final TransactionStatus status) {
                                 //get all stats with delta > 0
-                                List<UserStatisticsVO> updatedStats = _userStatsDao.listUpdatedStats();
-                                Date updatedTime = new Date();
-                                for (UserStatisticsVO stat : updatedStats) {
+                                final List<UserStatisticsVO> updatedStats = _userStatsDao.listUpdatedStats();
+                                final Date updatedTime = new Date();
+                                for (final UserStatisticsVO stat : updatedStats) {
                                     //update agg bytes
                                     stat.setAggBytesReceived(stat.getCurrentBytesReceived() + stat.getNetBytesReceived());
                                     stat.setAggBytesSent(stat.getCurrentBytesSent() + stat.getNetBytesSent());
                                     _userStatsDao.update(stat.getId(), stat);
                                     //insert into op_user_stats_log
-                                    UserStatsLogVO statsLog =
+                                    final UserStatsLogVO statsLog =
                                         new UserStatsLogVO(stat.getId(), stat.getNetBytesReceived(), stat.getNetBytesSent(), stat.getCurrentBytesReceived(),
                                             stat.getCurrentBytesSent(), stat.getAggBytesReceived(), stat.getAggBytesSent(), updatedTime);
                                     _userStatsLogDao.persist(statsLog);
@@ -1027,13 +1026,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                                 s_logger.debug("Successfully updated aggregate network stats");
                             }
                         });
-                    } catch (Exception e) {
+                    } catch (final Exception e) {
                         s_logger.debug("Failed to update aggregate network stats", e);
                     } finally {
                         scanLock.unlock();
                     }
                 }
-            } catch (Exception e) {
+            } catch (final Exception e) {
                 s_logger.debug("Exception while trying to acquire network stats lock", e);
             } finally {
                 scanLock.releaseRef();
@@ -1042,14 +1041,14 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     @DB
-    protected void updateSite2SiteVpnConnectionState(List<DomainRouterVO> routers) {
-        for (DomainRouterVO router : routers) {
-            List<Site2SiteVpnConnectionVO> conns = _s2sVpnMgr.getConnectionsForRouter(router);
+    protected void updateSite2SiteVpnConnectionState(final List<DomainRouterVO> routers) {
+        for (final DomainRouterVO router : routers) {
+            final List<Site2SiteVpnConnectionVO> conns = _s2sVpnMgr.getConnectionsForRouter(router);
             if (conns == null || conns.isEmpty()) {
                 continue;
             }
             if (router.getState() != State.Running) {
-                for (Site2SiteVpnConnectionVO conn : conns) {
+                for (final Site2SiteVpnConnectionVO conn : conns) {
                     if (conn.getState() != Site2SiteVpnConnection.State.Error) {
                         conn.setState(Site2SiteVpnConnection.State.Disconnected);
                         _s2sVpnConnectionDao.persist(conn);
@@ -1057,16 +1056,16 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                 }
                 continue;
             }
-            List<String> ipList = new ArrayList<String>();
-            for (Site2SiteVpnConnectionVO conn : conns) {
+            final List<String> ipList = new ArrayList<String>();
+            for (final Site2SiteVpnConnectionVO conn : conns) {
                 if (conn.getState() != Site2SiteVpnConnection.State.Connected && conn.getState() != Site2SiteVpnConnection.State.Disconnected) {
                     continue;
                 }
-                Site2SiteCustomerGateway gw = _s2sCustomerGatewayDao.findById(conn.getCustomerGatewayId());
+                final Site2SiteCustomerGateway gw = _s2sCustomerGatewayDao.findById(conn.getCustomerGatewayId());
                 ipList.add(gw.getGatewayIp());
             }
-            String privateIP = router.getPrivateIpAddress();
-            HostVO host = _hostDao.findById(router.getHostId());
+            final String privateIP = router.getPrivateIpAddress();
+            final HostVO host = _hostDao.findById(router.getHostId());
             if (host == null || host.getState() != Status.Up) {
                 continue;
             } else if (host.getManagementServerId() != ManagementServerNode.getManagementServerId()) {
@@ -1089,8 +1088,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                     s_logger.warn("Unable to update router " + router.getHostName() + "'s VPN connection status");
                     continue;
                 }
-                for (Site2SiteVpnConnectionVO conn : conns) {
-                    Site2SiteVpnConnectionVO lock = _s2sVpnConnectionDao.acquireInLockTable(conn.getId());
+                for (final Site2SiteVpnConnectionVO conn : conns) {
+                    final Site2SiteVpnConnectionVO lock = _s2sVpnConnectionDao.acquireInLockTable(conn.getId());
                     if (lock == null) {
                         throw new CloudRuntimeException("Unable to acquire lock on " + lock);
                     }
@@ -1098,8 +1097,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                         if (conn.getState() != Site2SiteVpnConnection.State.Connected && conn.getState() != Site2SiteVpnConnection.State.Disconnected) {
                             continue;
                         }
-                        Site2SiteVpnConnection.State oldState = conn.getState();
-                        Site2SiteCustomerGateway gw = _s2sCustomerGatewayDao.findById(conn.getCustomerGatewayId());
+                        final Site2SiteVpnConnection.State oldState = conn.getState();
+                        final Site2SiteCustomerGateway gw = _s2sCustomerGatewayDao.findById(conn.getCustomerGatewayId());
                         if (answer.isConnected(gw.getGatewayIp())) {
                             conn.setState(Site2SiteVpnConnection.State.Connected);
                         } else {
@@ -1107,8 +1106,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                         }
                         _s2sVpnConnectionDao.persist(conn);
                         if (oldState != conn.getState()) {
-                            String title = "Site-to-site Vpn Connection to " + gw.getName() + " just switch from " + oldState + " to " + conn.getState();
-                            String context =
+                            final String title = "Site-to-site Vpn Connection to " + gw.getName() + " just switch from " + oldState + " to " + conn.getState();
+                            final String context =
                                 "Site-to-site Vpn Connection to " + gw.getName() + " on router " + router.getHostName() + "(id: " + router.getId() + ") " +
                                     " just switch from " + oldState + " to " + conn.getState();
                             s_logger.info(context);
@@ -1122,21 +1121,21 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         }
     }
 
-    protected void updateRoutersRedundantState(List<DomainRouterVO> routers) {
+    protected void updateRoutersRedundantState(final List<DomainRouterVO> routers) {
         boolean updated = false;
-        for (DomainRouterVO router : routers) {
+        for (final DomainRouterVO router : routers) {
             updated = false;
             if (!router.getIsRedundantRouter()) {
                 continue;
             }
-            RedundantState prevState = router.getRedundantState();
+            final RedundantState prevState = router.getRedundantState();
             if (router.getState() != State.Running) {
                 router.setRedundantState(RedundantState.UNKNOWN);
                 router.setIsPriorityBumpUp(false);
                 updated = true;
             } else {
-                String privateIP = router.getPrivateIpAddress();
-                HostVO host = _hostDao.findById(router.getHostId());
+                final String privateIP = router.getPrivateIpAddress();
+                final HostVO host = _hostDao.findById(router.getHostId());
                 if (host == null || host.getState() != Status.Up) {
                     router.setRedundantState(RedundantState.UNKNOWN);
                     updated = true;
@@ -1166,10 +1165,10 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             if (updated) {
                 _routerDao.update(router.getId(), router);
             }
-            RedundantState currState = router.getRedundantState();
+            final RedundantState currState = router.getRedundantState();
             if (prevState != currState) {
-                String title = "Redundant virtual router " + router.getInstanceName() + " just switch from " + prevState + " to " + currState;
-                String context =
+                final String title = "Redundant virtual router " + router.getInstanceName() + " just switch from " + prevState + " to " + currState;
+                final String context =
                     "Redundant virtual router (name: " + router.getHostName() + ", id: " + router.getId() + ") " + " just switch from " + prevState + " to " + currState;
                 s_logger.info(context);
                 if (currState == RedundantState.MASTER) {
@@ -1180,30 +1179,30 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     //Ensure router status is update to date before execute this function. The function would try best to recover all routers except MASTER
-    protected void recoverRedundantNetwork(DomainRouterVO masterRouter, DomainRouterVO backupRouter) {
+    protected void recoverRedundantNetwork(final DomainRouterVO masterRouter, final DomainRouterVO backupRouter) {
         if (masterRouter.getState() == State.Running && backupRouter.getState() == State.Running) {
-            HostVO masterHost = _hostDao.findById(masterRouter.getHostId());
-            HostVO backupHost = _hostDao.findById(backupRouter.getHostId());
+            final HostVO masterHost = _hostDao.findById(masterRouter.getHostId());
+            final HostVO backupHost = _hostDao.findById(backupRouter.getHostId());
             if (masterHost.getState() == Status.Up && backupHost.getState() == Status.Up) {
-                String title = "Reboot " + backupRouter.getInstanceName() + " to ensure redundant virtual routers work";
+                final String title = "Reboot " + backupRouter.getInstanceName() + " to ensure redundant virtual routers work";
                 if (s_logger.isDebugEnabled()) {
                     s_logger.debug(title);
                 }
                 _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER, backupRouter.getDataCenterId(), backupRouter.getPodIdToDeployIn(), title, title);
                 try {
                     rebootRouter(backupRouter.getId(), true);
-                } catch (ConcurrentOperationException e) {
+                } catch (final ConcurrentOperationException e) {
                     s_logger.warn("Fail to reboot " + backupRouter.getInstanceName(), e);
-                } catch (ResourceUnavailableException e) {
+                } catch (final ResourceUnavailableException e) {
                     s_logger.warn("Fail to reboot " + backupRouter.getInstanceName(), e);
-                } catch (InsufficientCapacityException e) {
+                } catch (final InsufficientCapacityException e) {
                     s_logger.warn("Fail to reboot " + backupRouter.getInstanceName(), e);
                 }
             }
         }
     }
 
-    private int getRealPriority(DomainRouterVO router) {
+    private int getRealPriority(final DomainRouterVO router) {
         int priority = router.getPriority();
         if (router.getIsPriorityBumpUp()) {
             priority += DEFAULT_DELTA;
@@ -1221,27 +1220,27 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
          * 1. Backup router's priority = Master's priority - DELTA + 1
          * 2. Backup router's priority hasn't been bumped up.
          */
-        private void checkSanity(List<DomainRouterVO> routers) {
-            Set<Long> checkedNetwork = new HashSet<Long>();
-            for (DomainRouterVO router : routers) {
+        private void checkSanity(final List<DomainRouterVO> routers) {
+            final Set<Long> checkedNetwork = new HashSet<Long>();
+            for (final DomainRouterVO router : routers) {
                 if (!router.getIsRedundantRouter()) {
                     continue;
                 }
 
-                List<Long> routerGuestNtwkIds = _routerDao.getRouterNetworks(router.getId());
+                final List<Long> routerGuestNtwkIds = _routerDao.getRouterNetworks(router.getId());
 
-                for (Long routerGuestNtwkId : routerGuestNtwkIds) {
+                for (final Long routerGuestNtwkId : routerGuestNtwkIds) {
                     if (checkedNetwork.contains(routerGuestNtwkId)) {
                         continue;
                     }
                     checkedNetwork.add(routerGuestNtwkId);
-                    List<DomainRouterVO> checkingRouters = _routerDao.listByNetworkAndRole(routerGuestNtwkId, Role.VIRTUAL_ROUTER);
+                    final List<DomainRouterVO> checkingRouters = _routerDao.listByNetworkAndRole(routerGuestNtwkId, Role.VIRTUAL_ROUTER);
                     if (checkingRouters.size() != 2) {
                         continue;
                     }
                     DomainRouterVO masterRouter = null;
                     DomainRouterVO backupRouter = null;
-                    for (DomainRouterVO r : checkingRouters) {
+                    for (final DomainRouterVO r : checkingRouters) {
                         if (r.getRedundantState() == RedundantState.MASTER) {
                             if (masterRouter == null) {
                                 masterRouter = r;
@@ -1266,18 +1265,18 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             }
         }
 
-        private void checkDuplicateMaster(List<DomainRouterVO> routers) {
-            Map<Long, DomainRouterVO> networkRouterMaps = new HashMap<Long, DomainRouterVO>();
-            for (DomainRouterVO router : routers) {
-                List<Long> routerGuestNtwkIds = _routerDao.getRouterNetworks(router.getId());
+        private void checkDuplicateMaster(final List<DomainRouterVO> routers) {
+            final Map<Long, DomainRouterVO> networkRouterMaps = new HashMap<Long, DomainRouterVO>();
+            for (final DomainRouterVO router : routers) {
+                final List<Long> routerGuestNtwkIds = _routerDao.getRouterNetworks(router.getId());
 
-                for (Long routerGuestNtwkId : routerGuestNtwkIds) {
+                for (final Long routerGuestNtwkId : routerGuestNtwkIds) {
                     if (router.getRedundantState() == RedundantState.MASTER) {
                         if (networkRouterMaps.containsKey(routerGuestNtwkId)) {
-                            DomainRouterVO dupRouter = networkRouterMaps.get(routerGuestNtwkId);
-                            String title =
+                            final DomainRouterVO dupRouter = networkRouterMaps.get(routerGuestNtwkId);
+                            final String title =
                                 "More than one redundant virtual router is in MASTER state! Router " + router.getHostName() + " and router " + dupRouter.getHostName();
-                            String context =
+                            final String context =
                                 "Virtual router (name: " + router.getHostName() + ", id: " + router.getId() + " and router (name: " + dupRouter.getHostName() + ", id: " +
                                     router.getId() + ") are both in MASTER state! If the problem persist, restart both of routers. ";
                             _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER, router.getDataCenterId(), router.getPodIdToDeployIn(), title, context);
@@ -1296,8 +1295,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         protected void runInContext() {
             while (true) {
                 try {
-                    Long networkId = _vrUpdateQueue.take();  // This is a blocking call so this thread won't run all the time if no work item in queue.
-                    List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(networkId, Role.VIRTUAL_ROUTER);
+                    final Long networkId = _vrUpdateQueue.take();  // This is a blocking call so this thread won't run all the time if no work item in queue.
+                    final List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(networkId, Role.VIRTUAL_ROUTER);
 
                     if (routers.size() != 2) {
                         continue;
@@ -1306,8 +1305,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                      * We update the router pair which the lower id router owned by this mgmt server, in order
                      * to prevent duplicate update of router status from cluster mgmt servers
                      */
-                    DomainRouterVO router0 = routers.get(0);
-                    DomainRouterVO router1 = routers.get(1);
+                    final DomainRouterVO router0 = routers.get(0);
+                    final DomainRouterVO router1 = routers.get(1);
                     DomainRouterVO router = router0;
                     if ((router0.getId() < router1.getId()) && router0.getHostId() != null) {
                         router = router0;
@@ -1318,7 +1317,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                         s_logger.debug("Skip router pair (" + router0.getInstanceName() + "," + router1.getInstanceName() + ") due to can't find host");
                         continue;
                     }
-                    HostVO host = _hostDao.findById(router.getHostId());
+                    final HostVO host = _hostDao.findById(router.getHostId());
                     if (host == null || host.getManagementServerId() == null || host.getManagementServerId() != ManagementServerNode.getManagementServerId()) {
                         s_logger.debug("Skip router pair (" + router0.getInstanceName() + "," + router1.getInstanceName() + ") due to not belong to this mgmt server");
                         continue;
@@ -1326,7 +1325,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                     updateRoutersRedundantState(routers);
                     checkDuplicateMaster(routers);
                     checkSanity(routers);
-                } catch (Exception ex) {
+                } catch (final Exception ex) {
                     s_logger.error("Fail to complete the RvRStatusUpdateTask! ", ex);
                 }
             }
@@ -1348,13 +1347,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
                 final List<NetworkVO> networks = _networkDao.listRedundantNetworks();
                 s_logger.debug("Found " + networks.size() + " networks to update RvR status. ");
-                for (NetworkVO network : networks) {
+                for (final NetworkVO network : networks) {
                     if (!_vrUpdateQueue.offer(network.getId(), 500, TimeUnit.MILLISECONDS)) {
                         s_logger.warn("Cannot insert into virtual router update queue! Adjustment of router.check.interval and router.check.poolsize maybe needed.");
                         break;
                     }
                 }
-            } catch (Exception ex) {
+            } catch (final Exception ex) {
                 s_logger.error("Fail to complete the CheckRouterTask! ", ex);
             }
         }
@@ -1363,13 +1362,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     private final static int DEFAULT_PRIORITY = 100;
     private final static int DEFAULT_DELTA = 2;
 
-    protected int getUpdatedPriority(Network guestNetwork, List<DomainRouterVO> routers, DomainRouterVO exclude) throws InsufficientVirtualNetworkCapcityException {
+    protected int getUpdatedPriority(final Network guestNetwork, final List<DomainRouterVO> routers, final DomainRouterVO exclude) throws InsufficientVirtualNetworkCapcityException {
         int priority;
         if (routers.size() == 0) {
             priority = DEFAULT_PRIORITY;
         } else {
             int maxPriority = 0;
-            for (DomainRouterVO r : routers) {
+            for (final DomainRouterVO r : routers) {
                 if (!r.getIsRedundantRouter()) {
                     throw new CloudRuntimeException("Redundant router is mixed with single router in one network!");
                 }
@@ -1397,19 +1396,19 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     /*
      * Ovm won't support any system. So we have to choose a partner cluster in the same pod to start domain router for us
      */
-    private HypervisorType getClusterToStartDomainRouterForOvm(long podId) {
-        List<ClusterVO> clusters = _clusterDao.listByPodId(podId);
-        for (ClusterVO cv : clusters) {
+    private HypervisorType getClusterToStartDomainRouterForOvm(final long podId) {
+        final List<ClusterVO> clusters = _clusterDao.listByPodId(podId);
+        for (final ClusterVO cv : clusters) {
             if (cv.getHypervisorType() == HypervisorType.Ovm || cv.getHypervisorType() == HypervisorType.BareMetal) {
                 continue;
             }
 
-            List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(cv.getId());
+            final List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(cv.getId());
             if (hosts == null || hosts.isEmpty()) {
                 continue;
             }
 
-            for (HostVO h : hosts) {
+            for (final HostVO h : hosts) {
                 if (h.getState() == Status.Up) {
                     s_logger.debug("Pick up host that has hypervisor type " + h.getHypervisorType() + " in cluster " + cv.getId() + " to start domain router for OVM");
                     return h.getHypervisorType();
@@ -1417,16 +1416,16 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             }
         }
 
-        String errMsg =
+        final String errMsg =
             "Cannot find an available cluster in Pod " + podId + " to start domain router for Ovm. \n Ovm won't support any system vm including domain router, " +
                 "please make sure you have a cluster with hypervisor type of any of xenserver/KVM/Vmware in the same pod" +
                 " with Ovm cluster. And there is at least one host in UP status in that cluster.";
         throw new CloudRuntimeException(errMsg);
     }
 
-    private void checkAndResetPriorityOfRedundantRouter(List<DomainRouterVO> routers) {
+    private void checkAndResetPriorityOfRedundantRouter(final List<DomainRouterVO> routers) {
         boolean allStopped = true;
-        for (DomainRouterVO router : routers) {
+        for (final DomainRouterVO router : routers) {
             if (!router.getIsRedundantRouter() || router.getState() != VirtualMachine.State.Stopped) {
                 allStopped = false;
                 break;
@@ -1436,7 +1435,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             return;
         }
 
-        for (DomainRouterVO router : routers) {
+        for (final DomainRouterVO router : routers) {
             // getUpdatedPriority() would update the value later
             router.setPriority(0);
             router.setIsPriorityBumpUp(false);
@@ -1445,11 +1444,11 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     @DB
-    protected List<DomainRouterVO> findOrDeployVirtualRouterInGuestNetwork(Network guestNetwork, DeployDestination dest, Account owner, boolean isRedundant,
-        Map<Param, Object> params) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
+    protected List<DomainRouterVO> findOrDeployVirtualRouterInGuestNetwork(final Network guestNetwork, final DeployDestination dest, Account owner, final boolean isRedundant,
+        final Map<Param, Object> params) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
 
         List<DomainRouterVO> routers = new ArrayList<DomainRouterVO>();
-        Network lock = _networkDao.acquireInLockTable(guestNetwork.getId(), NetworkOrchestrationService.NetworkLockTimeout.value());
+        final Network lock = _networkDao.acquireInLockTable(guestNetwork.getId(), NetworkOrchestrationService.NetworkLockTimeout.value());
         if (lock == null) {
             throw new ConcurrentOperationException("Unable to lock network " + guestNetwork.getId());
         }
@@ -1465,22 +1464,22 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             assert guestNetwork.getTrafficType() == TrafficType.Guest;
 
             // 1) Get deployment plan and find out the list of routers
-            boolean isPodBased = (dest.getDataCenter().getNetworkType() == NetworkType.Basic);
+            final boolean isPodBased = (dest.getDataCenter().getNetworkType() == NetworkType.Basic);
 
             // dest has pod=null, for Basic Zone findOrDeployVRs for all Pods
-            List<DeployDestination> destinations = new ArrayList<DeployDestination>();
+            final List<DeployDestination> destinations = new ArrayList<DeployDestination>();
 
             // for basic zone, if 'dest' has pod set to null then this is network restart scenario otherwise it is a vm deployment scenario
             if (dest.getDataCenter().getNetworkType() == NetworkType.Basic && dest.getPod() == null) {
                 // Find all pods in the data center with running or starting user vms
-                long dcId = dest.getDataCenter().getId();
-                List<HostPodVO> pods = listByDataCenterIdVMTypeAndStates(dcId, VirtualMachine.Type.User, VirtualMachine.State.Starting, VirtualMachine.State.Running);
+                final long dcId = dest.getDataCenter().getId();
+                final List<HostPodVO> pods = listByDataCenterIdVMTypeAndStates(dcId, VirtualMachine.Type.User, VirtualMachine.State.Starting, VirtualMachine.State.Running);
 
                 // Loop through all the pods skip those with running or starting VRs
-                for (HostPodVO pod : pods) {
+                for (final HostPodVO pod : pods) {
                     // Get list of VRs in starting or running state
-                    long podId = pod.getId();
-                    List<DomainRouterVO> virtualRouters = _routerDao.listByPodIdAndStates(podId, VirtualMachine.State.Starting, VirtualMachine.State.Running);
+                    final long podId = pod.getId();
+                    final List<DomainRouterVO> virtualRouters = _routerDao.listByPodIdAndStates(podId, VirtualMachine.State.Starting, VirtualMachine.State.Running);
 
                     assert (virtualRouters.size() <= 1) : "Pod can have utmost one VR in Basic Zone, please check!";
 
@@ -1502,8 +1501,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             }
 
             // Except for Basic Zone, the for loop will iterate only once
-            for (DeployDestination destination : destinations) {
-                Pair<DeploymentPlan, List<DomainRouterVO>> planAndRouters = getDeploymentPlanAndRouters(isPodBased, destination, guestNetwork.getId());
+            for (final DeployDestination destination : destinations) {
+                final Pair<DeploymentPlan, List<DomainRouterVO>> planAndRouters = getDeploymentPlanAndRouters(isPodBased, destination, guestNetwork.getId());
                 routers = planAndRouters.second();
 
                 // 2) Figure out required routers count
@@ -1526,13 +1525,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                 }
 
                 // Check if providers are supported in the physical networks
-                Type type = Type.VirtualRouter;
-                Long physicalNetworkId = _networkModel.getPhysicalNetworkId(guestNetwork);
-                PhysicalNetworkServiceProvider provider = _physicalProviderDao.findByServiceProvider(physicalNetworkId, type.toString());
+                final Type type = Type.VirtualRouter;
+                final Long physicalNetworkId = _networkModel.getPhysicalNetworkId(guestNetwork);
+                final PhysicalNetworkServiceProvider provider = _physicalProviderDao.findByServiceProvider(physicalNetworkId, type.toString());
                 if (provider == null) {
                     throw new CloudRuntimeException("Cannot find service provider " + type.toString() + " in physical network " + physicalNetworkId);
                 }
-                VirtualRouterProvider vrProvider = _vrProviderDao.findByNspIdAndType(provider.getId(), type);
+                final VirtualRouterProvider vrProvider = _vrProviderDao.findByNspIdAndType(provider.getId(), type);
                 if (vrProvider == null) {
                     throw new CloudRuntimeException("Cannot find virtual router provider " + type.toString() + " as service provider " + provider.getId());
                 }
@@ -1562,13 +1561,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                 }
 
                 // 3) deploy virtual router(s)
-                int count = routerCount - routers.size();
-                DeploymentPlan plan = planAndRouters.first();
+                final int count = routerCount - routers.size();
+                final DeploymentPlan plan = planAndRouters.first();
                 for (int i = 0; i < count; i++) {
-                    LinkedHashMap<Network, NicProfile> networks =
+                    final LinkedHashMap<Network, NicProfile> networks =
                         createRouterNetworks(owner, isRedundant, plan, guestNetwork, new Pair<Boolean, PublicIp>(publicNetwork, sourceNatIp));
                     //don't start the router as we are holding the network lock that needs to be released at the end of router allocation
-                    DomainRouterVO router = deployRouter(owner, destination, plan, params, isRedundant, vrProvider, offeringId, null, networks, false, null);
+                    final DomainRouterVO router = deployRouter(owner, destination, plan, params, isRedundant, vrProvider, offeringId, null, networks, false, null);
 
                     if (router != null) {
                         _routerDao.addRouterToGuestNetwork(router, guestNetwork);
@@ -1587,42 +1586,42 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         return routers;
     }
 
-    protected List<HostPodVO> listByDataCenterIdVMTypeAndStates(long id, VirtualMachine.Type type, VirtualMachine.State... states) {
-        SearchBuilder<VMInstanceVO> vmInstanceSearch = _vmDao.createSearchBuilder();
+    protected List<HostPodVO> listByDataCenterIdVMTypeAndStates(final long id, final VirtualMachine.Type type, final VirtualMachine.State... states) {
+        final SearchBuilder<VMInstanceVO> vmInstanceSearch = _vmDao.createSearchBuilder();
         vmInstanceSearch.and("type", vmInstanceSearch.entity().getType(), SearchCriteria.Op.EQ);
         vmInstanceSearch.and("states", vmInstanceSearch.entity().getState(), SearchCriteria.Op.IN);
 
-        SearchBuilder<HostPodVO> podIdSearch = _podDao.createSearchBuilder();
+        final SearchBuilder<HostPodVO> podIdSearch = _podDao.createSearchBuilder();
         podIdSearch.and("dc", podIdSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
         podIdSearch.select(null, SearchCriteria.Func.DISTINCT, podIdSearch.entity().getId());
         podIdSearch.join("vmInstanceSearch", vmInstanceSearch, podIdSearch.entity().getId(), vmInstanceSearch.entity().getPodIdToDeployIn(), JoinBuilder.JoinType.INNER);
         podIdSearch.done();
 
-        SearchCriteria<HostPodVO> sc = podIdSearch.create();
+        final SearchCriteria<HostPodVO> sc = podIdSearch.create();
         sc.setParameters("dc", id);
         sc.setJoinParameters("vmInstanceSearch", "type", type);
         sc.setJoinParameters("vmInstanceSearch", "states", (Object[])states);
         return _podDao.search(sc, null);
     }
 
-    protected DomainRouterVO deployRouter(Account owner, DeployDestination dest, DeploymentPlan plan, Map<Param, Object> params, boolean isRedundant,
-        VirtualRouterProvider vrProvider, long svcOffId, Long vpcId, LinkedHashMap<Network, NicProfile> networks, boolean startRouter,
-        List<HypervisorType> supportedHypervisors) throws ConcurrentOperationException, InsufficientAddressCapacityException, InsufficientServerCapacityException,
+    protected DomainRouterVO deployRouter(final Account owner, final DeployDestination dest, final DeploymentPlan plan, final Map<Param, Object> params, final boolean isRedundant,
+        final VirtualRouterProvider vrProvider, final long svcOffId, final Long vpcId, final LinkedHashMap<Network, NicProfile> networks, final boolean startRouter,
+        final List<HypervisorType> supportedHypervisors) throws ConcurrentOperationException, InsufficientAddressCapacityException, InsufficientServerCapacityException,
         InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException {
 
-        ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(svcOffId);
+        final ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(svcOffId);
 
         // Router is the network element, we don't know the hypervisor type yet.
         // Try to allocate the domR twice using diff hypervisors, and when failed both times, throw the exception up
-        List<HypervisorType> hypervisors = getHypervisors(dest, plan, supportedHypervisors);
+        final List<HypervisorType> hypervisors = getHypervisors(dest, plan, supportedHypervisors);
 
         int allocateRetry = 0;
         int startRetry = 0;
         DomainRouterVO router = null;
-        for (Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext();) {
-            HypervisorType hType = iter.next();
+        for (final Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext();) {
+            final HypervisorType hType = iter.next();
             try {
-                long id = _routerDao.getNextInSequence(Long.class, "id");
+                final long id = _routerDao.getNextInSequence(Long.class, "id");
                 if (s_logger.isDebugEnabled()) {
                     s_logger.debug("Allocating the VR i=" + id + " in datacenter " + dest.getDataCenter() + "with the hypervisor type " + hType);
                 }
@@ -1647,7 +1646,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                     default:
                         break;
                 }
-                VMTemplateVO template = _templateDao.findRoutingTemplate(hType, templateName);
+                final VMTemplateVO template = _templateDao.findRoutingTemplate(hType, templateName);
 
                 if (template == null) {
                     s_logger.debug(hType + " won't support system vm, skip it");
@@ -1669,7 +1668,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                 router = _routerDao.persist(router);
                 _itMgr.allocate(router.getInstanceName(), template, routerOffering, networks, plan, null);
                 router = _routerDao.findById(router.getId());
-            } catch (InsufficientCapacityException ex) {
+            } catch (final InsufficientCapacityException ex) {
                 if (allocateRetry < 2 && iter.hasNext()) {
                     s_logger.debug("Failed to allocate the VR with hypervisor type " + hType + ", retrying one more time");
                     continue;
@@ -1684,7 +1683,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                 try {
                     router = startVirtualRouter(router, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), params);
                     break;
-                } catch (InsufficientCapacityException ex) {
+                } catch (final InsufficientCapacityException ex) {
                     if (startRetry < 2 && iter.hasNext()) {
                         s_logger.debug("Failed to start the VR  " + router + " with hypervisor type " + hType + ", " + "destroying it and recreating one more time");
                         // destroy the router
@@ -1705,7 +1704,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         return router;
     }
 
-    protected List<HypervisorType> getHypervisors(DeployDestination dest, DeploymentPlan plan, List<HypervisorType> supportedHypervisors)
+    protected List<HypervisorType> getHypervisors(final DeployDestination dest, final DeploymentPlan plan, final List<HypervisorType> supportedHypervisors)
         throws InsufficientServerCapacityException {
         List<HypervisorType> hypervisors = new ArrayList<HypervisorType>();
 
@@ -1716,7 +1715,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                 hypervisors.add(dest.getCluster().getHypervisorType());
             }
         } else {
-            HypervisorType defaults = _resourceMgr.getDefaultHypervisor(dest.getDataCenter().getId());
+            final HypervisorType defaults = _resourceMgr.getDefaultHypervisor(dest.getDataCenter().getId());
             if (defaults != HypervisorType.None) {
                 hypervisors.add(defaults);
             } else {
@@ -1726,16 +1725,16 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         }
 
         //keep only elements defined in supported hypervisors
-        StringBuilder hTypesStr = new StringBuilder();
+        final StringBuilder hTypesStr = new StringBuilder();
         if (supportedHypervisors != null && !supportedHypervisors.isEmpty()) {
             hypervisors.retainAll(supportedHypervisors);
-            for (HypervisorType hType : supportedHypervisors) {
+            for (final HypervisorType hType : supportedHypervisors) {
                 hTypesStr.append(hType).append(" ");
             }
         }
 
         if (hypervisors.isEmpty()) {
-            String errMsg = (hTypesStr.capacity() > 0) ? "supporting hypervisors " + hTypesStr.toString() : "";
+            final String errMsg = (hTypesStr.capacity() > 0) ? "supporting hypervisors " + hTypesStr.toString() : "";
             if (plan.getPodId() != null) {
                 throw new InsufficientServerCapacityException("Unable to create virtual router, " + "there are no clusters in the pod " + errMsg, Pod.class,
                     plan.getPodId());
@@ -1746,8 +1745,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         return hypervisors;
     }
 
-    protected LinkedHashMap<Network, NicProfile> createRouterNetworks(Account owner, boolean isRedundant, DeploymentPlan plan, Network guestNetwork,
-        Pair<Boolean, PublicIp> publicNetwork) throws ConcurrentOperationException, InsufficientAddressCapacityException {
+    protected LinkedHashMap<Network, NicProfile> createRouterNetworks(final Account owner, final boolean isRedundant, final DeploymentPlan plan, final Network guestNetwork,
+        final Pair<Boolean, PublicIp> publicNetwork) throws ConcurrentOperationException, InsufficientAddressCapacityException {
 
         boolean setupPublicNetwork = false;
         if (publicNetwork != null) {
@@ -1755,7 +1754,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         }
 
         //Form networks
-        LinkedHashMap<Network, NicProfile> networks = new LinkedHashMap<Network, NicProfile>(3);
+        final LinkedHashMap<Network, NicProfile> networks = new LinkedHashMap<Network, NicProfile>(3);
 
         //1) Guest network
         boolean hasGuestNetwork = false;
@@ -1763,13 +1762,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             s_logger.debug("Adding nic for Virtual Router in Guest network " + guestNetwork);
             String defaultNetworkStartIp = null, defaultNetworkStartIpv6 = null;
             if (!setupPublicNetwork) {
-                Nic placeholder = _networkModel.getPlaceholderNicForRouter(guestNetwork, plan.getPodId());
+                final Nic placeholder = _networkModel.getPlaceholderNicForRouter(guestNetwork, plan.getPodId());
                 if (guestNetwork.getCidr() != null) {
                     if (placeholder != null && placeholder.getIp4Address() != null) {
                         s_logger.debug("Requesting ipv4 address " + placeholder.getIp4Address() + " stored in placeholder nic for the network " + guestNetwork);
                         defaultNetworkStartIp = placeholder.getIp4Address();
                     } else {
-                        String startIp = _networkModel.getStartIpAddress(guestNetwork.getId());
+                        final String startIp = _networkModel.getStartIpAddress(guestNetwork.getId());
                         if (startIp != null && _ipAddressDao.findByIpAndSourceNetworkId(guestNetwork.getId(), startIp).getAllocatedTime() == null) {
                             defaultNetworkStartIp = startIp;
                         } else if (s_logger.isDebugEnabled()) {
@@ -1784,7 +1783,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                         s_logger.debug("Requesting ipv6 address " + placeholder.getIp6Address() + " stored in placeholder nic for the network " + guestNetwork);
                         defaultNetworkStartIpv6 = placeholder.getIp6Address();
                     } else {
-                        String startIpv6 = _networkModel.getStartIpv6Address(guestNetwork.getId());
+                        final String startIpv6 = _networkModel.getStartIpv6Address(guestNetwork.getId());
                         if (startIpv6 != null && _ipv6Dao.findByNetworkIdAndIp(guestNetwork.getId(), startIpv6) == null) {
                             defaultNetworkStartIpv6 = startIpv6;
                         } else if (s_logger.isDebugEnabled()) {
@@ -1795,7 +1794,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                 }
             }
 
-            NicProfile gatewayNic = new NicProfile(defaultNetworkStartIp, defaultNetworkStartIpv6);
+            final NicProfile gatewayNic = new NicProfile(defaultNetworkStartIp, defaultNetworkStartIpv6);
             if (setupPublicNetwork) {
                 if (isRedundant) {
                     gatewayNic.setIp4Address(_ipAddrMgr.acquireGuestIpAddress(guestNetwork, null));
@@ -1806,7 +1805,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                 gatewayNic.setBroadcastType(guestNetwork.getBroadcastDomainType());
                 gatewayNic.setIsolationUri(guestNetwork.getBroadcastUri());
                 gatewayNic.setMode(guestNetwork.getMode());
-                String gatewayCidr = guestNetwork.getCidr();
+                final String gatewayCidr = guestNetwork.getCidr();
                 gatewayNic.setNetmask(NetUtils.getCidrNetmask(gatewayCidr));
             } else {
                 gatewayNic.setDefaultNic(true);
@@ -1818,24 +1817,24 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
         //2) Control network
         s_logger.debug("Adding nic for Virtual Router in Control network ");
-        List<? extends NetworkOffering> offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemControlNetwork);
-        NetworkOffering controlOffering = offerings.get(0);
-        Network controlConfig = _networkMgr.setupNetwork(_systemAcct, controlOffering, plan, null, null, false).get(0);
+        final List<? extends NetworkOffering> offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemControlNetwork);
+        final NetworkOffering controlOffering = offerings.get(0);
+        final Network controlConfig = _networkMgr.setupNetwork(_systemAcct, controlOffering, plan, null, null, false).get(0);
         networks.put(controlConfig, null);
 
         //3) Public network
         if (setupPublicNetwork) {
-            PublicIp sourceNatIp = publicNetwork.second();
+            final PublicIp sourceNatIp = publicNetwork.second();
             s_logger.debug("Adding nic for Virtual Router in Public network ");
             //if source nat service is supported by the network, get the source nat ip address
-            NicProfile defaultNic = new NicProfile();
+            final NicProfile defaultNic = new NicProfile();
             defaultNic.setDefaultNic(true);
             defaultNic.setIp4Address(sourceNatIp.getAddress().addr());
             defaultNic.setGateway(sourceNatIp.getGateway());
             defaultNic.setNetmask(sourceNatIp.getNetmask());
             defaultNic.setMacAddress(sourceNatIp.getMacAddress());
             // get broadcast from public network
-            Network pubNet = _networkDao.findById(sourceNatIp.getNetworkId());
+            final Network pubNet = _networkDao.findById(sourceNatIp.getNetworkId());
             if (pubNet.getBroadcastDomainType() == BroadcastDomainType.Vxlan) {
                 defaultNic.setBroadcastType(BroadcastDomainType.Vxlan);
                 defaultNic.setBroadcastUri(BroadcastDomainType.Vxlan.toUri(sourceNatIp.getVlanTag()));
@@ -1848,11 +1847,11 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             if (hasGuestNetwork) {
                 defaultNic.setDeviceId(2);
             }
-            NetworkOffering publicOffering = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemPublicNetwork).get(0);
-            List<? extends Network> publicNetworks = _networkMgr.setupNetwork(_systemAcct, publicOffering, plan, null, null, false);
-            String publicIp = defaultNic.getIp4Address();
+            final NetworkOffering publicOffering = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemPublicNetwork).get(0);
+            final List<? extends Network> publicNetworks = _networkMgr.setupNetwork(_systemAcct, publicOffering, plan, null, null, false);
+            final String publicIp = defaultNic.getIp4Address();
             // We want to use the identical MAC address for RvR on public interface if possible
-            NicVO peerNic = _nicDao.findByIp4AddressAndNetworkId(publicIp, publicNetworks.get(0).getId());
+            final NicVO peerNic = _nicDao.findByIp4AddressAndNetworkId(publicIp, publicNetworks.get(0).getId());
             if (peerNic != null) {
                 s_logger.info("Use same MAC as previous RvR, the MAC is " + peerNic.getMacAddress());
                 defaultNic.setMacAddress(peerNic.getMacAddress());
@@ -1863,12 +1862,12 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         return networks;
     }
 
-    protected Pair<DeploymentPlan, List<DomainRouterVO>> getDeploymentPlanAndRouters(boolean isPodBased, DeployDestination dest, long guestNetworkId) {
-        long dcId = dest.getDataCenter().getId();
+    protected Pair<DeploymentPlan, List<DomainRouterVO>> getDeploymentPlanAndRouters(final boolean isPodBased, final DeployDestination dest, final long guestNetworkId) {
+        final long dcId = dest.getDataCenter().getId();
         List<DomainRouterVO> routers = null;
         DeploymentPlan plan = new DataCenterDeployment(dcId);
         if (isPodBased) {
-            Pod pod = dest.getPod();
+            final Pod pod = dest.getPod();
             Long podId = null;
             if (pod != null) {
                 podId = pod.getId();
@@ -1884,7 +1883,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         return new Pair<DeploymentPlan, List<DomainRouterVO>>(plan, routers);
     }
 
-    private DomainRouterVO startVirtualRouter(DomainRouterVO router, User user, Account caller, Map<Param, Object> params) throws StorageUnavailableException,
+    private DomainRouterVO startVirtualRouter(final DomainRouterVO router, final User user, final Account caller, final Map<Param, Object> params) throws StorageUnavailableException,
         InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
 
         if (router.getRole() != Role.VIRTUAL_ROUTER || !router.getIsRedundantRouter()) {
@@ -1896,18 +1895,18 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             return router;
         }
 
-        DataCenterDeployment plan = new DataCenterDeployment(0, null, null, null, null, null);
+        final DataCenterDeployment plan = new DataCenterDeployment(0, null, null, null, null, null);
         DomainRouterVO result = null;
         assert router.getIsRedundantRouter();
-        List<Long> networkIds = _routerDao.getRouterNetworks(router.getId());
+        final List<Long> networkIds = _routerDao.getRouterNetworks(router.getId());
         //Not support VPC now
         if (networkIds.size() > 1) {
             throw new ResourceUnavailableException("Unable to support more than one guest network for redundant router now!", DataCenter.class, router.getDataCenterId());
         }
         DomainRouterVO routerToBeAvoid = null;
         if (networkIds.size() != 0) {
-            List<DomainRouterVO> routerList = _routerDao.findByNetwork(networkIds.get(0));
-            for (DomainRouterVO rrouter : routerList) {
+            final List<DomainRouterVO> routerList = _routerDao.findByNetwork(networkIds.get(0));
+            for (final DomainRouterVO rrouter : routerList) {
                 if (rrouter.getHostId() != null && rrouter.getIsRedundantRouter() && rrouter.getState() == State.Running) {
                     if (routerToBeAvoid != null) {
                         throw new ResourceUnavailableException("Try to start router " + router.getInstanceName() + "(" + router.getId() + ")" +
@@ -1923,14 +1922,14 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             return this.start(router, user, caller, params, null);
         }
         // We would try best to deploy the router to another place
-        int retryIndex = 5;
-        ExcludeList[] avoids = new ExcludeList[5];
+        final int retryIndex = 5;
+        final ExcludeList[] avoids = new ExcludeList[5];
         avoids[0] = new ExcludeList();
         avoids[0].addPod(routerToBeAvoid.getPodIdToDeployIn());
         avoids[1] = new ExcludeList();
         avoids[1].addCluster(_hostDao.findById(routerToBeAvoid.getHostId()).getClusterId());
         avoids[2] = new ExcludeList();
-        List<VolumeVO> volumes = _volumeDao.findByInstanceAndType(routerToBeAvoid.getId(), Volume.Type.ROOT);
+        final List<VolumeVO> volumes = _volumeDao.findByInstanceAndType(routerToBeAvoid.getId(), Volume.Type.ROOT);
         if (volumes != null && volumes.size() != 0) {
             avoids[2].addPool(volumes.get(0).getPoolId());
         }
@@ -1946,7 +1945,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             plan.setAvoids(avoids[i]);
             try {
                 result = this.start(router, user, caller, params, plan);
-            } catch (InsufficientServerCapacityException ex) {
+            } catch (final InsufficientServerCapacityException ex) {
                 result = null;
             }
             if (result != null) {
@@ -1957,15 +1956,15 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     @Override
-    public List<DomainRouterVO> deployVirtualRouterInGuestNetwork(Network guestNetwork, DeployDestination dest, Account owner, Map<Param, Object> params,
-        boolean isRedundant) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
+    public List<DomainRouterVO> deployVirtualRouterInGuestNetwork(final Network guestNetwork, final DeployDestination dest, final Account owner, final Map<Param, Object> params,
+        final boolean isRedundant) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
 
-        List<DomainRouterVO> routers = findOrDeployVirtualRouterInGuestNetwork(guestNetwork, dest, owner, isRedundant, params);
+        final List<DomainRouterVO> routers = findOrDeployVirtualRouterInGuestNetwork(guestNetwork, dest, owner, isRedundant, params);
 
         return startRouters(params, routers);
     }
 
-    protected List<DomainRouterVO> startRouters(Map<Param, Object> params, List<DomainRouterVO> routers) throws StorageUnavailableException,
+    protected List<DomainRouterVO> startRouters(final Map<Param, Object> params, final List<DomainRouterVO> routers) throws StorageUnavailableException,
         InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
         List<DomainRouterVO> runningRouters = null;
 
@@ -1975,9 +1974,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
         for (DomainRouterVO router : routers) {
             boolean skip = false;
-            State state = router.getState();
+            final State state = router.getState();
             if (router.getHostId() != null && state != State.Running) {
-                HostVO host = _hostDao.findById(router.getHostId());
+                final HostVO host = _hostDao.findById(router.getHostId());
                 if (host == null || host.getState() != Status.Up) {
                     skip = true;
                 }
@@ -1995,22 +1994,22 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     @Override
-    public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) {
+    public boolean finalizeVirtualMachineProfile(final VirtualMachineProfile profile, final DeployDestination dest, final ReservationContext context) {
 
         boolean dnsProvided = true;
         boolean dhcpProvided = true;
         boolean publicNetwork = false;
-        DataCenterVO dc = _dcDao.findById(dest.getDataCenter().getId());
+        final DataCenterVO dc = _dcDao.findById(dest.getDataCenter().getId());
         _dcDao.loadDetails(dc);
 
         //1) Set router details
-        DomainRouterVO router = _routerDao.findById(profile.getVirtualMachine().getId());
-        Map<String, String> details = _vmDetailsDao.listDetailsKeyPairs(router.getId());
+        final DomainRouterVO router = _routerDao.findById(profile.getVirtualMachine().getId());
+        final Map<String, String> details = _vmDetailsDao.listDetailsKeyPairs(router.getId());
         router.setDetails(details);
 
         //2) Prepare boot loader elements related with Control network
 
-        StringBuilder buf = profile.getBootArgsBuilder();
+        final StringBuilder buf = profile.getBootArgsBuilder();
         buf.append(" template=domP");
         buf.append(" name=").append(profile.getHostName());
 
@@ -2023,8 +2022,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         String defaultDns2 = null;
         String defaultIp6Dns1 = null;
         String defaultIp6Dns2 = null;
-        for (NicProfile nic : profile.getNics()) {
-            int deviceId = nic.getDeviceId();
+        for (final NicProfile nic : profile.getNics()) {
+            final int deviceId = nic.getDeviceId();
             boolean ipv4 = false, ipv6 = false;
             if (nic.getIp4Address() != null) {
                 ipv4 = true;
@@ -2091,7 +2090,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
             throw new CloudRuntimeException("Didn't start a control port");
         }
 
-        String rpValue = _configDao.getValue(Config.NetworkRouterRpFilter.key());
+        final String rpValue = _configDao.getValue(Config.NetworkRouterRpFilter.key());
         if (rpValue != null && rpValue.equalsIgnoreCase("true")) {
             _disableRpFilter = true;
         } else {
@@ -2120,7 +2119,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
 
         buf.append(" type=" + type + rpFilter);
 
-        String domain_suffix = dc.getDetail(ZoneConfig.DnsSearchOrder.getName());
+        final String domain_suffix = dc.getDetail(ZoneConfig.DnsSearchOrder.getName());
         if (domain_suffix != null) {
             buf.append(" dnssearchorder=").append(domain_suffix);
         }
@@ -2162,36 +2161,36 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         return true;
     }
 
-    protected StringBuilder createGuestBootLoadArgs(NicProfile guestNic, String defaultDns1, String defaultDns2, DomainRouterVO router) {
-        long guestNetworkId = guestNic.getNetworkId();
-        NetworkVO guestNetwork = _networkDao.findById(guestNetworkId);
+    protected StringBuilder createGuestBootLoadArgs(final NicProfile guestNic, final String defaultDns1, final String defaultDns2, DomainRouterVO router) {
+        final long guestNetworkId = guestNic.getNetworkId();
+        final NetworkVO guestNetwork = _networkDao.findById(guestNetworkId);
         String dhcpRange = null;
-        DataCenterVO dc = _dcDao.findById(guestNetwork.getDataCenterId());
+        final DataCenterVO dc = _dcDao.findById(guestNetwork.getDataCenterId());
 
-        StringBuilder buf = new StringBuilder();
+        final StringBuilder buf = new StringBuilder();
 
-        boolean isRedundant = router.getIsRedundantRouter();
+        final boolean isRedundant = router.getIsRedundantRouter();
         if (isRedundant) {
             buf.append(" redundant_router=1");
-            List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(guestNetwork.getId(), Role.VIRTUAL_ROUTER);
+            final List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(guestNetwork.getId(), Role.VIRTUAL_ROUTER);
             try {
-                int priority = getUpdatedPriority(guestNetwork, routers, router);
+                final int priority = getUpdatedPriority(guestNetwork, routers, router);
                 router.setPriority(priority);
                 router = _routerDao.persist(router);
-            } catch (InsufficientVirtualNetworkCapcityException e) {
+            } catch (final InsufficientVirtualNetworkCapcityException e) {
                 s_logger.error("Failed to get update priority!", e);
                 throw new CloudRuntimeException("Failed to get update priority!");
             }
-            Network net = _networkModel.getNetwork(guestNic.getNetworkId());
+            final Network net = _networkModel.getNetwork(guestNic.getNetworkId());
             buf.append(" guestgw=").append(net.getGateway());
-            String brd = NetUtils.long2Ip(NetUtils.ip2Long(guestNic.getIp4Address()) | ~NetUtils.ip2Long(guestNic.getNetmask()));
+            final String brd = NetUtils.long2Ip(NetUtils.ip2Long(guestNic.getIp4Address()) | ~NetUtils.ip2Long(guestNic.getNetmask()));
             buf.append(" guestbrd=").append(brd);
             buf.append(" guestcidrsize=").append(NetUtils.getCidrSize(guestNic.getNetmask()));
             buf.append(" router_pr=").append(router.getPriority());
         }
 
         //setup network domain
-        String domain = guestNetwork.getNetworkDomain();
+        final String domain = guestNetwork.getNetworkDomain();
         if (domain != null) {
             buf.append(" domain=" + domain);
         }
@@ -2199,14 +2198,14 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         //setup dhcp range
         if (dc.getNetworkType() == NetworkType.Basic) {
             if (guestNic.isDefaultNic()) {
-                long cidrSize = NetUtils.getCidrSize(guestNic.getNetmask());
-                String cidr = NetUtils.getCidrSubNet(guestNic.getGateway(), cidrSize);
+                final long cidrSize = NetUtils.getCidrSize(guestNic.getNetmask());
+                final String cidr = NetUtils.getCidrSubNet(guestNic.getGateway(), cidrSize);
                 if (cidr != null) {
                     dhcpRange = NetUtils.getIpRangeStartIpFromCidr(cidr, cidrSize);
                 }
             }
         } else if (dc.getNetworkType() == NetworkType.Advanced) {
-            String cidr = guestNetwork.getCidr();
+            final String cidr = guestNetwork.getCidr();
             if (cidr != null) {
                 dhcpRange = NetUtils.getDhcpRange(cidr);
             }
@@ -2219,17 +2218,17 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         return buf;
     }
 
-    protected String getGuestDhcpRange(NicProfile guestNic, Network guestNetwork, DataCenter dc) {
+    protected String getGuestDhcpRange(final NicProfile guestNic, final Network guestNetwork, final DataCenter dc) {
         String dhcpRange = null;
         //setup dhcp range
         if (dc.getNetworkType() == NetworkType.Basic) {
-            long cidrSize = NetUtils.getCidrSize(guestNic.getNetmask());
-            String cidr = NetUtils.getCidrSubNet(guestNic.getGateway(), cidrSize);
+            final long cidrSize = NetUtils.getCidrSize(guestNic.getNetmask());
+            final String cidr = NetUtils.getCidrSubNet(guestNic.getGateway(), cidrSize);
             if (cidr != null) {
                 dhcpRange = NetUtils.getIpRangeStartIpFromCidr(cidr, cidrSize);
             }
         } else if (dc.getNetworkType() == NetworkType.Advanced) {
-            String cidr = guestNetwork.getCidr();
+            final String cidr = guestNetwork.getCidr();
             if (cidr != null) {
                 dhcpRange = NetUtils.getDhcpRange(cidr);
             }
@@ -2238,7 +2237,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     @Override
-    public boolean setupDhcpForPvlan(boolean add, DomainRouterVO router, Long hostId, NicProfile nic) {
+    public boolean setupDhcpForPvlan(final boolean add, final DomainRouterVO router, final Long hostId, final NicProfile nic) {
         if (!nic.getBroadCastUri().getScheme().equals("pvlan")) {
             return false;
         }
@@ -2246,18 +2245,18 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
         if (!add) {
             op = "delete";
         }
-        Network network = _networkDao.findById(nic.getNetworkId());
-        String networkTag = _networkModel.getNetworkTag(router.getHypervisorType(), network);
-        PvlanSetupCommand cmd =
+        final Network network = _networkDao.findById(nic.getNetworkId());
+        final String networkTag = _networkModel.getNetworkTag(router.getHypervisorType(), network);
+        final PvlanSetupCommand cmd =
             PvlanSetupCommand.createDhcpSetup(op, nic.getBroadCastUri(), networkTag, router.getInstanceName(), nic.getMacAddress(), nic.getIp4Address());
         // In fact we send command to the host of router, we're not programming router but the host
         Answer answer = null;
         try {
             answer = _agentMgr.se

<TRUNCATED>

[3/6] CLOUDSTACK-6003 fixing plus refactoring dispatcher

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/network/as/AutoScaleManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/as/AutoScaleManagerImpl.java b/server/src/com/cloud/network/as/AutoScaleManagerImpl.java
index a2cc32e..f1ca007 100644
--- a/server/src/com/cloud/network/as/AutoScaleManagerImpl.java
+++ b/server/src/com/cloud/network/as/AutoScaleManagerImpl.java
@@ -53,10 +53,11 @@ import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
 import org.apache.cloudstack.config.ApiServiceConfiguration;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+
 import org.apache.log4j.Logger;
 
 import com.cloud.api.ApiDBUtils;
-import com.cloud.api.ApiDispatcher;
+import com.cloud.api.dispatch.DispatchChainFactory;
 import com.cloud.configuration.ConfigurationManager;
 import com.cloud.dc.DataCenter;
 import com.cloud.dc.DataCenter.NetworkType;
@@ -118,14 +119,17 @@ import com.cloud.utils.db.TransactionStatus;
 import com.cloud.utils.net.NetUtils;
 import com.cloud.vm.UserVmManager;
 import com.cloud.vm.UserVmService;
+
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
 
 @Local(value = {AutoScaleService.class, AutoScaleManager.class})
 public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScaleManager, AutoScaleService {
     private static final Logger s_logger = Logger.getLogger(AutoScaleManagerImpl.class);
-    private ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1);
+    private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1);
 
+    @Inject()
+    protected DispatchChainFactory dispatchChainFactory = null;
     @Inject
     EntityManager _entityMgr;
     @Inject
@@ -179,35 +183,35 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     @Inject
     LoadBalancingRulesService _loadBalancingRulesService;
 
-    public List<AutoScaleCounter> getSupportedAutoScaleCounters(long networkid) {
-        String capability = _lbRulesMgr.getLBCapability(networkid, Capability.AutoScaleCounters.getName());
+    public List<AutoScaleCounter> getSupportedAutoScaleCounters(final long networkid) {
+        final String capability = _lbRulesMgr.getLBCapability(networkid, Capability.AutoScaleCounters.getName());
         if (capability == null) {
             return null;
         }
-        Gson gson = new Gson();
-        java.lang.reflect.Type listType = new TypeToken<List<AutoScaleCounter>>() {
+        final Gson gson = new Gson();
+        final java.lang.reflect.Type listType = new TypeToken<List<AutoScaleCounter>>() {
         }.getType();
-        List<AutoScaleCounter> result = gson.fromJson(capability, listType);
+        final List<AutoScaleCounter> result = gson.fromJson(capability, listType);
         return result;
     }
 
-    public void validateAutoScaleCounters(long networkid, List<Counter> counters, List<Pair<String, String>> counterParamPassed) {
-        List<AutoScaleCounter> supportedCounters = getSupportedAutoScaleCounters(networkid);
+    public void validateAutoScaleCounters(final long networkid, final List<Counter> counters, final List<Pair<String, String>> counterParamPassed) {
+        final List<AutoScaleCounter> supportedCounters = getSupportedAutoScaleCounters(networkid);
         if (supportedCounters == null) {
             throw new InvalidParameterException("AutoScale is not supported in the network");
         }
-        for (Counter counter : counters) {
-            String counterName = counter.getSource().name().toString();
+        for (final Counter counter : counters) {
+            final String counterName = counter.getSource().name().toString();
             boolean isCounterSupported = false;
-            for (AutoScaleCounter autoScaleCounter : supportedCounters) {
+            for (final AutoScaleCounter autoScaleCounter : supportedCounters) {
                 if (autoScaleCounter.getName().equals(counterName)) {
                     isCounterSupported = true;
-                    List<AutoScaleCounterParam> counterParams = autoScaleCounter.getParamList();
-                    for (AutoScaleCounterParam autoScaleCounterParam : counterParams) {
-                        boolean isRequiredParameter = autoScaleCounterParam.getRequired();
+                    final List<AutoScaleCounterParam> counterParams = autoScaleCounter.getParamList();
+                    for (final AutoScaleCounterParam autoScaleCounterParam : counterParams) {
+                        final boolean isRequiredParameter = autoScaleCounterParam.getRequired();
                         if (isRequiredParameter) {
                             boolean isRequiredParamPresent = false;
-                            for (Pair<String, String> pair : counterParamPassed) {
+                            for (final Pair<String, String> pair : counterParamPassed) {
                                 if (pair.first().equals(autoScaleCounterParam.getParamName()))
                                     isRequiredParamPresent = true;
 
@@ -227,9 +231,9 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
         }
     }
 
-    private <VO extends ControlledEntity> VO getEntityInDatabase(Account caller, String paramName, Long id, GenericDao<VO, Long> dao) {
+    private <VO extends ControlledEntity> VO getEntityInDatabase(final Account caller, final String paramName, final Long id, final GenericDao<VO, Long> dao) {
 
-        VO vo = dao.findById(id);
+        final VO vo = dao.findById(id);
 
         if (vo == null) {
             throw new InvalidParameterValueException("Unable to find " + paramName);
@@ -240,27 +244,27 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
         return vo;
     }
 
-    private boolean isAutoScaleScaleUpPolicy(AutoScalePolicy policyVO) {
+    private boolean isAutoScaleScaleUpPolicy(final AutoScalePolicy policyVO) {
         return policyVO.getAction().equals("scaleup");
     }
 
-    private List<AutoScalePolicyVO> getAutoScalePolicies(String paramName, List<Long> policyIds, List<Counter> counters, int interval, boolean scaleUpPolicies) {
-        SearchBuilder<AutoScalePolicyVO> policySearch = _autoScalePolicyDao.createSearchBuilder();
+    private List<AutoScalePolicyVO> getAutoScalePolicies(final String paramName, final List<Long> policyIds, final List<Counter> counters, final int interval, final boolean scaleUpPolicies) {
+        final SearchBuilder<AutoScalePolicyVO> policySearch = _autoScalePolicyDao.createSearchBuilder();
         policySearch.and("ids", policySearch.entity().getId(), Op.IN);
         policySearch.done();
-        SearchCriteria<AutoScalePolicyVO> sc = policySearch.create();
+        final SearchCriteria<AutoScalePolicyVO> sc = policySearch.create();
 
         sc.setParameters("ids", policyIds.toArray(new Object[0]));
-        List<AutoScalePolicyVO> policies = _autoScalePolicyDao.search(sc, null);
+        final List<AutoScalePolicyVO> policies = _autoScalePolicyDao.search(sc, null);
 
         int prevQuietTime = 0;
 
-        for (AutoScalePolicyVO policy : policies) {
-            int quietTime = policy.getQuietTime();
+        for (final AutoScalePolicyVO policy : policies) {
+            final int quietTime = policy.getQuietTime();
             if (prevQuietTime == 0) {
                 prevQuietTime = quietTime;
             }
-            int duration = policy.getDuration();
+            final int duration = policy.getDuration();
             if (duration < interval) {
                 throw new InvalidParameterValueException("duration : " + duration + " specified in a policy cannot be less than vm group's interval : " + interval);
             }
@@ -278,11 +282,11 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
                     throw new InvalidParameterValueException("Only scaledown policies can be specified in scaledownpolicyids");
                 }
             }
-            List<AutoScalePolicyConditionMapVO> policyConditionMapVOs = _autoScalePolicyConditionMapDao.listByAll(policy.getId(), null);
-            for (AutoScalePolicyConditionMapVO policyConditionMapVO : policyConditionMapVOs) {
-                long conditionid = policyConditionMapVO.getConditionId();
-                Condition condition = _conditionDao.findById(conditionid);
-                Counter counter = _counterDao.findById(condition.getCounterid());
+            final List<AutoScalePolicyConditionMapVO> policyConditionMapVOs = _autoScalePolicyConditionMapDao.listByAll(policy.getId(), null);
+            for (final AutoScalePolicyConditionMapVO policyConditionMapVO : policyConditionMapVOs) {
+                final long conditionid = policyConditionMapVO.getConditionId();
+                final Condition condition = _conditionDao.findById(conditionid);
+                final Counter counter = _counterDao.findById(condition.getCounterid());
                 counters.add(counter);
             }
         }
@@ -291,11 +295,11 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @DB
     protected AutoScaleVmProfileVO checkValidityAndPersist(AutoScaleVmProfileVO vmProfile) {
-        long templateId = vmProfile.getTemplateId();
-        long autoscaleUserId = vmProfile.getAutoScaleUserId();
-        int destroyVmGraceperiod = vmProfile.getDestroyVmGraceperiod();
+        final long templateId = vmProfile.getTemplateId();
+        final long autoscaleUserId = vmProfile.getAutoScaleUserId();
+        final int destroyVmGraceperiod = vmProfile.getDestroyVmGraceperiod();
 
-        VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, templateId);
+        final VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, templateId);
         // Make sure a valid template ID was specified
         if (template == null) {
             throw new InvalidParameterValueException("Unable to use the given template.");
@@ -305,14 +309,14 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             throw new InvalidParameterValueException("Destroy Vm Grace Period cannot be less than 0.");
         }
 
-        User user = _userDao.findById(autoscaleUserId);
+        final User user = _userDao.findById(autoscaleUserId);
         if (user.getAccountId() != vmProfile.getAccountId()) {
             throw new InvalidParameterValueException("AutoScale User id does not belong to the same account");
         }
 
-        String apiKey = user.getApiKey();
-        String secretKey = user.getSecretKey();
-        String csUrl = ApiServiceConfiguration.ApiServletPath.value();
+        final String apiKey = user.getApiKey();
+        final String secretKey = user.getSecretKey();
+        final String csUrl = ApiServiceConfiguration.ApiServletPath.value();
 
         if (apiKey == null) {
             throw new InvalidParameterValueException("apiKey for user: " + user.getUsername() + " is empty. Please generate it");
@@ -333,39 +337,41 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_AUTOSCALEVMPROFILE_CREATE, eventDescription = "creating autoscale vm profile", create = true)
-    public AutoScaleVmProfile createAutoScaleVmProfile(CreateAutoScaleVmProfileCmd cmd) {
+    public AutoScaleVmProfile createAutoScaleVmProfile(final CreateAutoScaleVmProfileCmd cmd) {
 
-        Account owner = _accountDao.findById(cmd.getAccountId());
-        Account caller = CallContext.current().getCallingAccount();
+        final Account owner = _accountDao.findById(cmd.getAccountId());
+        final Account caller = CallContext.current().getCallingAccount();
         _accountMgr.checkAccess(caller, null, true, owner);
 
-        long zoneId = cmd.getZoneId();
-        long serviceOfferingId = cmd.getServiceOfferingId();
-        long autoscaleUserId = cmd.getAutoscaleUserId();
+        final long zoneId = cmd.getZoneId();
+        final long serviceOfferingId = cmd.getServiceOfferingId();
+        final long autoscaleUserId = cmd.getAutoscaleUserId();
 
-        DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId);
+        final DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId);
 
         if (zone == null) {
             throw new InvalidParameterValueException("Unable to find zone by id");
         }
 
-        ServiceOffering serviceOffering = _entityMgr.findById(ServiceOffering.class, serviceOfferingId);
+        final ServiceOffering serviceOffering = _entityMgr.findById(ServiceOffering.class, serviceOfferingId);
         if (serviceOffering == null) {
             throw new InvalidParameterValueException("Unable to find service offering by id");
         }
 
         // validations
-        HashMap<String, String> deployParams = cmd.getDeployParamMap();
-        if (deployParams.containsKey("networks") && deployParams.get("networks").length() > 0) {
+        final HashMap<String, Object> deployParams = cmd.getDeployParamMap();
+        final Object networks = deployParams.get("networks");
+        if (networks != null && networks instanceof String && ((String)networks).length() > 0) {
             throw new InvalidParameterValueException(
                 "'networks' is not a valid parameter, network for an AutoScaled VM is chosen automatically. An autoscaled VM is deployed in the loadbalancer's network");
         }
+
         /*
          * Just for making sure the values are right in other deploy params.
          * For ex. if projectId is given as a string instead of an long value, this
          * will be throwing an error.
          */
-        ApiDispatcher.processParameters(new DeployVMCmd(), deployParams);
+        dispatchChainFactory.getStandardDispatchChain().dispatch(new DeployVMCmd(), deployParams);
 
         AutoScaleVmProfileVO profileVO =
             new AutoScaleVmProfileVO(cmd.getZoneId(), cmd.getDomainId(), cmd.getAccountId(), cmd.getServiceOfferingId(), cmd.getTemplateId(), cmd.getOtherDeployParams(),
@@ -378,13 +384,13 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_AUTOSCALEVMPROFILE_UPDATE, eventDescription = "updating autoscale vm profile")
-    public AutoScaleVmProfile updateAutoScaleVmProfile(UpdateAutoScaleVmProfileCmd cmd) {
-        Long profileId = cmd.getId();
-        Long templateId = cmd.getTemplateId();
-        Long autoscaleUserId = cmd.getAutoscaleUserId();
-        Map counterParamList = cmd.getCounterParamList();
+    public AutoScaleVmProfile updateAutoScaleVmProfile(final UpdateAutoScaleVmProfileCmd cmd) {
+        final Long profileId = cmd.getId();
+        final Long templateId = cmd.getTemplateId();
+        final Long autoscaleUserId = cmd.getAutoscaleUserId();
+        final Map counterParamList = cmd.getCounterParamList();
 
-        Integer destroyVmGraceperiod = cmd.getDestroyVmGraceperiod();
+        final Integer destroyVmGraceperiod = cmd.getDestroyVmGraceperiod();
 
         AutoScaleVmProfileVO vmProfile = getEntityInDatabase(CallContext.current().getCallingAccount(), "Auto Scale Vm Profile", profileId, _autoScaleVmProfileDao);
 
@@ -404,8 +410,8 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             vmProfile.setDestroyVmGraceperiod(destroyVmGraceperiod);
         }
 
-        List<AutoScaleVmGroupVO> vmGroupList = _autoScaleVmGroupDao.listByAll(null, profileId);
-        for (AutoScaleVmGroupVO vmGroupVO : vmGroupList) {
+        final List<AutoScaleVmGroupVO> vmGroupList = _autoScaleVmGroupDao.listByAll(null, profileId);
+        for (final AutoScaleVmGroupVO vmGroupVO : vmGroupList) {
             if (!vmGroupVO.getState().equals(AutoScaleVmGroup.State_Disabled)) {
                 throw new InvalidParameterValueException("The AutoScale Vm Profile can be updated only if the Vm Group it is associated with is disabled in state");
             }
@@ -419,13 +425,13 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_AUTOSCALEVMPROFILE_DELETE, eventDescription = "deleting autoscale vm profile")
-    public boolean deleteAutoScaleVmProfile(long id) {
+    public boolean deleteAutoScaleVmProfile(final long id) {
         /* Check if entity is in database */
         getEntityInDatabase(CallContext.current().getCallingAccount(), "AutoScale Vm Profile", id, _autoScaleVmProfileDao);
         if (_autoScaleVmGroupDao.isProfileInUse(id)) {
             throw new InvalidParameterValueException("Cannot delete AutoScale Vm Profile when it is in use by one more vm groups");
         }
-        boolean success = _autoScaleVmProfileDao.remove(id);
+        final boolean success = _autoScaleVmProfileDao.remove(id);
         if (success) {
             s_logger.info("Successfully deleted AutoScale Vm Profile with Id: " + id);
         }
@@ -433,22 +439,22 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     }
 
     @Override
-    public List<? extends AutoScaleVmProfile> listAutoScaleVmProfiles(ListAutoScaleVmProfilesCmd cmd) {
-        Long id = cmd.getId();
-        Long templateId = cmd.getTemplateId();
-        String otherDeployParams = cmd.getOtherDeployParams();
-        Long serviceOffId = cmd.getServiceOfferingId();
-        Long zoneId = cmd.getZoneId();
+    public List<? extends AutoScaleVmProfile> listAutoScaleVmProfiles(final ListAutoScaleVmProfilesCmd cmd) {
+        final Long id = cmd.getId();
+        final Long templateId = cmd.getTemplateId();
+        final String otherDeployParams = cmd.getOtherDeployParams();
+        final Long serviceOffId = cmd.getServiceOfferingId();
+        final Long zoneId = cmd.getZoneId();
 
-        SearchWrapper<AutoScaleVmProfileVO> searchWrapper = new SearchWrapper<AutoScaleVmProfileVO>(_autoScaleVmProfileDao, AutoScaleVmProfileVO.class, cmd, cmd.getId());
-        SearchBuilder<AutoScaleVmProfileVO> sb = searchWrapper.getSearchBuilder();
+        final SearchWrapper<AutoScaleVmProfileVO> searchWrapper = new SearchWrapper<AutoScaleVmProfileVO>(_autoScaleVmProfileDao, AutoScaleVmProfileVO.class, cmd, cmd.getId());
+        final SearchBuilder<AutoScaleVmProfileVO> sb = searchWrapper.getSearchBuilder();
 
         sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
         sb.and("templateId", sb.entity().getTemplateId(), SearchCriteria.Op.EQ);
         sb.and("serviceOfferingId", sb.entity().getServiceOfferingId(), SearchCriteria.Op.EQ);
         sb.and("otherDeployParams", sb.entity().getOtherDeployParams(), SearchCriteria.Op.LIKE);
         sb.and("zoneId", sb.entity().getZoneId(), SearchCriteria.Op.EQ);
-        SearchCriteria<AutoScaleVmProfileVO> sc = searchWrapper.buildSearchCriteria();
+        final SearchCriteria<AutoScaleVmProfileVO> sc = searchWrapper.buildSearchCriteria();
 
         if (id != null) {
             sc.setParameters("id", id);
@@ -486,19 +492,19 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
         return Transaction.execute(new TransactionCallback<AutoScalePolicyVO>() {
             @Override
-            public AutoScalePolicyVO doInTransaction(TransactionStatus status) {
-                AutoScalePolicyVO autoScalePolicyVO = _autoScalePolicyDao.persist(autoScalePolicyVOFinal);
+            public AutoScalePolicyVO doInTransaction(final TransactionStatus status) {
+                final AutoScalePolicyVO autoScalePolicyVO = _autoScalePolicyDao.persist(autoScalePolicyVOFinal);
 
                 if (conditionIds != null) {
-                    SearchBuilder<ConditionVO> conditionsSearch = _conditionDao.createSearchBuilder();
+                    final SearchBuilder<ConditionVO> conditionsSearch = _conditionDao.createSearchBuilder();
                     conditionsSearch.and("ids", conditionsSearch.entity().getId(), Op.IN);
                     conditionsSearch.done();
-                    SearchCriteria<ConditionVO> sc = conditionsSearch.create();
+                    final SearchCriteria<ConditionVO> sc = conditionsSearch.create();
 
                     sc.setParameters("ids", conditionIds.toArray(new Object[0]));
-                    List<ConditionVO> conditions = _conditionDao.search(sc, null);
+                    final List<ConditionVO> conditions = _conditionDao.search(sc, null);
 
-                    ControlledEntity[] sameOwnerEntities = conditions.toArray(new ControlledEntity[conditions.size() + 1]);
+                    final ControlledEntity[] sameOwnerEntities = conditions.toArray(new ControlledEntity[conditions.size() + 1]);
                     sameOwnerEntities[sameOwnerEntities.length - 1] = autoScalePolicyVO;
                     _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, sameOwnerEntities);
 
@@ -507,8 +513,8 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
                         throw new InvalidParameterValueException("Unable to find the condition specified");
                     }
 
-                    ArrayList<Long> counterIds = new ArrayList<Long>();
-                    for (ConditionVO condition : conditions) {
+                    final ArrayList<Long> counterIds = new ArrayList<Long>();
+                    for (final ConditionVO condition : conditions) {
                         if (counterIds.contains(condition.getCounterid())) {
                             throw new InvalidParameterValueException(
                                 "atleast two conditions in the conditionids have the same counter. It is not right to apply two different conditions for the same counter");
@@ -519,8 +525,8 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
                     /* For update case remove the existing mappings and create fresh ones */
                     _autoScalePolicyConditionMapDao.removeByAutoScalePolicyId(autoScalePolicyVO.getId());
 
-                    for (Long conditionId : conditionIds) {
-                        AutoScalePolicyConditionMapVO policyConditionMapVO = new AutoScalePolicyConditionMapVO(autoScalePolicyVO.getId(), conditionId);
+                    for (final Long conditionId : conditionIds) {
+                        final AutoScalePolicyConditionMapVO policyConditionMapVO = new AutoScalePolicyConditionMapVO(autoScalePolicyVO.getId(), conditionId);
                         _autoScalePolicyConditionMapDao.persist(policyConditionMapVO);
                     }
                 }
@@ -532,9 +538,9 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_AUTOSCALEPOLICY_CREATE, eventDescription = "creating autoscale policy", create = true)
-    public AutoScalePolicy createAutoScalePolicy(CreateAutoScalePolicyCmd cmd) {
+    public AutoScalePolicy createAutoScalePolicy(final CreateAutoScalePolicyCmd cmd) {
 
-        int duration = cmd.getDuration();
+        final int duration = cmd.getDuration();
         Integer quietTime = cmd.getQuietTime();
         String action = cmd.getAction();
 
@@ -567,7 +573,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
         return Transaction.execute(new TransactionCallback<Boolean>() {
             @Override
-            public Boolean doInTransaction(TransactionStatus status) {
+            public Boolean doInTransaction(final TransactionStatus status) {
                 boolean success = true;
                 success = _autoScalePolicyDao.remove(id);
                 if (!success) {
@@ -586,11 +592,11 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
         });
     }
 
-    public void checkCallerAccess(String accountName, Long domainId) {
-        Account caller = CallContext.current().getCallingAccount();
-        Account owner = _accountDao.findActiveAccount(accountName, domainId);
+    public void checkCallerAccess(final String accountName, final Long domainId) {
+        final Account caller = CallContext.current().getCallingAccount();
+        final Account owner = _accountDao.findActiveAccount(accountName, domainId);
         if (owner == null) {
-            List<String> idList = new ArrayList<String>();
+            final List<String> idList = new ArrayList<String>();
             idList.add(ApiDBUtils.findDomainById(domainId).getUuid());
             throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain with specifed domainId");
         }
@@ -607,23 +613,23 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
         ListProjectResourcesCriteria listProjectResourcesCriteria;
         Filter searchFilter;
 
-        public SearchWrapper(GenericDao<VO, Long> dao, Class<VO> entityClass, BaseListAccountResourcesCmd cmd, Long id) {
+        public SearchWrapper(final GenericDao<VO, Long> dao, final Class<VO> entityClass, final BaseListAccountResourcesCmd cmd, final Long id) {
             this.dao = dao;
             this.searchBuilder = dao.createSearchBuilder();
             domainId = cmd.getDomainId();
-            String accountName = cmd.getAccountName();
+            final String accountName = cmd.getAccountName();
             isRecursive = cmd.isRecursive();
-            boolean listAll = cmd.listAll();
-            long startIndex = cmd.getStartIndex();
-            long pageSizeVal = cmd.getPageSizeVal();
-            Account caller = CallContext.current().getCallingAccount();
+            final boolean listAll = cmd.listAll();
+            final long startIndex = cmd.getStartIndex();
+            final long pageSizeVal = cmd.getPageSizeVal();
+            final Account caller = CallContext.current().getCallingAccount();
 
-            Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject =
+            final Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject =
                 new Ternary<Long, Boolean, ListProjectResourcesCriteria>(domainId, isRecursive, null);
             _accountMgr.buildACLSearchParameters(caller, id, accountName, null, permittedAccounts, domainIdRecursiveListProject, listAll, false);
             domainId = domainIdRecursiveListProject.first();
             isRecursive = domainIdRecursiveListProject.second();
-            ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
+            final ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
             _accountMgr.buildACLSearchBuilder(searchBuilder, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
             searchFilter = new Filter(entityClass, "id", false, startIndex, pageSizeVal);
         }
@@ -644,30 +650,30 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     }
 
     @Override
-    public List<? extends AutoScalePolicy> listAutoScalePolicies(ListAutoScalePoliciesCmd cmd) {
-        SearchWrapper<AutoScalePolicyVO> searchWrapper = new SearchWrapper<AutoScalePolicyVO>(_autoScalePolicyDao, AutoScalePolicyVO.class, cmd, cmd.getId());
-        SearchBuilder<AutoScalePolicyVO> sb = searchWrapper.getSearchBuilder();
-        Long id = cmd.getId();
-        Long conditionId = cmd.getConditionId();
-        String action = cmd.getAction();
-        Long vmGroupId = cmd.getVmGroupId();
+    public List<? extends AutoScalePolicy> listAutoScalePolicies(final ListAutoScalePoliciesCmd cmd) {
+        final SearchWrapper<AutoScalePolicyVO> searchWrapper = new SearchWrapper<AutoScalePolicyVO>(_autoScalePolicyDao, AutoScalePolicyVO.class, cmd, cmd.getId());
+        final SearchBuilder<AutoScalePolicyVO> sb = searchWrapper.getSearchBuilder();
+        final Long id = cmd.getId();
+        final Long conditionId = cmd.getConditionId();
+        final String action = cmd.getAction();
+        final Long vmGroupId = cmd.getVmGroupId();
 
         sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
         sb.and("action", sb.entity().getAction(), SearchCriteria.Op.EQ);
 
         if (conditionId != null) {
-            SearchBuilder<AutoScalePolicyConditionMapVO> asPolicyConditionSearch = _autoScalePolicyConditionMapDao.createSearchBuilder();
+            final SearchBuilder<AutoScalePolicyConditionMapVO> asPolicyConditionSearch = _autoScalePolicyConditionMapDao.createSearchBuilder();
             asPolicyConditionSearch.and("conditionId", asPolicyConditionSearch.entity().getConditionId(), SearchCriteria.Op.EQ);
             sb.join("asPolicyConditionSearch", asPolicyConditionSearch, sb.entity().getId(), asPolicyConditionSearch.entity().getPolicyId(), JoinBuilder.JoinType.INNER);
         }
 
         if (vmGroupId != null) {
-            SearchBuilder<AutoScaleVmGroupPolicyMapVO> asVmGroupPolicySearch = _autoScaleVmGroupPolicyMapDao.createSearchBuilder();
+            final SearchBuilder<AutoScaleVmGroupPolicyMapVO> asVmGroupPolicySearch = _autoScaleVmGroupPolicyMapDao.createSearchBuilder();
             asVmGroupPolicySearch.and("vmGroupId", asVmGroupPolicySearch.entity().getVmGroupId(), SearchCriteria.Op.EQ);
             sb.join("asVmGroupPolicySearch", asVmGroupPolicySearch, sb.entity().getId(), asVmGroupPolicySearch.entity().getPolicyId(), JoinBuilder.JoinType.INNER);
         }
 
-        SearchCriteria<AutoScalePolicyVO> sc = searchWrapper.buildSearchCriteria();
+        final SearchCriteria<AutoScalePolicyVO> sc = searchWrapper.buildSearchCriteria();
 
         if (id != null) {
             sc.setParameters("id", id);
@@ -690,11 +696,11 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_AUTOSCALEPOLICY_UPDATE, eventDescription = "updating autoscale policy")
-    public AutoScalePolicy updateAutoScalePolicy(UpdateAutoScalePolicyCmd cmd) {
-        Long policyId = cmd.getId();
-        Integer duration = cmd.getDuration();
-        Integer quietTime = cmd.getQuietTime();
-        List<Long> conditionIds = cmd.getConditionIds();
+    public AutoScalePolicy updateAutoScalePolicy(final UpdateAutoScalePolicyCmd cmd) {
+        final Long policyId = cmd.getId();
+        final Integer duration = cmd.getDuration();
+        final Integer quietTime = cmd.getQuietTime();
+        final List<Long> conditionIds = cmd.getConditionIds();
         AutoScalePolicyVO policy = getEntityInDatabase(CallContext.current().getCallingAccount(), "Auto Scale Policy", policyId, _autoScalePolicyDao);
 
         if (duration != null) {
@@ -705,9 +711,9 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             policy.setQuietTime(quietTime);
         }
 
-        List<AutoScaleVmGroupPolicyMapVO> vmGroupPolicyList = _autoScaleVmGroupPolicyMapDao.listByPolicyId(policyId);
-        for (AutoScaleVmGroupPolicyMapVO vmGroupPolicy : vmGroupPolicyList) {
-            AutoScaleVmGroupVO vmGroupVO = _autoScaleVmGroupDao.findById(vmGroupPolicy.getVmGroupId());
+        final List<AutoScaleVmGroupPolicyMapVO> vmGroupPolicyList = _autoScaleVmGroupPolicyMapDao.listByPolicyId(policyId);
+        for (final AutoScaleVmGroupPolicyMapVO vmGroupPolicy : vmGroupPolicyList) {
+            final AutoScaleVmGroupVO vmGroupVO = _autoScaleVmGroupDao.findById(vmGroupPolicy.getVmGroupId());
             if (vmGroupVO == null) {
                 s_logger.warn("Stale database entry! There is an entry in VmGroupPolicyMap but the vmGroup is missing:" + vmGroupPolicy.getVmGroupId());
 
@@ -729,18 +735,18 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_AUTOSCALEVMGROUP_CREATE, eventDescription = "creating autoscale vm group", create = true)
-    public AutoScaleVmGroup createAutoScaleVmGroup(CreateAutoScaleVmGroupCmd cmd) {
-        int minMembers = cmd.getMinMembers();
-        int maxMembers = cmd.getMaxMembers();
+    public AutoScaleVmGroup createAutoScaleVmGroup(final CreateAutoScaleVmGroupCmd cmd) {
+        final int minMembers = cmd.getMinMembers();
+        final int maxMembers = cmd.getMaxMembers();
         Integer interval = cmd.getInterval();
 
         if (interval == null) {
             interval = NetUtils.DEFAULT_AUTOSCALE_POLICY_INTERVAL_TIME;
         }
 
-        LoadBalancerVO loadBalancer = getEntityInDatabase(CallContext.current().getCallingAccount(), ApiConstants.LBID, cmd.getLbRuleId(), _lbDao);
+        final LoadBalancerVO loadBalancer = getEntityInDatabase(CallContext.current().getCallingAccount(), ApiConstants.LBID, cmd.getLbRuleId(), _lbDao);
 
-        Long zoneId = _ipAddressDao.findById(loadBalancer.getSourceIpAddressId()).getDataCenterId();
+        final Long zoneId = _ipAddressDao.findById(loadBalancer.getSourceIpAddressId()).getDataCenterId();
 
         if (_autoScaleVmGroupDao.isAutoScaleLoadBalancer(loadBalancer.getId())) {
             throw new InvalidParameterValueException("an AutoScaleVmGroup is already attached to the lb rule, the existing vm group has to be first deleted");
@@ -761,23 +767,23 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     }
 
     @Override
-    public boolean configureAutoScaleVmGroup(CreateAutoScaleVmGroupCmd cmd) throws ResourceUnavailableException {
+    public boolean configureAutoScaleVmGroup(final CreateAutoScaleVmGroupCmd cmd) throws ResourceUnavailableException {
         return configureAutoScaleVmGroup(cmd.getEntityId(), AutoScaleVmGroup.State_New);
     }
 
-    public boolean isLoadBalancerBasedAutoScaleVmGroup(AutoScaleVmGroup vmGroup) {
+    public boolean isLoadBalancerBasedAutoScaleVmGroup(final AutoScaleVmGroup vmGroup) {
         return vmGroup.getLoadBalancerId() != null;
     }
 
-    private boolean configureAutoScaleVmGroup(long vmGroupid, String currentState) throws ResourceUnavailableException {
-        AutoScaleVmGroup vmGroup = _autoScaleVmGroupDao.findById(vmGroupid);
+    private boolean configureAutoScaleVmGroup(final long vmGroupid, final String currentState) throws ResourceUnavailableException {
+        final AutoScaleVmGroup vmGroup = _autoScaleVmGroupDao.findById(vmGroupid);
 
         if (isLoadBalancerBasedAutoScaleVmGroup(vmGroup)) {
             try {
                 return _lbRulesMgr.configureLbAutoScaleVmGroup(vmGroupid, currentState);
-            } catch (ResourceUnavailableException re) {
+            } catch (final ResourceUnavailableException re) {
                 throw re;
-            } catch (Exception e) {
+            } catch (final Exception e) {
                 s_logger.warn("Exception during configureLbAutoScaleVmGroup in lb rules manager", e);
                 return false;
             }
@@ -791,20 +797,20 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     @DB
     @ActionEvent(eventType = EventTypes.EVENT_AUTOSCALEVMGROUP_DELETE, eventDescription = "deleting autoscale vm group")
     public boolean deleteAutoScaleVmGroup(final long id) {
-        AutoScaleVmGroupVO autoScaleVmGroupVO = getEntityInDatabase(CallContext.current().getCallingAccount(), "AutoScale Vm Group", id, _autoScaleVmGroupDao);
+        final AutoScaleVmGroupVO autoScaleVmGroupVO = getEntityInDatabase(CallContext.current().getCallingAccount(), "AutoScale Vm Group", id, _autoScaleVmGroupDao);
 
         if (autoScaleVmGroupVO.getState().equals(AutoScaleVmGroup.State_New)) {
             /* This condition is for handling failures during creation command */
             return _autoScaleVmGroupDao.remove(id);
         }
-        String bakupState = autoScaleVmGroupVO.getState();
+        final String bakupState = autoScaleVmGroupVO.getState();
         autoScaleVmGroupVO.setState(AutoScaleVmGroup.State_Revoke);
         _autoScaleVmGroupDao.persist(autoScaleVmGroupVO);
         boolean success = false;
 
         try {
             success = configureAutoScaleVmGroup(id, bakupState);
-        } catch (ResourceUnavailableException e) {
+        } catch (final ResourceUnavailableException e) {
             autoScaleVmGroupVO.setState(bakupState);
             _autoScaleVmGroupDao.persist(autoScaleVmGroupVO);
         } finally {
@@ -816,7 +822,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
         return Transaction.execute(new TransactionCallback<Boolean>() {
             @Override
-            public Boolean doInTransaction(TransactionStatus status) {
+            public Boolean doInTransaction(final TransactionStatus status) {
                 boolean success = _autoScaleVmGroupDao.remove(id);
 
                 if (!success) {
@@ -838,15 +844,15 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     }
 
     @Override
-    public List<? extends AutoScaleVmGroup> listAutoScaleVmGroups(ListAutoScaleVmGroupsCmd cmd) {
-        Long id = cmd.getId();
-        Long policyId = cmd.getPolicyId();
-        Long loadBalancerId = cmd.getLoadBalancerId();
-        Long profileId = cmd.getProfileId();
-        Long zoneId = cmd.getZoneId();
+    public List<? extends AutoScaleVmGroup> listAutoScaleVmGroups(final ListAutoScaleVmGroupsCmd cmd) {
+        final Long id = cmd.getId();
+        final Long policyId = cmd.getPolicyId();
+        final Long loadBalancerId = cmd.getLoadBalancerId();
+        final Long profileId = cmd.getProfileId();
+        final Long zoneId = cmd.getZoneId();
 
-        SearchWrapper<AutoScaleVmGroupVO> searchWrapper = new SearchWrapper<AutoScaleVmGroupVO>(_autoScaleVmGroupDao, AutoScaleVmGroupVO.class, cmd, cmd.getId());
-        SearchBuilder<AutoScaleVmGroupVO> sb = searchWrapper.getSearchBuilder();
+        final SearchWrapper<AutoScaleVmGroupVO> searchWrapper = new SearchWrapper<AutoScaleVmGroupVO>(_autoScaleVmGroupDao, AutoScaleVmGroupVO.class, cmd, cmd.getId());
+        final SearchBuilder<AutoScaleVmGroupVO> sb = searchWrapper.getSearchBuilder();
 
         sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
         sb.and("loadBalancerId", sb.entity().getLoadBalancerId(), SearchCriteria.Op.EQ);
@@ -854,12 +860,12 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
         sb.and("zoneId", sb.entity().getZoneId(), SearchCriteria.Op.EQ);
 
         if (policyId != null) {
-            SearchBuilder<AutoScaleVmGroupPolicyMapVO> asVmGroupPolicySearch = _autoScaleVmGroupPolicyMapDao.createSearchBuilder();
+            final SearchBuilder<AutoScaleVmGroupPolicyMapVO> asVmGroupPolicySearch = _autoScaleVmGroupPolicyMapDao.createSearchBuilder();
             asVmGroupPolicySearch.and("policyId", asVmGroupPolicySearch.entity().getPolicyId(), SearchCriteria.Op.EQ);
             sb.join("asVmGroupPolicySearch", asVmGroupPolicySearch, sb.entity().getId(), asVmGroupPolicySearch.entity().getVmGroupId(), JoinBuilder.JoinType.INNER);
         }
 
-        SearchCriteria<AutoScaleVmGroupVO> sc = searchWrapper.buildSearchCriteria();
+        final SearchCriteria<AutoScaleVmGroupVO> sc = searchWrapper.buildSearchCriteria();
         if (id != null) {
             sc.setParameters("id", id);
         }
@@ -881,14 +887,14 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     @DB
     protected AutoScaleVmGroupVO checkValidityAndPersist(final AutoScaleVmGroupVO vmGroup, final List<Long> passedScaleUpPolicyIds,
         final List<Long> passedScaleDownPolicyIds) {
-        int minMembers = vmGroup.getMinMembers();
-        int maxMembers = vmGroup.getMaxMembers();
-        int interval = vmGroup.getInterval();
-        List<Counter> counters = new ArrayList<Counter>();
-        List<AutoScalePolicyVO> policies = new ArrayList<AutoScalePolicyVO>();
+        final int minMembers = vmGroup.getMinMembers();
+        final int maxMembers = vmGroup.getMaxMembers();
+        final int interval = vmGroup.getInterval();
+        final List<Counter> counters = new ArrayList<Counter>();
+        final List<AutoScalePolicyVO> policies = new ArrayList<AutoScalePolicyVO>();
         final List<Long> policyIds = new ArrayList<Long>();
-        List<Long> currentScaleUpPolicyIds = new ArrayList<Long>();
-        List<Long> currentScaleDownPolicyIds = new ArrayList<Long>();
+        final List<Long> currentScaleUpPolicyIds = new ArrayList<Long>();
+        final List<Long> currentScaleDownPolicyIds = new ArrayList<Long>();
         if (vmGroup.getCreated() != null) {
             ApiDBUtils.getAutoScaleVmGroupPolicyIds(vmGroup.getId(), currentScaleUpPolicyIds, currentScaleDownPolicyIds);
         }
@@ -927,26 +933,26 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             getAutoScalePolicies("scaledownpolicyid", currentScaleDownPolicyIds, counters, interval, false);
             policyIds.addAll(currentScaleDownPolicyIds);
         }
-        AutoScaleVmProfileVO profileVO =
+        final AutoScaleVmProfileVO profileVO =
             getEntityInDatabase(CallContext.current().getCallingAccount(), ApiConstants.VMPROFILE_ID, vmGroup.getProfileId(), _autoScaleVmProfileDao);
 
-        LoadBalancerVO loadBalancer = getEntityInDatabase(CallContext.current().getCallingAccount(), ApiConstants.LBID, vmGroup.getLoadBalancerId(), _lbDao);
+        final LoadBalancerVO loadBalancer = getEntityInDatabase(CallContext.current().getCallingAccount(), ApiConstants.LBID, vmGroup.getLoadBalancerId(), _lbDao);
         validateAutoScaleCounters(loadBalancer.getNetworkId(), counters, profileVO.getCounterParams());
 
-        ControlledEntity[] sameOwnerEntities = policies.toArray(new ControlledEntity[policies.size() + 2]);
+        final ControlledEntity[] sameOwnerEntities = policies.toArray(new ControlledEntity[policies.size() + 2]);
         sameOwnerEntities[sameOwnerEntities.length - 2] = loadBalancer;
         sameOwnerEntities[sameOwnerEntities.length - 1] = profileVO;
         _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, sameOwnerEntities);
 
         return Transaction.execute(new TransactionCallback<AutoScaleVmGroupVO>() {
             @Override
-            public AutoScaleVmGroupVO doInTransaction(TransactionStatus status) {
-                AutoScaleVmGroupVO vmGroupNew = _autoScaleVmGroupDao.persist(vmGroup);
+            public AutoScaleVmGroupVO doInTransaction(final TransactionStatus status) {
+                final AutoScaleVmGroupVO vmGroupNew = _autoScaleVmGroupDao.persist(vmGroup);
 
                 if (passedScaleUpPolicyIds != null || passedScaleDownPolicyIds != null) {
                     _autoScaleVmGroupPolicyMapDao.removeByGroupId(vmGroupNew.getId());
 
-                    for (Long policyId : policyIds) {
+                    for (final Long policyId : policyIds) {
                         _autoScaleVmGroupPolicyMapDao.persist(new AutoScaleVmGroupPolicyMapVO(vmGroupNew.getId(), policyId));
                     }
                 }
@@ -959,14 +965,14 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_AUTOSCALEVMGROUP_UPDATE, eventDescription = "updating autoscale vm group")
-    public AutoScaleVmGroup updateAutoScaleVmGroup(UpdateAutoScaleVmGroupCmd cmd) {
-        Long vmGroupId = cmd.getId();
-        Integer minMembers = cmd.getMinMembers();
-        Integer maxMembers = cmd.getMaxMembers();
-        Integer interval = cmd.getInterval();
+    public AutoScaleVmGroup updateAutoScaleVmGroup(final UpdateAutoScaleVmGroupCmd cmd) {
+        final Long vmGroupId = cmd.getId();
+        final Integer minMembers = cmd.getMinMembers();
+        final Integer maxMembers = cmd.getMaxMembers();
+        final Integer interval = cmd.getInterval();
 
-        List<Long> scaleUpPolicyIds = cmd.getScaleUpPolicyIds();
-        List<Long> scaleDownPolicyIds = cmd.getScaleDownPolicyIds();
+        final List<Long> scaleUpPolicyIds = cmd.getScaleUpPolicyIds();
+        final List<Long> scaleDownPolicyIds = cmd.getScaleDownPolicyIds();
 
         AutoScaleVmGroupVO vmGroupVO = getEntityInDatabase(CallContext.current().getCallingAccount(), "AutoScale Vm Group", vmGroupId, _autoScaleVmGroupDao);
 
@@ -997,7 +1003,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     @Override
     @DB
     @ActionEvent(eventType = EventTypes.EVENT_AUTOSCALEVMGROUP_ENABLE, eventDescription = "enabling autoscale vm group")
-    public AutoScaleVmGroup enableAutoScaleVmGroup(Long id) {
+    public AutoScaleVmGroup enableAutoScaleVmGroup(final Long id) {
         AutoScaleVmGroupVO vmGroup = getEntityInDatabase(CallContext.current().getCallingAccount(), "AutoScale Vm Group", id, _autoScaleVmGroupDao);
         boolean success = false;
         if (!vmGroup.getState().equals(AutoScaleVmGroup.State_Disabled)) {
@@ -1008,7 +1014,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             vmGroup.setState(AutoScaleVmGroup.State_Enabled);
             vmGroup = _autoScaleVmGroupDao.persist(vmGroup);
             success = configureAutoScaleVmGroup(id, AutoScaleVmGroup.State_Disabled);
-        } catch (ResourceUnavailableException e) {
+        } catch (final ResourceUnavailableException e) {
             vmGroup.setState(AutoScaleVmGroup.State_Disabled);
             _autoScaleVmGroupDao.persist(vmGroup);
         } finally {
@@ -1024,7 +1030,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_AUTOSCALEVMGROUP_DISABLE, eventDescription = "disabling autoscale vm group")
     @DB
-    public AutoScaleVmGroup disableAutoScaleVmGroup(Long id) {
+    public AutoScaleVmGroup disableAutoScaleVmGroup(final Long id) {
         AutoScaleVmGroupVO vmGroup = getEntityInDatabase(CallContext.current().getCallingAccount(), "AutoScale Vm Group", id, _autoScaleVmGroupDao);
         boolean success = false;
         if (!vmGroup.getState().equals(AutoScaleVmGroup.State_Enabled)) {
@@ -1035,7 +1041,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             vmGroup.setState(AutoScaleVmGroup.State_Disabled);
             vmGroup = _autoScaleVmGroupDao.persist(vmGroup);
             success = configureAutoScaleVmGroup(id, AutoScaleVmGroup.State_Enabled);
-        } catch (ResourceUnavailableException e) {
+        } catch (final ResourceUnavailableException e) {
             vmGroup.setState(AutoScaleVmGroup.State_Enabled);
             _autoScaleVmGroupDao.persist(vmGroup);
         } finally {
@@ -1051,14 +1057,14 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_COUNTER_CREATE, eventDescription = "Counter", create = true)
     @DB
-    public Counter createCounter(CreateCounterCmd cmd) {
-        String source = cmd.getSource().toLowerCase();
-        String name = cmd.getName();
+    public Counter createCounter(final CreateCounterCmd cmd) {
+        final String source = cmd.getSource().toLowerCase();
+        final String name = cmd.getName();
         Counter.Source src;
         // Validate Source
         try {
             src = Counter.Source.valueOf(source);
-        } catch (Exception ex) {
+        } catch (final Exception ex) {
             throw new InvalidParameterValueException("The Source " + source + " does not exist; Unable to create Counter");
         }
 
@@ -1073,21 +1079,21 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_CONDITION_CREATE, eventDescription = "Condition", create = true)
-    public Condition createCondition(CreateConditionCmd cmd) {
+    public Condition createCondition(final CreateConditionCmd cmd) {
         checkCallerAccess(cmd.getAccountName(), cmd.getDomainId());
-        String opr = cmd.getRelationalOperator().toUpperCase();
-        long cid = cmd.getCounterId();
-        long threshold = cmd.getThreshold();
+        final String opr = cmd.getRelationalOperator().toUpperCase();
+        final long cid = cmd.getCounterId();
+        final long threshold = cmd.getThreshold();
         Condition.Operator op;
         // Validate Relational Operator
         try {
             op = Condition.Operator.valueOf(opr);
-        } catch (IllegalArgumentException ex) {
+        } catch (final IllegalArgumentException ex) {
             throw new InvalidParameterValueException("The Operator " + opr + " does not exist; Unable to create Condition.");
         }
         // TODO - Validate threshold
 
-        CounterVO counter = _counterDao.findById(cid);
+        final CounterVO counter = _counterDao.findById(cid);
 
         if (counter == null) {
             throw new InvalidParameterValueException("Unable to find counter");
@@ -1102,29 +1108,29 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     }
 
     @Override
-    public List<? extends Counter> listCounters(ListCountersCmd cmd) {
-        String name = cmd.getName();
-        Long id = cmd.getId();
+    public List<? extends Counter> listCounters(final ListCountersCmd cmd) {
+        final String name = cmd.getName();
+        final Long id = cmd.getId();
         String source = cmd.getSource();
         if (source != null)
             source = source.toLowerCase();
 
-        Filter searchFilter = new Filter(CounterVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
+        final Filter searchFilter = new Filter(CounterVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
 
-        List<CounterVO> counters = _counterDao.listCounters(id, name, source, cmd.getKeyword(), searchFilter);
+        final List<CounterVO> counters = _counterDao.listCounters(id, name, source, cmd.getKeyword(), searchFilter);
 
         return counters;
     }
 
     @Override
-    public List<? extends Condition> listConditions(ListConditionsCmd cmd) {
-        Long id = cmd.getId();
-        Long counterId = cmd.getCounterId();
-        Long policyId = cmd.getPolicyId();
-        SearchWrapper<ConditionVO> searchWrapper = new SearchWrapper<ConditionVO>(_conditionDao, ConditionVO.class, cmd, cmd.getId());
-        SearchBuilder<ConditionVO> sb = searchWrapper.getSearchBuilder();
+    public List<? extends Condition> listConditions(final ListConditionsCmd cmd) {
+        final Long id = cmd.getId();
+        final Long counterId = cmd.getCounterId();
+        final Long policyId = cmd.getPolicyId();
+        final SearchWrapper<ConditionVO> searchWrapper = new SearchWrapper<ConditionVO>(_conditionDao, ConditionVO.class, cmd, cmd.getId());
+        final SearchBuilder<ConditionVO> sb = searchWrapper.getSearchBuilder();
         if (policyId != null) {
-            SearchBuilder<AutoScalePolicyConditionMapVO> asPolicyConditionSearch = _autoScalePolicyConditionMapDao.createSearchBuilder();
+            final SearchBuilder<AutoScalePolicyConditionMapVO> asPolicyConditionSearch = _autoScalePolicyConditionMapDao.createSearchBuilder();
             asPolicyConditionSearch.and("policyId", asPolicyConditionSearch.entity().getPolicyId(), SearchCriteria.Op.EQ);
             sb.join("asPolicyConditionSearch", asPolicyConditionSearch, sb.entity().getId(), asPolicyConditionSearch.entity().getConditionId(),
                 JoinBuilder.JoinType.INNER);
@@ -1134,7 +1140,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
         sb.and("counterId", sb.entity().getCounterid(), SearchCriteria.Op.EQ);
 
         // now set the SC criteria...
-        SearchCriteria<ConditionVO> sc = searchWrapper.buildSearchCriteria();
+        final SearchCriteria<ConditionVO> sc = searchWrapper.buildSearchCriteria();
 
         if (id != null) {
             sc.setParameters("id", id);
@@ -1153,22 +1159,22 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_COUNTER_DELETE, eventDescription = "counter")
-    public boolean deleteCounter(long counterId) throws ResourceInUseException {
+    public boolean deleteCounter(final long counterId) throws ResourceInUseException {
         // Verify Counter id
-        CounterVO counter = _counterDao.findById(counterId);
+        final CounterVO counter = _counterDao.findById(counterId);
         if (counter == null) {
             throw new InvalidParameterValueException("Unable to find Counter");
         }
 
         // Verify if it is used in any Condition
 
-        ConditionVO condition = _conditionDao.findByCounterId(counterId);
+        final ConditionVO condition = _conditionDao.findByCounterId(counterId);
         if (condition != null) {
             s_logger.info("Cannot delete counter " + counter.getName() + " as it is being used in a condition.");
             throw new ResourceInUseException("Counter is in use.");
         }
 
-        boolean success = _counterDao.remove(counterId);
+        final boolean success = _counterDao.remove(counterId);
         if (success) {
             s_logger.info("Successfully deleted counter with Id: " + counterId);
         }
@@ -1178,9 +1184,9 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_CONDITION_DELETE, eventDescription = "condition")
-    public boolean deleteCondition(long conditionId) throws ResourceInUseException {
+    public boolean deleteCondition(final long conditionId) throws ResourceInUseException {
         /* Check if entity is in database */
-        ConditionVO condition = getEntityInDatabase(CallContext.current().getCallingAccount(), "Condition", conditionId, _conditionDao);
+        final ConditionVO condition = getEntityInDatabase(CallContext.current().getCallingAccount(), "Condition", conditionId, _conditionDao);
         if (condition == null) {
             throw new InvalidParameterValueException("Unable to find Condition");
         }
@@ -1190,7 +1196,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             s_logger.info("Cannot delete condition " + conditionId + " as it is being used in a condition.");
             throw new ResourceInUseException("Cannot delete Condition when it is in use by one or more AutoScale Policies.");
         }
-        boolean success = _conditionDao.remove(conditionId);
+        final boolean success = _conditionDao.remove(conditionId);
         if (success) {
             s_logger.info("Successfully deleted condition " + condition.getId());
         }
@@ -1198,7 +1204,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     }
 
     @Override
-    public void cleanUpAutoScaleResources(Long accountId) {
+    public void cleanUpAutoScaleResources(final Long accountId) {
         // cleans Autoscale VmProfiles, AutoScale Policies and Conditions belonging to an account
         int count = 0;
         count = _autoScaleVmProfileDao.removeByAccountId(accountId);
@@ -1215,10 +1221,10 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
         }
     }
 
-    private boolean checkConditionUp(AutoScaleVmGroupVO asGroup, Integer numVm) {
+    private boolean checkConditionUp(final AutoScaleVmGroupVO asGroup, final Integer numVm) {
         // check maximum
-        Integer currentVM = _autoScaleVmGroupVmMapDao.countByGroup(asGroup.getId());
-        Integer maxVm = asGroup.getMaxMembers();
+        final Integer currentVM = _autoScaleVmGroupVmMapDao.countByGroup(asGroup.getId());
+        final Integer maxVm = asGroup.getMaxMembers();
         if (currentVM + numVm > maxVm) {
             s_logger.warn("number of VM will greater than the maximum in this group if scaling up, so do nothing more");
             return false;
@@ -1226,9 +1232,9 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
         return true;
     }
 
-    private boolean checkConditionDown(AutoScaleVmGroupVO asGroup) {
-        Integer currentVM = _autoScaleVmGroupVmMapDao.countByGroup(asGroup.getId());
-        Integer minVm = asGroup.getMinMembers();
+    private boolean checkConditionDown(final AutoScaleVmGroupVO asGroup) {
+        final Integer currentVM = _autoScaleVmGroupVmMapDao.countByGroup(asGroup.getId());
+        final Integer minVm = asGroup.getMinMembers();
         if (currentVM - 1 < minVm) {
             s_logger.warn("number of VM will less than the minimum in this group if scaling down, so do nothing more");
             return false;
@@ -1236,29 +1242,29 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
         return true;
     }
 
-    private long createNewVM(AutoScaleVmGroupVO asGroup) {
-        AutoScaleVmProfileVO profileVo = _autoScaleVmProfileDao.findById(asGroup.getProfileId());
-        long templateId = profileVo.getTemplateId();
-        long serviceOfferingId = profileVo.getServiceOfferingId();
+    private long createNewVM(final AutoScaleVmGroupVO asGroup) {
+        final AutoScaleVmProfileVO profileVo = _autoScaleVmProfileDao.findById(asGroup.getProfileId());
+        final long templateId = profileVo.getTemplateId();
+        final long serviceOfferingId = profileVo.getServiceOfferingId();
         if (templateId == -1) {
             return -1;
         }
         // create new VM into DB
         try {
             //Verify that all objects exist before passing them to the service
-            Account owner = _accountService.getActiveAccountById(profileVo.getAccountId());
+            final Account owner = _accountService.getActiveAccountById(profileVo.getAccountId());
 
-            DataCenter zone = _entityMgr.findById(DataCenter.class, profileVo.getZoneId());
+            final DataCenter zone = _entityMgr.findById(DataCenter.class, profileVo.getZoneId());
             if (zone == null) {
                 throw new InvalidParameterValueException("Unable to find zone by id=" + profileVo.getZoneId());
             }
 
-            ServiceOffering serviceOffering = _entityMgr.findById(ServiceOffering.class, serviceOfferingId);
+            final ServiceOffering serviceOffering = _entityMgr.findById(ServiceOffering.class, serviceOfferingId);
             if (serviceOffering == null) {
                 throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId);
             }
 
-            VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, templateId);
+            final VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, templateId);
             // Make sure a valid template ID was specified
             if (template == null) {
                 throw new InvalidParameterValueException("Unable to use template " + templateId);
@@ -1271,7 +1277,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             }
 
             UserVm vm = null;
-            IpAddresses addrs = new IpAddresses(null, null);
+            final IpAddresses addrs = new IpAddresses(null, null);
             if (zone.getNetworkType() == NetworkType.Basic) {
                 vm = _userVmService.createBasicSecurityGroupVirtualMachine(zone, serviceOffering, template, null, owner, "autoScaleVm-" + asGroup.getId() + "-" +
                     getCurrentTimeStampString(),
@@ -1297,41 +1303,41 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             } else {
                 return -1;
             }
-        } catch (InsufficientCapacityException ex) {
+        } catch (final InsufficientCapacityException ex) {
             s_logger.info(ex);
             s_logger.trace(ex.getMessage(), ex);
             throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage());
-        } catch (ResourceUnavailableException ex) {
+        } catch (final ResourceUnavailableException ex) {
             s_logger.warn("Exception: ", ex);
             throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
-        } catch (ConcurrentOperationException ex) {
+        } catch (final ConcurrentOperationException ex) {
             s_logger.warn("Exception: ", ex);
             throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
-        } catch (ResourceAllocationException ex) {
+        } catch (final ResourceAllocationException ex) {
             s_logger.warn("Exception: ", ex);
             throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
         }
     }
 
     private String getCurrentTimeStampString() {
-        Date current = new Date();
-        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+        final Date current = new Date();
+        final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
 
         return sdf.format(current);
     }
 
-    private boolean startNewVM(long vmId) {
+    private boolean startNewVM(final long vmId) {
         try {
             CallContext.current().setEventDetails("Vm Id: " + vmId);
             _userVmManager.startVirtualMachine(vmId, null, null);
-        } catch (ResourceUnavailableException ex) {
+        } catch (final ResourceUnavailableException ex) {
             s_logger.warn("Exception: ", ex);
             throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
-        } catch (ConcurrentOperationException ex) {
+        } catch (final ConcurrentOperationException ex) {
             s_logger.warn("Exception: ", ex);
             throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
-        } catch (InsufficientCapacityException ex) {
-            StringBuilder message = new StringBuilder(ex.getMessage());
+        } catch (final InsufficientCapacityException ex) {
+            final StringBuilder message = new StringBuilder(ex.getMessage());
             if (ex instanceof InsufficientServerCapacityException) {
                 if (((InsufficientServerCapacityException)ex).isAffinityApplied()) {
                     message.append(", Please check the affinity groups provided, there may not be sufficient capacity to follow them");
@@ -1344,14 +1350,14 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
         return true;
     }
 
-    private boolean assignLBruleToNewVm(long vmId, AutoScaleVmGroupVO asGroup) {
-        List<Long> lstVmId = new ArrayList<Long>();
-        long lbId = asGroup.getLoadBalancerId();
+    private boolean assignLBruleToNewVm(final long vmId, final AutoScaleVmGroupVO asGroup) {
+        final List<Long> lstVmId = new ArrayList<Long>();
+        final long lbId = asGroup.getLoadBalancerId();
 
-        List<LoadBalancerVMMapVO> LbVmMapVos = _lbVmMapDao.listByLoadBalancerId(lbId);
+        final List<LoadBalancerVMMapVO> LbVmMapVos = _lbVmMapDao.listByLoadBalancerId(lbId);
         if ((LbVmMapVos != null) && (LbVmMapVos.size() > 0)) {
-            for (LoadBalancerVMMapVO LbVmMapVo : LbVmMapVos) {
-                long instanceId = LbVmMapVo.getInstanceId();
+            for (final LoadBalancerVMMapVO LbVmMapVo : LbVmMapVos) {
+                final long instanceId = LbVmMapVo.getInstanceId();
                 if (instanceId == vmId) {
                     s_logger.warn("the new VM is already mapped to LB rule. What's wrong?");
                     return true;
@@ -1363,17 +1369,17 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     }
 
-    private long removeLBrule(AutoScaleVmGroupVO asGroup) {
-        long lbId = asGroup.getLoadBalancerId();
+    private long removeLBrule(final AutoScaleVmGroupVO asGroup) {
+        final long lbId = asGroup.getLoadBalancerId();
         long instanceId = -1;
-        List<LoadBalancerVMMapVO> LbVmMapVos = _lbVmMapDao.listByLoadBalancerId(lbId);
+        final List<LoadBalancerVMMapVO> LbVmMapVos = _lbVmMapDao.listByLoadBalancerId(lbId);
         if ((LbVmMapVos != null) && (LbVmMapVos.size() > 0)) {
-            for (LoadBalancerVMMapVO LbVmMapVo : LbVmMapVos) {
+            for (final LoadBalancerVMMapVO LbVmMapVo : LbVmMapVos) {
                 instanceId = LbVmMapVo.getInstanceId();
             }
         }
         // take last VM out of the list
-        List<Long> lstVmId = new ArrayList<Long>();
+        final List<Long> lstVmId = new ArrayList<Long>();
         if (instanceId != -1)
             lstVmId.add(instanceId);
         if (_loadBalancingRulesService.removeFromLoadBalancer(lbId, lstVmId))
@@ -1383,8 +1389,8 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
     }
 
     @Override
-    public void doScaleUp(long groupId, Integer numVm) {
-        AutoScaleVmGroupVO asGroup = _autoScaleVmGroupDao.findById(groupId);
+    public void doScaleUp(final long groupId, final Integer numVm) {
+        final AutoScaleVmGroupVO asGroup = _autoScaleVmGroupDao.findById(groupId);
         if (asGroup == null) {
             s_logger.error("Can not find the groupid " + groupId + " for scaling up");
             return;
@@ -1393,7 +1399,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             return;
         }
         for (int i = 0; i < numVm; i++) {
-            long vmId = createNewVM(asGroup);
+            final long vmId = createNewVM(asGroup);
             if (vmId == -1) {
                 s_logger.error("Can not deploy new VM for scaling up in the group "
                     + asGroup.getId() + ". Waiting for next round");
@@ -1402,14 +1408,14 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             if (startNewVM(vmId)) {
                 if (assignLBruleToNewVm(vmId, asGroup)) {
                     // persist to DB
-                    AutoScaleVmGroupVmMapVO GroupVmVO = new AutoScaleVmGroupVmMapVO(
+                    final AutoScaleVmGroupVmMapVO GroupVmVO = new AutoScaleVmGroupVmMapVO(
                         asGroup.getId(), vmId);
                     _autoScaleVmGroupVmMapDao.persist(GroupVmVO);
                     // update last_quiettime
-                    List<AutoScaleVmGroupPolicyMapVO> GroupPolicyVOs = _autoScaleVmGroupPolicyMapDao
+                    final List<AutoScaleVmGroupPolicyMapVO> GroupPolicyVOs = _autoScaleVmGroupPolicyMapDao
                         .listByVmGroupId(groupId);
-                    for (AutoScaleVmGroupPolicyMapVO GroupPolicyVO : GroupPolicyVOs) {
-                        AutoScalePolicyVO vo = _autoScalePolicyDao
+                    for (final AutoScaleVmGroupPolicyMapVO GroupPolicyVO : GroupPolicyVOs) {
+                        final AutoScalePolicyVO vo = _autoScalePolicyDao
                             .findById(GroupPolicyVO.getPolicyId());
                         if (vo.getAction().equals("scaleup")) {
                             vo.setLastQuiteTime(new Date());
@@ -1431,7 +1437,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
     @Override
     public void doScaleDown(final long groupId) {
-        AutoScaleVmGroupVO asGroup = _autoScaleVmGroupDao.findById(groupId);
+        final AutoScaleVmGroupVO asGroup = _autoScaleVmGroupDao.findById(groupId);
         if (asGroup == null) {
             s_logger.error("Can not find the groupid " + groupId + " for scaling up");
             return;
@@ -1441,14 +1447,14 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
         }
         final long vmId = removeLBrule(asGroup);
         if (vmId != -1) {
-            long profileId = asGroup.getProfileId();
+            final long profileId = asGroup.getProfileId();
 
             // update group-vm mapping
             _autoScaleVmGroupVmMapDao.remove(groupId, vmId);
             // update last_quiettime
-            List<AutoScaleVmGroupPolicyMapVO> GroupPolicyVOs = _autoScaleVmGroupPolicyMapDao.listByVmGroupId(groupId);
-            for (AutoScaleVmGroupPolicyMapVO GroupPolicyVO : GroupPolicyVOs) {
-                AutoScalePolicyVO vo = _autoScalePolicyDao.findById(GroupPolicyVO.getPolicyId());
+            final List<AutoScaleVmGroupPolicyMapVO> GroupPolicyVOs = _autoScaleVmGroupPolicyMapDao.listByVmGroupId(groupId);
+            for (final AutoScaleVmGroupPolicyMapVO GroupPolicyVO : GroupPolicyVOs) {
+                final AutoScalePolicyVO vo = _autoScalePolicyDao.findById(GroupPolicyVO.getPolicyId());
                 if (vo.getAction().equals("scaledown")) {
                     vo.setLastQuiteTime(new Date());
                     _autoScalePolicyDao.persist(vo);
@@ -1457,8 +1463,8 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
             }
 
             // get destroyvmgrace param
-            AutoScaleVmProfileVO asProfile = _autoScaleVmProfileDao.findById(profileId);
-            Integer destroyVmGracePeriod = asProfile.getDestroyVmGraceperiod();
+            final AutoScaleVmProfileVO asProfile = _autoScaleVmProfileDao.findById(profileId);
+            final Integer destroyVmGracePeriod = asProfile.getDestroyVmGraceperiod();
             if (destroyVmGracePeriod >= 0) {
                 _executor.schedule(new Runnable() {
                     @Override
@@ -1467,9 +1473,9 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
 
                             _userVmManager.destroyVm(vmId);
 
-                        } catch (ResourceUnavailableException e) {
+                        } catch (final ResourceUnavailableException e) {
                             e.printStackTrace();
-                        } catch (ConcurrentOperationException e) {
+                        } catch (final ConcurrentOperationException e) {
                             e.printStackTrace();
                         }
                     }


[5/6] CLOUDSTACK-6003 fixing plus refactoring dispatcher

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/ApiServer.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java
index d715db6..290e9de 100755
--- a/server/src/com/cloud/api/ApiServer.java
+++ b/server/src/com/cloud/api/ApiServer.java
@@ -43,8 +43,6 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
@@ -86,6 +84,7 @@ import org.springframework.stereotype.Component;
 
 import org.apache.cloudstack.acl.APIChecker;
 import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.ApiErrorCode;
 import org.apache.cloudstack.api.BaseAsyncCmd;
 import org.apache.cloudstack.api.BaseAsyncCreateCmd;
@@ -122,6 +121,7 @@ import org.apache.cloudstack.framework.jobs.AsyncJobManager;
 import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
 import org.apache.cloudstack.managed.context.ManagedContextRunnable;
 
+import com.cloud.api.dispatch.DispatchChainFactory;
 import com.cloud.api.response.ApiResponseSerializer;
 import com.cloud.configuration.Config;
 import com.cloud.domain.Domain;
@@ -159,12 +159,14 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
     private static final Logger s_logger = Logger.getLogger(ApiServer.class.getName());
     private static final Logger s_accessLogger = Logger.getLogger("apiserver." + ApiServer.class.getName());
 
-    private static boolean encodeApiResponse = false;
-    private static String jsonContentType = "text/javascript";
-    private static String controlCharacters = "[\000-\011\013-\014\016-\037\177]"; // Non-printable ASCII characters - numbers 0 to 31 and 127 decimal
-    @Inject ApiDispatcher _dispatcher;
+    public static boolean encodeApiResponse = false;
+    public static String jsonContentType = "text/javascript";
 
     @Inject
+    protected ApiDispatcher _dispatcher;
+    @Inject()
+    protected DispatchChainFactory dispatchChainFactory = null;
+    @Inject
     private AccountManager _accountMgr;
     @Inject
     private DomainManager _domainMgr;
@@ -191,27 +193,27 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
     }
 
     @Override
-    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+    public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
         return true;
     }
 
     @Override
     public boolean start() {
         Integer apiPort = null; // api port, null by default
-        SearchCriteria<ConfigurationVO> sc = _configDao.createSearchCriteria();
+        final SearchCriteria<ConfigurationVO> sc = _configDao.createSearchCriteria();
         sc.addAnd("name", SearchCriteria.Op.EQ, Config.IntegrationAPIPort.key());
-        List<ConfigurationVO> values = _configDao.search(sc, null);
+        final List<ConfigurationVO> values = _configDao.search(sc, null);
         if ((values != null) && (values.size() > 0)) {
-            ConfigurationVO apiPortConfig = values.get(0);
+            final ConfigurationVO apiPortConfig = values.get(0);
             if (apiPortConfig.getValue() != null) {
                 apiPort = Integer.parseInt(apiPortConfig.getValue());
             }
         }
 
-        Map<String, String> configs = _configDao.getConfiguration();
-        String strSnapshotLimit = configs.get(Config.ConcurrentSnapshotsThresholdPerHost.key());
+        final Map<String, String> configs = _configDao.getConfiguration();
+        final String strSnapshotLimit = configs.get(Config.ConcurrentSnapshotsThresholdPerHost.key());
         if (strSnapshotLimit != null) {
-            Long snapshotLimit = NumbersUtil.parseLong(strSnapshotLimit, 1L);
+            final Long snapshotLimit = NumbersUtil.parseLong(strSnapshotLimit, 1L);
             if (snapshotLimit.longValue() <= 0) {
                 s_logger.debug("Global config parameter " + Config.ConcurrentSnapshotsThresholdPerHost.toString() + " is less or equal 0; defaulting to unlimited");
             } else {
@@ -219,20 +221,20 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             }
         }
 
-        Set<Class<?>> cmdClasses = new HashSet<Class<?>>();
-        for (PluggableService pluggableService : _pluggableServices) {
+        final Set<Class<?>> cmdClasses = new HashSet<Class<?>>();
+        for (final PluggableService pluggableService : _pluggableServices) {
             cmdClasses.addAll(pluggableService.getCommands());
             if (s_logger.isDebugEnabled()) {
                 s_logger.debug("Discovered plugin " + pluggableService.getClass().getSimpleName());
             }
         }
 
-        for (Class<?> cmdClass : cmdClasses) {
-            APICommand at = cmdClass.getAnnotation(APICommand.class);
+        for (final Class<?> cmdClass : cmdClasses) {
+            final APICommand at = cmdClass.getAnnotation(APICommand.class);
             if (at == null) {
                 throw new CloudRuntimeException(String.format("%s is claimed as a API command, but it doesn't have @APICommand annotation", cmdClass.getName()));
             }
-            String apiName = at.name();
+            final String apiName = at.name();
             if (s_apiNameCmdClassMap.containsKey(apiName)) {
                 s_logger.error("API Cmd class " + cmdClass.getName() + " has non-unique apiname" + apiName);
                 continue;
@@ -241,13 +243,13 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
         }
 
         setEncodeApiResponse(Boolean.valueOf(_configDao.getValue(Config.EncodeApiResponse.key())));
-        String jsonType = _configDao.getValue(Config.JavaScriptDefaultContentType.key());
+        final String jsonType = _configDao.getValue(Config.JavaScriptDefaultContentType.key());
         if (jsonType != null) {
             jsonContentType = jsonType;
         }
 
         if (apiPort != null) {
-            ListenerThread listenerThread = new ListenerThread(this, apiPort);
+            final ListenerThread listenerThread = new ListenerThread(this, apiPort);
             listenerThread.start();
         }
 
@@ -258,13 +260,13 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
     // If integration api port is not configured, actual OTW requests will be received by ApiServlet
     @SuppressWarnings({"unchecked", "rawtypes"})
     @Override
-    public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
+    public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) throws HttpException, IOException {
 
         // Create StringBuffer to log information in access log
-        StringBuffer sb = new StringBuffer();
-        HttpServerConnection connObj = (HttpServerConnection)context.getAttribute("http.connection");
+        final StringBuffer sb = new StringBuffer();
+        final HttpServerConnection connObj = (HttpServerConnection)context.getAttribute("http.connection");
         if (connObj instanceof SocketHttpServerConnection) {
-            InetAddress remoteAddr = ((SocketHttpServerConnection)connObj).getRemoteAddress();
+            final InetAddress remoteAddr = ((SocketHttpServerConnection)connObj).getRemoteAddress();
             sb.append(remoteAddr.toString() + " -- ");
         }
         sb.append(StringUtils.cleanString(request.getRequestLine().toString()));
@@ -273,7 +275,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             List<NameValuePair> paramList = null;
             try {
                 paramList = URLEncodedUtils.parse(new URI(request.getRequestLine().getUri()), "UTF-8");
-            } catch (URISyntaxException e) {
+            } catch (final URISyntaxException e) {
                 s_logger.error("Error parsing url request", e);
             }
 
@@ -282,9 +284,9 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             // APITODO: Use Guava's (import com.google.common.collect.Multimap;)
             // (Immutable)Multimap<String, String> paramMultiMap = HashMultimap.create();
             // Map<String, Collection<String>> parameterMap = paramMultiMap.asMap();
-            Map parameterMap = new HashMap<String, String[]>();
+            final Map parameterMap = new HashMap<String, String[]>();
             String responseType = BaseCmd.RESPONSE_TYPE_XML;
-            for (NameValuePair param : paramList) {
+            for (final NameValuePair param : paramList) {
                 if (param.getName().equalsIgnoreCase("response")) {
                     responseType = param.getValue();
                     continue;
@@ -304,15 +306,15 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
                 // always trust commands from API port, user context will always be UID_SYSTEM/ACCOUNT_ID_SYSTEM
                 CallContext.register(_accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
                 sb.insert(0, "(userId=" + User.UID_SYSTEM + " accountId=" + Account.ACCOUNT_ID_SYSTEM + " sessionId=" + null + ") ");
-                String responseText = handleRequest(parameterMap, responseType, sb);
+                final String responseText = handleRequest(parameterMap, responseType, sb);
                 sb.append(" 200 " + ((responseText == null) ? 0 : responseText.length()));
 
                 writeResponse(response, responseText, HttpStatus.SC_OK, responseType, null);
-            } catch (ServerApiException se) {
-                String responseText = getSerializedApiError(se, parameterMap, responseType);
+            } catch (final ServerApiException se) {
+                final String responseText = getSerializedApiError(se, parameterMap, responseType);
                 writeResponse(response, responseText, se.getErrorCode().getHttpCode(), responseType, se.getDescription());
                 sb.append(" " + se.getErrorCode() + " " + se.getDescription());
-            } catch (RuntimeException e) {
+            } catch (final RuntimeException e) {
                 // log runtime exception like NullPointerException to help identify the source easier
                 s_logger.error("Unhandled exception, ", e);
                 throw e;
@@ -325,77 +327,70 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
 
     @Override
     @SuppressWarnings("rawtypes")
-    public String handleRequest(Map params, String responseType, StringBuffer auditTrailSb) throws ServerApiException {
+    public String handleRequest(final Map rawParams, final String responseType, final StringBuffer auditTrailSb) throws ServerApiException {
+        final Map<String, Object> params = ParameterHandler.unpackParams(rawParams);
+
         String response = null;
-        String[] command = null;
+        String command = null;
 
         try {
-            command = (String[])params.get("command");
+            command = (String) params.get(ApiConstants.COMMAND);
             if (command == null) {
                 s_logger.error("invalid request, no command sent");
                 if (s_logger.isTraceEnabled()) {
                     s_logger.trace("dumping request parameters");
-                    for (Object key : params.keySet()) {
-                        String keyStr = (String)key;
-                        String[] value = (String[])params.get(key);
-                        s_logger.trace("   key: " + keyStr + ", value: " + ((value == null) ? "'null'" : value[0]));
+                    for (final Object key : params.keySet()) {
+                        final String keyStr = (String)key;
+                        final Object value = params.get(key);
+                        s_logger.trace("   key: " + keyStr + ", value: " + ((value == null) ? "'null'" : value));
                     }
                 }
                 throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "Invalid request, no command sent");
             } else {
-                Map<String, String> paramMap = new HashMap<String, String>();
-                Set keys = params.keySet();
-                Iterator keysIter = keys.iterator();
+                final Map<String, String> paramMap = new HashMap<String, String>();
+                final Set keys = rawParams.keySet();
+                final Iterator keysIter = keys.iterator();
                 while (keysIter.hasNext()) {
-                    String key = (String)keysIter.next();
+                    final String key = (String)keysIter.next();
                     if ("command".equalsIgnoreCase(key)) {
                         continue;
                     }
-                    String[] value = (String[])params.get(key);
-                    // fail if parameter value contains ASCII control (non-printable) characters
-                    if (value[0] != null) {
-                        Pattern pattern = Pattern.compile(controlCharacters);
-                        Matcher matcher = pattern.matcher(value[0]);
-                        if (matcher.find()) {
-                            throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Received value " + value[0] + " for parameter " + key +
-                                " is invalid, contains illegal ASCII non-printable characters");
-                        }
-                    }
+                    final String[] value = (String[])rawParams.get(key);
                     paramMap.put(key, value[0]);
                 }
 
-                Class<?> cmdClass = getCmdClass(command[0]);
+                final Class<?> cmdClass = getCmdClass(command);
                 if (cmdClass != null) {
                     BaseCmd cmdObj = (BaseCmd)cmdClass.newInstance();
                     cmdObj = ComponentContext.inject(cmdObj);
                     cmdObj.configure();
                     cmdObj.setFullUrlParams(paramMap);
                     cmdObj.setResponseType(responseType);
-                    cmdObj.setHttpMethod(paramMap.get("httpmethod").toString());
+                    cmdObj.setHttpMethod(params.get(ApiConstants.HTTPMETHOD).toString());
 
                     // This is where the command is either serialized, or directly dispatched
-                    response = queueCommand(cmdObj, paramMap);
-                    buildAuditTrail(auditTrailSb, command[0], response);
+                    response = queueCommand(cmdObj, params);
+                    buildAuditTrail(auditTrailSb, command, response);
                 } else {
-                    if (!command[0].equalsIgnoreCase("login") && !command[0].equalsIgnoreCase("logout")) {
-                        String errorString = "Unknown API command: " + command[0];
+                    if (!command.equalsIgnoreCase("login") && !command.equalsIgnoreCase("logout")) {
+                        final String errorString = "Unknown API command: " + command;
                         s_logger.warn(errorString);
                         auditTrailSb.append(" " + errorString);
                         throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, errorString);
                     }
                 }
             }
-        } catch (InvalidParameterValueException ex) {
+        } catch (final InvalidParameterValueException ex) {
             s_logger.info(ex.getMessage());
             throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex);
-        } catch (IllegalArgumentException ex) {
+        } catch (final IllegalArgumentException ex) {
             s_logger.info(ex.getMessage());
             throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex);
-        } catch (PermissionDeniedException ex) {
-            ArrayList<ExceptionProxyObject> idList = ex.getIdProxyList();
+        } catch (final PermissionDeniedException ex) {
+            final ArrayList<ExceptionProxyObject> idList = ex.getIdProxyList();
             if (idList != null) {
-                StringBuffer buf = new StringBuffer();
-                for (ExceptionProxyObject obj : idList) {
+                final StringBuffer buf = new StringBuffer();
+                for (final ExceptionProxyObject obj : idList) {
                     buf.append(obj.getDescription());
                     buf.append(":");
                     buf.append(obj.getUuid());
@@ -406,10 +401,10 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
                 s_logger.info("PermissionDenied: " + ex.getMessage());
             }
             throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, ex.getMessage(), ex);
-        } catch (AccountLimitException ex) {
+        } catch (final AccountLimitException ex) {
             s_logger.info(ex.getMessage());
             throw new ServerApiException(ApiErrorCode.ACCOUNT_RESOURCE_LIMIT_ERROR, ex.getMessage(), ex);
-        } catch (InsufficientCapacityException ex) {
+        } catch (final InsufficientCapacityException ex) {
             s_logger.info(ex.getMessage());
             String errorMsg = ex.getMessage();
             if (CallContext.current().getCallingAccount().getType() != Account.ACCOUNT_TYPE_ADMIN) {
@@ -417,10 +412,10 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
                 errorMsg = BaseCmd.USER_ERROR_MESSAGE;
             }
             throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg, ex);
-        } catch (ResourceAllocationException ex) {
+        } catch (final ResourceAllocationException ex) {
             s_logger.info(ex.getMessage());
             throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage(), ex);
-        } catch (ResourceUnavailableException ex) {
+        } catch (final ResourceUnavailableException ex) {
             s_logger.info(ex.getMessage());
             String errorMsg = ex.getMessage();
             if (CallContext.current().getCallingAccount().getType() != Account.ACCOUNT_TYPE_ADMIN) {
@@ -428,11 +423,11 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
                 errorMsg = BaseCmd.USER_ERROR_MESSAGE;
             }
             throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, errorMsg, ex);
-        } catch (ServerApiException ex) {
+        } catch (final ServerApiException ex) {
             s_logger.info(ex.getDescription());
             throw ex;
-        } catch (Exception ex) {
-            s_logger.error("unhandled exception executing api command: " + ((command == null) ? "null" : command[0]), ex);
+        } catch (final Exception ex) {
+            s_logger.error("unhandled exception executing api command: " + ((command == null) ? "null" : command), ex);
             String errorMsg = ex.getMessage();
             if (CallContext.current().getCallingAccount().getType() != Account.ACCOUNT_TYPE_ADMIN) {
                 // hide internal details to non-admin user for security reason
@@ -444,28 +439,28 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
         return response;
     }
 
-    private String getBaseAsyncResponse(long jobId, BaseAsyncCmd cmd) {
-        AsyncJobResponse response = new AsyncJobResponse();
+    private String getBaseAsyncResponse(final long jobId, final BaseAsyncCmd cmd) {
+        final AsyncJobResponse response = new AsyncJobResponse();
 
-        AsyncJob job = _entityMgr.findById(AsyncJob.class, jobId);
+        final AsyncJob job = _entityMgr.findById(AsyncJob.class, jobId);
         response.setJobId(job.getUuid());
         response.setResponseName(cmd.getCommandName());
         return ApiResponseSerializer.toSerializedString(response, cmd.getResponseType());
     }
 
-    private String getBaseAsyncCreateResponse(long jobId, BaseAsyncCreateCmd cmd, String objectUuid) {
-        CreateCmdResponse response = new CreateCmdResponse();
-        AsyncJob job = _entityMgr.findById(AsyncJob.class, jobId);
+    private String getBaseAsyncCreateResponse(final long jobId, final BaseAsyncCreateCmd cmd, final String objectUuid) {
+        final CreateCmdResponse response = new CreateCmdResponse();
+        final AsyncJob job = _entityMgr.findById(AsyncJob.class, jobId);
         response.setJobId(job.getUuid());
         response.setId(objectUuid);
         response.setResponseName(cmd.getCommandName());
         return ApiResponseSerializer.toSerializedString(response, cmd.getResponseType());
     }
 
-    private String queueCommand(BaseCmd cmdObj, Map<String, String> params) throws Exception {
-        CallContext ctx = CallContext.current();
-        Long callerUserId = ctx.getCallingUserId();
-        Account caller = ctx.getCallingAccount();
+    private String queueCommand(final BaseCmd cmdObj, final Map<String, Object> params) throws Exception {
+        final CallContext ctx = CallContext.current();
+        final Long callerUserId = ctx.getCallingUserId();
+        final Account caller = ctx.getCallingAccount();
 
         // Queue command based on Cmd super class:
         // BaseCmd: cmd is dispatched to ApiDispatcher, executed, serialized and returned.
@@ -475,16 +470,16 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             Long objectId = null;
             String objectUuid = null;
             if (cmdObj instanceof BaseAsyncCreateCmd) {
-                BaseAsyncCreateCmd createCmd = (BaseAsyncCreateCmd)cmdObj;
+                final BaseAsyncCreateCmd createCmd = (BaseAsyncCreateCmd)cmdObj;
                 _dispatcher.dispatchCreateCmd(createCmd, params);
                 objectId = createCmd.getEntityId();
                 objectUuid = createCmd.getEntityUuid();
                 params.put("id", objectId.toString());
             } else {
-                ApiDispatcher.processParameters(cmdObj, params);
+                dispatchChainFactory.getStandardDispatchChain().dispatch(cmdObj, params);
             }
 
-            BaseAsyncCmd asyncCmd = (BaseAsyncCmd)cmdObj;
+            final BaseAsyncCmd asyncCmd = (BaseAsyncCmd)cmdObj;
 
             if (callerUserId != null) {
                 params.put("ctxUserId", callerUserId.toString());
@@ -497,7 +492,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             asyncCmd.setStartEventId(startEventId);
 
             // save the scheduled event
-            Long eventId =
+            final Long eventId =
                 ActionEventUtils.onScheduledActionEvent((callerUserId == null) ? User.UID_SYSTEM : callerUserId, asyncCmd.getEntityOwnerId(), asyncCmd.getEventType(),
                     asyncCmd.getEventDescription(), startEventId);
             if (startEventId == 0) {
@@ -508,22 +503,22 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             params.put("ctxStartEventId", String.valueOf(startEventId));
             params.put("cmdEventType", asyncCmd.getEventType().toString());
 
-            Long instanceId = (objectId == null) ? asyncCmd.getInstanceId() : objectId;
-            AsyncJobVO job =
+            final Long instanceId = (objectId == null) ? asyncCmd.getInstanceId() : objectId;
+            final AsyncJobVO job =
                 new AsyncJobVO(ctx.getContextId(), callerUserId, caller.getId(), cmdObj.getClass().getName(), ApiGsonHelper.getBuilder().create().toJson(params),
                     instanceId, asyncCmd.getInstanceType() != null ? asyncCmd.getInstanceType().toString() : null);
             job.setDispatcher(_asyncDispatcher.getName());
 
-            long jobId = _asyncMgr.submitAsyncJob(job);
+            final long jobId = _asyncMgr.submitAsyncJob(job);
 
             if (jobId == 0L) {
-                String errorMsg = "Unable to schedule async job for command " + job.getCmd();
+                final String errorMsg = "Unable to schedule async job for command " + job.getCmd();
                 s_logger.warn(errorMsg);
                 throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg);
             }
 
             if (objectId != null) {
-                String objUuid = (objectUuid == null) ? objectId.toString() : objectUuid;
+                final String objUuid = (objectUuid == null) ? objectId.toString() : objectUuid;
                 return getBaseAsyncCreateResponse(jobId, (BaseAsyncCreateCmd)asyncCmd, objUuid);
             } else {
                 SerializationContext.current().setUuidTranslation(true);
@@ -550,8 +545,8 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
     }
 
     @SuppressWarnings("unchecked")
-    private void buildAsyncListResponse(BaseListCmd command, Account account) {
-        List<ResponseObject> responses = ((ListResponse)command.getResponseObject()).getResponses();
+    private void buildAsyncListResponse(final BaseListCmd command, final Account account) {
+        final List<ResponseObject> responses = ((ListResponse)command.getResponseObject()).getResponses();
         if (responses != null && responses.size() > 0) {
             List<? extends AsyncJob> jobs = null;
 
@@ -566,18 +561,18 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
                 return;
             }
 
-            Map<String, AsyncJob> objectJobMap = new HashMap<String, AsyncJob>();
-            for (AsyncJob job : jobs) {
+            final Map<String, AsyncJob> objectJobMap = new HashMap<String, AsyncJob>();
+            for (final AsyncJob job : jobs) {
                 if (job.getInstanceId() == null) {
                     continue;
                 }
-                String instanceUuid = ApiDBUtils.findJobInstanceUuid(job);
+                final String instanceUuid = ApiDBUtils.findJobInstanceUuid(job);
                 objectJobMap.put(instanceUuid, job);
             }
 
-            for (ResponseObject response : responses) {
+            for (final ResponseObject response : responses) {
                 if (response.getObjectId() != null && objectJobMap.containsKey(response.getObjectId())) {
-                    AsyncJob job = objectJobMap.get(response.getObjectId());
+                    final AsyncJob job = objectJobMap.get(response.getObjectId());
                     response.setJobId(job.getUuid());
                     response.setJobStatus(job.getStatus().ordinal());
                 }
@@ -585,7 +580,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
         }
     }
 
-    private void buildAuditTrail(StringBuffer auditTrailSb, String command, String result) {
+    private void buildAuditTrail(final StringBuffer auditTrailSb, final String command, final String result) {
         if (result == null) {
             return;
         }
@@ -598,31 +593,31 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
     }
 
     @Override
-    public boolean verifyRequest(Map<String, Object[]> requestParameters, Long userId) throws ServerApiException {
+    public boolean verifyRequest(final Map<String, Object[]> requestParameters, final Long userId) throws ServerApiException {
         try {
             String apiKey = null;
             String secretKey = null;
             String signature = null;
             String unsignedRequest = null;
 
-            String[] command = (String[])requestParameters.get("command");
+            final String[] command = (String[])requestParameters.get(ApiConstants.COMMAND);
             if (command == null) {
                 s_logger.info("missing command, ignoring request...");
                 return false;
             }
 
-            String commandName = command[0];
+            final String commandName = command[0];
 
             // if userId not null, that mean that user is logged in
             if (userId != null) {
-                User user = ApiDBUtils.findUserById(userId);
+                final User user = ApiDBUtils.findUserById(userId);
 
                 try {
                     checkCommandAvailable(user, commandName);
-                } catch (RequestLimitException ex) {
+                } catch (final RequestLimitException ex) {
                     s_logger.debug(ex.getMessage());
                     throw new ServerApiException(ApiErrorCode.API_LIMIT_EXCEED, ex.getMessage());
-                } catch (PermissionDeniedException ex) {
+                } catch (final PermissionDeniedException ex) {
                     s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user with id:" + userId);
                     throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "The given command does not exist or it is not available for user");
                 }
@@ -637,9 +632,9 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
 
             // - build a request string with sorted params, make sure it's all lowercase
             // - sign the request, verify the signature is the same
-            List<String> parameterNames = new ArrayList<String>();
+            final List<String> parameterNames = new ArrayList<String>();
 
-            for (Object paramNameObj : requestParameters.keySet()) {
+            for (final Object paramNameObj : requestParameters.keySet()) {
                 parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
             }
 
@@ -648,9 +643,9 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             String signatureVersion = null;
             String expires = null;
 
-            for (String paramName : parameterNames) {
+            for (final String paramName : parameterNames) {
                 // parameters come as name/value pairs in the form String/String[]
-                String paramValue = ((String[])requestParameters.get(paramName))[0];
+                final String paramValue = ((String[])requestParameters.get(paramName))[0];
 
                 if ("signature".equalsIgnoreCase(paramName)) {
                     signature = paramValue;
@@ -688,30 +683,30 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
                 synchronized (DateFormatToUse) {
                     try {
                         expiresTS = DateFormatToUse.parse(expires);
-                    } catch (ParseException pe) {
+                    } catch (final ParseException pe) {
                         s_logger.debug("Incorrect date format for Expires parameter", pe);
                         return false;
                     }
                 }
-                Date now = new Date(System.currentTimeMillis());
+                final Date now = new Date(System.currentTimeMillis());
                 if (expiresTS.before(now)) {
                     s_logger.debug("Request expired -- ignoring ...sig: " + signature + ", apiKey: " + apiKey);
                     return false;
                 }
             }
 
-            TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
+            final TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
             txn.close();
             User user = null;
             // verify there is a user with this api key
-            Pair<User, Account> userAcctPair = _accountMgr.findUserByApiKey(apiKey);
+            final Pair<User, Account> userAcctPair = _accountMgr.findUserByApiKey(apiKey);
             if (userAcctPair == null) {
                 s_logger.debug("apiKey does not map to a valid user -- ignoring request, apiKey: " + apiKey);
                 return false;
             }
 
             user = userAcctPair.first();
-            Account account = userAcctPair.second();
+            final Account account = userAcctPair.second();
 
             if (user.getState() != Account.State.enabled || !account.getState().equals(Account.State.enabled)) {
                 s_logger.info("disabled or locked user accessing the api, userid = " + user.getId() + "; name = " + user.getUsername() + "; state: " + user.getState() +
@@ -721,10 +716,10 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
 
             try {
                 checkCommandAvailable(user, commandName);
-            } catch (RequestLimitException ex) {
+            } catch (final RequestLimitException ex) {
                 s_logger.debug(ex.getMessage());
                 throw new ServerApiException(ApiErrorCode.API_LIMIT_EXCEED, ex.getMessage());
-            } catch (PermissionDeniedException ex) {
+            } catch (final PermissionDeniedException ex) {
                 s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user");
                 throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "The given command:" + commandName + " does not exist or it is not available for user with id:"
                         + userId);
@@ -739,30 +734,30 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
 
             unsignedRequest = unsignedRequest.toLowerCase();
 
-            Mac mac = Mac.getInstance("HmacSHA1");
-            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1");
+            final Mac mac = Mac.getInstance("HmacSHA1");
+            final SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1");
             mac.init(keySpec);
             mac.update(unsignedRequest.getBytes());
-            byte[] encryptedBytes = mac.doFinal();
-            String computedSignature = Base64.encodeBase64String(encryptedBytes);
-            boolean equalSig = signature.equals(computedSignature);
+            final byte[] encryptedBytes = mac.doFinal();
+            final String computedSignature = Base64.encodeBase64String(encryptedBytes);
+            final boolean equalSig = signature.equals(computedSignature);
             if (!equalSig) {
                 s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
             } else {
                 CallContext.register(user, account);
             }
             return equalSig;
-        } catch (ServerApiException ex) {
+        } catch (final ServerApiException ex) {
             throw ex;
-        } catch (Exception ex) {
+        } catch (final Exception ex) {
             s_logger.error("unable to verify request signature");
         }
         return false;
     }
 
     @Override
-    public Long fetchDomainId(String domainUUID) {
-        Domain domain = _domainMgr.getDomain(domainUUID);
+    public Long fetchDomainId(final String domainUUID) {
+        final Domain domain = _domainMgr.getDomain(domainUUID);
         if (domain != null)
             return domain.getId();
         else
@@ -770,15 +765,15 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
     }
 
     @Override
-    public void loginUser(HttpSession session, String username, String password, Long domainId, String domainPath, String loginIpAddress,
-        Map<String, Object[]> requestParameters) throws CloudAuthenticationException {
+    public void loginUser(final HttpSession session, final String username, final String password, Long domainId, final String domainPath, final String loginIpAddress,
+        final Map<String, Object[]> requestParameters) throws CloudAuthenticationException {
         // We will always use domainId first. If that does not exist, we will use domain name. If THAT doesn't exist
         // we will default to ROOT
         if (domainId == null) {
             if (domainPath == null || domainPath.trim().length() == 0) {
                 domainId = Domain.ROOT_DOMAIN;
             } else {
-                Domain domainObj = _domainMgr.findDomainByPath(domainPath);
+                final Domain domainObj = _domainMgr.findDomainByPath(domainPath);
                 if (domainObj != null) {
                     domainId = domainObj.getId();
                 } else { // if an unknown path is passed in, fail the login call
@@ -787,26 +782,26 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             }
         }
 
-        UserAccount userAcct = _accountMgr.authenticateUser(username, password, domainId, loginIpAddress, requestParameters);
+        final UserAccount userAcct = _accountMgr.authenticateUser(username, password, domainId, loginIpAddress, requestParameters);
         if (userAcct != null) {
-            String timezone = userAcct.getTimezone();
+            final String timezone = userAcct.getTimezone();
             float offsetInHrs = 0f;
             if (timezone != null) {
-                TimeZone t = TimeZone.getTimeZone(timezone);
+                final TimeZone t = TimeZone.getTimeZone(timezone);
                 s_logger.info("Current user logged in under " + timezone + " timezone");
 
-                java.util.Date date = new java.util.Date();
-                long longDate = date.getTime();
-                float offsetInMs = (t.getOffset(longDate));
+                final java.util.Date date = new java.util.Date();
+                final long longDate = date.getTime();
+                final float offsetInMs = (t.getOffset(longDate));
                 offsetInHrs = offsetInMs / (1000 * 60 * 60);
                 s_logger.info("Timezone offset from UTC is: " + offsetInHrs);
             }
 
-            Account account = _accountMgr.getAccount(userAcct.getAccountId());
+            final Account account = _accountMgr.getAccount(userAcct.getAccountId());
 
             // set the userId and account object for everyone
             session.setAttribute("userid", userAcct.getId());
-            UserVO user = (UserVO)_accountMgr.getActiveUser(userAcct.getId());
+            final UserVO user = (UserVO)_accountMgr.getActiveUser(userAcct.getId());
             if (user.getUuid() != null) {
                 session.setAttribute("user_UUID", user.getUuid());
             }
@@ -818,7 +813,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             session.setAttribute("account", account.getAccountName());
 
             session.setAttribute("domainid", account.getDomainId());
-            DomainVO domain = (DomainVO)_domainMgr.getDomain(account.getDomainId());
+            final DomainVO domain = (DomainVO)_domainMgr.getDomain(account.getDomainId());
             if (domain.getUuid() != null) {
                 session.setAttribute("domain_UUID", domain.getUuid());
             }
@@ -834,10 +829,10 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
 
             // (bug 5483) generate a session key that the user must submit on every request to prevent CSRF, add that
             // to the login response so that session-based authenticators know to send the key back
-            SecureRandom sesssionKeyRandom = new SecureRandom();
-            byte sessionKeyBytes[] = new byte[20];
+            final SecureRandom sesssionKeyRandom = new SecureRandom();
+            final byte sessionKeyBytes[] = new byte[20];
             sesssionKeyRandom.nextBytes(sessionKeyBytes);
-            String sessionKey = Base64.encodeBase64String(sessionKeyBytes);
+            final String sessionKey = Base64.encodeBase64String(sessionKeyBytes);
             session.setAttribute("sessionkey", sessionKey);
 
             return;
@@ -846,14 +841,14 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
     }
 
     @Override
-    public void logoutUser(long userId) {
+    public void logoutUser(final long userId) {
         _accountMgr.logoutUser(userId);
         return;
     }
 
     @Override
-    public boolean verifyUser(Long userId) {
-        User user = _accountMgr.getUserIncludingRemoved(userId);
+    public boolean verifyUser(final Long userId) {
+        final User user = _accountMgr.getUserIncludingRemoved(userId);
         Account account = null;
         if (user != null) {
             account = _accountMgr.getAccount(user.getAccountId());
@@ -867,27 +862,27 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
         return true;
     }
 
-    private void checkCommandAvailable(User user, String commandName) throws PermissionDeniedException {
+    private void checkCommandAvailable(final User user, final String commandName) throws PermissionDeniedException {
         if (user == null) {
             throw new PermissionDeniedException("User is null for role based API access check for command" + commandName);
         }
 
-        for (APIChecker apiChecker : _apiAccessCheckers) {
+        for (final APIChecker apiChecker : _apiAccessCheckers) {
             apiChecker.checkAccess(user, commandName);
         }
     }
 
-    private Class<?> getCmdClass(String cmdName) {
+    private Class<?> getCmdClass(final String cmdName) {
         return s_apiNameCmdClassMap.get(cmdName);
     }
 
     // FIXME: rather than isError, we might was to pass in the status code to give more flexibility
-    private void writeResponse(HttpResponse resp, final String responseText, final int statusCode, String responseType, String reasonPhrase) {
+    private void writeResponse(final HttpResponse resp, final String responseText, final int statusCode, final String responseType, final String reasonPhrase) {
         try {
             resp.setStatusCode(statusCode);
             resp.setReasonPhrase(reasonPhrase);
 
-            BasicHttpEntity body = new BasicHttpEntity();
+            final BasicHttpEntity body = new BasicHttpEntity();
             if (BaseCmd.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
                 // JSON response
                 body.setContentType(jsonContentType);
@@ -905,7 +900,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
                 body.setContent(new ByteArrayInputStream(responseText.getBytes("UTF-8")));
             }
             resp.setEntity(body);
-        } catch (Exception ex) {
+        } catch (final Exception ex) {
             s_logger.error("error!", ex);
         }
     }
@@ -920,10 +915,10 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
         private ServerSocket _serverSocket = null;
         private HttpParams _params = null;
 
-        public ListenerThread(ApiServer requestHandler, int port) {
+        public ListenerThread(final ApiServer requestHandler, final int port) {
             try {
                 _serverSocket = new ServerSocket(port);
-            } catch (IOException ioex) {
+            } catch (final IOException ioex) {
                 s_logger.error("error initializing api server", ioex);
                 return;
             }
@@ -936,14 +931,14 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
                 .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1");
 
             // Set up the HTTP protocol processor
-            BasicHttpProcessor httpproc = new BasicHttpProcessor();
+            final BasicHttpProcessor httpproc = new BasicHttpProcessor();
             httpproc.addInterceptor(new ResponseDate());
             httpproc.addInterceptor(new ResponseServer());
             httpproc.addInterceptor(new ResponseContent());
             httpproc.addInterceptor(new ResponseConnControl());
 
             // Set up request handlers
-            HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
+            final HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
             reqistry.register("*", requestHandler);
 
             // Set up the HTTP service
@@ -958,15 +953,15 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             while (!Thread.interrupted()) {
                 try {
                     // Set up HTTP connection
-                    Socket socket = _serverSocket.accept();
-                    DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
+                    final Socket socket = _serverSocket.accept();
+                    final DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
                     conn.bind(socket, _params);
 
                     // Execute a new worker task to handle the request
                     s_executor.execute(new WorkerTask(_httpService, conn, s_workerCount++));
-                } catch (InterruptedIOException ex) {
+                } catch (final InterruptedIOException ex) {
                     break;
-                } catch (IOException e) {
+                } catch (final IOException e) {
                     s_logger.error("I/O error initializing connection thread", e);
                     break;
                 }
@@ -985,33 +980,33 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
 
         @Override
         protected void runInContext() {
-            HttpContext context = new BasicHttpContext(null);
+            final HttpContext context = new BasicHttpContext(null);
             try {
                 while (!Thread.interrupted() && _conn.isOpen()) {
                     _httpService.handleRequest(_conn, context);
                     _conn.close();
                 }
-            } catch (ConnectionClosedException ex) {
+            } catch (final ConnectionClosedException ex) {
                 if (s_logger.isTraceEnabled()) {
                     s_logger.trace("ApiServer:  Client closed connection");
                 }
-            } catch (IOException ex) {
+            } catch (final IOException ex) {
                 if (s_logger.isTraceEnabled()) {
                     s_logger.trace("ApiServer:  IOException - " + ex);
                 }
-            } catch (HttpException ex) {
+            } catch (final HttpException ex) {
                 s_logger.warn("ApiServer:  Unrecoverable HTTP protocol violation" + ex);
             } finally {
                 try {
                     _conn.shutdown();
-                } catch (IOException ignore) {
+                } catch (final IOException ignore) {
                 }
             }
         }
     }
 
     @Override
-    public String getSerializedApiError(int errorCode, String errorText, Map<String, Object[]> apiCommandParams, String responseType) {
+    public String getSerializedApiError(final int errorCode, final String errorText, final Map<String, Object[]> apiCommandParams, final String responseType) {
         String responseName = null;
         Class<?> cmdClass = null;
         String responseText = null;
@@ -1020,10 +1015,10 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             if (apiCommandParams == null || apiCommandParams.isEmpty()) {
                 responseName = "errorresponse";
             } else {
-                Object cmdObj = apiCommandParams.get("command");
+                final Object cmdObj = apiCommandParams.get(ApiConstants.COMMAND);
                 // cmd name can be null when "command" parameter is missing in the request
                 if (cmdObj != null) {
-                    String cmdName = ((String[])cmdObj)[0];
+                    final String cmdName = ((String[])cmdObj)[0];
                     cmdClass = getCmdClass(cmdName);
                     if (cmdClass != null) {
                         responseName = ((BaseCmd)cmdClass.newInstance()).getCommandName();
@@ -1032,21 +1027,21 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
                     }
                 }
             }
-            ExceptionResponse apiResponse = new ExceptionResponse();
+            final ExceptionResponse apiResponse = new ExceptionResponse();
             apiResponse.setErrorCode(errorCode);
             apiResponse.setErrorText(errorText);
             apiResponse.setResponseName(responseName);
             SerializationContext.current().setUuidTranslation(true);
             responseText = ApiResponseSerializer.toSerializedString(apiResponse, responseType);
 
-        } catch (Exception e) {
+        } catch (final Exception e) {
             s_logger.error("Exception responding to http request", e);
         }
         return responseText;
     }
 
     @Override
-    public String getSerializedApiError(ServerApiException ex, Map<String, Object[]> apiCommandParams, String responseType) {
+    public String getSerializedApiError(final ServerApiException ex, final Map<String, Object[]> apiCommandParams, final String responseType) {
         String responseName = null;
         Class<?> cmdClass = null;
         String responseText = null;
@@ -1059,11 +1054,11 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             if (ex.getErrorCode() == ApiErrorCode.UNSUPPORTED_ACTION_ERROR || apiCommandParams == null || apiCommandParams.isEmpty()) {
                 responseName = "errorresponse";
             } else {
-                Object cmdObj = apiCommandParams.get("command");
+                final Object cmdObj = apiCommandParams.get(ApiConstants.COMMAND);
                 // cmd name can be null when "command" parameter is missing in
                 // the request
                 if (cmdObj != null) {
-                    String cmdName = ((String[])cmdObj)[0];
+                    final String cmdName = ((String[])cmdObj)[0];
                     cmdClass = getCmdClass(cmdName);
                     if (cmdClass != null) {
                         responseName = ((BaseCmd)cmdClass.newInstance()).getCommandName();
@@ -1072,11 +1067,11 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
                     }
                 }
             }
-            ExceptionResponse apiResponse = new ExceptionResponse();
+            final ExceptionResponse apiResponse = new ExceptionResponse();
             apiResponse.setErrorCode(ex.getErrorCode().getHttpCode());
             apiResponse.setErrorText(ex.getDescription());
             apiResponse.setResponseName(responseName);
-            ArrayList<ExceptionProxyObject> idList = ex.getIdProxyList();
+            final ArrayList<ExceptionProxyObject> idList = ex.getIdProxyList();
             if (idList != null) {
                 for (int i = 0; i < idList.size(); i++) {
                     apiResponse.addProxyObject(idList.get(i));
@@ -1089,7 +1084,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
             SerializationContext.current().setUuidTranslation(true);
             responseText = ApiResponseSerializer.toSerializedString(apiResponse, responseType);
 
-        } catch (Exception e) {
+        } catch (final Exception e) {
             s_logger.error("Exception responding to http request", e);
         }
         return responseText;
@@ -1100,7 +1095,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
     }
 
     @Inject
-    public void setPluggableServices(List<PluggableService> pluggableServices) {
+    public void setPluggableServices(final List<PluggableService> pluggableServices) {
         _pluggableServices = pluggableServices;
     }
 
@@ -1109,7 +1104,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
     }
 
     @Inject
-    public void setApiAccessCheckers(List<APIChecker> apiAccessCheckers) {
+    public void setApiAccessCheckers(final List<APIChecker> apiAccessCheckers) {
         _apiAccessCheckers = apiAccessCheckers;
     }
 
@@ -1117,7 +1112,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
         return encodeApiResponse;
     }
 
-    private static void setEncodeApiResponse(boolean encodeApiResponse) {
+    private static void setEncodeApiResponse(final boolean encodeApiResponse) {
         ApiServer.encodeApiResponse = encodeApiResponse;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/ApiServlet.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiServlet.java b/server/src/com/cloud/api/ApiServlet.java
index 46f7eba..901a0fd 100755
--- a/server/src/com/cloud/api/ApiServlet.java
+++ b/server/src/com/cloud/api/ApiServlet.java
@@ -35,6 +35,7 @@ import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 import org.springframework.web.context.support.SpringBeanAutowiringSupport;
 
+import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.ApiErrorCode;
 import org.apache.cloudstack.api.BaseCmd;
 import org.apache.cloudstack.api.ServerApiException;
@@ -67,40 +68,40 @@ public class ApiServlet extends HttpServlet {
     }
 
     @Override
-    public void init(ServletConfig config) throws ServletException {
+    public void init(final ServletConfig config) throws ServletException {
         SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());
     }
 
     @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
+    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) {
         processRequest(req, resp);
     }
 
     @Override
-    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
+    protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) {
         processRequest(req, resp);
     }
 
-    private void utf8Fixup(HttpServletRequest req, Map<String, Object[]> params) {
+    private void utf8Fixup(final HttpServletRequest req, final Map<String, Object[]> params) {
         if (req.getQueryString() == null) {
             return;
         }
 
-        String[] paramsInQueryString = req.getQueryString().split("&");
+        final String[] paramsInQueryString = req.getQueryString().split("&");
         if (paramsInQueryString != null) {
-            for (String param : paramsInQueryString) {
-                String[] paramTokens = param.split("=", 2);
+            for (final String param : paramsInQueryString) {
+                final String[] paramTokens = param.split("=", 2);
                 if (paramTokens != null && paramTokens.length == 2) {
                     String name = paramTokens[0];
                     String value = paramTokens[1];
 
                     try {
                         name = URLDecoder.decode(name, "UTF-8");
-                    } catch (UnsupportedEncodingException e) {
+                    } catch (final UnsupportedEncodingException e) {
                     }
                     try {
                         value = URLDecoder.decode(value, "UTF-8");
-                    } catch (UnsupportedEncodingException e) {
+                    } catch (final UnsupportedEncodingException e) {
                     }
                     params.put(name, new String[] {value});
                 } else {
@@ -119,13 +120,13 @@ public class ApiServlet extends HttpServlet {
         });
     }
 
-    private void processRequestInContext(HttpServletRequest req, HttpServletResponse resp) {
-        StringBuffer auditTrailSb = new StringBuffer();
+    private void processRequestInContext(final HttpServletRequest req, final HttpServletResponse resp) {
+        final StringBuffer auditTrailSb = new StringBuffer();
         auditTrailSb.append(" " + req.getRemoteAddr());
         auditTrailSb.append(" -- " + req.getMethod() + " ");
         // get the response format since we'll need it in a couple of places
         String responseType = BaseCmd.RESPONSE_TYPE_XML;
-        Map<String, Object[]> params = new HashMap<String, Object[]>();
+        final Map<String, Object[]> params = new HashMap<String, Object[]>();
         params.putAll(req.getParameterMap());
 
         // For HTTP GET requests, it seems that HttpServletRequest.getParameterMap() actually tries
@@ -143,19 +144,19 @@ public class ApiServlet extends HttpServlet {
 
         try {
             HttpSession session = req.getSession(false);
-            Object[] responseTypeParam = params.get("response");
+            final Object[] responseTypeParam = params.get(ApiConstants.RESPONSE);
             if (responseTypeParam != null) {
                 responseType = (String)responseTypeParam[0];
             }
 
-            Object[] commandObj = params.get("command");
-            if (commandObj != null) {
-                String command = (String)commandObj[0];
+            final Object[] commandParam = params.get(ApiConstants.COMMAND);
+            if (commandParam != null) {
+                final String command = (String)commandParam[0];
                 if ("logout".equalsIgnoreCase(command)) {
                     // if this is just a logout, invalidate the session and return
                     if (session != null) {
-                        Long userId = (Long)session.getAttribute("userid");
-                        Account account = (Account)session.getAttribute("accountobj");
+                        final Long userId = (Long)session.getAttribute("userid");
+                        final Account account = (Account)session.getAttribute("accountobj");
                         Long accountId = null;
                         if (account != null) {
                             accountId = account.getId();
@@ -166,7 +167,7 @@ public class ApiServlet extends HttpServlet {
                         }
                         try {
                             session.invalidate();
-                        } catch (IllegalStateException ise) {
+                        } catch (final IllegalStateException ise) {
                         }
                     }
                     auditTrailSb.append("command=logout");
@@ -179,18 +180,18 @@ public class ApiServlet extends HttpServlet {
                     if (session != null) {
                         try {
                             session.invalidate();
-                        } catch (IllegalStateException ise) {
+                        } catch (final IllegalStateException ise) {
                         }
                     }
                     session = req.getSession(true);
-                    String[] username = (String[])params.get("username");
-                    String[] password = (String[])params.get("password");
-                    String[] domainIdArr = (String[])params.get("domainid");
+                    final String[] username = (String[])params.get(ApiConstants.USERNAME);
+                    final String[] password = (String[])params.get(ApiConstants.PASSWORD);
+                    String[] domainIdArr = (String[])params.get(ApiConstants.DOMAIN_ID);
 
                     if (domainIdArr == null) {
-                        domainIdArr = (String[])params.get("domainId");
+                        domainIdArr = (String[])params.get(ApiConstants.DOMAIN__ID);
                     }
-                    String[] domainName = (String[])params.get("domain");
+                    final String[] domainName = (String[])params.get(ApiConstants.DOMAIN);
                     Long domainId = null;
                     if ((domainIdArr != null) && (domainIdArr.length > 0)) {
                         try {
@@ -200,10 +201,10 @@ public class ApiServlet extends HttpServlet {
                                 domainId = new Long(Long.parseLong(domainIdArr[0]));
                             }
                             auditTrailSb.append(" domainid=" + domainId);// building the params for POST call
-                        } catch (NumberFormatException e) {
+                        } catch (final NumberFormatException e) {
                             s_logger.warn("Invalid domain id entered by user");
                             auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " + "Invalid domain id entered, please enter a valid one");
-                            String serializedResponse =
+                            final String serializedResponse =
                                 _apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid domain id entered, please enter a valid one", params,
                                     responseType);
                             writeResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED, responseType);
@@ -225,24 +226,24 @@ public class ApiServlet extends HttpServlet {
                     }
 
                     if (username != null) {
-                        String pwd = ((password == null) ? null : password[0]);
+                        final String pwd = ((password == null) ? null : password[0]);
                         try {
                             _apiServer.loginUser(session, username[0], pwd, domainId, domain, req.getRemoteAddr(), params);
                             auditTrailSb.insert(0, "(userId=" + session.getAttribute("userid") + " accountId=" + ((Account)session.getAttribute("accountobj")).getId() +
                                 " sessionId=" + session.getId() + ")");
-                            String loginResponse = getLoginSuccessResponse(session, responseType);
+                            final String loginResponse = getLoginSuccessResponse(session, responseType);
                             writeResponse(resp, loginResponse, HttpServletResponse.SC_OK, responseType);
                             return;
-                        } catch (CloudAuthenticationException ex) {
+                        } catch (final CloudAuthenticationException ex) {
                             // TODO: fall through to API key, or just fail here w/ auth error? (HTTP 401)
                             try {
                                 session.invalidate();
-                            } catch (IllegalStateException ise) {
+                            } catch (final IllegalStateException ise) {
                             }
 
                             auditTrailSb.append(" " + ApiErrorCode.ACCOUNT_ERROR + " " + ex.getMessage() != null ? ex.getMessage()
                                 : "failed to authenticate user, check if username/password are correct");
-                            String serializedResponse =
+                            final String serializedResponse =
                                 _apiServer.getSerializedApiError(ApiErrorCode.ACCOUNT_ERROR.getHttpCode(), ex.getMessage() != null ? ex.getMessage()
                                     : "failed to authenticate user, check if username/password are correct", params, responseType);
                             writeResponse(resp, serializedResponse, ApiErrorCode.ACCOUNT_ERROR.getHttpCode(), responseType);
@@ -252,7 +253,7 @@ public class ApiServlet extends HttpServlet {
                 }
             }
             auditTrailSb.append(req.getQueryString());
-            boolean isNew = ((session == null) ? true : session.isNew());
+            final boolean isNew = ((session == null) ? true : session.isNew());
 
             // Initialize an empty context and we will update it after we have verified the request below,
             // we no longer rely on web-session here, verifyRequest will populate user/account information
@@ -261,17 +262,17 @@ public class ApiServlet extends HttpServlet {
 
             if (!isNew) {
                 userId = (Long)session.getAttribute("userid");
-                String account = (String)session.getAttribute("account");
-                Object accountObj = session.getAttribute("accountobj");
-                String sessionKey = (String)session.getAttribute("sessionkey");
-                String[] sessionKeyParam = (String[])params.get("sessionkey");
+                final String account = (String)session.getAttribute("account");
+                final Object accountObj = session.getAttribute("accountobj");
+                final String sessionKey = (String)session.getAttribute("sessionkey");
+                final String[] sessionKeyParam = (String[])params.get(ApiConstants.SESSIONKEY);
                 if ((sessionKeyParam == null) || (sessionKey == null) || !sessionKey.equals(sessionKeyParam[0])) {
                     try {
                         session.invalidate();
-                    } catch (IllegalStateException ise) {
+                    } catch (final IllegalStateException ise) {
                     }
                     auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " + "unable to verify user credentials");
-                    String serializedResponse =
+                    final String serializedResponse =
                         _apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to verify user credentials", params, responseType);
                     writeResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED, responseType);
                     return;
@@ -279,26 +280,25 @@ public class ApiServlet extends HttpServlet {
 
                 // Do a sanity check here to make sure the user hasn't already been deleted
                 if ((userId != null) && (account != null) && (accountObj != null) && _apiServer.verifyUser(userId)) {
-                    String[] command = (String[])params.get("command");
-                    if (command == null) {
+                    if (commandParam == null || commandParam[0] == null) {
                         s_logger.info("missing command, ignoring request...");
                         auditTrailSb.append(" " + HttpServletResponse.SC_BAD_REQUEST + " " + "no command specified");
-                        String serializedResponse = _apiServer.getSerializedApiError(HttpServletResponse.SC_BAD_REQUEST, "no command specified", params, responseType);
+                        final String serializedResponse = _apiServer.getSerializedApiError(HttpServletResponse.SC_BAD_REQUEST, "no command specified", params, responseType);
                         writeResponse(resp, serializedResponse, HttpServletResponse.SC_BAD_REQUEST, responseType);
                         return;
                     }
-                    User user = _entityMgr.findById(User.class, userId);
+                    final User user = _entityMgr.findById(User.class, userId);
                     CallContext.register(user, (Account)accountObj);
                 } else {
                     // Invalidate the session to ensure we won't allow a request across management server
                     // restarts if the userId was serialized to the stored session
                     try {
                         session.invalidate();
-                    } catch (IllegalStateException ise) {
+                    } catch (final IllegalStateException ise) {
                     }
 
                     auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " + "unable to verify user credentials");
-                    String serializedResponse =
+                    final String serializedResponse =
                         _apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to verify user credentials", params, responseType);
                     writeResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED, responseType);
                     return;
@@ -326,29 +326,29 @@ public class ApiServlet extends HttpServlet {
 
                 // Add the HTTP method (GET/POST/PUT/DELETE) as well into the params map.
                 params.put("httpmethod", new String[] {req.getMethod()});
-                String response = _apiServer.handleRequest(params, responseType, auditTrailSb);
+                final String response = _apiServer.handleRequest(params, responseType, auditTrailSb);
                 writeResponse(resp, response != null ? response : "", HttpServletResponse.SC_OK, responseType);
             } else {
                 if (session != null) {
                     try {
                         session.invalidate();
-                    } catch (IllegalStateException ise) {
+                    } catch (final IllegalStateException ise) {
                     }
                 }
 
                 auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " + "unable to verify user credentials and/or request signature");
-                String serializedResponse =
+                final String serializedResponse =
                     _apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to verify user credentials and/or request signature", params,
                         responseType);
                 writeResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED, responseType);
 
             }
-        } catch (ServerApiException se) {
-            String serializedResponseText = _apiServer.getSerializedApiError(se, params, responseType);
+        } catch (final ServerApiException se) {
+            final String serializedResponseText = _apiServer.getSerializedApiError(se, params, responseType);
             resp.setHeader("X-Description", se.getDescription());
             writeResponse(resp, serializedResponseText, se.getErrorCode().getHttpCode(), responseType);
             auditTrailSb.append(" " + se.getErrorCode() + " " + se.getDescription());
-        } catch (Exception ex) {
+        } catch (final Exception ex) {
             s_logger.error("unknown exception writing api response", ex);
             auditTrailSb.append(" unknown exception writing api response");
         } finally {
@@ -372,7 +372,7 @@ public class ApiServlet extends HttpServlet {
      */
 
     // FIXME: rather than isError, we might was to pass in the status code to give more flexibility
-    private void writeResponse(HttpServletResponse resp, String response, int responseCode, String responseType) {
+    private void writeResponse(final HttpServletResponse resp, final String response, final int responseCode, final String responseType) {
         try {
             if (BaseCmd.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
                 resp.setContentType(ApiServer.getJsonContentType() + "; charset=UTF-8");
@@ -382,11 +382,11 @@ public class ApiServlet extends HttpServlet {
 
             resp.setStatus(responseCode);
             resp.getWriter().print(response);
-        } catch (IOException ioex) {
+        } catch (final IOException ioex) {
             if (s_logger.isTraceEnabled()) {
                 s_logger.trace("exception writing response: " + ioex);
             }
-        } catch (Exception ex) {
+        } catch (final Exception ex) {
             if (!(ex instanceof IllegalStateException)) {
                 s_logger.error("unknown exception writing api response", ex);
             }
@@ -394,29 +394,29 @@ public class ApiServlet extends HttpServlet {
     }
 
     @SuppressWarnings("rawtypes")
-    private String getLoginSuccessResponse(HttpSession session, String responseType) {
-        StringBuffer sb = new StringBuffer();
-        int inactiveInterval = session.getMaxInactiveInterval();
+    private String getLoginSuccessResponse(final HttpSession session, final String responseType) {
+        final StringBuffer sb = new StringBuffer();
+        final int inactiveInterval = session.getMaxInactiveInterval();
 
-        String user_UUID = (String)session.getAttribute("user_UUID");
+        final String user_UUID = (String)session.getAttribute("user_UUID");
         session.removeAttribute("user_UUID");
 
-        String domain_UUID = (String)session.getAttribute("domain_UUID");
+        final String domain_UUID = (String)session.getAttribute("domain_UUID");
         session.removeAttribute("domain_UUID");
 
         if (BaseCmd.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
             sb.append("{ \"loginresponse\" : { ");
-            Enumeration attrNames = session.getAttributeNames();
+            final Enumeration attrNames = session.getAttributeNames();
             if (attrNames != null) {
                 sb.append("\"timeout\" : \"" + inactiveInterval + "\"");
                 while (attrNames.hasMoreElements()) {
-                    String attrName = (String)attrNames.nextElement();
+                    final String attrName = (String)attrNames.nextElement();
                     if ("userid".equalsIgnoreCase(attrName)) {
                         sb.append(", \"" + attrName + "\" : \"" + user_UUID + "\"");
                     } else if ("domainid".equalsIgnoreCase(attrName)) {
                         sb.append(", \"" + attrName + "\" : \"" + domain_UUID + "\"");
                     } else {
-                        Object attrObj = session.getAttribute(attrName);
+                        final Object attrObj = session.getAttribute(attrName);
                         if ((attrObj instanceof String) || (attrObj instanceof Long)) {
                             sb.append(", \"" + attrName + "\" : \"" + attrObj.toString() + "\"");
                         }
@@ -428,16 +428,16 @@ public class ApiServlet extends HttpServlet {
             sb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
             sb.append("<loginresponse cloud-stack-version=\"" + ApiDBUtils.getVersion() + "\">");
             sb.append("<timeout>" + inactiveInterval + "</timeout>");
-            Enumeration attrNames = session.getAttributeNames();
+            final Enumeration attrNames = session.getAttributeNames();
             if (attrNames != null) {
                 while (attrNames.hasMoreElements()) {
-                    String attrName = (String)attrNames.nextElement();
+                    final String attrName = (String)attrNames.nextElement();
                     if ("userid".equalsIgnoreCase(attrName)) {
                         sb.append("<" + attrName + ">" + user_UUID + "</" + attrName + ">");
                     } else if ("domainid".equalsIgnoreCase(attrName)) {
                         sb.append("<" + attrName + ">" + domain_UUID + "</" + attrName + ">");
                     } else {
-                        Object attrObj = session.getAttribute(attrName);
+                        final Object attrObj = session.getAttribute(attrName);
                         if (attrObj instanceof String || attrObj instanceof Long || attrObj instanceof Short) {
                             sb.append("<" + attrName + ">" + attrObj.toString() + "</" + attrName + ">");
                         }
@@ -450,8 +450,8 @@ public class ApiServlet extends HttpServlet {
         return sb.toString();
     }
 
-    private String getLogoutSuccessResponse(String responseType) {
-        StringBuffer sb = new StringBuffer();
+    private String getLogoutSuccessResponse(final String responseType) {
+        final StringBuffer sb = new StringBuffer();
         if (BaseCmd.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
             sb.append("{ \"logoutresponse\" : { \"description\" : \"success\" } }");
         } else {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/ParameterHandler.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ParameterHandler.java b/server/src/com/cloud/api/ParameterHandler.java
new file mode 100644
index 0000000..a9eb390
--- /dev/null
+++ b/server/src/com/cloud/api/ParameterHandler.java
@@ -0,0 +1,138 @@
+// 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 com.cloud.api;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.ServerApiException;
+
+public class ParameterHandler {
+
+    private static final Logger s_logger = Logger.getLogger(ParameterHandler.class.getName());
+
+    /**
+     * Non-printable ASCII characters - numbers 0 to 31 and 127 decimal
+     */
+    public static final String CONTROL_CHARACTERS = "[\000-\011\013-\014\016-\037\177]";
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public static Map<String, Object> unpackParams(final Map params) {
+        final Map<String, String> stringMap = new HashMap<String, String>();
+        final Set keys = params.keySet();
+        final Iterator keysIter = keys.iterator();
+        while (keysIter.hasNext()) {
+            final String key = (String)keysIter.next();
+            final String[] value = (String[])params.get(key);
+            // fail if parameter value contains ASCII control (non-printable) characters
+            if (value[0] != null) {
+                final Pattern pattern = Pattern.compile(CONTROL_CHARACTERS);
+                final Matcher matcher = pattern.matcher(value[0]);
+                if (matcher.find()) {
+                    throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Received value " + value[0] + " for parameter " + key +
+                        " is invalid, contains illegal ASCII non-printable characters");
+                }
+            }
+            stringMap.put(key, value[0]);
+        }
+
+        final Map<String, Object> lowercaseParams = new HashMap<String, Object>();
+        for (final Object keyObject : stringMap.keySet()) {
+            final String key = (String) keyObject;
+            final int arrayStartIndex = key.indexOf('[');
+            final int arrayStartLastIndex = key.lastIndexOf('[');
+            if (arrayStartIndex != arrayStartLastIndex) {
+                throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
+                    "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
+            }
+
+            if (arrayStartIndex > 0) {
+                final int arrayEndIndex = key.indexOf(']');
+                final int arrayEndLastIndex = key.lastIndexOf(']');
+                if ((arrayEndIndex < arrayStartIndex) || (arrayEndIndex != arrayEndLastIndex)) {
+                    // malformed parameter
+                    throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
+                        "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
+                }
+
+                // Now that we have an array object, check for a field name in the case of a complex object
+                final int fieldIndex = key.indexOf('.');
+                String fieldName = null;
+                if (fieldIndex < arrayEndIndex) {
+                    throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
+                        "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
+                } else {
+                    fieldName = key.substring(fieldIndex + 1);
+                }
+
+                // parse the parameter name as the text before the first '[' character
+                String paramName = key.substring(0, arrayStartIndex);
+                paramName = paramName.toLowerCase();
+
+                Map<Integer, Map> mapArray = null;
+                Map<String, Object> mapValue = null;
+                final String indexStr = key.substring(arrayStartIndex + 1, arrayEndIndex);
+                int index = 0;
+                boolean parsedIndex = false;
+                try {
+                    if (indexStr != null) {
+                        index = Integer.parseInt(indexStr);
+                        parsedIndex = true;
+                    }
+                } catch (final NumberFormatException nfe) {
+                    s_logger.warn("Invalid parameter " + key + " received, unable to parse object array, returning an error.");
+                }
+
+                if (!parsedIndex) {
+                    throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
+                        "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
+                }
+
+                final Object value = lowercaseParams.get(paramName);
+                if (value == null) {
+                    // for now, assume object array with sub fields
+                    mapArray = new HashMap<Integer, Map>();
+                    mapValue = new HashMap<String, Object>();
+                    mapArray.put(Integer.valueOf(index), mapValue);
+                } else if (value instanceof Map) {
+                    mapArray = (HashMap)value;
+                    mapValue = mapArray.get(Integer.valueOf(index));
+                    if (mapValue == null) {
+                        mapValue = new HashMap<String, Object>();
+                        mapArray.put(Integer.valueOf(index), mapValue);
+                    }
+                }
+
+                // we are ready to store the value for a particular field into the map for this object
+                mapValue.put(fieldName, stringMap.get(key));
+
+                lowercaseParams.put(paramName, mapArray);
+            } else {
+                lowercaseParams.put(key.toLowerCase(), stringMap.get(key));
+            }
+        }
+        return lowercaseParams;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/dispatch/CommandCreationWorker.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/dispatch/CommandCreationWorker.java b/server/src/com/cloud/api/dispatch/CommandCreationWorker.java
new file mode 100644
index 0000000..3e11cc0
--- /dev/null
+++ b/server/src/com/cloud/api/dispatch/CommandCreationWorker.java
@@ -0,0 +1,55 @@
+// 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 com.cloud.api.dispatch;
+
+import java.util.Map;
+
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCreateCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.ServerApiException;
+
+import com.cloud.exception.ResourceAllocationException;
+
+
+/**
+ * This worker validates parameters in a semantic way, that is of
+ * course specific for each {@link BaseCmd}, so actually it delegates
+ * the validation on the {@link BaseCmd} itself
+ *
+ * @author afornie
+ */
+public class CommandCreationWorker implements DispatchWorker {
+
+    @Override
+    public boolean handle(final BaseCmd cmd, final Map<String, Object> params) {
+        if (cmd instanceof BaseAsyncCreateCmd) {
+            try {
+                ((BaseAsyncCreateCmd)cmd).create();
+            } catch (final ResourceAllocationException e) {
+                throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR,
+                        e.getMessage(), e);
+            }
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
+                    "Trying to invoke creation on a Command that is not  BaseAsyncCreateCmd");
+        }
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/dispatch/DispatchChain.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/dispatch/DispatchChain.java b/server/src/com/cloud/api/dispatch/DispatchChain.java
new file mode 100644
index 0000000..ecbb883
--- /dev/null
+++ b/server/src/com/cloud/api/dispatch/DispatchChain.java
@@ -0,0 +1,45 @@
+// 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 com.cloud.api.dispatch;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.ServerApiException;
+
+public class DispatchChain {
+
+    protected List<DispatchWorker> workers = new ArrayList<DispatchWorker>();
+
+    public DispatchChain add(final DispatchWorker worker) {
+        workers.add(worker);
+        return this;
+    }
+
+    public void dispatch(final BaseCmd cmd, final Map<String, Object> params)
+            throws ServerApiException {
+
+        for (final DispatchWorker worker : workers) {
+            if (!worker.handle(cmd, params)) {
+                break;
+            }
+        }
+    }
+}


[6/6] git commit: updated refs/heads/master to 447430c

Posted by da...@apache.org.
CLOUDSTACK-6003 fixing plus refactoring dispatcher

Signed-off-by: Daan Hoogland <da...@onecht.net>
(cherry picked from commit a9bcc1ea3b7dfd3fcc5c795b0095c77851ebe618)
Signed-off-by: Daan Hoogland <da...@onecht.net>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/447430c3
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/447430c3
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/447430c3

Branch: refs/heads/master
Commit: 447430c3df38c36d947c44c4aebd961d8cbb14c4
Parents: ca1b340
Author: Antonio Fornie <af...@schubergphilis.com>
Authored: Fri Jan 31 02:28:57 2014 +0100
Committer: Daan Hoogland <da...@onecht.net>
Committed: Tue Feb 4 13:37:08 2014 +0100

----------------------------------------------------------------------
 .../org/apache/cloudstack/api/ApiConstants.java |    5 +
 api/src/org/apache/cloudstack/api/BaseCmd.java  |  155 ++-
 .../org/apache/cloudstack/api/BaseListCmd.java  |   30 +-
 .../autoscale/CreateAutoScaleVmProfileCmd.java  |   30 +-
 .../core/spring-server-core-misc-context.xml    |   10 +
 .../com/cloud/api/ApiAsyncJobDispatcher.java    |   26 +-
 server/src/com/cloud/api/ApiDispatcher.java     |  486 +------
 server/src/com/cloud/api/ApiServer.java         |  345 +++--
 server/src/com/cloud/api/ApiServlet.java        |  134 +-
 server/src/com/cloud/api/ParameterHandler.java  |  138 ++
 .../api/dispatch/CommandCreationWorker.java     |   55 +
 .../com/cloud/api/dispatch/DispatchChain.java   |   45 +
 .../api/dispatch/DispatchChainFactory.java      |   68 +
 .../com/cloud/api/dispatch/DispatchWorker.java  |   34 +
 .../dispatch/ParamGenericValidationWorker.java  |   95 ++
 .../cloud/api/dispatch/ParamProcessWorker.java  |  429 ++++++
 .../dispatch/ParamSemanticValidationWorker.java |   40 +
 .../cloud/network/as/AutoScaleManagerImpl.java  |  496 +++----
 .../VirtualNetworkApplianceManagerImpl.java     | 1282 +++++++++---------
 .../storage/snapshot/SnapshotSchedulerImpl.java |  107 +-
 .../test/com/cloud/api/ApiDispatcherTest.java   |  106 --
 .../api/dispatch/CommandCreationWorkerTest.java |   48 +
 .../api/dispatch/DispatchChainFactoryTest.java  |   54 +
 .../ParamGenericValidationWorkerTest.java       |  163 +++
 .../api/dispatch/ParamProcessWorkerTest.java    |  107 ++
 .../ParamSemanticValidationWorkerTest.java      |   48 +
 26 files changed, 2673 insertions(+), 1863 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index d500303..749a814 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -48,10 +48,12 @@ public class ApiConstants {
     public static final String CLUSTER_ID = "clusterid";
     public static final String CLUSTER_NAME = "clustername";
     public static final String CLUSTER_TYPE = "clustertype";
+    public static final String COMMAND = "command";
     public static final String COMPONENT = "component";
     public static final String CPU_NUMBER = "cpunumber";
     public static final String CPU_SPEED = "cpuspeed";
     public static final String CREATED = "created";
+    public static final String CTX_START_EVENT_ID = "ctxStartEventId";
     public static final String CUSTOMIZED = "customized";
     public static final String CUSTOMIZED_IOPS = "customizediops";
     public static final String CUSTOM_ID = "customid";
@@ -78,6 +80,7 @@ public class ApiConstants {
     public static final String IP6_DNS2 = "ip6dns2";
     public static final String DOMAIN = "domain";
     public static final String DOMAIN_ID = "domainid";
+    public static final String DOMAIN__ID = "domainId";
     public static final String DURATION = "duration";
     public static final String EMAIL = "email";
     public static final String END_DATE = "enddate";
@@ -208,6 +211,7 @@ public class ApiConstants {
     public static final String SENT = "sent";
     public static final String SENT_BYTES = "sentbytes";
     public static final String SERVICE_OFFERING_ID = "serviceofferingid";
+    public static final String SESSIONKEY = "sessionkey";
     public static final String SHOW_CAPACITIES = "showcapacities";
     public static final String SHOW_REMOVED = "showremoved";
     public static final String SIZE = "size";
@@ -276,6 +280,7 @@ public class ApiConstants {
     public static final String NETWORKRATE = "networkrate";
     public static final String HOST_TAGS = "hosttags";
     public static final String SSH_KEYPAIR = "keypair";
+    public static final String HTTPMETHOD = "httpmethod";
     public static final String HOST_CPU_CAPACITY = "hostcpucapacity";
     public static final String HOST_CPU_NUM = "hostcpunum";
     public static final String HOST_MEM_CAPACITY = "hostmemcapacity";

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/api/src/org/apache/cloudstack/api/BaseCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java
index 4229ec9..aa0549a 100644
--- a/api/src/org/apache/cloudstack/api/BaseCmd.java
+++ b/api/src/org/apache/cloudstack/api/BaseCmd.java
@@ -17,10 +17,13 @@
 
 package org.apache.cloudstack.api;
 
+import java.lang.reflect.Field;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
 
@@ -28,8 +31,10 @@ import javax.inject.Inject;
 
 import org.apache.log4j.Logger;
 
+import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.affinity.AffinityGroupService;
 import org.apache.cloudstack.alert.AlertService;
+import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
 import org.apache.cloudstack.network.lb.ApplicationLoadBalancerService;
 import org.apache.cloudstack.network.lb.InternalLoadBalancerVMService;
@@ -75,6 +80,7 @@ import com.cloud.user.Account;
 import com.cloud.user.AccountService;
 import com.cloud.user.DomainService;
 import com.cloud.user.ResourceLimitService;
+import com.cloud.utils.ReflectUtil;
 import com.cloud.utils.db.EntityManager;
 import com.cloud.vm.UserVmService;
 import com.cloud.vm.snapshot.VMSnapshotService;
@@ -97,6 +103,8 @@ public abstract class BaseCmd {
     public static Pattern newInputDateFormat = Pattern.compile("[\\d]+-[\\d]+-[\\d]+ [\\d]+:[\\d]+:[\\d]+");
     private static final DateFormat s_outputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
 
+    protected static final Map<Class<?>, List<Field>> fieldsForCmdClass = new HashMap<Class<?>, List<Field>>();
+
     private Object _responseObject = null;
     private Map<String, String> fullUrlParams;
 
@@ -203,7 +211,7 @@ public abstract class BaseCmd {
         return httpMethod;
     }
 
-    public void setHttpMethod(String method) {
+    public void setHttpMethod(final String method) {
         if (method != null) {
             if (method.equalsIgnoreCase("GET"))
                 httpMethod = HTTPMethod.GET;
@@ -225,7 +233,7 @@ public abstract class BaseCmd {
         return responseType;
     }
 
-    public void setResponseType(String responseType) {
+    public void setResponseType(final String responseType) {
         this.responseType = responseType;
     }
 
@@ -243,7 +251,7 @@ public abstract class BaseCmd {
         return _responseObject;
     }
 
-    public void setResponseObject(Object responseObject) {
+    public void setResponseObject(final Object responseObject) {
         _responseObject = responseObject;
     }
 
@@ -251,7 +259,7 @@ public abstract class BaseCmd {
         return _mgr;
     }
 
-    public static String getDateString(Date date) {
+    public static String getDateString(final Date date) {
         if (date == null) {
             return "";
         }
@@ -262,101 +270,83 @@ public abstract class BaseCmd {
         return formattedString;
     }
 
-    // FIXME: move this to a utils method so that maps can be unpacked and integer/long values can be appropriately cast
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    public Map<String, Object> unpackParams(Map<String, String> params) {
-        Map<String, Object> lowercaseParams = new HashMap<String, Object>();
-        for (String key : params.keySet()) {
-            int arrayStartIndex = key.indexOf('[');
-            int arrayStartLastIndex = key.lastIndexOf('[');
-            if (arrayStartIndex != arrayStartLastIndex) {
-                throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
-                    "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
-            }
+    protected List<Field> getAllFieldsForClass(final Class<?> clazz) {
+        List<Field> filteredFields = fieldsForCmdClass.get(clazz);
 
-            if (arrayStartIndex > 0) {
-                int arrayEndIndex = key.indexOf(']');
-                int arrayEndLastIndex = key.lastIndexOf(']');
-                if ((arrayEndIndex < arrayStartIndex) || (arrayEndIndex != arrayEndLastIndex)) {
-                    // malformed parameter
-                    throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
-                        "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
-                }
+        // If list of fields was not cached yet
+        if (filteredFields == null) {
+            final List<Field> allFields = ReflectUtil.getAllFieldsForClass(this.getClass(), BaseCmd.class);
+            filteredFields = new ArrayList<Field>();
 
-                // Now that we have an array object, check for a field name in the case of a complex object
-                int fieldIndex = key.indexOf('.');
-                String fieldName = null;
-                if (fieldIndex < arrayEndIndex) {
-                    throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
-                        "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
-                } else {
-                    fieldName = key.substring(fieldIndex + 1);
+            for (final Field field : allFields) {
+                final Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
+                if ((parameterAnnotation != null) && parameterAnnotation.expose()) {
+                    filteredFields.add(field);
                 }
+            }
 
-                // parse the parameter name as the text before the first '[' character
-                String paramName = key.substring(0, arrayStartIndex);
-                paramName = paramName.toLowerCase();
-
-                Map<Integer, Map> mapArray = null;
-                Map<String, Object> mapValue = null;
-                String indexStr = key.substring(arrayStartIndex + 1, arrayEndIndex);
-                int index = 0;
-                boolean parsedIndex = false;
-                try {
-                    if (indexStr != null) {
-                        index = Integer.parseInt(indexStr);
-                        parsedIndex = true;
-                    }
-                } catch (NumberFormatException nfe) {
-                    s_logger.warn("Invalid parameter " + key + " received, unable to parse object array, returning an error.");
-                }
+            // Cache the prepared list for future use
+            fieldsForCmdClass.put(clazz, filteredFields);
+        }
+        return filteredFields;
+    }
 
-                if (!parsedIndex) {
-                    throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
-                        "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
-                }
+    protected Account getCurrentContextAccount() {
+        return CallContext.current().getCallingAccount();
+    }
 
-                Object value = lowercaseParams.get(paramName);
-                if (value == null) {
-                    // for now, assume object array with sub fields
-                    mapArray = new HashMap<Integer, Map>();
-                    mapValue = new HashMap<String, Object>();
-                    mapArray.put(Integer.valueOf(index), mapValue);
-                } else if (value instanceof Map) {
-                    mapArray = (HashMap)value;
-                    mapValue = mapArray.get(Integer.valueOf(index));
-                    if (mapValue == null) {
-                        mapValue = new HashMap<String, Object>();
-                        mapArray.put(Integer.valueOf(index), mapValue);
+    /**
+     * this method doesn't return all the @{link Parameter}, but only the ones exposed
+     * and allowed for current @{link RoleType}
+     *
+     * @return
+     */
+    public List<Field> getParamFields() {
+        final List<Field> allFields = getAllFieldsForClass(this.getClass());
+        final List<Field> validFields = new ArrayList<Field>();
+        final Account caller = getCurrentContextAccount();
+
+        for (final Field field : allFields) {
+            final Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
+
+            //TODO: Annotate @Validate on API Cmd classes, FIXME how to process Validate
+            final RoleType[] allowedRoles = parameterAnnotation.authorized();
+            boolean roleIsAllowed = true;
+            if (allowedRoles.length > 0) {
+                roleIsAllowed = false;
+                for (final RoleType allowedRole : allowedRoles) {
+                    if (allowedRole.getValue() == caller.getType()) {
+                        roleIsAllowed = true;
+                        break;
                     }
                 }
+            }
 
-                // we are ready to store the value for a particular field into the map for this object
-                mapValue.put(fieldName, params.get(key));
-
-                lowercaseParams.put(paramName, mapArray);
+            if (roleIsAllowed) {
+                validFields.add(field);
             } else {
-                lowercaseParams.put(key.toLowerCase(), params.get(key));
+                s_logger.debug("Ignoring paremeter " + parameterAnnotation.name() + " as the caller is not authorized to pass it in");
             }
         }
-        return lowercaseParams;
+
+        return validFields;
     }
 
-    protected long getInstanceIdFromJobSuccessResult(String result) {
+    protected long getInstanceIdFromJobSuccessResult(final String result) {
         s_logger.debug("getInstanceIdFromJobSuccessResult not overridden in subclass " + this.getClass().getName());
         return 0;
     }
 
-    public static boolean isAdmin(short accountType) {
+    public static boolean isAdmin(final short accountType) {
         return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) ||
             (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
     }
 
-    public static boolean isRootAdmin(short accountType) {
+    public static boolean isRootAdmin(final short accountType) {
         return ((accountType == Account.ACCOUNT_TYPE_ADMIN));
     }
 
-    public void setFullUrlParams(Map<String, String> map) {
+    public void setFullUrlParams(final Map<String, String> map) {
         fullUrlParams = map;
     }
 
@@ -364,18 +354,18 @@ public abstract class BaseCmd {
         return fullUrlParams;
     }
 
-    public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) {
+    public Long finalyzeAccountId(final String accountName, final Long domainId, final Long projectId, final boolean enabledOnly) {
         if (accountName != null) {
             if (domainId == null) {
                 throw new InvalidParameterValueException("Account must be specified with domainId parameter");
             }
 
-            Domain domain = _domainService.getDomain(domainId);
+            final Domain domain = _domainService.getDomain(domainId);
             if (domain == null) {
                 throw new InvalidParameterValueException("Unable to find domain by id");
             }
 
-            Account account = _accountService.getActiveAccountByName(accountName, domainId);
+            final Account account = _accountService.getActiveAccountByName(accountName, domainId);
             if (account != null && account.getType() != Account.ACCOUNT_TYPE_PROJECT) {
                 if (!enabledOnly || account.getState() == Account.State.enabled) {
                     return account.getId();
@@ -392,12 +382,12 @@ public abstract class BaseCmd {
         }
 
         if (projectId != null) {
-            Project project = _projectService.getProject(projectId);
+            final Project project = _projectService.getProject(projectId);
             if (project != null) {
                 if (!enabledOnly || project.getState() == Project.State.Active) {
                     return project.getProjectAccountId();
                 } else {
-                    PermissionDeniedException ex =
+                    final PermissionDeniedException ex =
                         new PermissionDeniedException("Can't add resources to the project with specified projectId in state=" + project.getState() +
                             " as it's no longer active");
                     ex.addProxyObject(project.getUuid(), "projectId");
@@ -409,4 +399,11 @@ public abstract class BaseCmd {
         }
         return null;
     }
+
+    /**
+     * To be overwritten by any class who needs specific validation
+     */
+    public void validateSpecificParameters(final Map<String, Object> params){
+        // To be overwritten by any class who needs specific validation
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/api/src/org/apache/cloudstack/api/BaseListCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/BaseListCmd.java b/api/src/org/apache/cloudstack/api/BaseListCmd.java
index c1a4b4c..1876995 100644
--- a/api/src/org/apache/cloudstack/api/BaseListCmd.java
+++ b/api/src/org/apache/cloudstack/api/BaseListCmd.java
@@ -16,7 +16,10 @@
 // under the License.
 package org.apache.cloudstack.api;
 
+import java.util.Map;
+
 import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.utils.exception.CSExceptionErrorCode;
 
 public abstract class BaseListCmd extends BaseCmd {
 
@@ -83,7 +86,7 @@ public abstract class BaseListCmd extends BaseCmd {
 
     public Long getPageSizeVal() {
         Long defaultPageSize = s_maxPageSize;
-        Integer pageSizeInt = getPageSize();
+        final Integer pageSizeInt = getPageSize();
         if (pageSizeInt != null) {
             defaultPageSize = pageSizeInt.longValue();
         }
@@ -96,12 +99,12 @@ public abstract class BaseListCmd extends BaseCmd {
 
     public Long getStartIndex() {
         Long startIndex = Long.valueOf(0);
-        Long pageSizeVal = getPageSizeVal();
+        final Long pageSizeVal = getPageSizeVal();
 
         if (pageSizeVal == null) {
             startIndex = null;
         } else if (page != null) {
-            int pageNum = page.intValue();
+            final int pageNum = page.intValue();
             if (pageNum > 0) {
                 startIndex = Long.valueOf(pageSizeVal * (pageNum - 1));
             }
@@ -112,4 +115,25 @@ public abstract class BaseListCmd extends BaseCmd {
     public ApiCommandJobType getInstanceType() {
         return ApiCommandJobType.None;
     }
+
+    @Override
+    public void validateSpecificParameters(final Map<String, Object> params){
+        super.validateSpecificParameters(params);
+
+        final Object pageSizeObj = params.get(ApiConstants.PAGE_SIZE);
+        Long pageSize = null;
+        if (pageSizeObj != null) {
+            pageSize = Long.valueOf((String)pageSizeObj);
+        }
+
+        if (params.get(ApiConstants.PAGE) == null &&
+                pageSize != null &&
+                !pageSize.equals(BaseListCmd.s_pageSizeUnlimited)) {
+            final ServerApiException ex = new ServerApiException(ApiErrorCode.PARAM_ERROR, "\"page\" parameter is required when \"pagesize\" is specified");
+            ex.setCSErrorCode(CSExceptionErrorCode.getCSErrCode(ex.getClass().getName()));
+            throw ex;
+        } else if (pageSize == null && (params.get(ApiConstants.PAGE) != null)) {
+            throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "\"pagesize\" parameter is required when \"page\" is specified");
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java
index bee1b22..ccdd557 100644
--- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java
@@ -151,7 +151,7 @@ public class CreateAutoScaleVmProfileCmd extends BaseAsyncCreateCmd {
         }
         Account account = null;
         if (autoscaleUserId != null) {
-            User user = _entityMgr.findById(User.class, autoscaleUserId);
+            final User user = _entityMgr.findById(User.class, autoscaleUserId);
             account = _entityMgr.findById(Account.class, user.getAccountId());
         } else {
             account = CallContext.current().getCallingAccount();
@@ -167,21 +167,21 @@ public class CreateAutoScaleVmProfileCmd extends BaseAsyncCreateCmd {
         }
         if (otherDeployParams == null)
             return;
-        String[] keyValues = otherDeployParams.split("&"); // hostid=123, hypervisor=xenserver
-        for (String keyValue : keyValues) { // keyValue == "hostid=123"
-            String[] keyAndValue = keyValue.split("="); // keyValue = hostid, 123
+        final String[] keyValues = otherDeployParams.split("&"); // hostid=123, hypervisor=xenserver
+        for (final String keyValue : keyValues) { // keyValue == "hostid=123"
+            final String[] keyAndValue = keyValue.split("="); // keyValue = hostid, 123
             if (keyAndValue.length != 2) {
                 throw new InvalidParameterValueException("Invalid parameter in otherDeployParam : " + keyValue);
             }
-            String paramName = keyAndValue[0]; // hostid
-            String paramValue = keyAndValue[1]; // 123
+            final String paramName = keyAndValue[0]; // hostid
+            final String paramValue = keyAndValue[1]; // 123
             otherDeployParamMap.put(paramName, paramValue);
         }
     }
 
-    public HashMap<String, String> getDeployParamMap() {
+    public HashMap<String, Object> getDeployParamMap() {
         createOtherDeployParamMap();
-        HashMap<String, String> deployParams = new HashMap<String, String>(otherDeployParamMap);
+        final HashMap<String, Object> deployParams = new HashMap<String, Object>(otherDeployParamMap);
         deployParams.put("command", "deployVirtualMachine");
         deployParams.put("zoneId", zoneId.toString());
         deployParams.put("serviceOfferingId", serviceOfferingId.toString());
@@ -189,7 +189,7 @@ public class CreateAutoScaleVmProfileCmd extends BaseAsyncCreateCmd {
         return deployParams;
     }
 
-    public String getOtherDeployParam(String param) {
+    public String getOtherDeployParam(final String param) {
         if (param == null) {
             return null;
         }
@@ -232,19 +232,19 @@ public class CreateAutoScaleVmProfileCmd extends BaseAsyncCreateCmd {
 
     @Override
     public void execute() {
-        AutoScaleVmProfile result = _entityMgr.findById(AutoScaleVmProfile.class, getEntityId());
-        AutoScaleVmProfileResponse response = _responseGenerator.createAutoScaleVmProfileResponse(result);
+        final AutoScaleVmProfile result = _entityMgr.findById(AutoScaleVmProfile.class, getEntityId());
+        final AutoScaleVmProfileResponse response = _responseGenerator.createAutoScaleVmProfileResponse(result);
         response.setResponseName(getCommandName());
-        this.setResponseObject(response);
+        setResponseObject(response);
     }
 
     @Override
     public void create() throws ResourceAllocationException {
 
-        AutoScaleVmProfile result = _autoScaleService.createAutoScaleVmProfile(this);
+        final AutoScaleVmProfile result = _autoScaleService.createAutoScaleVmProfile(this);
         if (result != null) {
-            this.setEntityId(result.getId());
-            this.setEntityUuid(result.getUuid());
+            setEntityId(result.getId());
+            setEntityUuid(result.getUuid());
         } else {
             throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create Autoscale Vm Profile");
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml
----------------------------------------------------------------------
diff --git a/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml b/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml
index fd2f5fb..f35ee5e 100644
--- a/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml
+++ b/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml
@@ -50,6 +50,16 @@
 
     <bean id="apiDispatcher" class="com.cloud.api.ApiDispatcher" />
 
+    <bean id="dispatchChainFactory" class="com.cloud.api.dispatch.DispatchChainFactory" />
+
+    <bean id="paramSemanticValidationWorker" class="com.cloud.api.dispatch.ParamSemanticValidationWorker" />
+
+    <bean id="paramProcessWorker" class="com.cloud.api.dispatch.ParamProcessWorker" />
+
+    <bean id="paramGenericValidationWorker" class="com.cloud.api.dispatch.ParamGenericValidationWorker" />
+
+    <bean id="commandCreationWorker" class="com.cloud.api.dispatch.CommandCreationWorker" />
+
     <bean id="apiResponseHelper" class="com.cloud.api.ApiResponseHelper" />
 
     <bean id="apiServer" class="com.cloud.api.ApiServer">

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/ApiAsyncJobDispatcher.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiAsyncJobDispatcher.java b/server/src/com/cloud/api/ApiAsyncJobDispatcher.java
index 71ac616..565e3a4 100644
--- a/server/src/com/cloud/api/ApiAsyncJobDispatcher.java
+++ b/server/src/com/cloud/api/ApiAsyncJobDispatcher.java
@@ -70,30 +70,30 @@ public class ApiAsyncJobDispatcher extends AdapterBase implements AsyncJobDispat
         });
     }
 
-    protected void runJobInContext(AsyncJob job) {
+    protected void runJobInContext(final AsyncJob job) {
         BaseAsyncCmd cmdObj = null;
         try {
-            Class<?> cmdClass = Class.forName(job.getCmd());
+            final Class<?> cmdClass = Class.forName(job.getCmd());
             cmdObj = (BaseAsyncCmd)cmdClass.newInstance();
             cmdObj = ComponentContext.inject(cmdObj);
             cmdObj.configure();
             cmdObj.setJob(job);
 
-            Type mapType = new TypeToken<Map<String, String>>() {
+            final Type mapType = new TypeToken<Map<String, String>>() {
             }.getType();
-            Gson gson = ApiGsonHelper.getBuilder().create();
-            Map<String, String> params = gson.fromJson(job.getCmdInfo(), mapType);
+            final Gson gson = ApiGsonHelper.getBuilder().create();
+            final Map<String, Object> params = gson.fromJson(job.getCmdInfo(), mapType);
 
             // whenever we deserialize, the UserContext needs to be updated
-            String userIdStr = params.get("ctxUserId");
-            String acctIdStr = params.get("ctxAccountId");
+            final String userIdStr = (String) params.get("ctxUserId");
+            final String acctIdStr = (String) params.get("ctxAccountId");
             Long userId = null;
             Account accountObject = null;
 
             if (cmdObj instanceof BaseAsyncCreateCmd) {
-                BaseAsyncCreateCmd create = (BaseAsyncCreateCmd)cmdObj;
-                create.setEntityId(Long.parseLong(params.get("id")));
-                create.setEntityUuid(params.get("uuid"));
+                final BaseAsyncCreateCmd create = (BaseAsyncCreateCmd)cmdObj;
+                create.setEntityId(Long.parseLong((String) params.get("id")));
+                create.setEntityUuid((String) params.get("uuid"));
             }
 
             User user = null;
@@ -116,19 +116,19 @@ public class ApiAsyncJobDispatcher extends AdapterBase implements AsyncJobDispat
             } finally {
                 CallContext.unregister();
             }
-        } catch (Throwable e) {
+        } catch (final Throwable e) {
             String errorMsg = null;
             int errorCode = ApiErrorCode.INTERNAL_ERROR.getHttpCode();
             if (!(e instanceof ServerApiException)) {
                 s_logger.error("Unexpected exception while executing " + job.getCmd(), e);
                 errorMsg = e.getMessage();
             } else {
-                ServerApiException sApiEx = (ServerApiException)e;
+                final ServerApiException sApiEx = (ServerApiException)e;
                 errorMsg = sApiEx.getDescription();
                 errorCode = sApiEx.getErrorCode().getHttpCode();
             }
 
-            ExceptionResponse response = new ExceptionResponse();
+            final ExceptionResponse response = new ExceptionResponse();
             response.setErrorCode(errorCode);
             response.setErrorText(errorMsg);
             response.setResponseName((cmdObj == null) ? "unknowncommandresponse" : cmdObj.getCommandName());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/ApiDispatcher.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiDispatcher.java b/server/src/com/cloud/api/ApiDispatcher.java
index 55ef53a..19406c2 100755
--- a/server/src/com/cloud/api/ApiDispatcher.java
+++ b/server/src/com/cloud/api/ApiDispatcher.java
@@ -16,125 +16,65 @@
 // under the License.
 package com.cloud.api;
 
-import static org.apache.commons.lang.StringUtils.isNotBlank;
-
-import java.lang.reflect.Field;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.regex.Matcher;
 
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 
 import org.apache.log4j.Logger;
-
-import org.apache.cloudstack.acl.ControlledEntity;
-import org.apache.cloudstack.acl.InfrastructureEntity;
-import org.apache.cloudstack.acl.RoleType;
-import org.apache.cloudstack.acl.SecurityChecker.AccessType;
-import org.apache.cloudstack.api.ACL;
 import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.ApiErrorCode;
 import org.apache.cloudstack.api.BaseAsyncCmd;
 import org.apache.cloudstack.api.BaseAsyncCreateCmd;
 import org.apache.cloudstack.api.BaseCmd;
-import org.apache.cloudstack.api.BaseCmd.CommandType;
-import org.apache.cloudstack.api.BaseListCmd;
-import org.apache.cloudstack.api.EntityReference;
-import org.apache.cloudstack.api.InternalIdentity;
-import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
-import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd;
-import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd;
-import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd;
-import org.apache.cloudstack.api.command.user.event.DeleteEventsCmd;
-import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.framework.jobs.AsyncJob;
 import org.apache.cloudstack.framework.jobs.AsyncJobManager;
 
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.user.Account;
-import com.cloud.user.AccountManager;
-import com.cloud.utils.DateUtil;
-import com.cloud.utils.ReflectUtil;
-import com.cloud.utils.db.EntityManager;
-import com.cloud.utils.exception.CSExceptionErrorCode;
-import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.api.dispatch.DispatchChain;
+import com.cloud.api.dispatch.DispatchChainFactory;
 
 public class ApiDispatcher {
     private static final Logger s_logger = Logger.getLogger(ApiDispatcher.class.getName());
 
     Long _createSnapshotQueueSizeLimit;
+
     @Inject
     AsyncJobManager _asyncMgr = null;
-    @Inject
-    AccountManager _accountMgr = null;
-    @Inject
-    EntityManager _entityMgr = null;
 
-    private static ApiDispatcher s_instance;
+    @Inject()
+    protected DispatchChainFactory dispatchChainFactory = null;
 
-    public static ApiDispatcher getInstance() {
-        return s_instance;
-    }
+    protected DispatchChain standardDispatchChain = null;
+
+    protected DispatchChain asyncCreationDispatchChain = null;
 
     public ApiDispatcher() {
     }
 
     @PostConstruct
-    void init() {
-        s_instance = this;
+    public void setup() {
+        standardDispatchChain = dispatchChainFactory.getStandardDispatchChain();
+        asyncCreationDispatchChain = dispatchChainFactory.getAsyncCreationDispatchChain();
     }
 
-    public void setCreateSnapshotQueueSizeLimit(Long snapshotLimit) {
+    public void setCreateSnapshotQueueSizeLimit(final Long snapshotLimit) {
         _createSnapshotQueueSizeLimit = snapshotLimit;
     }
 
-    public void dispatchCreateCmd(BaseAsyncCreateCmd cmd, Map<String, String> params) throws Exception {
-        processParameters(cmd, params);
-
-        cmd.create();
-
+    public void dispatchCreateCmd(final BaseAsyncCreateCmd cmd, final Map<String, Object> params) throws Exception {
+        asyncCreationDispatchChain.dispatch(cmd, params);
     }
 
-    private void doAccessChecks(BaseCmd cmd, Map<Object, AccessType> entitiesToAccess) {
-        Account caller = CallContext.current().getCallingAccount();
-        Account owner = _accountMgr.getActiveAccountById(cmd.getEntityOwnerId());
+    public void dispatch(final BaseCmd cmd, final Map<String, Object> params, final boolean execute) throws Exception {
+        // Let the chain of responsibility dispatch gradually
+        standardDispatchChain.dispatch(cmd, params);
 
-        if (cmd instanceof BaseAsyncCreateCmd) {
-            //check that caller can access the owner account.
-            _accountMgr.checkAccess(caller, null, true, owner);
-        }
-
-        if (!entitiesToAccess.isEmpty()) {
-            //check that caller can access the owner account.
-            _accountMgr.checkAccess(caller, null, true, owner);
-            for (Object entity : entitiesToAccess.keySet()) {
-                if (entity instanceof ControlledEntity) {
-                    _accountMgr.checkAccess(caller, entitiesToAccess.get(entity), true, (ControlledEntity)entity);
-                } else if (entity instanceof InfrastructureEntity) {
-                    //FIXME: Move this code in adapter, remove code from Account manager
-                }
-            }
-        }
-    }
-
-    public void dispatch(BaseCmd cmd, Map<String, String> params, boolean execute) throws Exception {
-        processParameters(cmd, params);
-        CallContext ctx = CallContext.current();
+        final CallContext ctx = CallContext.current();
 
         if (cmd instanceof BaseAsyncCmd) {
 
-            BaseAsyncCmd asyncCmd = (BaseAsyncCmd)cmd;
-            String startEventId = params.get("ctxStartEventId");
+            final BaseAsyncCmd asyncCmd = (BaseAsyncCmd)cmd;
+            final String startEventId = (String) params.get(ApiConstants.CTX_START_EVENT_ID);
             ctx.setStartEventId(Long.valueOf(startEventId));
 
             // Synchronise job on the object if needed
@@ -158,392 +98,6 @@ public class ApiDispatcher {
             }
         }
         cmd.execute();
-
-    }
-
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    public static void processParameters(BaseCmd cmd, Map<String, String> params) {
-        Map<Object, AccessType> entitiesToAccess = new HashMap<Object, AccessType>();
-        Map<String, Object> unpackedParams = cmd.unpackParams(params);
-
-        if (cmd instanceof BaseListCmd) {
-            Object pageSizeObj = unpackedParams.get(ApiConstants.PAGE_SIZE);
-            Long pageSize = null;
-            if (pageSizeObj != null) {
-                pageSize = Long.valueOf((String)pageSizeObj);
-            }
-
-            if ((unpackedParams.get(ApiConstants.PAGE) == null) && (pageSize != null && !pageSize.equals(BaseListCmd.s_pageSizeUnlimited))) {
-                ServerApiException ex = new ServerApiException(ApiErrorCode.PARAM_ERROR, "\"page\" parameter is required when \"pagesize\" is specified");
-                ex.setCSErrorCode(CSExceptionErrorCode.getCSErrCode(ex.getClass().getName()));
-                throw ex;
-            } else if (pageSize == null && (unpackedParams.get(ApiConstants.PAGE) != null)) {
-                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "\"pagesize\" parameter is required when \"page\" is specified");
-            }
-        }
-
-        List<Field> fields = ReflectUtil.getAllFieldsForClass(cmd.getClass(), BaseCmd.class);
-
-        for (Field field : fields) {
-            Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
-            if ((parameterAnnotation == null) || !parameterAnnotation.expose()) {
-                continue;
-            }
-
-            //TODO: Annotate @Validate on API Cmd classes, FIXME how to process Validate
-            RoleType[] allowedRoles = parameterAnnotation.authorized();
-            if (allowedRoles.length > 0) {
-                boolean permittedParameter = false;
-                Account caller = CallContext.current().getCallingAccount();
-                for (RoleType allowedRole : allowedRoles) {
-                    if (allowedRole.getValue() == caller.getType()) {
-                        permittedParameter = true;
-                        break;
-                    }
-                }
-                if (!permittedParameter) {
-                    s_logger.debug("Ignoring paremeter " + parameterAnnotation.name() + " as the caller is not authorized to pass it in");
-                    continue;
-                }
-            }
-
-            Object paramObj = unpackedParams.get(parameterAnnotation.name());
-            if (paramObj == null) {
-                if (parameterAnnotation.required()) {
-                    throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to execute API command " +
-                        cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to missing parameter " + parameterAnnotation.name());
-                }
-                continue;
-            }
-
-            // marshall the parameter into the correct type and set the field value
-            try {
-                setFieldValue(field, cmd, paramObj, parameterAnnotation);
-            } catch (IllegalArgumentException argEx) {
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Unable to execute API command " + cmd.getCommandName() + " due to invalid value " + paramObj + " for parameter " +
-                        parameterAnnotation.name());
-                }
-                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to execute API command " +
-                    cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value " + paramObj + " for parameter " +
-                    parameterAnnotation.name());
-            } catch (ParseException parseEx) {
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Invalid date parameter " + paramObj + " passed to command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8));
-                }
-                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to parse date " + paramObj + " for command " +
-                    cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + ", please pass dates in the format mentioned in the api documentation");
-            } catch (InvalidParameterValueException invEx) {
-                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to execute API command " +
-                    cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value. " + invEx.getMessage());
-            } catch (CloudRuntimeException cloudEx) {
-                s_logger.error("CloudRuntimeException", cloudEx);
-                // FIXME: Better error message? This only happens if the API command is not executable, which typically
-                //means
-                // there was
-                // and IllegalAccessException setting one of the parameters.
-                throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Internal error executing API command " +
-                    cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8));
-            }
-
-            //check access on the resource this field points to
-            try {
-                ACL checkAccess = field.getAnnotation(ACL.class);
-                CommandType fieldType = parameterAnnotation.type();
-
-                if (checkAccess != null) {
-                    // Verify that caller can perform actions in behalf of vm owner
-                    //acumulate all Controlled Entities together.
-
-                    //parse the array of resource types and in case of map check access on key or value or both as specified in @acl
-                    //implement external dao for classes that need findByName
-                    //for maps, specify access to be checkd on key or value.
-
-                    // find the controlled entity DBid by uuid
-                    if (parameterAnnotation.entityType() != null) {
-                        Class<?>[] entityList = parameterAnnotation.entityType()[0].getAnnotation(EntityReference.class).value();
-
-                        for (Class entity : entityList) {
-                            // Check if the parameter type is a single
-                            // Id or list of id's/name's
-                            switch (fieldType) {
-                                case LIST:
-                                    CommandType listType = parameterAnnotation.collectionType();
-                                    switch (listType) {
-                                        case LONG:
-                                        case UUID:
-                                            List<Long> listParam = (List<Long>)field.get(cmd);
-                                            for (Long entityId : listParam) {
-                                                Object entityObj = s_instance._entityMgr.findById(entity, entityId);
-                                                entitiesToAccess.put(entityObj, checkAccess.accessType());
-                                            }
-                                            break;
-                                        /*
-                                         * case STRING: List<String> listParam =
-                                         * new ArrayList<String>(); listParam =
-                                         * (List)field.get(cmd); for(String
-                                         * entityName: listParam){
-                                         * ControlledEntity entityObj =
-                                         * (ControlledEntity
-                                         * )daoClassInstance(entityId);
-                                         * entitiesToAccess.add(entityObj); }
-                                         * break;
-                                         */
-                                        default:
-                                            break;
-                                    }
-                                    break;
-                                case LONG:
-                                case UUID:
-                                    Object entityObj = s_instance._entityMgr.findById(entity, (Long)field.get(cmd));
-                                    entitiesToAccess.put(entityObj, checkAccess.accessType());
-                                    break;
-                                default:
-                                    break;
-                            }
-
-                            if (ControlledEntity.class.isAssignableFrom(entity)) {
-                                if (s_logger.isDebugEnabled()) {
-                                    s_logger.debug("ControlledEntity name is:" + entity.getName());
-                                }
-                            }
-
-                            if (InfrastructureEntity.class.isAssignableFrom(entity)) {
-                                if (s_logger.isDebugEnabled()) {
-                                    s_logger.debug("InfrastructureEntity name is:" + entity.getName());
-                                }
-                            }
-                        }
-
-                    }
-
-                }
-
-            } catch (IllegalArgumentException e) {
-                s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
-                throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() +
-                    " is not accessible]");
-            } catch (IllegalAccessException e) {
-                s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
-                throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() +
-                    " is not accessible]");
-            }
-
-        }
-
-        //check access on the entities.
-        getInstance().doAccessChecks(cmd, entitiesToAccess);
-
-    }
-
-    private static Long translateUuidToInternalId(String uuid, Parameter annotation) {
-        if (uuid.equals("-1")) {
-            // FIXME: This is to handle a lot of hardcoded special cases where -1 is sent
-            // APITODO: Find and get rid of all hardcoded params in API Cmds and service layer
-            return -1L;
-        }
-        Long internalId = null;
-        // If annotation's empty, the cmd existed before 3.x try conversion to long
-        boolean isPre3x = annotation.since().isEmpty();
-        // Match against Java's UUID regex to check if input is uuid string
-        boolean isUuid = uuid.matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
-        // Enforce that it's uuid for newly added apis from version 3.x
-        if (!isPre3x && !isUuid)
-            return null;
-        // Allow both uuid and internal id for pre3x apis
-        if (isPre3x && !isUuid) {
-            try {
-                internalId = Long.parseLong(uuid);
-            } catch (NumberFormatException e) {
-                internalId = null;
-            }
-            if (internalId != null)
-                return internalId;
-        }
-        // There may be multiple entities defined on the @EntityReference of a Response.class
-        // UUID CommandType would expect only one entityType, so use the first entityType
-        Class<?>[] entities = annotation.entityType()[0].getAnnotation(EntityReference.class).value();
-        // Go through each entity which is an interface to a VO class and get a VO object
-        // Try to getId() for the object using reflection, break on first non-null value
-        for (Class<?> entity : entities) {
-            // For backward compatibility, we search within removed entities and let service layer deal
-            // with removed ones, return empty response or error
-            Object objVO = s_instance._entityMgr.findByUuidIncludingRemoved(entity, uuid);
-            if (objVO == null) {
-                continue;
-            }
-            // Invoke the getId method, get the internal long ID
-            // If that fails hide exceptions as the uuid may not exist
-            try {
-                internalId = ((InternalIdentity)objVO).getId();
-            } catch (IllegalArgumentException e) {
-            } catch (NullPointerException e) {
-            }
-            // Return on first non-null Id for the uuid entity
-            if (internalId != null)
-                break;
-        }
-        if (internalId == null) {
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Object entity uuid = " + uuid + " does not exist in the database.");
-            throw new InvalidParameterValueException("Invalid parameter " + annotation.name() + " value=" + uuid +
-                " due to incorrect long value format, or entity does not exist or due to incorrect parameter annotation for the field in api cmd class.");
-        }
-        return internalId;
-    }
-
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    private static void setFieldValue(Field field, BaseCmd cmdObj, Object paramObj, Parameter annotation) throws IllegalArgumentException, ParseException {
-        try {
-            field.setAccessible(true);
-            CommandType fieldType = annotation.type();
-            switch (fieldType) {
-                case BOOLEAN:
-                    field.set(cmdObj, Boolean.valueOf(paramObj.toString()));
-                    break;
-                case DATE:
-                    // This piece of code is for maintaining backward compatibility
-                    // and support both the date formats(Bug 9724)
-                    // Do the date messaging for ListEventsCmd only
-                    if (cmdObj instanceof ListEventsCmd || cmdObj instanceof DeleteEventsCmd || cmdObj instanceof ArchiveEventsCmd ||
-                        cmdObj instanceof ArchiveAlertsCmd || cmdObj instanceof DeleteAlertsCmd) {
-                        boolean isObjInNewDateFormat = isObjInNewDateFormat(paramObj.toString());
-                        if (isObjInNewDateFormat) {
-                            DateFormat newFormat = BaseCmd.NEW_INPUT_FORMAT;
-                            synchronized (newFormat) {
-                                field.set(cmdObj, newFormat.parse(paramObj.toString()));
-                            }
-                        } else {
-                            DateFormat format = BaseCmd.INPUT_FORMAT;
-                            synchronized (format) {
-                                Date date = format.parse(paramObj.toString());
-                                if (field.getName().equals("startDate")) {
-                                    date = messageDate(date, 0, 0, 0);
-                                } else if (field.getName().equals("endDate")) {
-                                    date = messageDate(date, 23, 59, 59);
-                                }
-                                field.set(cmdObj, date);
-                            }
-                        }
-                    } else {
-                        DateFormat format = BaseCmd.INPUT_FORMAT;
-                        synchronized (format) {
-                        format.setLenient(false);
-                            field.set(cmdObj, format.parse(paramObj.toString()));
-                        }
-                    }
-                    break;
-                case FLOAT:
-                    // Assuming that the parameters have been checked for required before now,
-                    // we ignore blank or null values and defer to the command to set a default
-                    // value for optional parameters ...
-                    if (paramObj != null && isNotBlank(paramObj.toString())) {
-                        field.set(cmdObj, Float.valueOf(paramObj.toString()));
-                    }
-                    break;
-                case INTEGER:
-                    // Assuming that the parameters have been checked for required before now,
-                    // we ignore blank or null values and defer to the command to set a default
-                    // value for optional parameters ...
-                    if (paramObj != null && isNotBlank(paramObj.toString())) {
-                        field.set(cmdObj, Integer.valueOf(paramObj.toString()));
-                    }
-                    break;
-                case LIST:
-                    List listParam = new ArrayList();
-                    StringTokenizer st = new StringTokenizer(paramObj.toString(), ",");
-                    while (st.hasMoreTokens()) {
-                        String token = st.nextToken();
-                        CommandType listType = annotation.collectionType();
-                        switch (listType) {
-                            case INTEGER:
-                                listParam.add(Integer.valueOf(token));
-                                break;
-                            case UUID:
-                                if (token.isEmpty())
-                                    break;
-                                Long internalId = translateUuidToInternalId(token, annotation);
-                                listParam.add(internalId);
-                                break;
-                            case LONG: {
-                                listParam.add(Long.valueOf(token));
-                            }
-                                break;
-                            case SHORT:
-                                listParam.add(Short.valueOf(token));
-                            case STRING:
-                                listParam.add(token);
-                                break;
-                        }
-                    }
-                    field.set(cmdObj, listParam);
-                    break;
-                case UUID:
-                    if (paramObj.toString().isEmpty())
-                        break;
-                    Long internalId = translateUuidToInternalId(paramObj.toString(), annotation);
-                    field.set(cmdObj, internalId);
-                    break;
-                case LONG:
-                    field.set(cmdObj, Long.valueOf(paramObj.toString()));
-                    break;
-                case SHORT:
-                    field.set(cmdObj, Short.valueOf(paramObj.toString()));
-                    break;
-                case STRING:
-                    if ((paramObj != null) && paramObj.toString().length() > annotation.length()) {
-                        s_logger.error("Value greater than max allowed length " + annotation.length() + " for param: " + field.getName());
-                        throw new InvalidParameterValueException("Value greater than max allowed length " + annotation.length() + " for param: " + field.getName());
-                    }
-                    field.set(cmdObj, paramObj.toString());
-                    break;
-                case TZDATE:
-                    field.set(cmdObj, DateUtil.parseTZDateString(paramObj.toString()));
-                    break;
-                case MAP:
-                default:
-                    field.set(cmdObj, paramObj);
-                    break;
-            }
-        } catch (IllegalAccessException ex) {
-            s_logger.error("Error initializing command " + cmdObj.getCommandName() + ", field " + field.getName() + " is not accessible.");
-            throw new CloudRuntimeException("Internal error initializing parameters for command " + cmdObj.getCommandName() + " [field " + field.getName() +
-                " is not accessible]");
-        }
     }
 
-    private static boolean isObjInNewDateFormat(String string) {
-        Matcher matcher = BaseCmd.newInputDateFormat.matcher(string);
-        return matcher.matches();
-    }
-
-    private static Date messageDate(Date date, int hourOfDay, int minute, int second) {
-        Calendar cal = Calendar.getInstance();
-        cal.setTime(date);
-        cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
-        cal.set(Calendar.MINUTE, minute);
-        cal.set(Calendar.SECOND, second);
-        return cal.getTime();
-    }
-
-    public static void plugService(Field field, BaseCmd cmd) {
-
-        Class<?> fc = field.getType();
-        Object instance = null;
-
-        if (instance == null) {
-            throw new CloudRuntimeException("Unable to plug service " + fc.getSimpleName() + " in command " + cmd.getClass().getSimpleName());
-        }
-
-        try {
-            field.setAccessible(true);
-            field.set(cmd, instance);
-        } catch (IllegalArgumentException e) {
-            s_logger.error("IllegalArgumentException at plugService for command " + cmd.getCommandName() + ", field " + field.getName());
-            throw new CloudRuntimeException("Internal error at plugService for command " + cmd.getCommandName() + " [Illegal argumet at field " + field.getName() + "]");
-        } catch (IllegalAccessException e) {
-            s_logger.error("Error at plugService for command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
-            throw new CloudRuntimeException("Internal error at plugService for command " + cmd.getCommandName() + " [field " + field.getName() + " is not accessible]");
-        }
-    }
 }


[4/6] CLOUDSTACK-6003 fixing plus refactoring dispatcher

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/dispatch/DispatchChainFactory.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/dispatch/DispatchChainFactory.java b/server/src/com/cloud/api/dispatch/DispatchChainFactory.java
new file mode 100644
index 0000000..f3c6973
--- /dev/null
+++ b/server/src/com/cloud/api/dispatch/DispatchChainFactory.java
@@ -0,0 +1,68 @@
+// 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 com.cloud.api.dispatch;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import com.cloud.user.AccountManager;
+
+public class DispatchChainFactory {
+
+    @Inject
+    protected AccountManager _accountMgr = null;
+
+    @Inject
+    protected ParamGenericValidationWorker paramGenericValidationWorker = null;
+
+    @Inject
+    protected ParamProcessWorker paramProcessWorker = null;
+
+    @Inject
+    protected ParamSemanticValidationWorker paramSemanticValidationWorker = null;
+
+    @Inject
+    protected CommandCreationWorker commandCreationWorker = null;
+
+    protected DispatchChain standardDispatchChain = null;
+
+    protected DispatchChain asyncCreationDispatchChain = null;
+
+    @PostConstruct
+    public void setup() {
+        standardDispatchChain = new DispatchChain().
+                add(paramGenericValidationWorker).
+                add(paramProcessWorker).
+                add(paramSemanticValidationWorker);
+
+        asyncCreationDispatchChain = new DispatchChain().
+                add(paramGenericValidationWorker).
+                add(paramProcessWorker).
+                add(paramSemanticValidationWorker).
+                add(commandCreationWorker);
+
+    }
+
+    public DispatchChain getStandardDispatchChain() {
+        return standardDispatchChain;
+    }
+
+    public DispatchChain getAsyncCreationDispatchChain() {
+        return asyncCreationDispatchChain;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/dispatch/DispatchWorker.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/dispatch/DispatchWorker.java b/server/src/com/cloud/api/dispatch/DispatchWorker.java
new file mode 100644
index 0000000..5f2b592
--- /dev/null
+++ b/server/src/com/cloud/api/dispatch/DispatchWorker.java
@@ -0,0 +1,34 @@
+// 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 com.cloud.api.dispatch;
+
+import java.util.Map;
+
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.ServerApiException;
+
+public interface DispatchWorker {
+
+    /**
+    *
+    * @return false to stop the chain of responsibility, true
+    * to continue the chain with the next worker
+    */
+    public boolean handle(BaseCmd cmd, Map<String, Object> params)
+            throws ServerApiException;
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java b/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java
new file mode 100644
index 0000000..edc1510
--- /dev/null
+++ b/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java
@@ -0,0 +1,95 @@
+// 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 com.cloud.api.dispatch;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+
+/**
+ * This worker validates parameters in a generic way, by using annotated
+ * restrictions without involving the {@Link BaseCmd}. This worker doesn't
+ * know or care about the meaning of the parameters and that's why we can
+ * have it out of the {@Link BaseCmd}
+ *
+ * @author afornie
+ */
+public class ParamGenericValidationWorker implements DispatchWorker {
+
+    protected static Logger s_logger = Logger.getLogger(ParamGenericValidationWorker.class.getName());
+
+    protected static List<String> defaultParamNames = new ArrayList<String>();
+
+    static {
+        defaultParamNames.add(ApiConstants.CTX_START_EVENT_ID);
+        defaultParamNames.add(ApiConstants.COMMAND);
+        defaultParamNames.add(ApiConstants.USERNAME);
+        defaultParamNames.add(ApiConstants.USER_ID);
+        defaultParamNames.add(ApiConstants.PASSWORD);
+        defaultParamNames.add(ApiConstants.DOMAIN);
+        defaultParamNames.add(ApiConstants.DOMAIN_ID);
+        defaultParamNames.add(ApiConstants.DOMAIN__ID);
+        defaultParamNames.add(ApiConstants.SESSIONKEY);
+        defaultParamNames.add(ApiConstants.RESPONSE);
+        defaultParamNames.add(ApiConstants.PAGE);
+        defaultParamNames.add(ApiConstants.PAGE_SIZE);
+        defaultParamNames.add(ApiConstants.HTTPMETHOD);
+        defaultParamNames.add("_");
+    }
+
+    protected static final String ERROR_MSG_PREFIX = "Unknown parameters :";
+
+    @Override
+    public boolean handle(final BaseCmd cmd, final Map<String, Object> params) {
+        final List<String> expectedParamNames = getParamNamesForCommand(cmd);
+
+        final StringBuilder errorMsg = new StringBuilder(ERROR_MSG_PREFIX);
+        boolean foundUnknownParam = false;
+        for (final String paramName : params.keySet()) {
+            if (!expectedParamNames.contains(paramName)) {
+                errorMsg.append(" ").append(paramName);
+                foundUnknownParam= true;
+            }
+        }
+
+        if (foundUnknownParam) {
+            s_logger.warn(String.format("Received unkown parameters for command %s. %s", cmd.getCommandName(), errorMsg));
+        }
+
+        return true;
+    }
+
+    protected List<String> getParamNamesForCommand(final BaseCmd cmd) {
+        final List<String> paramNames = new ArrayList<String>();
+        // The expected param names are all the specific for the current command class ...
+        for (final Field field : cmd.getParamFields()) {
+            final Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
+            paramNames.add(parameterAnnotation.name());
+        }
+        // ... plus the default ones
+        paramNames.addAll(defaultParamNames);
+        return paramNames;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/dispatch/ParamProcessWorker.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/dispatch/ParamProcessWorker.java b/server/src/com/cloud/api/dispatch/ParamProcessWorker.java
new file mode 100644
index 0000000..6c058c3
--- /dev/null
+++ b/server/src/com/cloud/api/dispatch/ParamProcessWorker.java
@@ -0,0 +1,429 @@
+// 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 com.cloud.api.dispatch;
+
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+
+import java.lang.reflect.Field;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.ControlledEntity;
+import org.apache.cloudstack.acl.InfrastructureEntity;
+import org.apache.cloudstack.acl.SecurityChecker.AccessType;
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCreateCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.api.InternalIdentity;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.BaseCmd.CommandType;
+import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd;
+import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd;
+import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd;
+import org.apache.cloudstack.api.command.user.event.DeleteEventsCmd;
+import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.utils.DateUtil;
+import com.cloud.utils.db.EntityManager;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+public class ParamProcessWorker implements DispatchWorker {
+
+    private static final Logger s_logger = Logger.getLogger(ParamProcessWorker.class.getName());
+
+    @Inject
+    protected AccountManager _accountMgr = null;
+
+    @Inject
+    protected EntityManager _entityMgr = null;
+
+    @Override
+    public boolean handle(final BaseCmd cmd, final Map<String, Object> params) {
+        processParameters(cmd, params);
+        return true;
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public void processParameters(final BaseCmd cmd, final Map<String, Object> params) {
+        final Map<Object, AccessType> entitiesToAccess = new HashMap<Object, AccessType>();
+
+        final List<Field> cmdFields = cmd.getParamFields();
+
+        for (final Field field : cmdFields) {
+            final Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
+            final Object paramObj = params.get(parameterAnnotation.name());
+            if (paramObj == null) {
+                if (parameterAnnotation.required()) {
+                    throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to execute API command " +
+                        cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) +
+                        " due to missing parameter " + parameterAnnotation.name());
+                }
+                continue;
+            }
+
+            // marshall the parameter into the correct type and set the field value
+            try {
+                setFieldValue(field, cmd, paramObj, parameterAnnotation);
+            } catch (final IllegalArgumentException argEx) {
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("Unable to execute API command " + cmd.getCommandName() + " due to invalid value " + paramObj + " for parameter " +
+                            parameterAnnotation.name());
+                }
+                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to execute API command " +
+                    cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value " + paramObj + " for parameter " +
+                    parameterAnnotation.name());
+            } catch (final ParseException parseEx) {
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("Invalid date parameter " + paramObj + " passed to command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8));
+                }
+                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to parse date " + paramObj + " for command " +
+                    cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + ", please pass dates in the format mentioned in the api documentation");
+            } catch (final InvalidParameterValueException invEx) {
+                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to execute API command " +
+                    cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value. " + invEx.getMessage());
+            } catch (final CloudRuntimeException cloudEx) {
+                s_logger.error("CloudRuntimeException", cloudEx);
+                // FIXME: Better error message? This only happens if the API command is not executable, which typically
+                //means
+                // there was
+                // and IllegalAccessException setting one of the parameters.
+                throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Internal error executing API command " +
+                    cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8));
+            }
+
+            //check access on the resource this field points to
+            try {
+                final ACL checkAccess = field.getAnnotation(ACL.class);
+                final CommandType fieldType = parameterAnnotation.type();
+
+                if (checkAccess != null) {
+                    // Verify that caller can perform actions in behalf of vm owner
+                    //acumulate all Controlled Entities together.
+
+                    //parse the array of resource types and in case of map check access on key or value or both as specified in @acl
+                    //implement external dao for classes that need findByName
+                    //for maps, specify access to be checkd on key or value.
+
+                    // find the controlled entity DBid by uuid
+                    if (parameterAnnotation.entityType() != null) {
+                        final Class<?>[] entityList = parameterAnnotation.entityType()[0].getAnnotation(EntityReference.class).value();
+
+                        for (final Class entity : entityList) {
+                            // Check if the parameter type is a single
+                            // Id or list of id's/name's
+                            switch (fieldType) {
+                                case LIST:
+                                    final CommandType listType = parameterAnnotation.collectionType();
+                                    switch (listType) {
+                                        case LONG:
+                                        case UUID:
+                                            final List<Long> listParam = (List<Long>)field.get(cmd);
+                                            for (final Long entityId : listParam) {
+                                                final Object entityObj = _entityMgr.findById(entity, entityId);
+                                                entitiesToAccess.put(entityObj, checkAccess.accessType());
+                                            }
+                                            break;
+                                        /*
+                                         * case STRING: List<String> listParam =
+                                         * new ArrayList<String>(); listParam =
+                                         * (List)field.get(cmd); for(String
+                                         * entityName: listParam){
+                                         * ControlledEntity entityObj =
+                                         * (ControlledEntity
+                                         * )daoClassInstance(entityId);
+                                         * entitiesToAccess.add(entityObj); }
+                                         * break;
+                                         */
+                                        default:
+                                            break;
+                                    }
+                                    break;
+                                case LONG:
+                                case UUID:
+                                    final Object entityObj = _entityMgr.findById(entity, (Long)field.get(cmd));
+                                    entitiesToAccess.put(entityObj, checkAccess.accessType());
+                                    break;
+                                default:
+                                    break;
+                            }
+
+                            if (ControlledEntity.class.isAssignableFrom(entity)) {
+                                if (s_logger.isDebugEnabled()) {
+                                    s_logger.debug("ControlledEntity name is:" + entity.getName());
+                                }
+                            }
+
+                            if (InfrastructureEntity.class.isAssignableFrom(entity)) {
+                                if (s_logger.isDebugEnabled()) {
+                                    s_logger.debug("InfrastructureEntity name is:" + entity.getName());
+                                }
+                            }
+                        }
+
+                    }
+
+                }
+
+            } catch (final IllegalArgumentException e) {
+                s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
+                throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() +
+                    " is not accessible]");
+            } catch (final IllegalAccessException e) {
+                s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
+                throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() +
+                    " is not accessible]");
+            }
+
+        }
+
+        doAccessChecks(cmd, entitiesToAccess);
+    }
+
+
+    private void doAccessChecks(final BaseCmd cmd, final Map<Object, AccessType> entitiesToAccess) {
+        final Account caller = CallContext.current().getCallingAccount();
+        final Account owner = _accountMgr.getActiveAccountById(cmd.getEntityOwnerId());
+
+        if (cmd instanceof BaseAsyncCreateCmd) {
+            //check that caller can access the owner account.
+            _accountMgr.checkAccess(caller, null, true, owner);
+        }
+
+        if (!entitiesToAccess.isEmpty()) {
+            //check that caller can access the owner account.
+            _accountMgr.checkAccess(caller, null, true, owner);
+            for (final Object entity : entitiesToAccess.keySet()) {
+                if (entity instanceof ControlledEntity) {
+                    _accountMgr.checkAccess(caller, entitiesToAccess.get(entity), true, (ControlledEntity)entity);
+                } else if (entity instanceof InfrastructureEntity) {
+                    //FIXME: Move this code in adapter, remove code from Account manager
+                }
+            }
+        }
+    }
+
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    private void setFieldValue(final Field field, final BaseCmd cmdObj, final Object paramObj, final Parameter annotation) throws IllegalArgumentException, ParseException {
+        try {
+            field.setAccessible(true);
+            final CommandType fieldType = annotation.type();
+            switch (fieldType) {
+                case BOOLEAN:
+                    field.set(cmdObj, Boolean.valueOf(paramObj.toString()));
+                    break;
+                case DATE:
+                    // This piece of code is for maintaining backward compatibility
+                    // and support both the date formats(Bug 9724)
+                    // Do the date messaging for ListEventsCmd only
+                    if (cmdObj instanceof ListEventsCmd || cmdObj instanceof DeleteEventsCmd || cmdObj instanceof ArchiveEventsCmd ||
+                        cmdObj instanceof ArchiveAlertsCmd || cmdObj instanceof DeleteAlertsCmd) {
+                        final boolean isObjInNewDateFormat = isObjInNewDateFormat(paramObj.toString());
+                        if (isObjInNewDateFormat) {
+                            final DateFormat newFormat = BaseCmd.NEW_INPUT_FORMAT;
+                            synchronized (newFormat) {
+                                field.set(cmdObj, newFormat.parse(paramObj.toString()));
+                            }
+                        } else {
+                            final DateFormat format = BaseCmd.INPUT_FORMAT;
+                            synchronized (format) {
+                                Date date = format.parse(paramObj.toString());
+                                if (field.getName().equals("startDate")) {
+                                    date = messageDate(date, 0, 0, 0);
+                                } else if (field.getName().equals("endDate")) {
+                                    date = messageDate(date, 23, 59, 59);
+                                }
+                                field.set(cmdObj, date);
+                            }
+                        }
+                    } else {
+                        final DateFormat format = BaseCmd.INPUT_FORMAT;
+                        format.setLenient(false);
+                        synchronized (format) {
+                            field.set(cmdObj, format.parse(paramObj.toString()));
+                        }
+                    }
+                    break;
+                case FLOAT:
+                    // Assuming that the parameters have been checked for required before now,
+                    // we ignore blank or null values and defer to the command to set a default
+                    // value for optional parameters ...
+                    if (paramObj != null && isNotBlank(paramObj.toString())) {
+                        field.set(cmdObj, Float.valueOf(paramObj.toString()));
+                    }
+                    break;
+                case INTEGER:
+                    // Assuming that the parameters have been checked for required before now,
+                    // we ignore blank or null values and defer to the command to set a default
+                    // value for optional parameters ...
+                    if (paramObj != null && isNotBlank(paramObj.toString())) {
+                        field.set(cmdObj, Integer.valueOf(paramObj.toString()));
+                    }
+                    break;
+                case LIST:
+                    final List listParam = new ArrayList();
+                    final StringTokenizer st = new StringTokenizer(paramObj.toString(), ",");
+                    while (st.hasMoreTokens()) {
+                        final String token = st.nextToken();
+                        final CommandType listType = annotation.collectionType();
+                        switch (listType) {
+                            case INTEGER:
+                                listParam.add(Integer.valueOf(token));
+                                break;
+                            case UUID:
+                                if (token.isEmpty())
+                                    break;
+                                final Long internalId = translateUuidToInternalId(token, annotation);
+                                listParam.add(internalId);
+                                break;
+                            case LONG: {
+                                listParam.add(Long.valueOf(token));
+                            }
+                                break;
+                            case SHORT:
+                                listParam.add(Short.valueOf(token));
+                            case STRING:
+                                listParam.add(token);
+                                break;
+                        }
+                    }
+                    field.set(cmdObj, listParam);
+                    break;
+                case UUID:
+                    if (paramObj.toString().isEmpty())
+                        break;
+                    final Long internalId = translateUuidToInternalId(paramObj.toString(), annotation);
+                    field.set(cmdObj, internalId);
+                    break;
+                case LONG:
+                    field.set(cmdObj, Long.valueOf(paramObj.toString()));
+                    break;
+                case SHORT:
+                    field.set(cmdObj, Short.valueOf(paramObj.toString()));
+                    break;
+                case STRING:
+                    if ((paramObj != null) && paramObj.toString().length() > annotation.length()) {
+                        s_logger.error("Value greater than max allowed length " + annotation.length() + " for param: " + field.getName());
+                        throw new InvalidParameterValueException("Value greater than max allowed length " + annotation.length() + " for param: " + field.getName());
+                    }
+                    field.set(cmdObj, paramObj.toString());
+                    break;
+                case TZDATE:
+                    field.set(cmdObj, DateUtil.parseTZDateString(paramObj.toString()));
+                    break;
+                case MAP:
+                default:
+                    field.set(cmdObj, paramObj);
+                    break;
+            }
+        } catch (final IllegalAccessException ex) {
+            s_logger.error("Error initializing command " + cmdObj.getCommandName() + ", field " + field.getName() + " is not accessible.");
+            throw new CloudRuntimeException("Internal error initializing parameters for command " + cmdObj.getCommandName() + " [field " + field.getName() +
+                " is not accessible]");
+        }
+    }
+
+    private boolean isObjInNewDateFormat(final String string) {
+        final Matcher matcher = BaseCmd.newInputDateFormat.matcher(string);
+        return matcher.matches();
+    }
+
+    private Date messageDate(final Date date, final int hourOfDay, final int minute, final int second) {
+        final Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
+        cal.set(Calendar.MINUTE, minute);
+        cal.set(Calendar.SECOND, second);
+        return cal.getTime();
+    }
+
+    private Long translateUuidToInternalId(final String uuid, final Parameter annotation) {
+        if (uuid.equals("-1")) {
+            // FIXME: This is to handle a lot of hardcoded special cases where -1 is sent
+            // APITODO: Find and get rid of all hardcoded params in API Cmds and service layer
+            return -1L;
+        }
+        Long internalId = null;
+        // If annotation's empty, the cmd existed before 3.x try conversion to long
+        final boolean isPre3x = annotation.since().isEmpty();
+        // Match against Java's UUID regex to check if input is uuid string
+        final boolean isUuid = uuid.matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
+        // Enforce that it's uuid for newly added apis from version 3.x
+        if (!isPre3x && !isUuid)
+            return null;
+        // Allow both uuid and internal id for pre3x apis
+        if (isPre3x && !isUuid) {
+            try {
+                internalId = Long.parseLong(uuid);
+            } catch (final NumberFormatException e) {
+                internalId = null;
+            }
+            if (internalId != null)
+                return internalId;
+        }
+        // There may be multiple entities defined on the @EntityReference of a Response.class
+        // UUID CommandType would expect only one entityType, so use the first entityType
+        final Class<?>[] entities = annotation.entityType()[0].getAnnotation(EntityReference.class).value();
+        // Go through each entity which is an interface to a VO class and get a VO object
+        // Try to getId() for the object using reflection, break on first non-null value
+        for (final Class<?> entity : entities) {
+            // For backward compatibility, we search within removed entities and let service layer deal
+            // with removed ones, return empty response or error
+            final Object objVO = _entityMgr.findByUuidIncludingRemoved(entity, uuid);
+            if (objVO == null) {
+                continue;
+            }
+            // Invoke the getId method, get the internal long ID
+            // If that fails hide exceptions as the uuid may not exist
+            try {
+                internalId = ((InternalIdentity)objVO).getId();
+            } catch (final IllegalArgumentException e) {
+            } catch (final NullPointerException e) {
+            }
+            // Return on first non-null Id for the uuid entity
+            if (internalId != null)
+                break;
+        }
+        if (internalId == null) {
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Object entity uuid = " + uuid + " does not exist in the database.");
+            throw new InvalidParameterValueException("Invalid parameter " + annotation.name() + " value=" + uuid +
+                " due to incorrect long value format, or entity does not exist or due to incorrect parameter annotation for the field in api cmd class.");
+        }
+        return internalId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/447430c3/server/src/com/cloud/api/dispatch/ParamSemanticValidationWorker.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/dispatch/ParamSemanticValidationWorker.java b/server/src/com/cloud/api/dispatch/ParamSemanticValidationWorker.java
new file mode 100644
index 0000000..4733dcc
--- /dev/null
+++ b/server/src/com/cloud/api/dispatch/ParamSemanticValidationWorker.java
@@ -0,0 +1,40 @@
+// 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 com.cloud.api.dispatch;
+
+import java.util.Map;
+
+import org.apache.cloudstack.api.BaseCmd;
+
+
+/**
+ * This worker validates parameters in a semantic way, that is of
+ * course specific for each {@link BaseCmd}, so actually it delegates
+ * the validation on the {@link BaseCmd} itself
+ *
+ * @author afornie
+ */
+public class ParamSemanticValidationWorker implements DispatchWorker {
+
+    @Override
+    public boolean handle(final BaseCmd cmd, final Map<String, Object> params) {
+        cmd.validateSpecificParameters(params);
+        return true;
+    }
+
+}