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