You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2013/04/22 11:27:37 UTC
svn commit: r1470424 [4/5] - in
/sling/trunk/contrib/extensions/discovery/impl: ./ src/ src/main/
src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/sling/ src/main/java/org/apache/sling/discovery/
src/main/java/org/ap...
Added: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClient.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClient.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClient.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClient.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.topology.connector;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.UUID;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.URIException;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.discovery.impl.Config;
+import org.apache.sling.discovery.impl.cluster.ClusterViewService;
+import org.apache.sling.discovery.impl.topology.announcement.Announcement;
+import org.apache.sling.discovery.impl.topology.announcement.AnnouncementRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A topology connector client is used for sending (pinging) a remote topology
+ * connector servlet and exchanging announcements with it
+ */
+public class TopologyConnectorClient implements
+ TopologyConnectorClientInformation {
+
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ /** the endpoint url **/
+ private final URL connectorUrl;
+
+ /** the cluster view service **/
+ private final ClusterViewService clusterViewService;
+
+ /** the config service to user **/
+ private final Config config;
+
+ /** the id of this connection **/
+ private final UUID id;
+
+ /** the announcement registry **/
+ private final AnnouncementRegistry announcementRegistry;
+
+ /** the last inherited announcement **/
+ private Announcement lastInheritedAnnouncement;
+
+ /** the information as to where this connector came from **/
+ private final OriginInfo originInfo;
+
+ /** the information about this server **/
+ private final String serverInfo;
+
+ TopologyConnectorClient(final ClusterViewService clusterViewService,
+ final AnnouncementRegistry announcementRegistry, final Config config,
+ final URL connectorUrl, final OriginInfo originInfo, final String serverInfo) {
+ if (clusterViewService == null) {
+ throw new IllegalArgumentException(
+ "clusterViewService must not be null");
+ }
+ if (announcementRegistry == null) {
+ throw new IllegalArgumentException(
+ "announcementRegistry must not be null");
+ }
+ if (config == null) {
+ throw new IllegalArgumentException("config must not be null");
+ }
+ if (connectorUrl == null) {
+ throw new IllegalArgumentException("connectorUrl must not be null");
+ }
+ if (originInfo == null) {
+ throw new IllegalArgumentException("originInfo must not be null");
+ }
+ this.clusterViewService = clusterViewService;
+ this.announcementRegistry = announcementRegistry;
+ this.config = config;
+ this.connectorUrl = connectorUrl;
+ this.originInfo = originInfo;
+ this.serverInfo = serverInfo;
+ this.id = UUID.randomUUID();
+ }
+
+ /** ping the server and pass the announcements between the two **/
+ void ping() {
+ logger.debug("ping: connectorUrl=" + connectorUrl);
+ HttpClient httpClient = new HttpClient();
+ PostMethod method = new PostMethod(connectorUrl.toString());
+
+ try {
+ String userInfo = connectorUrl.getUserInfo();
+ if (userInfo != null) {
+ Credentials c = new UsernamePasswordCredentials(userInfo);
+ httpClient.getState().setCredentials(
+ new AuthScope(method.getURI().getHost(), method
+ .getURI().getPort()), c);
+ }
+
+ Announcement topologyAnnouncement = new Announcement(
+ clusterViewService.getSlingId());
+ topologyAnnouncement.setOriginInfo(originInfo);
+ topologyAnnouncement.setServerInfo(serverInfo);
+ topologyAnnouncement.setLocalCluster(clusterViewService
+ .getClusterView());
+ announcementRegistry.addAllExcept(topologyAnnouncement, null);
+ final String p = topologyAnnouncement.asJSON();
+
+ logger.debug("ping: topologyAnnouncement json is: " + p);
+ method.addParameter("topologyAnnouncement", p);
+ httpClient.executeMethod(method);
+ logger.debug("ping: done. code=" + method.getStatusCode() + " - "
+ + method.getStatusText());
+ String responseBody = method.getResponseBodyAsString();
+ logger.debug("ping: response body=" + responseBody);
+ Announcement inheritedAnnouncement = Announcement
+ .fromJSON(responseBody);
+ inheritedAnnouncement.setInherited(true);
+ if (!announcementRegistry
+ .registerAnnouncement(inheritedAnnouncement)) {
+ logger.info("ping: connector response is from an instance which I already see in my topology"
+ + inheritedAnnouncement);
+ lastInheritedAnnouncement = null;
+ return;
+ }
+ lastInheritedAnnouncement = inheritedAnnouncement;
+ } catch (URIException e) {
+ logger.error("ping: Got URIException: " + e, e);
+ } catch (IOException e) {
+ logger.error("ping: got IOException: " + e, e);
+ } catch (JSONException e) {
+ logger.error("ping: got JSONException: " + e, e);
+ } catch (RuntimeException re) {
+ logger.error("ping: got RuntimeException: " + re, re);
+ }
+ }
+
+ public URL getConnectorUrl() {
+ return connectorUrl;
+ }
+
+ public boolean isConnected() {
+ if (lastInheritedAnnouncement == null) {
+ return false;
+ } else {
+ return !lastInheritedAnnouncement.hasExpired(config);
+ }
+ }
+
+ public String getRemoteSlingId() {
+ if (lastInheritedAnnouncement == null) {
+ return null;
+ } else {
+ return lastInheritedAnnouncement.getOwnerId();
+ }
+ }
+
+ public OriginInfo getOriginInfo() {
+ return originInfo;
+ }
+
+ public String getId() {
+ return id.toString();
+ }
+
+ /** Disconnect this connector **/
+ public void disconnect() {
+ logger.debug("disconnect: connectorUrl=" + connectorUrl);
+
+ if (lastInheritedAnnouncement != null) {
+ announcementRegistry
+ .unregisterAnnouncement(lastInheritedAnnouncement
+ .getOwnerId());
+ }
+
+ HttpClient httpClient = new HttpClient();
+ PostMethod method = new PostMethod(connectorUrl.toString());
+
+ try {
+ String userInfo = connectorUrl.getUserInfo();
+ if (userInfo != null) {
+ Credentials c = new UsernamePasswordCredentials(userInfo);
+ httpClient.getState().setCredentials(
+ new AuthScope(method.getURI().getHost(), method
+ .getURI().getPort()), c);
+ }
+
+ method.addParameter("topologyDisconnect",
+ clusterViewService.getSlingId());
+ httpClient.executeMethod(method);
+ logger.debug("disconnect: done. code=" + method.getStatusCode()
+ + " - " + method.getStatusText());
+ } catch (URIException e) {
+ logger.error("disconnect: Got URIException: " + e, e);
+ } catch (IOException e) {
+ logger.error("disconnect: got IOException: " + e, e);
+ } catch (RuntimeException re) {
+ logger.error("disconnect: got RuntimeException: " + re, re);
+ }
+ }
+}
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClient.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClient.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClient.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClientInformation.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClientInformation.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClientInformation.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClientInformation.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.topology.connector;
+
+import java.net.URL;
+
+/**
+ * provides information about a topology connector client
+ */
+public interface TopologyConnectorClientInformation {
+
+ public static enum OriginInfo {
+ Config, // this connector was created via config
+ WebConsole, // this connector was created via the wbconsole
+ Programmatically // this connector was created programmatically
+ }
+
+ /** the endpoint url where this connector is connecting to **/
+ public URL getConnectorUrl();
+
+ /** whether or not this connector was able to successfully connect **/
+ public boolean isConnected();
+
+ /** the sling id of the remote end **/
+ public String getRemoteSlingId();
+
+ // public List<String> listFallbackConnectorUrls();
+
+ /** the unique id of this connector **/
+ public String getId();
+
+ /** the information about how this connector was created **/
+ public OriginInfo getOriginInfo();
+
+}
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClientInformation.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClientInformation.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorClientInformation.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.topology.connector;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletException;
+
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.sling.SlingServlet;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.discovery.impl.Config;
+import org.apache.sling.discovery.impl.cluster.ClusterViewService;
+import org.apache.sling.discovery.impl.common.heartbeat.HeartbeatHandler;
+import org.apache.sling.discovery.impl.topology.announcement.Announcement;
+import org.apache.sling.discovery.impl.topology.announcement.AnnouncementFilter;
+import org.apache.sling.discovery.impl.topology.announcement.AnnouncementRegistry;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Servlet which receives topology announcements at
+ * /libs/sling/topology/connector (which is reachable without authorization)
+ */
+@SlingServlet(paths = { "/libs/sling/topology/connector" })
+@Property(name = "sling.auth.requirements", value = { "-/libs/sling/topology/connector" })
+public class TopologyConnectorServlet extends SlingAllMethodsServlet {
+
+ public static final String TOPOLOGY_CONNECTOR_PATH = "/libs/sling/topology/connector";
+
+ private static final long serialVersionUID = 1300640476823585873L;
+
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ @Reference
+ private AnnouncementRegistry announcementRegistry;
+
+ @Reference
+ private ClusterViewService clusterViewService;
+
+ @Reference
+ private HeartbeatHandler heartbeatHandler;
+
+ @Reference
+ private Config config;
+
+ /** the set of ips/hostnames which are allowed to connect to this servlet **/
+ private final Set<String> whitelist = new HashSet<String>();
+
+ protected void activate(final ComponentContext context) {
+ whitelist.clear();
+ String whitelistStr = config.getTopologyConnectorWhitelist();
+ StringTokenizer st = new StringTokenizer(whitelistStr, ",");
+ while (st.hasMoreTokens()) {
+ String entry = st.nextToken().trim();
+ logger.info("activate: adding whitelist entry: " + entry);
+ whitelist.add(entry);
+ }
+ }
+
+ @Override
+ protected void doPost(final SlingHttpServletRequest request,
+ final SlingHttpServletResponse response) throws ServletException,
+ IOException {
+
+ if (!isWhitelisted(request)) {
+ response.sendError(404); // in theory it would be 403==forbidden, but that would reveal that
+ // a resource would exist there in the first place
+ return;
+ }
+
+ final String topologyAnnouncementJSON = request
+ .getParameter("topologyAnnouncement");
+ final String topologyDisconnect = request
+ .getParameter("topologyDisconnect");
+ if (topologyDisconnect != null) {
+ announcementRegistry.unregisterAnnouncement(topologyDisconnect);
+ return;
+ }
+ logger.debug("doPost: incoming topology announcement is: "
+ + topologyAnnouncementJSON);
+ final Announcement incomingTopologyAnnouncement;
+ try {
+ incomingTopologyAnnouncement = Announcement
+ .fromJSON(topologyAnnouncementJSON);
+ incomingTopologyAnnouncement.removeInherited(clusterViewService
+ .getSlingId());
+
+ if (clusterViewService.contains(incomingTopologyAnnouncement
+ .getOwnerId())) {
+ logger.info("doPost: rejecting an announcement from an instance that is part of my cluster: "
+ + incomingTopologyAnnouncement);
+ response.sendError(500);
+ return;
+ }
+ if (clusterViewService.containsAny(incomingTopologyAnnouncement
+ .listInstances())) {
+ logger.info("doPost: rejecting an announcement as it contains instance(s) that is/are part of my cluster: "
+ + incomingTopologyAnnouncement);
+ response.sendError(500);
+ return;
+ }
+ if (!announcementRegistry
+ .registerAnnouncement(incomingTopologyAnnouncement)) {
+ logger.info("doPost: rejecting an announcement from an instance that I already see in my topology: "
+ + incomingTopologyAnnouncement);
+ response.sendError(500);
+ return;
+ }
+
+ Announcement replyAnnouncement = new Announcement(
+ clusterViewService.getSlingId());
+ replyAnnouncement.setLocalCluster(clusterViewService
+ .getClusterView());
+ announcementRegistry.addAllExcept(replyAnnouncement,
+ new AnnouncementFilter() {
+
+ public boolean accept(Announcement announcement) {
+ if (announcement.getPrimaryKey().equals(
+ incomingTopologyAnnouncement
+ .getPrimaryKey())) {
+ return false;
+ }
+ return true;
+ }
+ });
+ final String p = replyAnnouncement.asJSON();
+ PrintWriter pw = response.getWriter();
+ pw.print(p);
+ pw.flush();
+ } catch (JSONException e) {
+ logger.error("doPost: Got a JSONException: " + e, e);
+ response.sendError(500);
+ }
+
+ }
+
+ /** Checks if the provided request's remote server is whitelisted **/
+ private boolean isWhitelisted(final SlingHttpServletRequest request) {
+ if (whitelist.contains(request.getRemoteAddr())) {
+ return true;
+ } else if (whitelist.contains(request.getRemoteHost())) {
+ return true;
+ }
+ logger.info("isWhitelisted: rejecting " + request.getRemoteAddr()
+ + ", " + request.getRemoteHost());
+ return false;
+ }
+
+}
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties Mon Apr 22 09:27:35 2013
@@ -0,0 +1,28 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+#
+# This file contains localization strings for configuration labels and
+# descriptions as used in the metatype.xml descriptor generated by the
+# the SCR plugin
+
+org.apache.sling.discovery.impl.Config.description = The configuration of the \
+ resource based discovery service implementation.
+
+
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.cluster;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.Iterator;
+import java.util.UUID;
+
+import org.apache.sling.discovery.InstanceDescription;
+import org.apache.sling.discovery.TopologyEvent.Type;
+import org.apache.sling.discovery.impl.cluster.helpers.AcceptsMultiple;
+import org.apache.sling.discovery.impl.cluster.helpers.AssertingDiscoveryAware;
+import org.apache.sling.discovery.impl.setup.Instance;
+import org.apache.sling.discovery.impl.setup.PropertyProviderImpl;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ClusterTest {
+
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ Instance instance1;
+ Instance instance2;
+ Instance instance3;
+
+ private String property1Value;
+
+ protected String property2Value;
+
+ private String property1Name;
+
+ private String property2Name;
+
+ @Before
+ public void setup() throws Exception {
+ logger.debug("here we are");
+ instance1 = Instance.newStandaloneInstance("firstInstance", true);
+ instance2 = Instance.newClusterInstance("secondInstance", instance1,
+ false);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (instance3 != null) {
+ instance3.stop();
+ }
+ instance2.stop();
+ instance1.stop();
+ instance1 = null;
+ instance2 = null;
+ instance3 = null;
+ }
+
+ @Test
+ public void testClusterView() throws Exception {
+ assertNotNull(instance1);
+ assertNotNull(instance2);
+ assertNull(instance3);
+ instance3 = Instance.newClusterInstance("thirdInstance", instance1,
+ false);
+ assertNotNull(instance3);
+
+ assertEquals(instance1.getSlingId(), instance1.getClusterViewService()
+ .getSlingId());
+ assertEquals(instance2.getSlingId(), instance2.getClusterViewService()
+ .getSlingId());
+ assertEquals(instance3.getSlingId(), instance3.getClusterViewService()
+ .getSlingId());
+
+ int numC1 = instance1.getClusterViewService().getClusterView()
+ .getInstances().size();
+ assertEquals(1, numC1);
+ int numC2 = instance2.getClusterViewService().getClusterView()
+ .getInstances().size();
+ assertEquals(1, numC2);
+ int numC3 = instance3.getClusterViewService().getClusterView()
+ .getInstances().size();
+ assertEquals(1, numC3);
+
+ instance1.dumpRepo();
+
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+ instance3.runHeartbeatOnce();
+
+ instance1.dumpRepo();
+ Thread.sleep(2000);
+
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+ instance3.runHeartbeatOnce();
+ Thread.sleep(2000);
+
+ instance1.dumpRepo();
+ String clusterId1 = instance1.getClusterViewService().getClusterView()
+ .getId();
+ logger.info("clusterId1=" + clusterId1);
+ String clusterId2 = instance2.getClusterViewService().getClusterView()
+ .getId();
+ logger.info("clusterId2=" + clusterId2);
+ String clusterId3 = instance3.getClusterViewService().getClusterView()
+ .getId();
+ logger.info("clusterId3=" + clusterId3);
+ assertEquals(clusterId1, clusterId2);
+ assertEquals(clusterId1, clusterId3);
+
+ assertEquals(3, instance1.getClusterViewService().getClusterView()
+ .getInstances().size());
+ assertEquals(3, instance2.getClusterViewService().getClusterView()
+ .getInstances().size());
+ assertEquals(3, instance3.getClusterViewService().getClusterView()
+ .getInstances().size());
+ }
+
+ @Test
+ public void testAdditionalInstance() throws Throwable {
+ assertNotNull(instance1);
+ assertNotNull(instance2);
+
+ assertEquals(instance1.getSlingId(), instance1.getClusterViewService()
+ .getSlingId());
+ assertEquals(instance2.getSlingId(), instance2.getClusterViewService()
+ .getSlingId());
+
+ int numC1 = instance1.getClusterViewService().getClusterView()
+ .getInstances().size();
+ assertEquals(1, numC1);
+ int numC2 = instance2.getClusterViewService().getClusterView()
+ .getInstances().size();
+ assertEquals(1, numC2);
+
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+
+ instance1.dumpRepo();
+ Thread.sleep(2000);
+
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+ Thread.sleep(2000);
+
+ instance1.dumpRepo();
+ String clusterId1 = instance1.getClusterViewService().getClusterView()
+ .getId();
+ logger.info("clusterId1=" + clusterId1);
+ String clusterId2 = instance2.getClusterViewService().getClusterView()
+ .getId();
+ logger.info("clusterId2=" + clusterId2);
+ assertEquals(clusterId1, clusterId2);
+
+ assertEquals(2, instance1.getClusterViewService().getClusterView()
+ .getInstances().size());
+ assertEquals(2, instance2.getClusterViewService().getClusterView()
+ .getInstances().size());
+
+ AssertingDiscoveryAware assertingDiscoveryAware = new AssertingDiscoveryAware();
+ assertingDiscoveryAware.addExpected(Type.TOPOLOGY_INIT);
+ assertEquals(1, assertingDiscoveryAware.getRemainingExpectedCount());
+ instance1.bindDiscoveryAware(assertingDiscoveryAware);
+ assertEquals(0, assertingDiscoveryAware.getRemainingExpectedCount());
+
+ // startup instance 3
+ AcceptsMultiple acceptsMultiple = new AcceptsMultiple(
+ Type.TOPOLOGY_CHANGING, Type.TOPOLOGY_CHANGED);
+ assertingDiscoveryAware.addExpected(acceptsMultiple);
+ instance3 = Instance.newClusterInstance("thirdInstance", instance1,
+ false);
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+ instance3.runHeartbeatOnce();
+ Thread.sleep(2000);
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+ instance3.runHeartbeatOnce();
+ Thread.sleep(2000);
+ assertEquals(1, acceptsMultiple.getEventCnt(Type.TOPOLOGY_CHANGED));
+ }
+
+ @Test
+ public void testPropertyProviders() throws Throwable {
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+ assertNull(instance3);
+ instance3 = Instance.newClusterInstance("thirdInstance", instance1,
+ false);
+ instance3.runHeartbeatOnce();
+ Thread.sleep(2000);
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+ instance3.runHeartbeatOnce();
+ Thread.sleep(2000);
+
+ property1Value = UUID.randomUUID().toString();
+ property1Name = UUID.randomUUID().toString();
+ PropertyProviderImpl pp1 = new PropertyProviderImpl();
+ pp1.setProperty(property1Name, property1Value);
+ instance1.bindPropertyProvider(pp1, property1Name);
+
+ property2Value = UUID.randomUUID().toString();
+ property2Name = UUID.randomUUID().toString();
+ PropertyProviderImpl pp2 = new PropertyProviderImpl();
+ pp2.setProperty(property2Name, property2Value);
+ instance2.bindPropertyProvider(pp2, property2Name);
+
+ assertPropertyValues();
+
+ property1Value = UUID.randomUUID().toString();
+ pp1.setProperty(property1Name, property1Value);
+ instance1.runHeartbeatOnce();
+ instance2.runHeartbeatOnce();
+
+ assertPropertyValues();
+ assertNull(instance1.getClusterViewService().getClusterView()
+ .getInstances().get(0)
+ .getProperty(UUID.randomUUID().toString()));
+ assertNull(instance2.getClusterViewService().getClusterView()
+ .getInstances().get(0)
+ .getProperty(UUID.randomUUID().toString()));
+ }
+
+ private void assertPropertyValues() {
+ assertPropertyValues(instance1.getSlingId(), property1Name,
+ property1Value);
+ assertPropertyValues(instance2.getSlingId(), property2Name,
+ property2Value);
+ }
+
+ private void assertPropertyValues(String slingId, String name, String value) {
+ assertEquals(value, getInstance(instance1, slingId).getProperty(name));
+ assertEquals(value, getInstance(instance2, slingId).getProperty(name));
+ }
+
+ private InstanceDescription getInstance(Instance instance, String slingId) {
+ Iterator<InstanceDescription> it = instance.getClusterViewService()
+ .getClusterView().getInstances().iterator();
+ while (it.hasNext()) {
+ InstanceDescription id = it.next();
+ if (id.getSlingId().equals(slingId)) {
+ return id;
+ }
+ }
+ throw new IllegalStateException("instance not found: instance="
+ + instance + ", slingId=" + slingId);
+ }
+}
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/ClusterTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/SingleInstanceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/SingleInstanceTest.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/SingleInstanceTest.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/SingleInstanceTest.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,206 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.cluster;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.sling.discovery.ClusterView;
+import org.apache.sling.discovery.InstanceDescription;
+import org.apache.sling.discovery.TopologyEvent;
+import org.apache.sling.discovery.TopologyEvent.Type;
+import org.apache.sling.discovery.impl.cluster.helpers.AssertingDiscoveryAware;
+import org.apache.sling.discovery.impl.common.resource.EstablishedInstanceDescription;
+import org.apache.sling.discovery.impl.common.resource.IsolatedInstanceDescription;
+import org.apache.sling.discovery.impl.setup.Instance;
+import org.apache.sling.discovery.impl.setup.PropertyProviderImpl;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SingleInstanceTest {
+
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ Instance instance;
+
+ String propertyValue;
+
+ @Before
+ public void setup() throws Exception {
+ instance = Instance.newStandaloneInstance("standaloneInstance", true);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ instance.stop();
+ }
+
+ @Test
+ public void testGetters() {
+ assertNotNull(instance);
+ logger.info("sling id=" + instance.getSlingId());
+ assertNotNull(instance.getClusterViewService().getClusterView());
+
+ ClusterView cv = instance.getClusterViewService().getClusterView();
+ logger.info("cluster view: id=" + cv.getId());
+ assertNotNull(cv.getId());
+ assertNotSame(cv.getId(), "");
+
+ List<InstanceDescription> instances = cv.getInstances();
+ assertNotNull(instances);
+ assertTrue(instances.size() == 1);
+
+ InstanceDescription myInstance = instances.get(0);
+ assertNotNull(myInstance);
+ assertTrue(myInstance.getClusterView() == cv);
+ logger.info("instance id: " + myInstance.getSlingId());
+ assertEquals(instance.getSlingId(), myInstance.getSlingId());
+
+ Map<String, String> properties = myInstance.getProperties();
+ assertNotNull(properties);
+
+ assertNull(myInstance.getProperty("foo"));
+
+ assertTrue(myInstance.isLeader());
+
+ assertTrue(myInstance.isLocal());
+ }
+
+ @Test
+ public void testPropertyProviders() throws Throwable {
+ final String propertyName = UUID.randomUUID().toString();
+ propertyValue = UUID.randomUUID().toString();
+ PropertyProviderImpl pp = new PropertyProviderImpl();
+ pp.setProperty(propertyName, propertyValue);
+ instance.bindPropertyProvider(pp, propertyName);
+
+ assertEquals(propertyValue,
+ instance.getClusterViewService().getClusterView()
+ .getInstances().get(0).getProperty(propertyName));
+
+ propertyValue = UUID.randomUUID().toString();
+ pp.setProperty(propertyName, propertyValue);
+ instance.runHeartbeatOnce();
+
+ assertEquals(propertyValue,
+ instance.getClusterViewService().getClusterView()
+ .getInstances().get(0).getProperty(propertyName));
+ assertNull(instance.getClusterViewService().getClusterView()
+ .getInstances().get(0)
+ .getProperty(UUID.randomUUID().toString()));
+ }
+
+ @Test
+ public void testDiscoveryAwares() throws Throwable {
+ instance.runHeartbeatOnce();
+ Thread.sleep(2000);
+ instance.runHeartbeatOnce();
+ Thread.sleep(2000);
+
+ AssertingDiscoveryAware assertingDiscoveryAware = new AssertingDiscoveryAware();
+ assertingDiscoveryAware.addExpected(Type.TOPOLOGY_INIT);
+ instance.bindDiscoveryAware(assertingDiscoveryAware);
+ assertEquals(0, assertingDiscoveryAware.getRemainingExpectedCount());
+
+ final String propertyName = UUID.randomUUID().toString();
+ propertyValue = UUID.randomUUID().toString();
+ PropertyProviderImpl pp = new PropertyProviderImpl();
+ pp.setProperty(propertyName, propertyValue);
+
+ assertingDiscoveryAware.addExpected(Type.PROPERTIES_CHANGED);
+
+ assertEquals(1, assertingDiscoveryAware.getRemainingExpectedCount());
+ assertEquals(0, pp.getGetCnt());
+ instance.bindPropertyProvider(pp, propertyName);
+ assertEquals(0, assertingDiscoveryAware.getRemainingExpectedCount());
+ // we can only assume that the getProperty was called at least once - it
+ // could be called multiple times though..
+ assertTrue(pp.getGetCnt() > 0);
+
+ assertingDiscoveryAware.addExpected(Type.PROPERTIES_CHANGED);
+
+ assertEquals(1, assertingDiscoveryAware.getRemainingExpectedCount());
+ pp.setGetCnt(0);
+ propertyValue = UUID.randomUUID().toString();
+ pp.setProperty(propertyName, propertyValue);
+ assertEquals(0, pp.getGetCnt());
+ instance.runHeartbeatOnce();
+ Thread.sleep(2000);
+ assertEquals(0, assertingDiscoveryAware.getRemainingExpectedCount());
+ assertEquals(1, pp.getGetCnt());
+
+ // a heartbeat repeat should not result in another call though
+ instance.runHeartbeatOnce();
+ Thread.sleep(2000);
+ assertEquals(0, assertingDiscoveryAware.getRemainingExpectedCount());
+ assertEquals(2, pp.getGetCnt());
+
+ }
+
+ @Test
+ public void testBootstrap() throws Throwable {
+ ClusterView initialClusterView = instance.getClusterViewService()
+ .getClusterView();
+ assertNotNull(initialClusterView);
+
+ AssertingDiscoveryAware ada = new AssertingDiscoveryAware();
+ ada.addExpected(Type.TOPOLOGY_INIT);
+ instance.bindDiscoveryAware(ada);
+ assertEquals(1, ada.getEvents().size());
+ TopologyEvent initEvent = ada.getEvents().remove(0);
+ assertNotNull(initEvent);
+
+ assertEquals(initialClusterView.getId(), initEvent.getNewView()
+ .getClusterViews().iterator().next().getId());
+ assertEquals(initialClusterView.getInstances().get(0).getSlingId(),
+ initEvent.getNewView().getLocalInstance().getSlingId());
+
+ // hard assumption that the class we get is an
+ // IsolatedInstanceDescription
+ // this is because we dont have any established clusterview yet - hence
+ // still entirely isolated
+ assertEquals(IsolatedInstanceDescription.class, initialClusterView
+ .getInstances().get(0).getClass());
+ assertEquals(IsolatedInstanceDescription.class, instance
+ .getClusterViewService().getClusterView().getInstances().get(0)
+ .getClass());
+ instance.runHeartbeatOnce();
+ Thread.sleep(1000);
+ instance.runHeartbeatOnce();
+ Thread.sleep(1000);
+ assertEquals(0, ada.getEvents().size());
+
+ // after the view was established though, we expect it to be a normal
+ // ResourceInstanceDescription
+ assertEquals(EstablishedInstanceDescription.class, instance
+ .getClusterViewService().getClusterView().getInstances().get(0)
+ .getClass());
+ }
+
+}
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/SingleInstanceTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/SingleInstanceTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/SingleInstanceTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsMultiple.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsMultiple.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsMultiple.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsMultiple.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.cluster.helpers;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.discovery.TopologyEvent;
+import org.apache.sling.discovery.TopologyEvent.Type;
+
+public class AcceptsMultiple implements TopologyEventAsserter {
+
+ private final Type[] acceptedTypes;
+
+ private final Map<Type, Integer> counts = new HashMap<Type, Integer>();
+
+ public AcceptsMultiple(Type... acceptedTypes) {
+ this.acceptedTypes = acceptedTypes;
+ }
+
+ public synchronized void assertOk(TopologyEvent event) {
+ for (int i = 0; i < acceptedTypes.length; i++) {
+ Type aType = acceptedTypes[i];
+ if (aType == event.getType()) {
+ // perfect
+ Integer c = counts.remove(aType);
+ if (c == null) {
+ counts.put(aType, new Integer(1));
+ } else {
+ counts.put(aType, new Integer(c + 1));
+ }
+ return;
+ }
+ }
+
+ throw new IllegalStateException("Got an Event which I did not expect: "
+ + event.getType());
+ }
+
+ public synchronized int getEventCnt(Type type) {
+ return counts.get(type);
+ }
+
+}
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsMultiple.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsMultiple.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsMultiple.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsParticularTopologyEvent.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsParticularTopologyEvent.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsParticularTopologyEvent.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsParticularTopologyEvent.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.cluster.helpers;
+
+import org.apache.sling.discovery.TopologyEvent;
+import org.apache.sling.discovery.TopologyEvent.Type;
+
+public class AcceptsParticularTopologyEvent implements TopologyEventAsserter {
+
+ private final Type particularType;
+
+ private int eventCnt = 0;
+
+ /**
+ * @param singleInstanceTest
+ */
+ public AcceptsParticularTopologyEvent(Type particularType) {
+ this.particularType = particularType;
+ }
+
+ public void assertOk(TopologyEvent event) {
+ if (event.getType() == particularType) {
+ // fine
+ eventCnt++;
+ } else {
+ throw new IllegalStateException("expected " + particularType
+ + ", got " + event.getType());
+ }
+ }
+
+ public int getEventCnt() {
+ return eventCnt;
+ }
+}
\ No newline at end of file
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsParticularTopologyEvent.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsParticularTopologyEvent.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AcceptsParticularTopologyEvent.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AssertingDiscoveryAware.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AssertingDiscoveryAware.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AssertingDiscoveryAware.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AssertingDiscoveryAware.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.cluster.helpers;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.sling.discovery.DiscoveryAware;
+import org.apache.sling.discovery.TopologyEvent;
+import org.apache.sling.discovery.TopologyEvent.Type;
+
+public class AssertingDiscoveryAware implements DiscoveryAware {
+ private final List<TopologyEventAsserter> expectedEvents = new LinkedList<TopologyEventAsserter>();
+
+ public AssertingDiscoveryAware() {
+ }
+
+ private List<TopologyEvent> events_ = new LinkedList<TopologyEvent>();
+
+ public void handleTopologyEvent(TopologyEvent event) {
+ TopologyEventAsserter asserter = null;
+ synchronized (expectedEvents) {
+ if (expectedEvents.size() == 0) {
+ throw new IllegalStateException(
+ "no expected events anymore. But got: " + event);
+ }
+ asserter = expectedEvents.remove(0);
+ }
+ if (asserter == null) {
+ throw new IllegalStateException("this should not occur");
+ }
+ asserter.assertOk(event);
+ events_.add(event);
+ }
+
+ public List<TopologyEvent> getEvents() {
+ return events_;
+ }
+
+ public void addExpected(Type expectedType) {
+ addExpected(new AcceptsParticularTopologyEvent(expectedType));
+ }
+
+ public void addExpected(TopologyEventAsserter topologyEventAsserter) {
+ expectedEvents.add(topologyEventAsserter);
+ }
+
+ public int getRemainingExpectedCount() {
+ return expectedEvents.size();
+ }
+}
\ No newline at end of file
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AssertingDiscoveryAware.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AssertingDiscoveryAware.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/AssertingDiscoveryAware.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/TopologyEventAsserter.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/TopologyEventAsserter.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/TopologyEventAsserter.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/TopologyEventAsserter.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.cluster.helpers;
+
+import org.apache.sling.discovery.TopologyEvent;
+
+public interface TopologyEventAsserter {
+ public void assertOk(TopologyEvent event);
+}
\ No newline at end of file
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/TopologyEventAsserter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/TopologyEventAsserter.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/cluster/helpers/TopologyEventAsserter.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/ClusterViewTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/ClusterViewTest.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/ClusterViewTest.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/ClusterViewTest.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.common;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.fail;
+
+import java.util.UUID;
+
+import org.junit.Test;
+
+public class ClusterViewTest {
+
+ @Test
+ public void testConstructor() throws Exception {
+
+ try {
+ new DefaultClusterViewImpl(null);
+ fail("should throw an exception");
+ } catch (Exception e) {
+ // ok
+ }
+
+ try {
+ new DefaultClusterViewImpl("");
+ fail("should throw an exception");
+ } catch (Exception e) {
+ // ok
+ }
+
+ final String slingId = UUID.randomUUID().toString();
+ DefaultClusterViewImpl cv = new DefaultClusterViewImpl(slingId);
+ assertEquals(slingId, cv.getId());
+
+ try {
+ cv.getInstances();
+ fail("should throw an exception");
+ } catch (Exception e) {
+ // ok
+ }
+ try {
+ cv.getLeader();
+ fail("should throw an exception");
+ } catch (Exception e) {
+ // ok
+ }
+
+ try {
+ cv.getInstances();
+ fail("should complain that there were never any instances added...");
+ } catch (Exception e) {
+ // ok
+ }
+ DefaultInstanceDescriptionImpl id0 = new DefaultInstanceDescriptionImpl(
+ null, false, false, UUID.randomUUID().toString(), null);
+ try {
+ cv.getInstances();
+ fail("should complain that there were never any instances added...");
+ } catch (Exception e) {
+ // ok
+ }
+ cv.addInstanceDescription(id0);
+ assertEquals(1, cv.getInstances().size());
+ assertSame(id0, cv.getInstances().get(0));
+ try {
+ cv.addInstanceDescription(id0);
+ fail("can only set clusterview once");
+ } catch (Exception e) {
+ // ok
+ }
+
+ assertEquals(1, cv.getInstances().size());
+ DefaultInstanceDescriptionImpl id = new DefaultInstanceDescriptionImpl(
+ cv, true, false, UUID.randomUUID().toString(), null);
+ assertEquals(2, cv.getInstances().size());
+ try {
+ cv.addInstanceDescription(id);
+ fail("can only set clusterview once - already set in constructor above");
+ } catch (Exception e) {
+ // ok
+ }
+ assertEquals(2, cv.getInstances().size());
+ assertSame(id, cv.getInstances().get(1));
+ assertSame(id, cv.getLeader());
+
+ DefaultInstanceDescriptionImpl id2 = new DefaultInstanceDescriptionImpl(
+ cv, false, false, UUID.randomUUID().toString(), null);
+ try {
+ cv.addInstanceDescription(id2);
+ fail("can only set clusterview once - already set in constructor above");
+ } catch (Exception e) {
+ // ok
+ }
+ assertEquals(3, cv.getInstances().size());
+ assertSame(id, cv.getLeader());
+
+ try {
+ cv.addInstanceDescription(id);
+ fail("should throw an exception");
+ } catch (Exception e) {
+ // ok
+ }
+ try {
+ cv.addInstanceDescription(id2);
+ fail("should throw an exception");
+ } catch (Exception e) {
+ // ok
+ }
+ try {
+ DefaultInstanceDescriptionImpl id3 = new DefaultInstanceDescriptionImpl(
+ cv, true, false, UUID.randomUUID().toString(), null);
+ cv.addInstanceDescription(id3);
+ fail("should throw an exception");
+ } catch (Exception e) {
+ // ok
+ }
+ }
+}
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/ClusterViewTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/ClusterViewTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/ClusterViewTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/InstanceDescriptionTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/InstanceDescriptionTest.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/InstanceDescriptionTest.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/InstanceDescriptionTest.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.common;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.junit.Test;
+
+public class InstanceDescriptionTest {
+
+ @Test
+ public void testConstructor() throws Exception {
+ final String slingId = UUID.randomUUID().toString();
+
+ final DefaultClusterViewImpl clusterView = null;
+ final boolean isLeader = false;
+ final boolean isOwn = false;
+ final String theSlingId = null;
+ final Map<String, String> properties = null;
+ try {
+ constructInstanceDescription(clusterView, isLeader, isOwn,
+ theSlingId, properties);
+ fail("should have thrown an exception");
+ } catch (Exception e) {
+ // ok
+ }
+ try {
+ constructInstanceDescription(null, false, false, "", null);
+ fail("should have thrown an exception");
+ } catch (Exception e) {
+ // ok
+ }
+ try {
+ constructInstanceDescription(null, false, false, slingId, null)
+ .setClusterView(null);
+ fail("should have thrown an exception");
+ } catch (Exception e) {
+ // ok
+ }
+ try {
+ constructInstanceDescription(null, false, false, slingId, null)
+ .setProperties(null);
+ fail("should have thrown an exception");
+ } catch (Exception e) {
+ // ok
+ }
+ DefaultInstanceDescriptionImpl id = constructInstanceDescription(null,
+ false, false, slingId, null);
+ id.setClusterView(new DefaultClusterViewImpl(UUID.randomUUID()
+ .toString()));
+ try {
+ id.setClusterView(new DefaultClusterViewImpl(UUID.randomUUID()
+ .toString()));
+ fail("should have thrown an exception");
+ } catch (Exception e) {
+ // ok
+ }
+
+ assertEquals(slingId,
+ constructInstanceDescription(null, false, false, slingId, null)
+ .getSlingId());
+ assertEquals(true,
+ constructInstanceDescription(null, true, false, slingId, null)
+ .isLeader());
+ assertEquals(false,
+ constructInstanceDescription(null, false, false, slingId, null)
+ .isLeader());
+ assertEquals(false,
+ constructInstanceDescription(null, false, false, slingId, null)
+ .isLocal());
+
+ }
+
+ @Test
+ public void testNotOwnInstance() throws Exception {
+ final String slingId = UUID.randomUUID().toString();
+ assertEquals(true,
+ constructInstanceDescription(null, false, true, slingId, null)
+ .isLocal());
+ }
+
+ @Test
+ public void testPropertiesSetting() throws Exception {
+ String slingId = UUID.randomUUID().toString();
+ DefaultInstanceDescriptionImpl id = constructInstanceDescription(null,
+ false, false, slingId, null);
+ id.setProperties(new HashMap<String, String>());
+ // it is actually ok to set the properties multiple times...
+ id.setProperties(new HashMap<String, String>());
+ id.setProperties(new HashMap<String, String>());
+ id.setProperties(new HashMap<String, String>());
+ }
+
+ public DefaultInstanceDescriptionImpl constructInstanceDescription(
+ final DefaultClusterViewImpl clusterView, final boolean isLeader,
+ final boolean isOwn, final String theSlingId,
+ final Map<String, String> properties) throws Exception {
+ return new DefaultInstanceDescriptionImpl(clusterView, isLeader, isOwn,
+ theSlingId, properties);
+ }
+}
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/InstanceDescriptionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/InstanceDescriptionTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/InstanceDescriptionTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/resource/EstablishedInstanceDescriptionTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/resource/EstablishedInstanceDescriptionTest.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/resource/EstablishedInstanceDescriptionTest.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/resource/EstablishedInstanceDescriptionTest.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.common.resource;
+
+import java.util.Map;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.discovery.impl.common.DefaultClusterViewImpl;
+import org.apache.sling.discovery.impl.common.DefaultInstanceDescriptionImpl;
+import org.apache.sling.discovery.impl.common.InstanceDescriptionTest;
+import org.apache.sling.discovery.impl.setup.MockedResource;
+import org.apache.sling.discovery.impl.setup.MockedResourceResolver;
+
+public class EstablishedInstanceDescriptionTest extends InstanceDescriptionTest {
+
+ @Override
+ public DefaultInstanceDescriptionImpl constructInstanceDescription(
+ DefaultClusterViewImpl clusterView, boolean isLeader,
+ boolean isOwn, String theSlingId, Map<String, String> properties)
+ throws Exception {
+
+ Resource res = new MockedResource(new MockedResourceResolver(),
+ "/foo/bar", "nt:unstructured");
+
+ return new EstablishedInstanceDescription(clusterView, res, theSlingId,
+ isLeader, isOwn);
+ }
+
+}
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/resource/EstablishedInstanceDescriptionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/resource/EstablishedInstanceDescriptionTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/common/resource/EstablishedInstanceDescriptionTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/Instance.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/Instance.java?rev=1470424&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/Instance.java (added)
+++ sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/Instance.java Mon Apr 22 09:27:35 2013
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.setup;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.ObservationManager;
+
+import junitx.util.PrivateAccessor;
+
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.discovery.DiscoveryAware;
+import org.apache.sling.discovery.PropertyProvider;
+import org.apache.sling.discovery.impl.Config;
+import org.apache.sling.discovery.impl.DiscoveryServiceImpl;
+import org.apache.sling.discovery.impl.cluster.ClusterViewService;
+import org.apache.sling.discovery.impl.cluster.ClusterViewServiceImpl;
+import org.apache.sling.discovery.impl.cluster.voting.VotingHandler;
+import org.apache.sling.discovery.impl.common.heartbeat.HeartbeatHandler;
+import org.apache.sling.discovery.impl.topology.announcement.AnnouncementRegistry;
+import org.apache.sling.discovery.impl.topology.connector.ConnectorRegistry;
+import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Instance {
+
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ public final String slingId = UUID.randomUUID().toString();
+
+ ClusterViewServiceImpl clusterViewService;
+
+ private final ResourceResolverFactory resourceResolverFactory;
+
+ private final HeartbeatHandler heartbeatHandler;
+
+ private final OSGiMock osgiMock;
+
+ private final DiscoveryServiceImpl discoveryService;
+
+ private final AnnouncementRegistry announcementRegistry;
+
+ private final ConnectorRegistry connectorRegistry;
+
+ private final VotingHandler votingHandler;
+
+ @SuppressWarnings("unused")
+ private final String debugName;
+
+ private ResourceResolver resourceResolver;
+
+ private int serviceId = 999;
+
+ private Instance(String debugName,
+ ResourceResolverFactory resourceResolverFactory, boolean resetRepo)
+ throws Exception {
+ this.debugName = debugName;
+
+ osgiMock = new OSGiMock();
+
+ this.resourceResolverFactory = resourceResolverFactory;
+
+ Config config = new Config() {
+ @Override
+ public long getHeartbeatTimeout() {
+ return 20000;
+ }
+ };
+
+ clusterViewService = OSGiFactory.createClusterViewServiceImpl(slingId,
+ resourceResolverFactory, config);
+ announcementRegistry = OSGiFactory.createITopologyAnnouncementRegistry(
+ resourceResolverFactory, config, slingId);
+ connectorRegistry = OSGiFactory.createConnectorRegistry(
+ announcementRegistry, config);
+ heartbeatHandler = OSGiFactory.createHeartbeatHandler(
+ resourceResolverFactory, slingId, announcementRegistry,
+ connectorRegistry, config,
+ resourceResolverFactory.getAdministrativeResourceResolver(null)
+ .adaptTo(Repository.class));
+
+ discoveryService = OSGiFactory.createDiscoverService(slingId,
+ heartbeatHandler, clusterViewService, announcementRegistry,
+ resourceResolverFactory, config);
+
+ votingHandler = OSGiFactory.createVotingHandler(slingId,
+ resourceResolverFactory, config);
+
+ osgiMock.addService(clusterViewService);
+ osgiMock.addService(heartbeatHandler);
+ osgiMock.addService(discoveryService);
+ osgiMock.addService(announcementRegistry);
+ osgiMock.addService(votingHandler);
+
+ resourceResolver = resourceResolverFactory
+ .getAdministrativeResourceResolver(null);
+ Session session = resourceResolver.adaptTo(Session.class);
+ System.out
+ .println("GOING TO REGISTER LISTENER WITH SESSION " + session);
+ ObservationManager observationManager = session.getWorkspace()
+ .getObservationManager();
+
+ observationManager.addEventListener(
+ new EventListener() {
+
+ public void onEvent(EventIterator events) {
+ try {
+ while (events.hasNext()) {
+ Event event = events.nextEvent();
+ Properties properties = new Properties();
+ String topic;
+ if (event.getType() == Event.NODE_ADDED) {
+ topic = SlingConstants.TOPIC_RESOURCE_ADDED;
+ } else if (event.getType() == Event.NODE_MOVED) {
+ topic = SlingConstants.TOPIC_RESOURCE_CHANGED;
+ } else if (event.getType() == Event.NODE_REMOVED) {
+ topic = SlingConstants.TOPIC_RESOURCE_REMOVED;
+ } else {
+ topic = SlingConstants.TOPIC_RESOURCE_CHANGED;
+ }
+ try {
+ properties.put("path", event.getPath());
+ org.osgi.service.event.Event osgiEvent = new org.osgi.service.event.Event(
+ topic, properties);
+ votingHandler.handleEvent(osgiEvent);
+ } catch (RepositoryException e) {
+ logger.warn("RepositoryException: " + e, e);
+ }
+ }
+ } catch (Throwable th) {
+ try {
+ dumpRepo();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ logger.error(
+ "Throwable occurred in onEvent: " + th, th);
+ }
+ }
+ }, Event.NODE_ADDED | Event.NODE_REMOVED | Event.NODE_MOVED
+ | Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED
+ | Event.PROPERTY_REMOVED | Event.PERSIST, "/", true,
+ null,
+ null, false);
+
+ osgiMock.activateAll(resetRepo);
+ }
+
+ public static Instance newStandaloneInstance(String debugName,
+ boolean resetRepo) throws Exception {
+ ResourceResolverFactory resourceResolverFactory = MockFactory
+ .mockResourceResolverFactory();
+ return new Instance(debugName, resourceResolverFactory, resetRepo);
+ }
+
+ public static Instance newClusterInstance(String debugName, Instance other,
+ boolean resetRepo) throws Exception {
+ return new Instance(debugName, other.resourceResolverFactory, resetRepo);
+ }
+
+ public void bindPropertyProvider(PropertyProvider propertyProvider,
+ String... propertyNames) throws Throwable {
+ Map<String, Object> props = new HashMap<String, Object>();
+ props.put(Constants.SERVICE_ID, (long) serviceId++);
+ props.put(PropertyProvider.PROPERTY_PROPERTIES, propertyNames);
+
+ PrivateAccessor.invoke(discoveryService, "bindPropertyProvider",
+ new Class[] { PropertyProvider.class, Map.class },
+ new Object[] { propertyProvider, props });
+ }
+
+ public String getSlingId() {
+ return slingId;
+ }
+
+ public ClusterViewService getClusterViewService() {
+ return clusterViewService;
+ }
+
+ public void runHeartbeatOnce() {
+ heartbeatHandler.run();
+ }
+
+ public void dumpRepo() throws Exception {
+ Session session = resourceResolverFactory
+ .getAdministrativeResourceResolver(null).adaptTo(Session.class);
+ logger.info("dumpRepo: |");
+ logger.info("dumpRepo: |");
+ logger.info("dumpRepo: start");
+ logger.info("dumpRepo: |");
+ logger.info("dumpRepo: |");
+ logger.info("dumpRepo: repo = " + session.getRepository());
+ logger.info("dumpRepo: |");
+ logger.info("dumpRepo: |");
+
+ dump(session.getRootNode());
+
+ // session.logout();
+ logger.info("dumpRepo: |");
+ logger.info("dumpRepo: |");
+ logger.info("dumpRepo: end");
+ logger.info("dumpRepo: |");
+ logger.info("dumpRepo: |");
+
+ session.logout();
+ }
+
+ private void dump(Node node) throws RepositoryException {
+ if (node.getPath().equals("/jcr:system")
+ || node.getPath().equals("/rep:policy")) {
+ // ignore that one
+ return;
+ }
+
+ PropertyIterator pi = node.getProperties();
+ StringBuffer sb = new StringBuffer();
+ while (pi.hasNext()) {
+ Property p = pi.nextProperty();
+ sb.append(" ");
+ sb.append(p.getName());
+ sb.append("=");
+ if (p.getType() == PropertyType.BOOLEAN) {
+ sb.append(p.getBoolean());
+ } else if (p.getType() == PropertyType.STRING) {
+ sb.append(p.getString());
+ } else if (p.getType() == PropertyType.DATE) {
+ sb.append(p.getDate().getTime());
+ } else {
+ sb.append("<unknown type=" + p.getType() + "/>");
+ }
+ }
+
+ logger.info("dump: node=" + node + " - properties:" + sb);
+ NodeIterator it = node.getNodes();
+ while (it.hasNext()) {
+ Node child = it.nextNode();
+ dump(child);
+ }
+ }
+
+ public void stop() throws LoginException {
+ if (resourceResolver != null) {
+ resourceResolver.close();
+ }
+ }
+
+ public void bindDiscoveryAware(DiscoveryAware discoveryAware)
+ throws Throwable {
+ PrivateAccessor.invoke(discoveryService, "bindDiscoveryAware",
+ new Class[] { DiscoveryAware.class },
+ new Object[] { discoveryAware });
+ }
+
+}
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/Instance.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/Instance.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/contrib/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/setup/Instance.java
------------------------------------------------------------------------------
svn:mime-type = text/plain