001    package opendreams.proxy;
002    
003    import java.io.FileInputStream;
004    import java.io.FileNotFoundException;
005    import java.io.InputStream;
006    import java.io.Reader;
007    import java.security.cert.X509Certificate;
008    import java.security.interfaces.RSAPrivateKey;
009    import java.util.Properties;
010    import java.util.logging.Level;
011    
012    import openbusidl.rs.IRegistryService;
013    import openbusidl.rs.Property;
014    import openbusidl.rs.ServiceOffer;
015    
016    import org.omg.CORBA_2_3.ORB;
017    
018    import scs.core.IComponent;
019    import tecgraf.openbus.Openbus;
020    import tecgraf.openbus.DRMAA.JobInfoHelper;
021    import tecgraf.openbus.data_service.DataAccessDenied;
022    import tecgraf.openbus.data_service.DataDescription;
023    import tecgraf.openbus.data_service.IHierarchicalDataService;
024    import tecgraf.openbus.data_service.IHierarchicalDataServiceHelper;
025    import tecgraf.openbus.data_service.ServiceFailure;
026    import tecgraf.openbus.data_service.UnstructuredDataFactory;
027    import tecgraf.openbus.data_service.UnstructuredDataHelper;
028    import tecgraf.openbus.opendreams.IOpenDreams;
029    import tecgraf.openbus.opendreams.IOpenDreamsHelper;
030    import tecgraf.openbus.opendreams.JobInfoFactory;
031    import tecgraf.openbus.opendreams.JobParameterFactory;
032    import tecgraf.openbus.opendreams.JobParameterHelper;
033    import tecgraf.openbus.opendreams.OpenDreamsJobTemplateFactory;
034    import tecgraf.openbus.opendreams.OpenDreamsJobTemplateHelper;
035    import tecgraf.openbus.project.ProjectItemDescription;
036    import tecgraf.openbus.project.ProjectItemDescriptionFactory;
037    import tecgraf.openbus.project.ProjectItemDescriptionHelper;
038    import tecgraf.openbus.util.CryptoUtils;
039    import tecgraf.openbus.util.Log;
040    
041    /**
042     * O <code>OpenDreamsProxy</code> tem como objetivo encapsular os mecanismos
043     * de acesso ao OpenDreams. Faz o login no barramento e recupara as interfaces
044     * dos serviços usados pelo cliente desse barramento.
045     * 
046     * @author Tecgraf PUC-Rio
047     */
048    public class OpenDreamsProxy {
049      /**
050       * Nome do arquivo default com as propriedades para acesso ao OpenDreams.
051       */
052      public static String DEFAULT_PROPERTIES_FILE = "opendreams.properties";
053    
054      private IRegistryService registryService;
055      private IOpenDreams opendreams;
056      private IHierarchicalDataService dataService;
057      private OpenDreamsProperties properties = null;
058    
059      /**
060       * Constrói um proxy para o serviço OpenDreams do OpenBus, usando as
061       * propriedades especificadas.
062       * 
063       * @param properties as propriedades previamente configuradas
064       * @see opendreams.proxy.OpenDreamsProperties#PROPERTIES
065       * @throws OpenDreamsException se houve falha na carga das propriedades
066       */
067      public OpenDreamsProxy(Properties properties) throws OpenDreamsException {
068        this.properties = new OpenDreamsProperties(properties);
069      }
070    
071      /**
072       * Constrói um proxy para o serviço OpenDreams do OpenBus, usando as
073       * propriedades do arquivo default de propriedades
074       * 
075       * @see opendreams.proxy.OpenDreamsProperties#PROPERTIES
076       * @see #DEFAULT_PROPERTIES_FILE
077       * @see #loadProperties(InputStream)
078       * @see #loadProperties(Reader)
079       * @throws OpenDreamsException se houve falha na carga das propriedades
080       */
081      public OpenDreamsProxy() throws OpenDreamsException {
082        try {
083          loadProperties(new FileInputStream(DEFAULT_PROPERTIES_FILE));
084        }
085        catch (FileNotFoundException e) {
086          throw new OpenDreamsException(
087            "Arquivo de propriedades default jacorb.properties" + " não encontrado",
088            e);
089        }
090      }
091    
092      /**
093       * Carrega as propriedades para acesso ao OpenDreams.
094       * 
095       * @param propertiesFile objeto <code>InputStream</code> com as propriedades
096       * @throws OpenDreamsException se houve falha na carga das propriedades
097       */
098      protected void loadProperties(InputStream propertiesFile)
099        throws OpenDreamsException {
100        this.properties = new OpenDreamsProperties(propertiesFile);
101      }
102    
103      /**
104       * Carrega as propriedades para acesso ao OpenDreams.
105       * 
106       * @param propertiesFile objeto <code>Reader</code> com as propriedades
107       * @throws OpenDreamsException se houve falha na carga das propriedades
108       */
109      protected void loadProperties(Reader propertiesFile)
110        throws OpenDreamsException {
111        this.properties = new OpenDreamsProperties(propertiesFile);
112      }
113    
114      /**
115       * Iniciliza o contexto de acesso ao barramento.
116       * 
117       * @throws OpenDreamsException falha no acesso ao openbus
118       */
119      public void init() throws OpenDreamsException {
120        if (properties == null) {
121          throw new OpenDreamsException("Propriedades não definidas");
122        }
123        Log.setLogsLevel(Level.WARNING);
124        try {
125          Properties orbProps = new Properties();
126          orbProps.setProperty("org.omg.CORBA.ORBClass", properties.getORBClass());
127          orbProps.setProperty("org.omg.CORBA.ORBSingletonClass", properties
128            .getORBSingletonClass());
129          Openbus bus = Openbus.getInstance();
130          bus.resetAndInitialize(new String[] {}, orbProps, properties.getHost(),
131            properties.getPort());
132          String acsCertificateFile = properties.getCertificate();
133          RSAPrivateKey privateKey =
134            CryptoUtils.readPrivateKey(properties.getPrivateKey());
135          X509Certificate acsCertificate =
136            CryptoUtils.readCertificate(acsCertificateFile);
137          registryService =
138            bus.connect(properties.getEntityName(), privateKey, acsCertificate);
139          if (properties.hasDelegation()) {
140            String delegateToUser = properties.getDelegate();
141            bus.getCredential().delegate = delegateToUser;
142          }
143        }
144        catch (Exception e) {
145          throw new OpenDreamsException("Erro no acesso ao OpenBus: "
146            + properties.getHost() + " " + properties.getPort(), e);
147        }
148        registerFactories();
149      }
150    
151      /**
152       * Obtém o objeto registrado no openbus que implementa a interface
153       * <code>IOpenDreams</code>
154       * 
155       * @return o serviço <code>IOpenDreams</code>
156       * @throws OpenDreamsException se o serviço não foi encontrado
157       */
158      public IOpenDreams getIOpenDreams() throws OpenDreamsException {
159        if (opendreams == null) {
160          String componentId =
161            getComponentId(properties.getOpenDreamsComponentName().trim(),
162              properties.getOpenDreamsComponentVersion().trim());
163          Property property =
164            new Property("component_id", new String[] { componentId });
165          ServiceOffer[] servicesOffers =
166            registryService.findByCriteria(new String[] { "opendreams" },
167              new Property[] { property });
168          if (servicesOffers.length == 0) {
169            throw new OpenDreamsException("Não foi encontrado um serviço com "
170              + "identificador: " + componentId);
171          }
172          if (servicesOffers.length > 1) {
173            throw new OpenDreamsException("Foi encontrado mais de um serviço com "
174              + "identificador: " + componentId);
175          }
176          ServiceOffer serviceOffer = servicesOffers[0];
177          IComponent component = serviceOffer.member;
178          org.omg.CORBA.Object opendreamsObject =
179            component.getFacet(IOpenDreamsHelper.id());
180          opendreams = IOpenDreamsHelper.narrow(opendreamsObject);
181        }
182        return opendreams;
183      }
184    
185      /**
186       * Obtém o objeto registrado no openbus que implementa a interface
187       * <code>IOpenDreams</code>
188       * 
189       * @return o serviço <code>IOpenDreams</code>
190       * @throws OpenDreamsException se o serviço não foi encontrado
191       */
192      public IHierarchicalDataService getIDataService() throws OpenDreamsException {
193        if (dataService == null) {
194          String componentId =
195            getComponentId(properties.getDataServiceComponentName().trim(),
196              properties.getDataServiceComponentVersion().trim());
197          Property property =
198            new Property("component_id", new String[] { componentId });
199          ServiceOffer[] servicesOffers =
200            registryService.findByCriteria(new String[] { "ProjectDataService" },
201              new Property[] { property });
202          if (servicesOffers.length == 0) {
203            throw new OpenDreamsException("Não foi encontrado um serviço com "
204              + "identificador: " + componentId);
205          }
206          if (servicesOffers.length > 1) {
207            throw new OpenDreamsException("Foi encontrado mais de um serviço com "
208              + "identificador: " + componentId);
209          }
210          ServiceOffer serviceOffer = servicesOffers[0];
211          IComponent component = serviceOffer.member;
212          org.omg.CORBA.Object dataserviceObject =
213            component.getFacet(IHierarchicalDataServiceHelper.id());
214          dataService = IHierarchicalDataServiceHelper.narrow(dataserviceObject);
215        }
216        return dataService;
217      }
218    
219      /**
220       * Obtém um proxy para um projeto do usuário. O nome do projeto deve estar
221       * definido na propriedade <code>opendreams.project.name</code>. do arquivo
222       * de configuração.
223       * 
224       * @return um projeto.
225       * @throws OpenDreamsException se ocorrer um erro no acesso ao serviço de
226       *         projetos
227       */
228      public Project getProject() throws OpenDreamsException {
229        String projectName = properties.getProjectName();
230        if (projectName == null || projectName.isEmpty()) {
231          throw new OpenDreamsException(
232            "Propriedade opendreams.project.name não definida");
233        }
234        return getProject(projectName);
235      }
236    
237      /**
238       * Obtém um proxy para um projeto do usuário.
239       * 
240       * @param projectName nome do projeto
241       * 
242       * @return um projeto.
243       * @throws OpenDreamsException se ocorrer um erro no acesso ao serviço de
244       *         projetos
245       */
246      public Project getProject(String projectName) throws OpenDreamsException {
247        IHierarchicalDataService dataService = this.getIDataService();
248        DataDescription[] rootDescList;
249        try {
250          rootDescList = dataService.getRoots();
251          if (rootDescList.length < 1) {
252            throw new OpenDreamsException("O usuário não possui projetos");
253          }
254          for (int i = 0; i < rootDescList.length; i++) {
255            DataDescription rootDesc = rootDescList[i];
256            if (!(rootDesc instanceof ProjectItemDescription)) {
257              throw new OpenDreamsException("Descritor inválido:"
258                + rootDesc.toString());
259            }
260            if (rootDesc.fName.equals(projectName)) {
261              return new Project(rootDesc, properties.getUser(), dataService);
262            }
263          }
264        }
265        catch (ServiceFailure e) {
266          throw new OpenDreamsException("Falha no acesso ao serviço de projetos", e);
267        }
268        catch (DataAccessDenied e) {
269          throw new OpenDreamsException("Falha no acesso ao serviço de projetos", e);
270        }
271        return null;
272      }
273    
274      /**
275       * Fecha a conexão com o openbus.
276       * 
277       * @throws OpenDreamsException falha no acesso ao openbus
278       */
279      public void close() throws OpenDreamsException {
280        Openbus.getInstance().disconnect();
281      }
282    
283      /**
284       * Faz o registro no ORB das fábricas necessárias para construção
285       * (marshalling) dos value types.
286       */
287      private void registerFactories() {
288        Openbus bus = Openbus.getInstance();
289        ORB orb = (ORB) bus.getORB();
290        // Fábricas do OpenDreams
291        orb.register_value_factory(OpenDreamsJobTemplateHelper.id(),
292          new OpenDreamsJobTemplateFactory());
293        orb.register_value_factory(JobParameterHelper.id(),
294          new JobParameterFactory());
295        orb.register_value_factory(JobInfoHelper.id(), new JobInfoFactory());
296        // Fábricas do Serviço de Projetos
297        orb.register_value_factory(ProjectItemDescriptionHelper.id(),
298          new ProjectItemDescriptionFactory());
299        orb.register_value_factory(UnstructuredDataHelper.id(),
300          new UnstructuredDataFactory());
301      }
302    
303      /**
304       * Obtém o identificador do componente de acordo com o nome e a versão desse
305       * componente. Esse identificador é usado para encontrar o componente no
306       * OpenBus.
307       * 
308       * @return o identificador do componente.
309       */
310      private String getComponentId(String componentName, String componentVersion) {
311        final String[] tmp = componentVersion.split("[\\.]");
312        StringBuffer componentId = new StringBuffer(componentName);
313        componentId.append(':');
314        for (String s : tmp) {
315          componentId.append(s.trim());
316        }
317        return componentId.toString();
318      }
319    
320      /**
321       * Obtém as propriedades usadas por esse proxy.
322       * 
323       * @return as propriedades do acesso ao OpenDreams
324       */
325      public OpenDreamsProperties getProperties() {
326        return properties;
327      }
328    }