/*
* #%L
* OW2 Chameleon - Fuchsia Framework
* %%
* Copyright (C) 2009 - 2014 OW2 Chameleon
* %%
* 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.
* #L%
*/
package org.ow2.chameleon.fuchsia.importer.jsonrpc.test;
import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
import com.googlecode.jsonrpc4j.JsonRpcServer;
import junit.framework.Assert;
import org.apache.felix.ipojo.*;
import org.apache.felix.ipojo.architecture.InstanceDescription;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.NamespaceException;
import org.ow2.chameleon.fuchsia.core.declaration.Constants;
import org.ow2.chameleon.fuchsia.core.declaration.ImportDeclaration;
import org.ow2.chameleon.fuchsia.core.declaration.ImportDeclarationBuilder;
import org.ow2.chameleon.fuchsia.core.exceptions.BinderException;
import org.ow2.chameleon.fuchsia.importer.jsonrpc.JSONRPCImporter;
import org.ow2.chameleon.fuchsia.testing.common.GenericTest;
import org.ow2.chameleon.fuchsia.testing.common.ctd.ServiceForExportation;
import org.ow2.chameleon.fuchsia.testing.common.ctd.ServiceForExportationImpl;
import org.ow2.chameleon.fuchsia.testing.common.services.HttpServiceImpl;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import static org.fest.reflect.core.Reflection.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
public class JSONRPCImporterTest extends GenericTest<ImportDeclaration, JSONRPCImporter> {
private final ServiceForExportation serviceToBeExported = spy(new ServiceForExportationImpl());
HttpServiceImpl http;
ServiceForExportation proxyRegistered;
@Mock
ServiceRegistration proxyRegisteredServiceRegistration;
@Mock
Factory defaultProxyFactory;
@Before
public void initialize() throws Exception {
super.initialize();
fuchsiaDeclarationBinder = spy(constructor().withParameterTypes(BundleContext.class).in(JSONRPCImporter.class).newInstance(context));
fuchsiaDeclarationBinder.registration(fuchsiaDeclarationBinderServiceReference);
super.registerService(serviceToBeExported, serviceToBeExported);
http = new HttpServiceImpl(HTTP_PORT);
when(context.registerService(eq(ServiceForExportation.class.getName()), anyObject(), any(Dictionary.class))).thenAnswer(new Answer<ServiceRegistration>() {
public ServiceRegistration answer(InvocationOnMock invocation) throws Throwable {
proxyRegistered = (ServiceForExportation) invocation.getArguments()[1];
return proxyRegisteredServiceRegistration;
}
});
field("defaultProxyFactory").ofType(Factory.class).in(fuchsiaDeclarationBinder).set(defaultProxyFactory);
when(defaultProxyFactory.createComponentInstance(any(Dictionary.class))).thenAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
return new ComponentInstance() {
public void start() {
}
public void stop() {
}
public void dispose() {
}
public int getState() {
return 0;
}
public InstanceDescription getInstanceDescription() {
return null;
}
public ComponentFactory getFactory() {
return null;
}
public BundleContext getContext() {
return null;
}
public String getInstanceName() {
return null;
}
public boolean isStarted() {
return false;
}
public void reconfigure(Dictionary configuration) {
}
public void addInstanceStateListener(InstanceStateListener listener) {
}
public void removeInstanceStateListener(InstanceStateListener listener) {
}
};
}
});
method("start").in(fuchsiaDeclarationBinder).invoke();
}
@After
public void uninitialize() throws Exception {
http.getServer().stop();
}
@Test
public void useDeclaration() throws ServletException, NamespaceException, BinderException {
ImportDeclaration declaration = spy(getValidDeclarations().get(0));
JsonRpcServer jsonRpcServer = new JsonRpcServer(serviceToBeExported, ServiceForExportation.class);
Servlet gs = new RPCServlet(jsonRpcServer);
Dictionary<String, Object> dic = new Hashtable<String, Object>();
http.registerServlet("/ping", gs, dic, null);
fuchsiaDeclarationBinder.useDeclaration(declaration);
verify(declaration, times(1)).handle(fuchsiaDeclarationBinderServiceReference);
Map<String, ComponentInstance> registrations = field("registrations").ofType(Map.class).in(fuchsiaDeclarationBinder).get();
Map<String, JsonRpcHttpClient> clients = field("clients").ofType(Map.class).in(fuchsiaDeclarationBinder).get();
Assert.assertEquals(1, registrations.size());
Assert.assertEquals(1, clients.size());
}
@Test
public void useDeclarationDefaultProxy() throws ServletException, NamespaceException, BinderException {
Map<String, Object> metadata = new HashMap<String, Object>();
metadata.put(Constants.ID, "my-id");
metadata.put(Constants.URL, "http://localhost:" + HTTP_PORT + "/ping");
//metadata.put(Constants.SERVICE_CLASS,ServiceForExportation.class.getName());
final ImportDeclaration declaration = spy(ImportDeclarationBuilder.fromMetadata(metadata).build());
declaration.bind(fuchsiaDeclarationBinderServiceReference);
JsonRpcServer jsonRpcServer = new JsonRpcServer(serviceToBeExported, ServiceForExportation.class);
Servlet gs = new RPCServlet(jsonRpcServer);
Dictionary<String, Object> dic = new Hashtable<String, Object>();
http.registerServlet("/ping", gs, dic, null);
fuchsiaDeclarationBinder.useDeclaration(declaration);
verify(declaration, times(1)).handle(fuchsiaDeclarationBinderServiceReference);
Map<String, ComponentInstance> registrations = field("componentInstances").ofType(Map.class).in(fuchsiaDeclarationBinder).get();
Assert.assertEquals(1, registrations.size());
}
@Test
public void denyDeclarationCustomProxy() throws ServletException, NamespaceException, BinderException {
ImportDeclaration declaration = spy(getValidDeclarations().get(0));
JsonRpcServer jsonRpcServer = new JsonRpcServer(serviceToBeExported, ServiceForExportation.class);
Servlet gs = new RPCServlet(jsonRpcServer);
Dictionary<String, Object> dic = new Hashtable<String, Object>();
http.registerServlet("/ping", gs, dic, null);
fuchsiaDeclarationBinder.useDeclaration(declaration);
verify(declaration, times(1)).handle(fuchsiaDeclarationBinderServiceReference);
Map<String, ComponentInstance> registrations = field("registrations").ofType(Map.class).in(fuchsiaDeclarationBinder).get();
Map<String, JsonRpcHttpClient> clients = field("clients").ofType(Map.class).in(fuchsiaDeclarationBinder).get();
Assert.assertEquals(1, registrations.size());
Assert.assertEquals(1, clients.size());
fuchsiaDeclarationBinder.denyDeclaration(declaration);
verify(declaration, times(1)).unhandle(fuchsiaDeclarationBinderServiceReference);
Assert.assertEquals(0, registrations.size());
Assert.assertEquals(0, clients.size());
}
@Test
public void denyDeclarationDefaultProxy() throws ServletException, NamespaceException, BinderException {
Map<String, Object> metadata = new HashMap<String, Object>();
metadata.put(Constants.ID, "my-id");
metadata.put(Constants.URL, "http://localhost:" + HTTP_PORT + "/ping");
//metadata.put(Constants.SERVICE_CLASS,ServiceForExportation.class.getName());
ImportDeclaration declaration = spy(ImportDeclarationBuilder.fromMetadata(metadata).build());
declaration.bind(fuchsiaDeclarationBinderServiceReference);
JsonRpcServer jsonRpcServer = new JsonRpcServer(serviceToBeExported, ServiceForExportation.class);
Servlet gs = new RPCServlet(jsonRpcServer);
Dictionary<String, Object> dic = new Hashtable<String, Object>();
http.registerServlet("/ping", gs, dic, null);
fuchsiaDeclarationBinder.useDeclaration(declaration);
verify(declaration, times(1)).handle(fuchsiaDeclarationBinderServiceReference);
Map<String, ComponentInstance> componentInstances = field("componentInstances").ofType(Map.class).in(fuchsiaDeclarationBinder).get();
Assert.assertEquals(1, componentInstances.size());
fuchsiaDeclarationBinder.denyDeclaration(declaration);
verify(declaration, times(1)).unhandle(fuchsiaDeclarationBinderServiceReference);
Assert.assertEquals(0, componentInstances.size());
}
@Test
public void remoteInvocationCustomProxy() throws ServletException, NamespaceException, BinderException {
ImportDeclaration declaration = getValidDeclarations().get(0);
JsonRpcServer jsonRpcServer = new JsonRpcServer(serviceToBeExported, ServiceForExportation.class);
Servlet gs = new RPCServlet(jsonRpcServer);
Dictionary<String, Object> emptyDictionary = new Hashtable<String, Object>();
http.registerServlet("/ping", gs, emptyDictionary, null);
fuchsiaDeclarationBinder.useDeclaration(declaration);
verifyRemoteInvocation(serviceToBeExported, proxyRegistered);
}
@Override
public List<ImportDeclaration> getInvalidDeclarations() {
Map<String, Object> metadata = new HashMap<String, Object>();
metadata.put(Constants.ID, "my-id");
//metadata.put(Constants.URL,"http://localhost:"+HTTP_PORT+"");
metadata.put(Constants.SERVICE_CLASS, ServiceForExportation.class.getName());
final ImportDeclaration declaration = ImportDeclarationBuilder.fromMetadata(metadata).build();
declaration.bind(fuchsiaDeclarationBinderServiceReference);
return new ArrayList<ImportDeclaration>() {{
add(declaration);
}};
}
@Test
public void gracefulStop() throws BinderException, ServletException, NamespaceException, MissingHandlerException, UnacceptableConfiguration, ConfigurationException {
ImportDeclaration declaration = getValidDeclarations().get(0);
Map<String, Object> metadata = new HashMap<String, Object>();
metadata.put(Constants.ID, "my-id");
metadata.put(Constants.URL, "http://localhost:" + HTTP_PORT + "/ping");
ImportDeclaration declarationForDefaultProxy = spy(ImportDeclarationBuilder.fromMetadata(metadata).build());
declarationForDefaultProxy.bind(fuchsiaDeclarationBinderServiceReference);
JsonRpcServer jsonRpcServer = new JsonRpcServer(serviceToBeExported, ServiceForExportation.class);
Servlet gs = new RPCServlet(jsonRpcServer);
Dictionary<String, Object> emptyDictionary = new Hashtable<String, Object>();
http.registerServlet("/ping", gs, emptyDictionary, null);
fuchsiaDeclarationBinder.useDeclaration(declaration);
fuchsiaDeclarationBinder.useDeclaration(declarationForDefaultProxy);
verifyRemoteInvocation(serviceToBeExported, proxyRegistered);
Map<String, ComponentInstance> registrations = field("registrations").ofType(Map.class).in(fuchsiaDeclarationBinder).get();
Map<String, ComponentInstance> componentInstances = field("componentInstances").ofType(Map.class).in(fuchsiaDeclarationBinder).get();
Assert.assertEquals(1, registrations.size());
Assert.assertEquals(1, componentInstances.size());
method("stop").in(fuchsiaDeclarationBinder).invoke();
Assert.assertEquals(0, registrations.size());
Assert.assertEquals(0, componentInstances.size());
}
@Override
public List<ImportDeclaration> getValidDeclarations() {
Map<String, Object> metadata = new HashMap<String, Object>();
metadata.put(Constants.ID, "my-id");
metadata.put(Constants.URL, "http://localhost:" + HTTP_PORT + "/ping");
metadata.put(Constants.SERVICE_CLASS, ServiceForExportation.class.getName());
final ImportDeclaration declaration = ImportDeclarationBuilder.fromMetadata(metadata).build();
declaration.bind(fuchsiaDeclarationBinderServiceReference);
return new ArrayList<ImportDeclaration>() {{
add(declaration);
}};
}
class RPCServlet extends HttpServlet {
private final JsonRpcServer jsonRpcServer;
public RPCServlet(JsonRpcServer jsonRpcServer) {
this.jsonRpcServer = jsonRpcServer;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
jsonRpcServer.handle(req, resp);
}
}
}