Post on 07-Apr-2016
Tecgraf PUC-Riomaio de 2011
SDK Openbus - Java
A API do Openbus
• Para facilitar o desenvolvimento das aplicações que usam o barramento, provendo ou consumindo serviços, o SDK Java fornece uma classe Openbus que encapsula as principais funcionalidades para:• inicialização e conexão com o barramento.• obtenção das facetas dos serviços básicos.• obtenção do ORB e do POA utilizados
• A própria classe OpenBus já cuida da renovação da credencial emitida na conexão
Openbus é um Singleton
• Uma aplicação pode ter apenas uma instância de Openbus.• atualmente, uma nesma aplicação não pode
utilizar dois barramentos diferentes
public static Openbus getInstance();
Inicialização do barramento
• Possui métodos para inicializar o ORB com as propriedades informadas e faz reset no estado do barramento.• Ativa o mecanismo de interceptação das requisições para que a credencial seja utilizada• Ativa o POA “RootPOA”
public void init(String[] args, Properties props, String host, int port) throws UserException, OpenbusAlreadyInitializedException;
Conexão com o barramento
• Os métodos de inicialização são sobrecarregados para diferentes formas de conexão com o barramento
• Todos retornam a referência para o IRegistryService public synchronized IRegistryService connect(String user, String password)throws ACSLoginFailureException, ACSUnavailableException, ServiceUnavailableException, InvalidCredentialException, CORBAException, OpenBusException;
public synchronized IRegistryService connect(String name, RSAPrivateKey privateKey, X509Certificate acsCertificate)throws ACSLoginFailureException, ServiceUnavailableException, PKIException, ACSUnavailableException, InvalidCredentialException, OpenBusException, CORBAException;
public IRegistryService connect(Credential credential)throws InvalidCredentialException, OpenBusException, ServiceUnavailableException, ACSUnavailableException, CORBAException;
Listener para expiração da credencial
• Possui um método que permite adicionar um listener que é avisado quando a credencial expirou e não foi possível renovar o leasing.
• O listener é chamado pela thread que faz a renovação automática do leasing, que a própria instância do Openbus já inicia.
public void setLeaseExpiredCallback(LeaseExpiredCallback lec);
Credencial por Thread
• Possui o método setThreadCredential que permite que uma credencial válida, diferente daquela que foi usada na conexão, seja configurada para a thread corrente.
• As requisições aos serviço usam a credencial atribuída à thread corrente, caso exista.
public void setThreadCredential(Credential credential);
Credencial por Thread
• Um uso comum da credencial por thread é criar uma nova credencial como uma cópia daquela resultado da autenticação corrente, alterando apenas o delegate.
Credential credential = Openbus.getInstance().getCredential(); Credential newCredential = new Credential(credential.identifier, credential.owner, delegate); Openbus.getInstance().setThreadCredential(newCredential);
Acesso aos serviços básicos
• Possui métodos para obter as referências para as facetas do serviços básicos:• IAccessControlService• IRegistryService• ISessionService
public IAccessControlService getAccessControlService();
public IRegistryService getRegistryService();
public ISessionService getSessionService();
Acesso aos ORB e ao POA
• Possui métodos para obter as referências para as ORB utilizado e ao POA “RootPOA”:
public org.omg.CORBA.ORB getORB();
public POA getRootPOA();
Finaliza a conexão
• Possui um métod para suspender a renovação da credencial e fazer logout no serviço de acesso
public synchronized boolean disconnect();
Outras classes auxiliares
• CryptoUtils • Log• LeaseExpiredCallback• …
Desenvolvendo com oSDK Java Openbus
Passo 1: Obtendo o SDK Openbus
• A última versão do SDK Java do Openbus pode ser obtida em:• https://jira.tecgraf.puc-rio.br/confluence/display/
ESDPUB/Openbus+Download• Precisaremos também do JDK 1.5 ou superior
Libs do SDK Openbus 1.5• Openbus:
• openbus-api-1.5.0.jar• openbus-idl-jacorb-1.5.0.jar
• As libs do Jacorb são distribuídas com o SDK:• avalon-framework-4.1.5.jar• jacorb-2.3.0.jar• logkit-1.2.jar
• As libs do SCS são distribuídas com o SDK:• scs-core-1.1.0.jar• scs-idl-jacorb-1.1.0.jar
• A lib para encoding:• commons-codec-1.3.jar
Passo 2: Preparando os stubs e skeletons
• Usaremos como base, as mesmas IDLs do exemplo StockServer mostrado na parte de CORBA e do SCS • Compilar a IDL• Compilar o código Java das classes geradas pelo
compilador IDL e das classes que implementam as facetas descritas na IDL
Passo 3: Implementando as facetas do componente• O componente StockSeller possui duas facetas:
• StockServer• StockExchanger
• As classes StockServerImpl e StockExchangeImpl implementam, respectivamente, cada uma dessas facetas.
• Para compartilhar o estado entre as duas facetas, iremos implementar a classe StockSellerContextImpl de contexto do componente.
Implementando o contexto StockSellerContextImpl
public class StockSellerContextImpl extends ComponentContextImpl { /** As ações com seus respectivos valores */ private Map<String, Float> myStock; ...
public StockSellerContextImpl(ComponentBuilder builder, ComponentId componentId) { super(builder, componentId); ... } public synchronized boolean containsStockSymbol(String symbol) { return myStock.containsKey(symbol); } public synchronized float getStockValue(String symbol) { return myStock.get(symbol); } public synchronized String[] getAllSymbols() { return myStock.keySet().toArray(new String[0]); } public synchronized void decrementStockValue(String symbol, float value) { float newValue = getStockValue(symbol) - value; myStock.put(symbol, newValue); }
Implementando a faceta (Servant) StockServer
public class StockServerImpl extends StockServerPOA { private StockSellerContextImpl context;
public StockServerImpl(ComponentContext context) { this.context = StockSellerContextImpl.class.cast(context); } public float getStockValue(String symbol) { if (context.containsStockSymbol(symbol)) { return context.getStockValue(symbol); } else { return 0f; } } public String[] getStockSymbols() { return context.getAllSymbols(); }
public org.omg.CORBA.Object _get_component() { return context.getIComponent(); }}
Implementando a faceta (Servant) StockExchange
public class StockExchangeImpl extends StockExchangePOA {
StockSellerContextImpl context;
public StockExchangeImpl(ComponentContext context) { this.context = StockSellerContextImpl.class.cast(context); }
public boolean buyStock(String symbol) { if (!context.containsStockSymbol(symbol) || context.getStockValue(symbol) == 0.0F) { return false; } context.decrementStockValue(symbol, 1); return true; }
public org.omg.CORBA.Object _get_component() { return context.getIComponent(); }
Passo 4: Implementando o Servidor
• O programa servidor se encarrega de:– inicializar o Openbus– fazer a conexão por certificado– criar o componente que implementa as facetas
StockServer e StockExchange– registrar uma oferta de serviço– instalar um ShutdownHook para desconectar
com o barramento antes de finalizar a aplicação– iniciar a execução do ORB
Fluxo principal do servidor
private void run(String[] args) throws StockServerOpenbusException { Properties props = loadProperties(); initOpenbus(args, props); IRegistryService registryService = connectWithOpenBus(props); ComponentContext context = createComponent(props); String registrationId = registerServiceOffer(registryService, context); Runtime.getRuntime().addShutdownHook(new ShutdownThread(registrationId)); Openbus.getInstance().getORB().run(); }
public static void main(String[] args) { StockServerOpenbus demo = new StockServerOpenbus(); try { demo.run(args); } catch (Throwable e) { e.printStackTrace(); } }
Inicializar o Openbus
private void initOpenbus(String[] args, Properties props) throws StockServerOpenbusException { String host = props.getProperty("host.name"); String portString = props.getProperty("host.port"); int port = Integer.valueOf(portString);
Log.setLogsLevel(Level.WARNING);
Properties orbProps = new Properties(); orbProps.setProperty("org.omg.CORBA.ORBClass", "org.jacorb.orb.ORB"); orbProps.setProperty("org.omg.CORBA.ORBSingletonClass", "org.jacorb.orb.ORBSingleton"); Openbus bus = Openbus.getInstance(); try { bus.init(args, orbProps, host, port); } catch (Exception e) { throw new StockServerOpenbusException( "Erro durante a inicialização do Openbus.", e); }}
Fazer a conexão por certificadoprivate IRegistryService connectWithOpenBus(Properties props) throws StockServerOpenbusException {
String entityName = props.getProperty("entity.name"); String privateKeyFile = props.getProperty("private.key"); String acsCertificateFile = props.getProperty("acs.certificate"); try { RSAPrivateKey privateKey = CryptoUtils.readPrivateKey(privateKeyFile); X509Certificate acsCertificate = CryptoUtils.readCertificate(acsCertificateFile);
Openbus bus = Openbus.getInstance(); IRegistryService registryService = bus.connect(entityName, privateKey, acsCertificate); if (registryService == null) { throw new RSUnavailableException(); } System.out.println("Stock Server conectado."); return registryService; } catch (Exception e) { ... }}
Criar o componente private ComponentContext createComponent(Properties props) throws StockServerOpenbusException { Openbus bus = Openbus.getInstance(); ComponentBuilder builder = new ComponentBuilder(bus.getRootPOA(), bus.getORB()); ComponentId componentId = new ComponentId("StockSeller", (byte) 1, (byte) 0, (byte) 0, "Java"); ComponentContext context = new StockSellerContextImpl(builder, componentId); ExtendedFacetDescription[] facetDescriptions = createFacetDescriptions(props); ReceptacleDescription[] recDescriptions = createReceptacleDescriptions(); try { context = builder.newComponent(facetDescriptions, recDescriptions, componentId, context); return context; } catch (Exception e) { ... } }
Criar o componente - facetas private ExtendedFacetDescription[] createFacetDescriptions(Properties props) { String stockServerFacetClass = props.getProperty("stockserver.class"); String stockExchageFacetClass = props.getProperty("stockexchange.class"); ExtendedFacetDescription[] facetDescriptions = new ExtendedFacetDescription[2]; facetDescriptions[0] = new ExtendedFacetDescription("StockServer", StockServerHelper.id(), stockServerFacetClass); facetDescriptions[1] = new ExtendedFacetDescription("StockExchange", StockExchangeHelper.id(), stockExchageFacetClass); return facetDescriptions; }
Criar o componente - receptáculos private ReceptacleDescription[] createReceptacleDescriptions() { ReceptacleDescription[] recDescriptions = new ReceptacleDescription[1]; recDescriptions[0] = new ReceptacleDescription("Printer", ExchangePrinterHelper.id(), false, null); return recDescriptions; }
Registrar a oferta de serviçoprivate String registerServiceOffer(IRegistryService registryService, ComponentContext context) throws StockServerOpenbusException { org.omg.CORBA.Object obj = context.getIComponent(); IComponent component = IComponentHelper.narrow(obj); Property registrationProps[] = new Property[0]; ServiceOffer serviceOffer = new ServiceOffer(registrationProps, component); try { String registrationId = registryService.register(serviceOffer); System.out.println("Stock Server registrado."); return registrationId; } catch (Exception e) { throw new StockServerOpenbusException( "Erro ao registrar a oferta do componente SCS", e); } }
Instalar o ShutdownHook
Runtime.getRuntime().addShutdownHook(new ShutdownThread(registrationId));
...
private static class ShutdownThread extends Thread { private String registrationId;
ShutdownThread(String registrationId) { this.registrationId = registrationId; }
run() { Openbus bus = Openbus.getInstance(); IRegistryService registryService = bus.getRegistryService(); registryService.unregister(registrationId); bus.disconnect(); } }
Iniciar a execução do ORB
Openbus.getInstance().getORB().run();
Passo 5: Implementando o Cliente
• O programa cliente se encarrega de:– inicializar o Openbus– fazer a conexão por usuário e senha
Fluxo principal do cliente private void run(String[] args) throws StockClientOpenbusException { Properties props = loadProperties(); Openbus bus = initOpenbus(args, props); IRegistryService registryService = connectWithOpenBus(props); StockServer stockServer = getStockServer (registryService); System.out.println("Ações de mercado obtidas do StockServer:"); // Obtém os símbolos de todas as ações String[] stockSymbols = stockServer.getStockSymbols(); // Mostra as ações de mercado com seus respectivos valores for (int i = 0; i < stockSymbols.length; i++) { System.out.println(stockSymbols[i] + " " + stockServer.getStockValue(stockSymbols[i])); } StockExchange stockExchange = getStockExchange(registryService); // Compra uma ação if (stockSymbols.length > 0) { String first = stockSymbols[0]; System.out.println("--Compra a ação :" + first); stockExchange.buyStock(first); System.out.println("--Ação " + first + " depois da negociação: " + stockServer.getStockValue(first)); } bus.disconnect(); }
Conectando com usuário e senha private IRegistryService connectWithOpenBus(Properties props) throws StockClientOpenbusException { String userLogin = props.getProperty("login"); String userPassword = props.getProperty("password"); Openbus bus = Openbus.getInstance(); try { IRegistryService registryService = bus.connect(userLogin, userPassword); if (registryService == null) { throw new RSUnavailableException(); } System.out.println("Stock Client conectado."); return registryService; } catch (Exception e) { throw new StockClientOpenbusException( "Erro ao fazer a conexão com o Openbus", e); } }
Procurando pelas facetas private StockServer getStockServer(IRegistryService registryService) { ServiceOffer[] servicesOffers = registryService.find(new String[] { "StockServer”}); ServiceOffer serviceOffer = servicesOffers[0]; IComponent component = serviceOffer.member; org.omg.CORBA.Object stockServerObject = component.getFacetByName("StockServer"); return StockServerHelper.narrow(stockServerObject); }
private StockExchange getStockExchange(IRegistryService registryService) { ServiceOffer[] servicesOffers = registryService.find(new String[] { "StockServer" }); ServiceOffer serviceOffer = servicesOffers[0]; IComponent component = serviceOffer.member; org.omg.CORBA.Object stockExchangeObject = component.getFacetByName("StockExchange"); return StockExchangeHelper.narrow(stockExchangeObject); }