Mercurial > hg > release > thermostat-0.4
changeset 543:7c48230daefb
Client controllers
review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-August/002720.html
reviewed-by: omajid
PR 1107
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-controllers/pom.xml Fri Aug 17 12:52:08 2012 +0200 @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2012 Red Hat, Inc. + + This file is part of Thermostat. + + Thermostat is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + Thermostat is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Thermostat; see the file COPYING. If not see + <http://www.gnu.org/licenses />. + + Linking this code with other modules is making a combined work + based on this code. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + As a special exception, the copyright holders of this code give + you permission to link this code with independent modules to + produce an executable, regardless of the license terms of these + independent modules, and to copy and distribute the resulting + executable under terms of your choice, provided that you also + meet, for each linked independent module, the terms and conditions + of the license of that module. An independent module is a module + which is not derived from or based on this code. If you modify + this code, you may extend this exception to your version of the + library, but you are not obligated to do so. If you do not wish + to do so, delete this exception statement from your version. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-thread</artifactId> + <version>0.4.0-SNAPSHOT</version> + </parent> + + <artifactId>thermostat-thread-client-controllers</artifactId> + <packaging>bundle</packaging> + + <name>Thermostat Thread Info Client Controllers</name> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-common-core</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-client-core</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-thread-collector</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-thread-client-common</artifactId> + <version>${project.version}</version> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor> + <Bundle-Activator>com.redhat.thermostat.thread.client.controller.osgi.Activator</Bundle-Activator> + <Private-Package> + com.redhat.thermostat.thread.client.controller.osgi, + com.redhat.thermostat.thread.client.controller.impl, + </Private-Package> + <!-- Do not autogenerate uses clauses in Manifests --> + <_nouses>true</_nouses> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/CommonController.java Fri Aug 17 12:52:08 2012 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.controller.impl; + +public interface CommonController { + void initialise(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationController.java Fri Aug 17 12:52:08 2012 +0200 @@ -0,0 +1,205 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.controller.impl; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.client.osgi.service.ApplicationCache; +import com.redhat.thermostat.client.osgi.service.ApplicationService; +import com.redhat.thermostat.client.osgi.service.VmInformationServiceController; +import com.redhat.thermostat.client.osgi.service.BasicView.Action; +import com.redhat.thermostat.client.ui.UIComponent; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.NotImplementedException; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.Timer.SchedulingType; +import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.thread.client.common.ThreadView; +import com.redhat.thermostat.thread.client.common.ThreadViewProvider; +import com.redhat.thermostat.thread.client.common.VMThreadCapabilitiesView; +import com.redhat.thermostat.thread.client.common.ThreadView.ThreadAction; +import com.redhat.thermostat.thread.client.common.chart.LivingDaemonThreadDifferenceChart; + +import com.redhat.thermostat.thread.collector.ThreadCollector; +import com.redhat.thermostat.thread.collector.ThreadCollectorFactory; +import com.redhat.thermostat.thread.collector.ThreadSummary; +import com.redhat.thermostat.thread.collector.VMThreadCapabilities; + +public class ThreadInformationController implements VmInformationServiceController { + + private static final Logger logger = Logger.getLogger(ThreadInformationController.class.getSimpleName()); + + private ThreadView view; + private ThreadCollector collector; + private ApplicationService appService; + + private Timer timer; + private ApplicationCache cache; + + String CACHE_RECORDING_KEY = "thread-live-recording-"; + + private LivingDaemonThreadDifferenceChart model; + + public ThreadInformationController(VmRef ref, ApplicationService appService, + ThreadCollectorFactory collectorFactory, + ThreadViewProvider viewFactory) + { + CACHE_RECORDING_KEY = CACHE_RECORDING_KEY + ref.getStringID(); + + this.appService = appService; + cache = appService.getApplicationCache(); + + view = viewFactory.createView(); + collector = collectorFactory.getCollector(ref); + + initControllers(); + + timer = ApplicationContext.getInstance().getTimerFactory().createTimer(); + + timer.setInitialDelay(0); + timer.setDelay(1000); + timer.setTimeUnit(TimeUnit.MILLISECONDS); + timer.setSchedulingType(SchedulingType.FIXED_RATE); + + timer.setAction(new ThreadInformationDataCollector()); + + model = new LivingDaemonThreadDifferenceChart("Living Threads vs. Daemon Threads", + "time", "threads", "Living Threads", + "Daemon Threads"); + model.setMaximumItemCount(3600); + + view.addActionListener(new ActionListener<Action>() { + @Override + public void actionPerformed(ActionEvent<Action> actionEvent) { + switch (actionEvent.getActionId()) { + case HIDDEN: + timer.stop(); + break; + + case VISIBLE: + timer.start(); + break; + + default: + throw new NotImplementedException("unknown event: " + actionEvent.getActionId()); + } + } + }); + + view.setRecording(isRecording()); + view.addThreadActionListener(new ThreadActionListener()); + } + + private boolean isRecording() { + Boolean isRecording = (Boolean) cache.getAttribute(CACHE_RECORDING_KEY); + return (isRecording != null && isRecording); + } + + private void setRecording(boolean recording) { + cache.addAttribute(CACHE_RECORDING_KEY, recording); + } + + @Override + public String getLocalizedName() { + return "Threads"; + } + + @Override + public UIComponent getView() { + return view; + } + + private class ThreadInformationDataCollector implements Runnable { + @Override + public void run() { + + // load the very latest thread summary + ThreadSummary latestSummary = collector.getLatestThreadSummary(); + if (latestSummary.getTimeStamp() != 0) { + view.setLiveThreads(Long.toString(latestSummary.currentLiveThreads())); + view.setDaemonThreads(Long.toString(latestSummary.currentDaemonThreads())); + } + + long lastHour = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1); + List<ThreadSummary> summaries = collector.getThreadSummary(lastHour); + if (summaries.size() != 0) { + for (ThreadSummary summary : summaries) { + model.addData(summary.getTimeStamp(), summary.currentLiveThreads(), summary.currentDaemonThreads()); + } + view.updateLivingDaemonTimeline(model); + } + } + } + + private class ThreadActionListener implements ActionListener<ThreadAction> { + + @Override + public void actionPerformed(ActionEvent<ThreadAction> actionEvent) { + switch (actionEvent.getActionId()) { + case START_LIVE_RECORDING: + collector.startHarvester(); + setRecording(true); + break; + + case STOP_LIVE_RECORDING: + collector.stopHarvester(); + setRecording(false); + break; + + default: + logger.log(Level.WARNING, "unkown action: " + actionEvent.getActionId()); + break; + } + } + } + + private void initControllers() { + CommonController capsController = + new VMThreadCapabilitiesController(view.createVMThreadCapabilitiesView(), collector); + capsController.initialise(); + + CommonController threadTableController = + new ThreadTableController(view.createThreadTableView(), collector, + ApplicationContext.getInstance().getTimerFactory().createTimer()); + threadTableController.initialise(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationService.java Fri Aug 17 12:52:08 2012 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.controller.impl; + +import com.redhat.thermostat.client.osgi.service.AlwaysMatchFilter; +import com.redhat.thermostat.client.osgi.service.ApplicationService; +import com.redhat.thermostat.client.osgi.service.VmFilter; +import com.redhat.thermostat.client.osgi.service.VmInformationService; +import com.redhat.thermostat.client.osgi.service.VmInformationServiceController; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.thread.client.common.ThreadViewProvider; +import com.redhat.thermostat.thread.collector.ThreadCollectorFactory; + +public class ThreadInformationService implements VmInformationService { + + private VmFilter filter = new AlwaysMatchFilter(); + private ApplicationService service; + private ThreadCollectorFactory collectorFactory; + private ThreadViewProvider viewFactory; + + public ThreadInformationService(ApplicationService appService, ThreadCollectorFactory collectorFactory, + ThreadViewProvider viewFactory) + { + this.service = appService; + this.collectorFactory = collectorFactory; + this.viewFactory = viewFactory; + } + + @Override + public VmFilter getFilter() { + return filter; + } + + @Override + public VmInformationServiceController getInformationServiceController(VmRef ref) { + return new ThreadInformationController(ref, service, collectorFactory, viewFactory); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadTableController.java Fri Aug 17 12:52:08 2012 +0200 @@ -0,0 +1,182 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.controller.impl; + +import java.lang.Thread.State; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import com.redhat.thermostat.client.osgi.service.BasicView.Action; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.Timer.SchedulingType; +import com.redhat.thermostat.thread.client.common.ThreadTableBean; +import com.redhat.thermostat.thread.client.common.ThreadTableView; +import com.redhat.thermostat.thread.collector.ThreadCollector; +import com.redhat.thermostat.thread.collector.ThreadInfo; + +public class ThreadTableController implements CommonController { + + private ThreadTableView threadTableView; + private ThreadCollector collector; + private Timer timer; + + public ThreadTableController(ThreadTableView threadTableView, + ThreadCollector collector, + Timer timer) + { + this.collector = collector; + this.threadTableView = threadTableView; + this.timer = timer; + } + + @Override + public void initialise() { + + timer.setInitialDelay(0); + timer.setDelay(1000); + timer.setTimeUnit(TimeUnit.MILLISECONDS); + timer.setSchedulingType(SchedulingType.FIXED_RATE); + timer.setAction(new ThreadTableControllerAction()); + + threadTableView.addActionListener(new ActionListener<Action>() { + @Override + public void actionPerformed(ActionEvent<Action> actionEvent) { + switch (actionEvent.getActionId()) { + case VISIBLE: + timer.start(); + break; + + case HIDDEN: + timer.stop(); + break; + + default: + break; + } + } + }); + } + + private class ThreadTableControllerAction implements Runnable { + @Override + public void run() { + List<ThreadInfo> infos = collector.getThreadInfo(); + if(infos.size() > 0) { + + long lastPollTimestamp = infos.get(0).getTimeStamp(); + + // build the statistics for each thread in the + // collected thread list + + // first, get a map of all threads with the respective info + // the list will contain an ordered-by-timestamp list + // with the known history for each thread + Map<ThreadInfo, List<ThreadInfo>> stats = new HashMap<>(); + for (ThreadInfo info : infos) { + List<ThreadInfo> beanList = stats.get(info); + if (beanList == null) { + beanList = new ArrayList<ThreadInfo>(); + stats.put(info, beanList); + } + beanList.add(info); + } + + List<ThreadTableBean> tableBeans = new ArrayList<>(); + + // now we have the list, we can do all the analysis we need + for (ThreadInfo key : stats.keySet()) { + ThreadTableBean bean = new ThreadTableBean(); + + bean.setName(key.getName()); + bean.setId(key.getThreadID()); + + bean.setWaitedCount(key.getWaitedCount()); + bean.setBlockedCount(key.getBlockedCount()); + + // get start time and stop time, if any + List<ThreadInfo> beanList = stats.get(key); + long last = beanList.get(0).getTimeStamp(); + long first = beanList.get(beanList.size() - 1).getTimeStamp(); + + bean.setStartTimeStamp(first); + if (last < lastPollTimestamp) { + // this thread died somewhere after this polling time... rip + bean.setStopTimeStamp(last); + } + + // time for some stats + double running = 0; + double waiting = 0; + for (ThreadInfo info : beanList) { + State state = info.getState(); + switch (state) { + case RUNNABLE: + running++; + break; + case NEW: + case TERMINATED: + System.err.println("yeah!"); + break; + case BLOCKED: + case TIMED_WAITING: + case WAITING: + waiting++; + default: + break; + } + } + int polls = beanList.size(); + double runningPercent = (running/polls) * 100; + double waitingPercent = (waiting/polls) * 100; + + bean.setRunningPercent(runningPercent); + bean.setWaitingPercent(waitingPercent); + + tableBeans.add(bean); + } + + threadTableView.display(tableBeans); + } + + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/VMThreadCapabilitiesController.java Fri Aug 17 12:52:08 2012 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.controller.impl; + +import com.redhat.thermostat.client.osgi.service.BasicView.Action; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.thread.client.common.VMThreadCapabilitiesView; +import com.redhat.thermostat.thread.collector.ThreadCollector; +import com.redhat.thermostat.thread.collector.VMThreadCapabilities; + +public class VMThreadCapabilitiesController implements CommonController { + + private ThreadCollector collector; + private VMThreadCapabilitiesView view; + + public VMThreadCapabilitiesController(VMThreadCapabilitiesView view, ThreadCollector collector) { + this.view = view; + this.collector = collector; + } + + @Override + public void initialise() { + view.addActionListener(new ActionListener<Action>() { + @Override + public void actionPerformed(ActionEvent<Action> actionEvent) { + switch (actionEvent.getActionId()) { + case VISIBLE: + VMThreadCapabilities caps = collector.getVMThreadCapabilities(); + view.setVMThreadCapabilities(caps); + break; + + default: + break; + } + } + }); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/osgi/Activator.java Fri Aug 17 12:52:08 2012 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.controller.osgi; + +import java.util.Map; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +import com.redhat.thermostat.client.osgi.service.ApplicationService; +import com.redhat.thermostat.client.osgi.service.VmInformationService; +import com.redhat.thermostat.common.MultipleServiceTracker; +import com.redhat.thermostat.common.MultipleServiceTracker.Action; +import com.redhat.thermostat.thread.client.common.ThreadViewProvider; +import com.redhat.thermostat.thread.client.controller.impl.ThreadInformationService; +import com.redhat.thermostat.thread.collector.ThreadCollectorFactory; + +public class Activator implements BundleActivator { + + @SuppressWarnings({ "rawtypes" }) + @Override + public void start(final BundleContext context) throws Exception { + + Class[] classes = new Class[] { + ThreadCollectorFactory.class, + ApplicationService.class, + ThreadViewProvider.class + }; + + Action action = new Action() { + @Override + public void doIt(Map<String, Object> services) { + ThreadCollectorFactory collectorFactory = (ThreadCollectorFactory) services.get(ThreadCollectorFactory.class.getName()); + ApplicationService applicationService = (ApplicationService) services.get(ApplicationService.class.getName()); + ThreadViewProvider viewFactory = (ThreadViewProvider) services.get(ThreadViewProvider.class.getName()); + + VmInformationService vmInfoService = new ThreadInformationService(applicationService, collectorFactory, viewFactory); + context.registerService(VmInformationService.class.getName(), vmInfoService, null); + } + }; + + MultipleServiceTracker tracker = new MultipleServiceTracker(context, classes, action); + tracker.open(); + } + + @Override + public void stop(BundleContext context) throws Exception {} +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-controllers/src/test/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationControllerTest.java Fri Aug 17 12:52:08 2012 +0200 @@ -0,0 +1,188 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.controller.impl; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.anyString; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.client.osgi.service.ApplicationCache; +import com.redhat.thermostat.client.osgi.service.ApplicationService; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.appctx.ApplicationContextUtil; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.thread.client.common.ThreadTableView; +import com.redhat.thermostat.thread.client.common.ThreadView; +import com.redhat.thermostat.thread.client.common.ThreadViewProvider; +import com.redhat.thermostat.thread.client.common.VMThreadCapabilitiesView; +import com.redhat.thermostat.thread.collector.ThreadCollector; +import com.redhat.thermostat.thread.collector.ThreadCollectorFactory; + +public class ThreadInformationControllerTest { + + private Timer timer; + private ThreadView view; + private ActionListener<ThreadView.Action> actionListener; + + private ThreadViewProvider viewFactory; + private ThreadInformationController controller; + + private ApplicationService appService; + + @Before + public void setUp() { + ApplicationContextUtil.resetApplicationContext(); + setUpTimers(); + setUpView(); + } + + @After + public void tearDown() { + ApplicationContextUtil.resetApplicationContext(); + } + + private void setUpView() { + VMThreadCapabilitiesView commonController1 = mock(VMThreadCapabilitiesView.class); + ThreadTableView commonController2 = mock(ThreadTableView.class); + + view = mock(ThreadView.class); + viewFactory = mock(ThreadViewProvider.class); + when(viewFactory.createView()).thenReturn(view); + + when(view.createVMThreadCapabilitiesView()).thenReturn(commonController1); + when(view.createThreadTableView()).thenReturn(commonController2); + } + + private void setUpTimers() { + timer = mock(Timer.class); + ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor.forClass(Runnable.class); + doNothing().when(timer).setAction(timerActionCaptor.capture()); + + TimerFactory timerFactory = mock(TimerFactory.class); + when(timerFactory.createTimer()).thenReturn(timer); + ApplicationContext.getInstance().setTimerFactory(timerFactory); + } + + private void setUpListeners() { + ArgumentCaptor<ActionListener> viewArgumentCaptor1 = ArgumentCaptor.forClass(ActionListener.class); + doNothing().when(view).addActionListener(viewArgumentCaptor1.capture()); + + createController(); + + actionListener = viewArgumentCaptor1.getValue(); + } + + private void createController() { + ApplicationCache cache = mock(ApplicationCache.class); + appService = mock(ApplicationService.class); + when(appService.getApplicationCache()).thenReturn(cache); + + VmRef ref = mock(VmRef.class); + + ThreadCollectorFactory collectorFactory = mock(ThreadCollectorFactory.class); + + controller = new ThreadInformationController(ref, appService, collectorFactory, viewFactory); + } + + @Test + public void liveRecodingKeySet() { + + ActionListener<ThreadView.ThreadAction> threadActionListener; + ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class); + doNothing().when(view).addThreadActionListener(viewArgumentCaptor.capture()); + + VmRef ref = mock(VmRef.class); + when(ref.getStringID()).thenReturn("42"); + ThreadCollectorFactory collectorFactory = mock(ThreadCollectorFactory.class); + + ThreadCollector collector = mock(ThreadCollector.class); + when(collectorFactory.getCollector(ref)).thenReturn(collector); + + ApplicationCache cache = mock(ApplicationCache.class); + appService = mock(ApplicationService.class); + when(appService.getApplicationCache()).thenReturn(cache); + when(cache.getAttribute(anyString())).thenReturn(false).thenReturn(true); + + controller = new ThreadInformationController(ref, appService, collectorFactory, viewFactory); + assertEquals("thread-live-recording-42", controller.CACHE_RECORDING_KEY); + + verify(cache).getAttribute("thread-live-recording-42"); + verify(view).setRecording(false); + + threadActionListener = viewArgumentCaptor.getValue(); + threadActionListener.actionPerformed(new ActionEvent<>(view, ThreadView.ThreadAction.START_LIVE_RECORDING)); + + verify(cache).addAttribute("thread-live-recording-42", true); + verify(collector).startHarvester(); + + threadActionListener.actionPerformed(new ActionEvent<>(view, ThreadView.ThreadAction.STOP_LIVE_RECORDING)); + verify(cache).addAttribute("thread-live-recording-42", false); + verify(collector).stopHarvester(); + + // check that the value indeed persist across sessions + controller = new ThreadInformationController(ref, appService, collectorFactory, viewFactory); + verify(view).setRecording(true); + } + + @Test + public void testTimerStartOnViewVisible() { + setUpListeners(); + + actionListener.actionPerformed(new ActionEvent<>(view, ThreadView.Action.VISIBLE)); + verify(timer).start(); + } + + @Test + public void testTimerStopsOnViewHidden() { + setUpListeners(); + + actionListener.actionPerformed(new ActionEvent<>(view, ThreadView.Action.HIDDEN)); + verify(timer).stop(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-controllers/src/test/java/com/redhat/thermostat/thread/client/controller/impl/ThreadTableControllerTest.java Fri Aug 17 12:52:08 2012 +0200 @@ -0,0 +1,111 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.controller.impl; + +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.appctx.ApplicationContextUtil; +import com.redhat.thermostat.thread.client.common.ThreadTableView; +import com.redhat.thermostat.thread.collector.ThreadCollector; +import com.redhat.thermostat.thread.collector.ThreadInfo; + +public class ThreadTableControllerTest { + + private ThreadTableView view; + private ThreadCollector collector; + + private Timer timer; + + private ActionListener<ThreadTableView.Action> actionListener; + ArgumentCaptor<Runnable> timerActionCaptor; + + @Before + public void setUp() { + ApplicationContextUtil.resetApplicationContext(); + collector = mock(ThreadCollector.class); + + timer = mock(Timer.class); + + view = mock(ThreadTableView.class); + + setUpTimers(); + } + + @After + public void tearDown() { + ApplicationContextUtil.resetApplicationContext(); + } + + private void setUpTimers() { + timer = mock(Timer.class); + timerActionCaptor = ArgumentCaptor.forClass(Runnable.class); + doNothing().when(timer).setAction(timerActionCaptor.capture()); + } + + @Test + public void testStartThreadTableController() { + + ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class); + doNothing().when(view).addActionListener(viewArgumentCaptor.capture()); + + ThreadTableController controller = new ThreadTableController(view, collector, timer); + controller.initialise(); + + actionListener = viewArgumentCaptor.getValue(); + actionListener.actionPerformed(new ActionEvent<>(view, ThreadTableView.Action.VISIBLE)); + + verify(timer).start(); + + actionListener.actionPerformed(new ActionEvent<>(view, ThreadTableView.Action.HIDDEN)); + + verify(timer).stop(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-controllers/src/test/java/com/redhat/thermostat/thread/client/controller/impl/VMThreadCapabilitiesControllerTest.java Fri Aug 17 12:52:08 2012 +0200 @@ -0,0 +1,96 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.controller.impl; + +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.appctx.ApplicationContextUtil; +import com.redhat.thermostat.thread.client.common.VMThreadCapabilitiesView; +import com.redhat.thermostat.thread.collector.ThreadCollector; +import com.redhat.thermostat.thread.collector.VMThreadCapabilities; + +public class VMThreadCapabilitiesControllerTest { + + private VMThreadCapabilitiesView vmThreadCapsView; + private ThreadCollector collector; + private VMThreadCapabilities caps; + + private ActionListener<VMThreadCapabilitiesView.Action> actionListener; + + @Before + public void setUp() { + ApplicationContextUtil.resetApplicationContext(); + collector = mock(ThreadCollector.class); + caps = mock(VMThreadCapabilities.class); + + when(collector.getVMThreadCapabilities()).thenReturn(caps); + + vmThreadCapsView = mock(VMThreadCapabilitiesView.class); + } + + @After + public void tearDown() { + ApplicationContextUtil.resetApplicationContext(); + } + + @Test + public void testStartVMThreadCapabilities() { + + ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class); + doNothing().when(vmThreadCapsView).addActionListener(viewArgumentCaptor.capture()); + + VMThreadCapabilitiesController controller = new VMThreadCapabilitiesController(vmThreadCapsView, collector); + controller.initialise(); + + actionListener = viewArgumentCaptor.getValue(); + actionListener.actionPerformed(new ActionEvent<>(vmThreadCapsView, VMThreadCapabilitiesView.Action.VISIBLE)); + + verify(collector).getVMThreadCapabilities(); + verify(vmThreadCapsView).setVMThreadCapabilities(caps); + } + +}