Skip to content

Commit

Permalink
MOD_BD_20160915 using HttpServiceAvailabilityChecker service componen…
Browse files Browse the repository at this point in the history
…t to check if Http Service is really started and port is affected. (cohorte/cohorte-platforms#82)
  • Loading branch information
debbabi committed Sep 16, 2016
1 parent b886d32 commit 0b651dc
Show file tree
Hide file tree
Showing 6 changed files with 269 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Changes form the 0.0.5 to 1.0.0
* Multicast discovery : adding "format version" and "node uid" to the heartbeat paquet
* Multicast discovery : new configuration option to avoid discovering local peers (of same node)

** Bug Fix
* Using a Http Service Availability Checker component to determin the right Http Service port[#82]

Changes form the 0.0.4 to 0.0.5
-------------------------------

Expand Down
4 changes: 3 additions & 1 deletion java/org.cohorte.herald.http/HISTORY.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

- MOD_BD_20160915 (issue isandlatech/cohorte-platforms/issues/82)
- using HttpServiceAvailabilityChecker service component to check if Http Service is really started and port is affected.
the port assigned to service property "org.osgi.service.http.port" is wrong. The good one returned by this service if located on "osgi.http.service.endpoints" service property of HttpService.


- MOD_OG_20160726
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,9 @@ public interface IHttpConstants {
/** Message header : path **/
String MESSAGE_HEADER_PATH = "herald-http-tansport-path";

/** Name of the component that checks the availability of http service (fully started) */
String FACTORY_HTTPSERVICE_AVAILABILIY_CHECKER = "cohorte-http-service-availability-checker-factory";

/** Name of the http service availability checker component instance */
String INSTANC_HTTPSERVICE_AVAILABILIY_CHECKER = "cohorte-http-service-availability-checker";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright 2016 Cohorte Technologies (ex. isandlaTech)
*
* Licensed 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.cohorte.herald.http;

/**
* Checks if the Http Service is available (jetty server fully started)
*
* @author bassem debbabi
*/
public interface IHttpServiceAvailabilityChecker {

/**
* Gets the valid Http Port associated to the Http Service.
*
* @return
*/
int getPort();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/**
* Copyright 2016 Cohorte Technologies (ex. isandlaTech)
*
* Licensed 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.cohorte.herald.http.impl;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Instantiate;
import org.apache.felix.ipojo.annotations.Invalidate;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.ServiceController;
import org.apache.felix.ipojo.annotations.Validate;
import org.cohorte.herald.http.IHttpConstants;
import org.cohorte.herald.http.IHttpServiceAvailabilityChecker;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpService;
import org.osgi.service.log.LogService;

/**
*
* @author Bassem Debbabi
*
*/
@Component(name = IHttpConstants.FACTORY_HTTPSERVICE_AVAILABILIY_CHECKER)
@Provides(specifications = IHttpServiceAvailabilityChecker.class)
@Instantiate(name = IHttpConstants.INSTANC_HTTPSERVICE_AVAILABILIY_CHECKER)
public class CHttpServiceAvailabilityChecker implements IHttpServiceAvailabilityChecker {

/** name of servie property holding valid Http Service endpoints */
// TODO check on framework osgi api
private static final String HTTP_SERVICE_ENDPOINTS = "osgi.http.service.endpoints";

/** HTTP service port */
private int pHttpPort;

/** HTTP service, injected by iPOJO */
@Requires
private HttpService pHttpService;

/** Service controller */
@ServiceController(value = false)
boolean pController;

/** The log service */
@Requires(optional = true)
private LogService pLogger;

/** OSGi Bundle Context */
private BundleContext pBundleContext;

/** Timer used to check if endpoint's port is set */
private Timer pTimer;

/**
* Constructor.
* @param aBundleContext
*/
public CHttpServiceAvailabilityChecker(BundleContext aBundleContext) {
pBundleContext = aBundleContext;
}

/*
* (non-Javadoc)
* @see org.cohorte.isolates.discovery.local.IHttpServiceAvailabilityChecker#getPort()
*/
@Override
public int getPort() {
return pHttpPort;
}

@Validate
public void validate() {
// set service listener to check if endpoint port is changed
String wFilter = "(objectclass=" + HttpService.class.getName() + ")";
ServiceListener wListener = new ServiceListener() {
@Override
public void serviceChanged(ServiceEvent aServiceEvent) {
if (aServiceEvent.getType() == ServiceEvent.MODIFIED) {
pLogger.log(LogService.LOG_INFO, "Properties modified! should update Http service port..");
//checkEndpoints(aServiceEvent.getServiceReference().getProperty(HTTP_SERVICE_ENDPOINTS));
// to garanty the synchronization of tests, we call instead the synchronized method:
checkRegisteredHttpService();
}
}
};
try {
pBundleContext.addServiceListener(wListener, wFilter);
} catch (InvalidSyntaxException e) {
pLogger.log(LogService.LOG_ERROR, "Invalid syntax while registering a service listener: "
+ e.getMessage());
pController = false;
pHttpPort = -1;
}
// set a timer to check periodically if endpoint port is set the first time!
// when the port is set, the timer is canceled and we do use only service listener
// to check if port change again.
pTimer = new Timer();
pTimer.scheduleAtFixedRate(new TimerTask() {

@Override
public void run() {
checkRegisteredHttpService();
if (pHttpPort > 0) {
this.cancel();
}
}
}, 1000, 1000);
}

@Invalidate
public void invalidate() {
pController = false;
pHttpPort = -1;
if (pTimer != null) {
pTimer.cancel();
pTimer = null;
}
}

/**
* Checks if the Http Service has a service property "osgi.http.service.endpoints"
* that has valid urls with a port > 0.
*/
private synchronized void checkRegisteredHttpService() {
ServiceReference<?> wHttpServiceRef = pBundleContext.getServiceReference(HttpService.class);
if (wHttpServiceRef != null) {
Object wEndpointsObj = wHttpServiceRef.getProperty(HTTP_SERVICE_ENDPOINTS);
checkEndpoints(wEndpointsObj);
}
}

/**
* Checks the list of provided endpoints if the port is set.
*
* @param aEndpoints String array of endpoints
* @return
*/
private boolean checkEndpoints(Object aEndpoints) {
if (aEndpoints == null) {
pController = false;
pHttpPort = -1;
return false;
}
String[] wEndpoints = (String[])aEndpoints;
pLogger.log(LogService.LOG_INFO, "Checking endpoints: " + Arrays.toString(wEndpoints));
for (int i=0; i< wEndpoints.length; i++) {
int wPort = getPort(wEndpoints[i]);
if (wPort > 0) {
pLogger.log(LogService.LOG_INFO, "Check Ok. Port= " + wPort);
pHttpPort = wPort;
pController = true;
return true;
}
}
return false;
}

/**
* Extracts the port from an endpoint url.
*
* @param aEndpoint
* @return
*/
private int getPort(String aEndpoint) {
try {
URL wUrl = new URL(aEndpoint);
return wUrl.getPort();
} catch (MalformedURLException e) {
pLogger.log(LogService.LOG_ERROR,
"Cannot retrieve Http service port from malformed endpoint url exception! "
+ e.getMessage());
return -1;
}
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.cohorte.herald.http.HTTPAccess;
import org.cohorte.herald.http.HTTPExtra;
import org.cohorte.herald.http.IHttpConstants;
import org.cohorte.herald.http.IHttpServiceAvailabilityChecker;
import org.cohorte.herald.transport.IContactHook;
import org.cohorte.herald.transport.IDiscoveryConstants;
import org.cohorte.herald.transport.PeerContact;
Expand All @@ -71,6 +72,9 @@ public class HttpReceiver implements IHttpReceiver, IContactHook {
/** HTTPService dependency ID */
private static final String IPOJO_ID_HTTP = "http.service";

/** Http Service Availability Checker dependency ID */
private static final String BIND_ID_HTTPSERVICE_AVAILABILITY_CHECKER = "http.availability.checker.service";

/** The peer contact utility */
private PeerContact pContact;

Expand Down Expand Up @@ -108,18 +112,23 @@ public class HttpReceiver implements IHttpReceiver, IContactHook {
@ServiceProperty(name = "servlet.path", value = IHttpConstants.SERVLET_PATH)
private String pServletPath;

@Requires(id = BIND_ID_HTTPSERVICE_AVAILABILITY_CHECKER)
private IHttpServiceAvailabilityChecker pHttpServiceAvailabilityChecker;

/**
* HTTP service ready
*
* @param aHttpService
* The bound service
* @param aServiceProperties
* The HTTP service properties
* @deprecated
*/
@Bind(id = IPOJO_ID_HTTP)
private void bindHttpService(final HttpService aHttpService,
final Map<?, ?> aServiceProperties) {

// MOD_BD_20160915 using HttpServiceAvailabilityChecker component to retrieve the right port
/*
final Object rawPort = aServiceProperties.get(HTTP_SERVICE_PORT);
if (rawPort instanceof Number) {
Expand All @@ -139,8 +148,23 @@ private void bindHttpService(final HttpService aHttpService,
pLogger.log(LogService.LOG_INFO, "HTTP Receiver bound to port="
+ pHttpPort);
*/
}

/**
* Http Service Availability Checker ready
*
* @param aHttpServiceAvailablityChecker
* The bound service
*/
@Bind(id = BIND_ID_HTTPSERVICE_AVAILABILITY_CHECKER)
private void bindHttpServiceAvailabilityChecker(final IHttpServiceAvailabilityChecker aHttpServiceAvailablityChecker) {
// update port
pHttpPort = aHttpServiceAvailablityChecker.getPort();
pLogger.log(LogService.LOG_INFO, "HTTP Receiver bound to port="
+ pHttpPort);
}

/**
* Checks if the peer UID matches cached information (see
* {@link IHttpDirectory#checkAccess(String, String, int)}
Expand Down

0 comments on commit 0b651dc

Please sign in to comment.