Mercurial > hg > release > thermostat-1.0
changeset 1383:21466861b0ef
Add thermostat multi-module plug-in archetype.
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2014-January/009130.html
Reviewed-by: neugens
PR1671
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/pom.xml Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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> + + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-maven-archetype-multimodule</artifactId> + <version>1.1.0-SNAPSHOT</version> + <packaging>maven-archetype</packaging> + + <name>Thermostat archetype for a multi-module plugin scaffold</name> + + <build> + <extensions> + <extension> + <groupId>org.apache.maven.archetype</groupId> + <artifactId>archetype-packaging</artifactId> + <version>2.2</version> + </extension> + </extensions> + + <pluginManagement> + <plugins> + <plugin> + <artifactId>maven-archetype-plugin</artifactId> + <version>2.2</version> + </plugin> + </plugins> + </pluginManagement> + </build> + + <url>http://icedtea.classpath.org/thermostat/</url> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="thermostat-kernel-cmdline" + xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <requiredProperties> + <requiredProperty key="thermostat-core-version"> + <defaultValue>1.1.0-SNAPSHOT</defaultValue> + </requiredProperty> + <requiredProperty key="pluginDescription"> + <defaultValue>Thermostat example plugin</defaultValue> + </requiredProperty> + <requiredProperty key="helloMessage"> + <defaultValue>Hello World!</defaultValue> + </requiredProperty> + <requiredProperty key="pluginDeployDir"> + <defaultValue>example-plugin</defaultValue> + </requiredProperty> + </requiredProperties> + <fileSets> + <fileSet filtered="true" encoding="UTF-8"> + <directory></directory> + <includes> + <include>deploy.sh</include> + <include>README</include> + </includes> + </fileSet> + </fileSets> + <modules> + <module id="${rootArtifactId}-cli" dir="client-cli" name="${rootArtifactId}-cli"> + <fileSets> + <fileSet filtered="true" packaged="true" encoding="UTF-8"> + <directory>src/main/java</directory> + <includes> + <include>**/*.java</include> + </includes> + </fileSet> + </fileSets> + </module> + <module id="${rootArtifactId}-agent" dir="agent" name="${rootArtifactId}-agent"> + <fileSets> + <fileSet filtered="true" packaged="true" encoding="UTF-8"> + <directory>src/main/java</directory> + <includes> + <include>**/*.java</include> + </includes> + </fileSet> + <fileSet filtered="true" packaged="true" encoding="UTF-8"> + <directory>src/test/java</directory> + <includes> + <include>**/*.java</include> + </includes> + </fileSet> + <fileSet filtered="true" encoding="UTF-8"> + <directory>src/test/resources</directory> + <includes> + <include>**/*.txt</include> + </includes> + </fileSet> + </fileSets> + </module> + <module id="${rootArtifactId}-storage-common" dir="storage-common" name="${rootArtifactId}-storage-common"> + <fileSets> + <fileSet filtered="true" packaged="true" encoding="UTF-8"> + <directory>src/main/java</directory> + <includes> + <include>**/*.java</include> + </includes> + </fileSet> + <fileSet filtered="true" packaged="true" encoding="UTF-8"> + <directory>src/test/java</directory> + <includes> + <include>**/*.java</include> + </includes> + </fileSet> + </fileSets> + </module> + <module id="${rootArtifactId}-distribution" dir="distribution" name="${rootArtifactId}-distribution"> + <fileSets> + <fileSet filtered="true" encoding="UTF-8"> + <directory></directory> + <includes> + <include>thermostat-plugin.xml</include> + </includes> + </fileSet> + </fileSets> + </module> + </modules> +</archetype-descriptor>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/README Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,28 @@ +This is a simple multi-module Thermostat[1] plugin scaffold. + +The structure in the file system looks as follows: + +└── foo-plugin + ├── pom.xml (parent pom) + ├── agent + ├── storage-common + ├── client-cli + └── distribution + +The agent directory contains plug-in bits for thermostat agents. This usually +includes some form of back-end. + +The client-cli directory contains plug-in bits for thermostat command-line +clients. + +The storage-common directory contains model and DAO classes which your plug-in +may contribute. This module is usually a dependency of the agent and client-cli +modules. + +The distribution directory is an assembly helper for your plug-in. The most +important part in there is thermostat-plugin.xml. The assembled plug-in can +be found in this module's target directory after a successful maven build. + +Enjoy! + +[1] http://icedtea.classpath.org/thermostat/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/agent/pom.xml Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2012, 2013 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>${groupId}</groupId> + <artifactId>${rootArtifactId}</artifactId> + <version>${version}</version> + </parent> + + <artifactId>${artifactId}</artifactId> + <packaging>bundle</packaging> + + <name>${pluginDescription} - Agent</name> + + <dependencies> + + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + + <!-- thermostat specific dependencies --> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-agent-core</artifactId> + </dependency> + + <!-- plugin specific dependencies --> + + <dependency> + <groupId>${groupId}</groupId> + <artifactId>${rootArtifactId}-storage-common</artifactId> + <version>${version}</version> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-Activator>${package}.agent.internal.Activator</Bundle-Activator> + <Bundle-SymbolicName>${package}.agent</Bundle-SymbolicName> + <Private-Package>${package}.agent.internal</Private-Package> + <!-- Do not autogenerate uses clauses in Manifests --> + <_nouses>true</_nouses> + </instructions> + </configuration> + </plugin> + + <!-- No tests in this module, skip them in order to make the build pass --> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <skipTests>true</skipTests> + </configuration> + </plugin> + </plugins> + </build> + +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/agent/src/main/java/agent/internal/Activator.java Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,59 @@ +package ${package}.agent.internal; + +import java.util.Map; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.backend.BackendService; +import com.redhat.thermostat.common.ApplicationService; +import com.redhat.thermostat.common.MultipleServiceTracker; +import com.redhat.thermostat.common.MultipleServiceTracker.Action; +import com.redhat.thermostat.common.Version; +import com.redhat.thermostat.storage.core.WriterID; +import ${package}.storage.ExampleDAO; + +public class Activator implements BundleActivator { + + private MultipleServiceTracker tracker; + private ServiceRegistration reg; + private Backend backend; + + @Override + public void start(final BundleContext context) throws Exception { + Class<?>[] deps = new Class<?>[] { + BackendService.class, + ExampleDAO.class, + ApplicationService.class, + WriterID.class + }; + tracker = new MultipleServiceTracker(context, deps, new Action() { + @Override + public void dependenciesAvailable(Map<String, Object> services) { + ApplicationService appService = (ApplicationService) services.get(ApplicationService.class.getName()); + ExampleDAO dao = (ExampleDAO) services.get(ExampleDAO.class.getName()); + WriterID writer = (WriterID) services.get(WriterID.class.getName()); + Version version = new Version(context.getBundle()); + backend = new ExampleBackend(appService, version, dao, writer); + reg = context.registerService(Backend.class.getName(), backend, null); + } + + @Override + public void dependenciesUnavailable() { + if (backend.isActive()) { + backend.deactivate(); + } + reg.unregister(); + } + }); + tracker.open(); + } + + @Override + public void stop(BundleContext context) throws Exception { + tracker.close(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/agent/src/main/java/agent/internal/ExampleBackend.java Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,75 @@ +package ${package}.agent.internal; + +import java.util.concurrent.TimeUnit; + +import com.redhat.thermostat.backend.BaseBackend; +import com.redhat.thermostat.common.ApplicationService; +import com.redhat.thermostat.common.Ordered; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.Timer.SchedulingType; +import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.common.Version; +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.storage.core.WriterID; +import ${package}.storage.ExampleDAO; + +public class ExampleBackend extends BaseBackend { + + private static final int CHECK_INTERVAL_MINUTES = 60; + + private final ApplicationService appService; + private Timer timer; + private final ExampleDAO dao; + private boolean started; + + public ExampleBackend(ApplicationService service, Version version, ExampleDAO dao, WriterID writer) { + super("Example Backend", + "Saves a message for an agent", + "Red Hat, Inc.", + version.getVersionNumber()); + this.appService = service; + this.dao = dao; + this.started = false; + } + + @Override + public boolean activate() { + // This is silly and shouldn't really do this every 60 minutes. + // Anyhow, it's good to illustrate thermostat timers using appService. + TimerFactory timerFactory = appService.getTimerFactory(); + timer = timerFactory.createTimer(); + timer.setDelay(CHECK_INTERVAL_MINUTES); + timer.setInitialDelay(0); + timer.setSchedulingType(SchedulingType.FIXED_RATE); + timer.setTimeUnit(TimeUnit.MINUTES); + timer.setAction(new Runnable() { + + @Override + public void run() { + dao.putMessage("${helloMessage}"); + } + }); + timer.start(); + started = true; + return true; + } + + @Override + public boolean deactivate() { + started = false; + timer.stop(); + return true; + } + + @Override + public boolean isActive() { + return started; + } + + @Override + public int getOrderValue() { + // offset should be < 100 in this case 88. + return Ordered.ORDER_CPU_GROUP + 88; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/client-cli/pom.xml Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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>${groupId}</groupId> + <artifactId>${rootArtifactId}</artifactId> + <version>${version}</version> + </parent> + + <artifactId>${artifactId}</artifactId> + <packaging>bundle</packaging> + + <name>${pluginDescription} - CLI</name> + + <dependencies> + + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + + <!-- thermostat specific dependencies --> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-client-core</artifactId> + <type>jar</type> + </dependency> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-common-core</artifactId> + <type>jar</type> + </dependency> + + <!-- plugin specific dependencies --> + + <dependency> + <groupId>${groupId}</groupId> + <artifactId>${rootArtifactId}-storage-common</artifactId> + <version>${version}</version> + </dependency> + + </dependencies> + + <build> + <plugins> + + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-Activator>${package}.cli.internal.Activator</Bundle-Activator> + <Bundle-SymbolicName>${package}.cli</Bundle-SymbolicName> + <Private-Package>${package}.cli.internal</Private-Package> + <!-- Do not autogenerate uses clauses in Manifests --> + <_nouses>true</_nouses> + </instructions> + </configuration> + </plugin> + + <!-- No tests in this module, skip them in order to make the build pass --> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <skipTests>true</skipTests> + </configuration> + </plugin> + + </plugins> + + </build> + +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/client-cli/src/main/java/cli/internal/Activator.java Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,29 @@ +package ${package}.cli.internal; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import com.redhat.thermostat.common.cli.CommandRegistry; +import com.redhat.thermostat.common.cli.CommandRegistryImpl; + +/** + * Registers the {@link ExampleCommand} with Thermostat. + */ +public class Activator implements BundleActivator { + + private CommandRegistry reg; + + @Override + public void start(BundleContext context) throws Exception { + ExampleCommand cmd = new ExampleCommand(context); + reg = new CommandRegistryImpl(context); + reg.registerCommand(ExampleCommand.NAME, cmd); + } + + @Override + public void stop(BundleContext context) throws Exception { + if (reg != null) { + // unregisters commands which this registry registered + reg.unregisterCommands(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/client-cli/src/main/java/cli/internal/ExampleCommand.java Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,78 @@ +package ${package}.cli.internal; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; + +import com.redhat.thermostat.common.cli.AbstractCommand; +import com.redhat.thermostat.common.cli.Arguments; +import com.redhat.thermostat.common.cli.CommandContext; +import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.shared.locale.LocalizedString; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.model.AgentInformation; +import com.redhat.thermostat.storage.model.HostInfo; +import ${package}.storage.ExampleDAO; + +public class ExampleCommand extends AbstractCommand { + + public static final String NAME = "example-command"; + private static final String AGENT_ARG = "hostId"; + + private final BundleContext context; + + ExampleCommand(BundleContext context) { + this.context = context; + } + + @Override + public void run(CommandContext ctxt) throws CommandException { + Arguments args = ctxt.getArguments(); + if (!args.hasArgument(AGENT_ARG)) { + throw new CommandException(new LocalizedString("Agent argument required!")); + } + AgentInfoDAO agentInfo = getDaoService(AgentInfoDAO.class); + if (agentInfo == null) { + throw new CommandException(new LocalizedString("AgentInfoDAO unavaialable!")); + } + String agentId = args.getArgument(AGENT_ARG); + + // Use our DAO to resolve the agent, i.e. host + HostRef hostRef = new HostRef(agentId, "not-used"); + AgentInformation resolvedAgent = agentInfo.getAgentInformation(hostRef); + if (resolvedAgent == null) { + throw new CommandException(new LocalizedString("Unknown agentId: " + agentId)); + } + HostInfoDAO hostInfo = getDaoService(HostInfoDAO.class); + if (hostInfo == null) { + throw new CommandException(new LocalizedString("HostInfoDAO unavaialable!")); + } + HostInfo info = hostInfo.getHostInfo(hostRef); + ExampleDAO exampleDAO = getDaoService(ExampleDAO.class); + if (exampleDAO == null) { + throw new CommandException(new LocalizedString("ExampleDAO unavailable")); + } + String message = exampleDAO.getMessage(hostRef); + if (message == null) { + message = "something's fishy :)"; + } + // Here one should use appropriate formatters instead. Shame on me :( + ctxt.getConsole().getOutput().println("Host: " + info.getHostname()); + ctxt.getConsole().getOutput().println("Message: " + message); + } + + private <T> T getDaoService(Class<T> clazz) { + ServiceReference ref = context.getServiceReference(clazz.getName()); + @SuppressWarnings("unchecked") + T service = (T) context.getService(ref); + return service; + } + + @Override + public boolean isStorageRequired() { + // Let the launcher connect to storage for us + return true; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/deploy.sh Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,18 @@ +#/bin/bash +if [ x"$THERMOSTAT_DEV_HOME" = x ] ; then + echo "variable THERMOSTAT_DEV_HOME is not set, should point to the thermostat src directory" + exit -1 +fi + +PLUGIN_DIR=$THERMOSTAT_DEV_HOME/distribution/target/image/plugins + +TARGET_DIR="${pluginDeployDir}" + +if [ -e $PLUGIN_DIR/$TARGET_DIR ]; then + rm -rf $PLUGIN_DIR/$TARGET_DIR +fi + +DISTRO_ZIP=$(pwd)/distribution/target/${artifactId}-distribution*.zip +pushd $PLUGIN_DIR +unzip $DISTRO_ZIP +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/distribution/pom.xml Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2012 - 2014 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>${groupId}</groupId> + <artifactId>${rootArtifactId}</artifactId> + <version>${version}</version> + </parent> + + <artifactId>${artifactId}</artifactId> + <packaging>pom</packaging> + + <!-- Assembles the jars of this plugin in a zip file for easy + deployment. see target/${rootArtifactId}*.zip + after a maven build --> + <name>${pluginDescription} - Distribution</name> + + <properties> + <thermostat.plugin>${pluginDeployDir}</thermostat.plugin> + </properties> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <dependencies> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-assembly</artifactId> + <version>${thermostat-core-version}</version> + </dependency> + </dependencies> + <configuration> + <descriptorRefs> + <descriptorRef>plugin-assembly</descriptorRef> + </descriptorRefs> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + <executions> + <execution> + <id>assemble-plugin</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <!-- Explicitly list all plug-in artifacts, transitive dependencies + are not included in assembly. --> + <dependencies> + <dependency> + <groupId>${groupId}</groupId> + <artifactId>${rootArtifactId}-agent</artifactId> + <version>${version}</version> + </dependency> + <dependency> + <groupId>${groupId}</groupId> + <artifactId>${rootArtifactId}-storage-common</artifactId> + <version>${version}</version> + </dependency> + <dependency> + <groupId>${groupId}</groupId> + <artifactId>${rootArtifactId}-cli</artifactId> + <version>${version}</version> + </dependency> + </dependencies> + +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/distribution/thermostat-plugin.xml Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,55 @@ +#set( $symbol_dollar = '$' ) +<?xml version="1.0"?> +<plugin xmlns="http://icedtea.classpath.org/thermostat/plugins/v1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <commands> + <command> + <name>example-command</name> + <description>Show the message for a given agent</description> + <options> + <option> + <long>hostId</long> + <short>a</short> + <argument>hostId</argument> + <required>true</required> + <description>the ID of the agent to show the message for</description> + </option> + <option common="true"> + <long>dbUrl</long> + </option> + <option common="true"> + <long>logLevel</long> + </option> + </options> + <environments> + <environment>cli</environment> + <environment>shell</environment> + </environments> + <bundles> + <bundle><symbolic-name>${package}.cli</symbolic-name><version>${symbol_dollar}{project.version}</version></bundle> + <bundle><symbolic-name>${package}.storage</symbolic-name><version>${symbol_dollar}{project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.storage.core</symbolic-name><version>${symbol_dollar}{thermostat-core-version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.storage.mongodb</symbolic-name><version>${symbol_dollar}{thermostat-core-version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.web.common</symbolic-name><version>${symbol_dollar}{thermostat-core-version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.web.client</symbolic-name><version>${symbol_dollar}{thermostat-core-version}</version></bundle> + <bundle><symbolic-name>org.mongodb.mongo-java-driver</symbolic-name><version>${symbol_dollar}{mongo-driver.osgi-version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.beanutils</symbolic-name><version>${symbol_dollar}{commons-beanutils.version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.codec</symbolic-name><version>${symbol_dollar}{commons-codec.osgi-version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.collections</symbolic-name><version>${symbol_dollar}{commons-collections.version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.logging</symbolic-name><version>${symbol_dollar}{commons-logging.version}</version></bundle> + <bundle><symbolic-name>org.apache.httpcomponents.httpcore</symbolic-name><version>${symbol_dollar}{httpcomponents.core.version}</version></bundle> + <bundle><symbolic-name>org.apache.httpcomponents.httpclient</symbolic-name><version>${symbol_dollar}{httpcomponents.client.version}</version></bundle> + <bundle><symbolic-name>com.google.gson</symbolic-name><version>${symbol_dollar}{gson.version}</version></bundle> + </bundles> + </command> + </commands> + <extensions> + <extension> + <name>agent</name> + <bundles> + <bundle><symbolic-name>${package}.storage</symbolic-name><version>${symbol_dollar}{project.version}</version></bundle> + <bundle><symbolic-name>${package}.agent</symbolic-name><version>${symbol_dollar}{project.version}</version></bundle> + </bundles> + </extension> + </extensions> +</plugin>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/pom.xml Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,155 @@ +#set( $symbol_dollar = '$' ) +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2012 - 2014 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> + + <groupId>${groupId}</groupId> + <artifactId>${artifactId}</artifactId> + <version>${version}</version> + <packaging>pom</packaging> + + <name>${pluginDescription}</name> + + <properties> + + <main.basedir>${symbol_dollar}{project.basedir}</main.basedir> + + <maven.build.timestamp.format>yyyy-MM-dd</maven.build.timestamp.format> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <thermostat.java.version>1.7</thermostat.java.version> + <junit.version>4.10</junit.version> + + <osgi.core.version>4.2.0</osgi.core.version> + <felix.framework.version>4.0.2</felix.framework.version> + <!-- version of core thermostat we'll be using --> + <thermostat-core-version>${thermostat-core-version}</thermostat-core-version> + + <!-- Dependencies which core thermostat uses --> + <mongo-driver.osgi-version>2.11.2.RELEASE</mongo-driver.osgi-version> + <commons-beanutils.version>1.8.3</commons-beanutils.version> + <commons-codec.osgi-version>1.7.0</commons-codec.osgi-version> + <commons-collections.version>3.2.1</commons-collections.version> + <commons-logging.version>1.1.3</commons-logging.version> + <httpcomponents.core.version>4.1.2</httpcomponents.core.version> + <httpcomponents.client.version>4.1.2</httpcomponents.client.version> + <gson.version>2.2.2</gson.version> + + + </properties> + + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>2.3.2</version> + <configuration> + <source>${thermostat.java.version}</source> + <target>${thermostat.java.version}</target> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.12</version> + <dependencies> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit47</artifactId> + <version>2.12</version> + </dependency> + </dependencies> + </plugin> + + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>1.4.0</version> + </plugin> + + </plugins> + </pluginManagement> + </build> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>${symbol_dollar}{junit.version}</version> + </dependency> + + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>${symbol_dollar}{osgi.core.version}</version> + </dependency> + + <!-- thermostat dependencies --> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-common-core</artifactId> + <version>${symbol_dollar}{thermostat-core-version}</version> + </dependency> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-storage-core</artifactId> + <version>${symbol_dollar}{thermostat-core-version}</version> + </dependency> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-agent-core</artifactId> + <version>${symbol_dollar}{thermostat-core-version}</version> + </dependency> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-client-core</artifactId> + <version>${symbol_dollar}{thermostat-core-version}</version> + </dependency> + + </dependencies> + </dependencyManagement> + +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/storage-common/pom.xml Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,105 @@ +#set( $symbol_dollar = '$' ) +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2012, 2013 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>${groupId}</groupId> + <artifactId>${rootArtifactId}</artifactId> + <version>${version}</version> + </parent> + + <artifactId>${artifactId}</artifactId> + <packaging>bundle</packaging> + + <name>${pluginDescription} - Storage Common</name> + + <dependencies> + + <!-- osgi and test dependencies --> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + + <!-- thermostat specific dependencies --> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-storage-core</artifactId> + </dependency> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-common-core</artifactId> + </dependency> + + <!-- plugin specific dependencies --> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>${package}.storage</Bundle-SymbolicName> + <Bundle-Activator>${package}.storage.internal.Activator</Bundle-Activator> + <Export-Package>${package}.storage</Export-Package> + <Private-Package>${package}.storage.internal</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/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/storage-common/src/main/java/storage/ExampleDAO.java Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright 2012 - 2014 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 ${package}.storage; + +import com.redhat.thermostat.storage.core.Category; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.Key; + +public interface ExampleDAO { + + public static final Key<String> MESSAGE_KEY = new Key<>("message"); + + /* + * Schema description for the messages collection + */ + static final Category<ExampleMessage> exampleCategory = new Category<>("example-messages", + ExampleMessage.class, + Key.AGENT_ID, + MESSAGE_KEY); + + void putMessage(String message); + + String getMessage(HostRef ref); + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/storage-common/src/main/java/storage/ExampleMessage.java Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,51 @@ +package ${package}.storage; + +import java.util.Objects; + +import com.redhat.thermostat.storage.core.Entity; +import com.redhat.thermostat.storage.core.Persist; +import com.redhat.thermostat.storage.model.BasePojo; + +/** + * This is the model class which gets persisted + * + */ +@Entity +public class ExampleMessage extends BasePojo { + + private String message; + + public ExampleMessage(String writerId) { + super(writerId); + } + + // Used for JSON serialization. Don't + // explicitly use it. + public ExampleMessage() { + this(null); + } + + @Persist + public void setMessage(String message) { + this.message = message; + } + + @Persist + public String getMessage() { + return message; + } + + public int hashCode() { + return Objects.hash(super.hashCode(), message); + } + + public boolean equals(Object other) { + if (!(other instanceof ExampleMessage)) { + return false; + } + ExampleMessage o = (ExampleMessage)other; + return super.equals(o) && + message.equals(o.message); + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/storage-common/src/main/java/storage/internal/Activator.java Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,65 @@ +package ${package}.storage.internal; + +import java.util.Map; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +import com.redhat.thermostat.common.MultipleServiceTracker; +import com.redhat.thermostat.common.MultipleServiceTracker.Action; +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.storage.core.WriterID; +import ${package}.storage.ExampleDAO; + +public class Activator implements BundleActivator { + + private MultipleServiceTracker multiTracker; + + @Override + public void start(final BundleContext context) throws Exception { + Class<?>[] dependentServices = new Class[] { + Storage.class, + WriterID.class + }; + // Track Storage and WriterID and register our new DAO once services + // become available. + ServicesAvailableAction action = new ServicesAvailableAction(context); + multiTracker = new MultipleServiceTracker(context, + dependentServices, + action); + multiTracker.open(); + } + + @Override + public void stop(BundleContext context) throws Exception { + multiTracker.close(); + } + + private static final class ServicesAvailableAction implements Action { + + private final BundleContext context; + private ServiceRegistration reg; + + private ServicesAvailableAction(BundleContext context) { + this.context = context; + } + + @Override + public void dependenciesAvailable(Map<String, Object> services) { + Storage storage = (Storage)services.get(Storage.class.getName()); + WriterID writerId = (WriterID)services.get(WriterID.class.getName()); + ExampleDAO daoImpl = new ExampleDAOImpl(storage, writerId); + reg = context.registerService(ExampleDAO.class.getName(), daoImpl, null); + } + + @Override + public void dependenciesUnavailable() { + if (reg != null) { + reg.unregister(); + } + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/storage-common/src/main/java/storage/internal/ExampleDAOImpl.java Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,120 @@ +/* + * Copyright 2012 - 2014, 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 ${package}.storage.internal; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.storage.core.Cursor; +import com.redhat.thermostat.storage.core.DescriptorParsingException; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.Key; +import com.redhat.thermostat.storage.core.PreparedStatement; +import com.redhat.thermostat.storage.core.StatementDescriptor; +import com.redhat.thermostat.storage.core.StatementExecutionException; +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.storage.core.WriterID; +import ${package}.storage.ExampleMessage; +import ${package}.storage.ExampleDAO; + +public class ExampleDAOImpl implements ExampleDAO { + + private static final Logger logger = LoggingUtils.getLogger(ExampleDAOImpl.class); + + private static final String REPLACE_DESCRIPTOR = "REPLACE " + exampleCategory.getName() + + " SET '" + Key.AGENT_ID.getName() + "' = ?s , " + + "'" + MESSAGE_KEY.getName() + "' = ?s " + + "WHERE '" + Key.AGENT_ID.getName() + "' = ?s"; + private static final String QUERY_DESCRIPTOR = "QUERY " + exampleCategory.getName() + " WHERE " + + "'" + Key.AGENT_ID.getName() + "' = ?s"; + + private final Storage storage; + private final WriterID writerId; + + ExampleDAOImpl(Storage storage, WriterID writerId) { + this.storage = storage; + this.writerId = writerId; + storage.registerCategory(exampleCategory); + } + + @Override + public void putMessage(String message) { + try { + StatementDescriptor<ExampleMessage> stmtDesc = new StatementDescriptor<>(exampleCategory, REPLACE_DESCRIPTOR); + PreparedStatement<ExampleMessage> replace = storage.prepareStatement(stmtDesc); + replace.setString(0, writerId.getWriterID()); + replace.setString(1, message); + replace.setString(2, writerId.getWriterID()); + replace.execute(); + } catch (DescriptorParsingException e) { + // should not happen, but if it *does* happen, at least log it + logger.log(Level.SEVERE, "Preparing '" + REPLACE_DESCRIPTOR + "' failed!", e); + } catch (StatementExecutionException e) { + // should not happen, but if it *does* happen, at least log it + logger.log(Level.SEVERE, "Executing '" + REPLACE_DESCRIPTOR + "' failed!", e); + } + } + + @Override + public String getMessage(HostRef ref) { + Cursor<ExampleMessage> cursor = null; + try { + StatementDescriptor<ExampleMessage> stmtDesc = new StatementDescriptor<>(exampleCategory, QUERY_DESCRIPTOR); + PreparedStatement<ExampleMessage> query = storage.prepareStatement(stmtDesc); + query.setString(0, ref.getAgentId()); + cursor = query.executeQuery(); + } catch (DescriptorParsingException e) { + // should not happen, but if it *does* happen, at least log it + logger.log(Level.SEVERE, "Preparing '" + QUERY_DESCRIPTOR + "' failed!", e); + } catch (StatementExecutionException e) { + // should not happen, but if it *does* happen, at least log it + logger.log(Level.SEVERE, "Executing '" + QUERY_DESCRIPTOR + "' failed!", e); + } + if (cursor == null) { + return null; + } + if (cursor.hasNext()) { + ExampleMessage pojo = cursor.next(); + return pojo.getMessage(); + } else { + return null; + } + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/main/resources/archetype-resources/storage-common/src/test/java/storage/ExampleMessageTest.java Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,44 @@ +package ${package}.storage; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class ExampleMessageTest { + + @Test + public void testEquals() { + ExampleMessage message = new ExampleMessage(); + message.setAgentId("foo"); + message.setMessage("bar"); + + assertTrue(message.equals(message)); + ExampleMessage message2 = new ExampleMessage(); + assertFalse(message.equals(message2)); + assertFalse(message.equals("I'm a string")); + + message2.setAgentId("foo"); + assertFalse(message.equals(message2)); + message2.setMessage("bar"); + assertTrue(message.equals(message2)); + } + + @Test + public void testHashCode() { + ExampleMessage message = new ExampleMessage(); + message.setAgentId("foo"); + message.setMessage("bar"); + + assertTrue(message.hashCode() == message.hashCode()); + ExampleMessage message2 = new ExampleMessage(); + assertFalse(message.hashCode() == message2.hashCode()); + assertFalse(message.hashCode() == "I'm a string".hashCode()); + + message2.setAgentId("foo"); + assertFalse(message.hashCode() == message2.hashCode()); + message2.setMessage("bar"); + assertTrue(message.hashCode() == message2.hashCode()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/multi-module-plugin-archetype/src/test/resources/projects/basic/archetype.properties Tue Jan 21 19:17:27 2014 +0100 @@ -0,0 +1,8 @@ +#Mon Jan 20 17:42:19 CET 2014 +package=com.example.thermostat.plugins +version=0.0.1-SNAPSHOT +groupId=com.example.thermostat.plugins +artifactId=thermostat-example-plugin +pluginDescription=Thermostat example plug-in +helloMessage=Hello World! +pluginDeployDir=example-plugin \ No newline at end of file