001    package opendreams.proxy;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    import java.util.Properties;
006    
007    import openbus.util.OpenBusProxy;
008    import openbus.util.OpenBusProxyException;
009    import tecgraf.openbus.DRMAA.JobInfoHelper;
010    import tecgraf.openbus.data_service.DataAccessDenied;
011    import tecgraf.openbus.data_service.DataDescription;
012    import tecgraf.openbus.data_service.IHierarchicalDataService;
013    import tecgraf.openbus.data_service.IHierarchicalDataServiceHelper;
014    import tecgraf.openbus.data_service.ServiceFailure;
015    import tecgraf.openbus.data_service.UnstructuredDataFactory;
016    import tecgraf.openbus.data_service.UnstructuredDataHelper;
017    import tecgraf.openbus.opendreams.IOpenDreams;
018    import tecgraf.openbus.opendreams.IOpenDreamsHelper;
019    import tecgraf.openbus.opendreams.JobInfoFactory;
020    import tecgraf.openbus.opendreams.JobParameterFactory;
021    import tecgraf.openbus.opendreams.JobParameterHelper;
022    import tecgraf.openbus.opendreams.OpenDreamsJobTemplateFactory;
023    import tecgraf.openbus.opendreams.OpenDreamsJobTemplateHelper;
024    import tecgraf.openbus.project.ProjectItemDescription;
025    import tecgraf.openbus.data_service.project.ProjectItemDescriptionFactory;
026    import tecgraf.openbus.project.ProjectItemDescriptionHelper;
027    
028    /**
029     * O <code>OpenDreamsProxy</code> tem como objetivo encapsular os mecanismos de
030     * acesso ao OpenDreams. Faz o login no barramento e recupara as interfaces dos
031     * serviços usados pelo cliente desse barramento.
032     * 
033     * @author Tecgraf PUC-Rio
034     */
035    public class OpenDreamsProxy {
036      /**
037       * Nome do arquivo default com as propriedades para acesso ao OpenDreams.
038       */
039      public static String DEFAULT_PROPERTIES_FILE = "opendreams.properties";
040      /**
041       * Nome da propriedade que possui o nome do projeto configurado.
042       */
043      public static String PROJECT_PROPERTY = "opendreams.project.name";
044      /**
045       * O proxy para o OpenBus
046       */
047      private OpenBusProxy proxy;
048    
049      /**
050       * Constrói um proxy para o serviço OpenDreams do OpenBus, usando as
051       * propriedades especificadas.
052       * 
053       * @param properties as propriedades previamente configuradas
054       * @throws OpenDreamsException se houve falha na carga das propriedades
055       */
056      public OpenDreamsProxy(Properties properties) throws OpenDreamsException {
057        try {
058          this.proxy = new OpenBusProxy(properties);
059        }
060        catch (OpenBusProxyException e) {
061          throw new OpenDreamsException("Erro na construção do OpenDreamsProxy", e);
062        }
063      }
064    
065      /**
066       * Constrói um proxy para o serviço OpenDreams do OpenBus, usando as
067       * propriedades do arquivo default de propriedades
068       * 
069       * @see #DEFAULT_PROPERTIES_FILE
070       * @throws OpenDreamsException se houve falha na carga das propriedades
071       */
072      public OpenDreamsProxy() throws OpenDreamsException {
073        try {
074          this.proxy = new OpenBusProxy(DEFAULT_PROPERTIES_FILE);
075        }
076        catch (OpenBusProxyException e) {
077          throw new OpenDreamsException("Erro na construção do OpenDreamsProxy", e);
078        }
079      }
080    
081      /**
082       * Iniciliza o contexto de acesso ao barramento, através de certificados.
083       * 
084       * @throws OpenDreamsException falha no acesso ao openbus
085       */
086      public void init() throws OpenDreamsException {
087        if (!isEnabled())
088          throw new OpenDreamsException("O proxy para o serviço opendreams não" +
089            " está habilitado. Verifique as propriedades openbus.enabled e " +
090            "opendreams.component.export");
091        try {
092          proxy.open();
093        }
094        catch (OpenBusProxyException e) {
095          throw new OpenDreamsException("Erro ao abrir o proxy do OpenBus",e);
096        }
097        registerFactories();
098      }
099    
100      /**
101       * Iniciliza o contexto de acesso ao barramento, através de login/senha.
102       * 
103       * @param user usuário LDAP
104       * @param password senha
105       * 
106       * @throws OpenDreamsException falha no acesso ao openbus
107       */
108      public void init(String user, String password) throws OpenDreamsException {
109        if (!isEnabled())
110          throw new OpenDreamsException("O proxy para o serviço opendreams não" +
111            " está habilitado. Verifique as propriedades openbus.enabled e " +
112            "opendreams.component.export");
113        try {
114          proxy.open(user, password);
115        }
116        catch (OpenBusProxyException e) {
117          throw new OpenDreamsException("Erro ao abrir o proxy do OpenBus",e);
118        }
119        registerFactories();
120      }
121      
122      /**
123       * Faz o registro no ORB das fábricas necessárias para construção
124       * (marshalling) dos value types.
125       */
126      private void registerFactories() {
127        proxy.registerFactory(OpenDreamsJobTemplateHelper.id(),
128          new OpenDreamsJobTemplateFactory());
129        proxy.registerFactory(JobParameterHelper.id(), new JobParameterFactory());
130        proxy.registerFactory(JobInfoHelper.id(), new JobInfoFactory());
131        proxy.registerFactory(ProjectItemDescriptionHelper.id(),
132          new ProjectItemDescriptionFactory());
133        proxy.registerFactory(UnstructuredDataHelper.id(), new UnstructuredDataFactory());
134      }
135    
136      /**
137       * Obtém o objeto registrado no openbus que implementa a interface
138       * <code>IOpenDreams</code>
139       * 
140       * @return o serviço <code>IOpenDreams</code>
141       * @throws OpenDreamsException se o serviço não foi encontrado
142       */
143      public IOpenDreams getIOpenDreams() throws OpenDreamsException {
144        try {
145          return IOpenDreamsHelper.narrow(proxy.getComponent("opendreams").getFacet(
146            IOpenDreamsHelper.id()));
147        }
148        catch (OpenBusProxyException e) {
149          throw new OpenDreamsException("Erro ao recuperar o serviço opendreams",e);
150        }
151      }  
152    
153      /**
154       * Obtém o objeto registrado no openbus que implementa a interface
155       * <code>IOpenDreams</code>
156       * 
157       * @return o serviço <code>IOpenDreams</code>
158       * @throws OpenDreamsException se o serviço não foi encontrado
159       */
160      public IHierarchicalDataService getIDataService()
161        throws OpenDreamsException {
162        try {
163          return IHierarchicalDataServiceHelper.narrow(proxy.getComponent(
164            "ProjectDataService").getFacet(IHierarchicalDataServiceHelper.id()));
165        }
166        catch (OpenBusProxyException e) {
167          throw new OpenDreamsException("Erro ao recuperar o serviço ProjectDataService",e);
168        }
169      }
170    
171      /**
172       * Obtém um proxy para um projeto do usuário. O nome do projeto deve estar
173       * definido na propriedade <code>opendreams.project.name</code>. do arquivo de
174       * configuração.
175       * 
176       * @return um projeto.
177       * @throws OpenDreamsException se ocorrer um erro no acesso ao serviço de
178       *         projetos
179       */
180      public Project getProject() throws OpenDreamsException {
181        return getProject(getProjectName());
182      }
183    
184      /**
185       * Obtém o nome do projeto usado para acesso ao OpenDreams. Essa propriedade é
186       * opcional, mas
187       * 
188       * @return o nome do projeto
189       * @throws OpenDreamsException se o nome do projeto não estiver configurado
190       */
191      public String getProjectName() throws OpenDreamsException {
192        String projectName = proxy.getProperties().getProperty(PROJECT_PROPERTY);
193        if (projectName == null || projectName.isEmpty()) {
194          throw new OpenDreamsException("Propriedade " + PROJECT_PROPERTY
195            + " não definida");
196        }
197        return projectName;
198      }
199    
200      /**
201       * Obtém um proxy para um projeto do usuário.
202       * 
203       * @param projectName nome do projeto
204       * 
205       * @return um projeto.
206       * @throws OpenDreamsException se ocorrer um erro no acesso ao serviço de
207       *         projetos
208       */
209      public Project getProject(String projectName) throws OpenDreamsException {
210        IHierarchicalDataService dataService = this.getIDataService();
211        DataDescription[] rootDescList;
212        try {
213          rootDescList = dataService.getRoots();
214          if (rootDescList.length < 1) {
215            throw new OpenDreamsException("O usuário não possui projetos");
216          }
217          for (int i = 0; i < rootDescList.length; i++) {
218            DataDescription rootDesc = rootDescList[i];
219            if (!(rootDesc instanceof ProjectItemDescription)) {
220              throw new OpenDreamsException("Descritor inválido:"
221                + rootDesc.toString());
222            }
223            if (rootDesc.fName.equals(projectName)) {
224              return new Project(rootDesc, proxy.getProperties().getUser(), dataService);
225            }
226          }
227        }
228        catch (ServiceFailure e) {
229          throw new OpenDreamsException("Falha no acesso ao serviço de projetos",
230            e);
231        }
232        catch (DataAccessDenied e) {
233          throw new OpenDreamsException("Falha no acesso ao serviço de projetos",
234            e);
235        }
236        return null;
237      }
238    
239      /**
240       * Obtém uma lista de proxies para os projetos do usuário.
241       * 
242       * @return lista de projetos, que pode ser vazia, caso o usuário não tenha
243       *         nenhum projeto.
244       * @throws OpenDreamsException se ocorrer um erro no acesso ao serviço de
245       *         projetos
246       */
247      public List<Project> getAllProjects() throws OpenDreamsException {
248        ArrayList<Project> ret = new ArrayList<Project>();
249    
250        IHierarchicalDataService dataService = this.getIDataService();
251        DataDescription[] rootDescList;
252        try {
253          rootDescList = dataService.getRoots();
254    
255          for (int i = 0; i < rootDescList.length; i++) {
256            DataDescription rootDesc = rootDescList[i];
257            if (!(rootDesc instanceof ProjectItemDescription)) {
258              throw new OpenDreamsException("Descritor inválido:"
259                + rootDesc.toString());
260            }
261            ret.add(new Project(rootDesc, proxy.getProperties().getUser(), dataService));
262          }
263        }
264        catch (ServiceFailure e) {
265          throw new OpenDreamsException(
266            "Falha no acesso ao serviço de projetos (getAllProjects())", e);
267        }
268        catch (DataAccessDenied e) {
269          throw new OpenDreamsException(
270            "Falha no acesso ao serviço de projetos (getAllProjects())", e);
271        }
272        return ret;
273      }
274    
275      /**
276       * Fecha a conexão com o openbus.
277       * 
278       * @param className nome canônico da classe que implementa o serviço
279       * @return {@code true} caso o componente seja registrado ou {@code false},
280       *         caso contrário.
281       * @throws OpenDreamsException Caso o proxy não esteja aberto para fazer o
282       *         registro das ofertas de serviço.
283       */
284      public boolean addComponent(String className) throws OpenDreamsException {
285        try {
286          return proxy.addComponent("opendreams", IOpenDreamsHelper.id(), className);
287        }
288        catch (OpenBusProxyException e) {
289          throw new OpenDreamsException(
290            "Falha na publicação do componente opendreams", e);
291        }
292      }
293    
294      /**
295       * Verifica se o proxy está habilitado.
296       * Para o proxy estar habilitado é necessário que o barramento esteja 
297       * habilitado (openbus.enabled) e o componente esteja habilitado (opendreams.enabled).
298       * @return {@code true} se o proxy está habilitado ou
299       *         {@code false} caso contrário.
300       */
301      public boolean isEnabled() {
302        return proxy.isEnabled()
303          && proxy.getProperties().mayExportComponent("opendreams");
304      }
305      
306      /**
307       * Fecha o proxy
308       */
309      public void close() {
310        proxy.close();   
311      }
312      
313      /**
314       * Altera o usuário para o qual a credencial está sendo delegada.
315       * Essa delegação é feita na thread.
316       * @param user o login do usuário para o qual a credencial está sendo delegada
317       */
318      public void setThreadDelegate (String user) {
319        proxy.setThreadDelegate(user);
320      }
321    }