001/* 002 * Copyright (c) 2003-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: tao $' 006 * '$Date: 2014-04-21 23:34:35 +0000 (Mon, 21 Apr 2014) $' 007 * '$Revision: 32688 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.objectmanager.repository; 031 032import java.io.ByteArrayInputStream; 033import java.io.ByteArrayOutputStream; 034import java.io.File; 035import java.io.InputStream; 036import java.io.Reader; 037import java.io.StringReader; 038import java.net.URL; 039import java.util.Iterator; 040import java.util.List; 041import java.util.Vector; 042 043import org.apache.commons.logging.Log; 044import org.apache.commons.logging.LogFactory; 045import org.ecoinformatics.ecogrid.EcogridObjType; 046import org.ecoinformatics.ecogrid.authenticatedqueryservice.AuthenticatedQueryServiceClient; 047import org.ecoinformatics.ecogrid.authenticatedqueryservice.AuthenticatedQueryServiceGetToStreamClient; 048import org.ecoinformatics.ecogrid.client.AuthenticationServiceClient; 049import org.ecoinformatics.ecogrid.client.IdentifierServiceClient; 050import org.ecoinformatics.ecogrid.client.PutServiceClient; 051import org.ecoinformatics.ecogrid.client.RegistryServiceClient; 052import org.ecoinformatics.ecogrid.queryservice.QueryServiceClient; 053import org.ecoinformatics.ecogrid.queryservice.query.QueryType; 054import org.ecoinformatics.ecogrid.queryservice.resultset.ResultsetType; 055import org.ecoinformatics.ecogrid.queryservice.resultset.ResultsetTypeRecord; 056import org.ecoinformatics.ecogrid.queryservice.stub.QueryServiceStub; 057import org.ecoinformatics.ecogrid.registry.stub.RegistryEntryType; 058import org.kepler.authentication.AuthenticationException; 059import org.kepler.authentication.AuthenticationManager; 060import org.kepler.authentication.ProxyEntity; 061import org.kepler.gui.CanvasDropTargetListener; 062import org.kepler.kar.KARFile; 063import org.kepler.kar.karxml.KarXml; 064import org.kepler.objectmanager.lsid.KeplerLSID; 065 066import util.StaticUtil; 067 068/** 069 * This class represents an ecogrid repository 070 * 071 * @author Chad Berkley 072 */ 073public class EcogridRepository extends Repository { 074 private static final Log log = LogFactory.getLog(EcogridRepository.class 075 .getName()); 076 private static final boolean isDebugging = log.isDebugEnabled(); 077 078 private static final String WORKFLOWRUNTYPE = "org.kepler.util.WorkflowRun"; 079 080 private String ECOGRIDPUTSERVER; 081 private String ECOGRIDLSIDSERVER; 082 private String ECOGRIDQUERYSERVER; 083 private String ECOGRIDREGAUTHSERVER; 084 private String ECOGRIDAUTHORIZATIONSERVER; 085 private String ECOGRIDAUTHENTICATEDQUERYSERVICE; 086 private String regsessionid; 087 088 public EcogridRepository(String name, String repository, String putPath, 089 String authDomain, String lsidPath, String queryPath, String authenticatedQueryPath, 090 String authorizationPath, String registry, String registryauth, 091 String authProtocol, String lsidAuthority) { 092 super(name, repository, putPath, authDomain, lsidPath, queryPath, authenticatedQueryPath, 093 authorizationPath, registry, registryauth, authProtocol, lsidAuthority); 094 ECOGRIDPUTSERVER = authProtocol +"://"+ repository + putPath; 095 ECOGRIDLSIDSERVER = authProtocol +"://" + repository + lsidPath; 096 ECOGRIDQUERYSERVER = authProtocol +"://"+ repository + queryPath; 097 ECOGRIDAUTHORIZATIONSERVER = authProtocol +"://"+ repository + authorizationPath; 098 ECOGRIDREGAUTHSERVER = registryauth; 099 ECOGRIDAUTHENTICATEDQUERYSERVICE = authProtocol +"://"+ repository + authenticatedQueryPath; 100 101 if (isDebugging) { 102 log.debug("repository initialized with put server: " 103 + ECOGRIDPUTSERVER); 104 log.debug("repository initialized with lsid server: " 105 + ECOGRIDLSIDSERVER); 106 log.debug("repository initialized with query server: " 107 + ECOGRIDQUERYSERVER); 108 log.debug("repository initialized with registry: " + registry); 109 } 110 111 CanvasDropTargetListener cdtListener = CanvasDropTargetListener 112 .getInstance(); 113 cdtListener 114 .registerListener(new EcogridRepositoryKARDownloadListener()); 115 } 116 117 /** 118 * return the url for the lsid service associated with this repository 119 */ 120 public String getLSIDServerURL() { 121 return ECOGRIDLSIDSERVER; 122 } 123 124 /** 125 * Get the url for the authorization service associated with this repository 126 * @return 127 */ 128 public String getAuthorizationServerURL(){ 129 return ECOGRIDAUTHORIZATIONSERVER; 130 } 131 132 /** 133 * Search the repository and return an iterator of EcogridRepositoryResults. 134 * 135 * @see EcogridRepositoryResults 136 * @param queryString 137 * a string to search for 138 * @param authenticate 139 * boolean 140 * @return null if there are no results for the query. An iterator of 141 * EcogridRepositoryResults if there are results. 142 * @throws AuthenticationException 143 */ 144 public Iterator<EcogridRepositoryResults> search(String queryString, boolean authenticate) 145 throws RepositoryException, AuthenticationException { 146 if (isDebugging) { 147 log.debug("search(\"" + queryString + "\")"); 148 } 149 150 Vector<EcogridRepositoryResults> resultsVector = new Vector<EcogridRepositoryResults>(); 151 152 //System.out.println("EcogridRepository search(queryString,"+authenticate+") querying with queryString:" + 153 // queryString); 154 ResultsetType rst = arbitrarySearch(buildQueryDoc(queryString), authenticate); 155 if (rst == null) { // check to see if the resultsettype is null 156 return null; 157 } 158 159 ResultsetTypeRecord[] records = rst.getRecord(); 160 if (records == null || records.length == 0) { 161 // check to see if there are records 162 return null; 163 } 164 165 if (isDebugging) { 166 log.debug("There are " + records.length + " records"); 167 } 168 169 // create the EcogridRepositoryResult object and put it in the 170 // vector 171 for (int i = 0; i < records.length; i++) { 172 try { // catch this here so one result can't hose the whole 173 // resultset 174 List<EcogridRepositoryResults> results = 175 EcogridRepositoryResults.parseKarXml( 176 records[i].getIdentifier(), name, i, authenticate); 177 178 resultsVector.addAll(results); 179 } catch (Exception e) { 180 System.out.println("could not load result: " 181 + records[i].toString() + " error: " 182 + e.getMessage()); 183 } 184 // ResultsetTypeRecord currentRecord = records[i]; 185 } 186 187 return resultsVector.iterator(); 188 } 189 190 /** 191 * Search the repository and return an iterator of EcogridRepositoryResults. 192 * 193 * @param queryDocument 194 * - the query document to give the QueryServiceClient 195 * @return 196 * @throws RepositoryException 197 * @throws AuthenticationException 198 */ 199 public Iterator<EcogridRepositoryResults> advancedSearch( 200 Reader queryDocument, boolean authenticate) 201 throws RepositoryException, AuthenticationException { 202 203 Vector<EcogridRepositoryResults> resultsVector = new Vector<EcogridRepositoryResults>(); 204 205 ResultsetType rst = arbitrarySearch(queryDocument, authenticate); 206 if (rst == null) { // check to see if the resultsettype is null 207 return null; 208 } 209 210 ResultsetTypeRecord[] records = rst.getRecord(); 211 if (records == null || records.length == 0) { // check to see if 212 // there are records 213 return null; 214 } 215 216 if (isDebugging) { 217 log.debug("There are " + records.length + " records"); 218 } 219 220 // create the EcogridRepositoryResult object and put it in the 221 // vector 222 for (int i = 0; i < records.length; i++) { 223 try { // catch this here so one result can't hose the whole 224 // resultset 225 List<EcogridRepositoryResults> results = EcogridRepositoryResults 226 .parseKarXml(records[i].getIdentifier(), name, i, 227 authenticate); 228 resultsVector.addAll(results); 229 } catch (Exception e) { 230 System.out.println("could not load result: " 231 + records[i].toString() + " error: " + e.getMessage()); 232 } 233 // ResultsetTypeRecord currentRecord = records[i]; 234 } 235 236 return resultsVector.iterator(); 237 } 238 239 /** 240 * Search the repository using queryDocument. 241 * @param queryDocument 242 * @return ResultsetType from QueryServiceClient 243 * @throws RepositoryException 244 */ 245 private ResultsetType arbitrarySearch(Reader queryDocument) 246 throws RepositoryException { 247 248 try { 249 QueryServiceClient qclient = new QueryServiceClient( 250 ECOGRIDQUERYSERVER); 251 ResultsetType rst = qclient.query(queryDocument); 252 return rst; 253 254 } catch (Exception e) { 255 e.printStackTrace(); 256 throw new RepositoryException( 257 "Error searching ecogrid repository: " + e.getMessage()); 258 } 259 } 260 261 262 /** 263 * Search the repository using queryDocument. 264 * 265 * @param queryDocument 266 * @param authenticate 267 * @return ResultsetType, or null 268 * @throws RepositoryException 269 * @throws AuthenticationException 270 */ 271 public ResultsetType arbitrarySearch(Reader queryDocument, 272 boolean authenticate) throws RepositoryException, 273 AuthenticationException { 274 275 if (!authenticate) { 276 return arbitrarySearch(queryDocument); 277 } 278 279 String sessionId = authenticate(); 280 if (sessionId == null || sessionId.isEmpty()) { 281 return null; 282 } 283 284 QueryType queryType = AuthenticatedQueryServiceClient 285 .reader2QueryType(queryDocument); 286 try { 287 AuthenticatedQueryServiceClient authQueryClient = new AuthenticatedQueryServiceClient( 288 ECOGRIDAUTHENTICATEDQUERYSERVICE); 289 ResultsetType rst = authQueryClient.query(queryType, sessionId); 290 291 return rst; 292 293 } catch (Exception e) { 294 e.printStackTrace(); 295 throw new RepositoryException( 296 "Error searching ecogrid repository: " + e.getMessage()); 297 } 298 } 299 300 /** 301 * 302 * @return sessionId, or null 303 * @throws AuthenticationException 304 */ 305 private String authenticate() throws AuthenticationException { 306 AuthenticationManager authManager = AuthenticationManager.getManager(); 307 // first peek to see if already authenticated 308 ProxyEntity proxy; 309 310 proxy = authManager.peekProxy(authDomain); 311 312 // authenticate if necessary 313 if (proxy == null) { 314 proxy = authManager.getProxy(authDomain); 315 } 316 return proxy.getCredential(); 317 } 318 319 /** 320 * return an object using a ecogrid docid identifier 321 * @throws AuthenticationException 322 */ 323 public InputStream get(String docid, boolean authenticate) throws RepositoryException, AuthenticationException { 324 325 if (!authenticate){ 326 return get(docid); 327 } 328 329 String sessionId = authenticate(); 330 if (sessionId == null || sessionId.isEmpty()){ 331 return null; 332 } 333 try { 334 URL url = new URL(ECOGRIDAUTHENTICATEDQUERYSERVICE); 335 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 336 AuthenticatedQueryServiceGetToStreamClient aqsgtsc = 337 new AuthenticatedQueryServiceGetToStreamClient(url); 338 aqsgtsc.get(docid, sessionId, outputStream); 339 outputStream.close(); 340 341 return new ByteArrayInputStream(outputStream.toByteArray()); 342 343 } catch (Exception e) { 344 throw new RepositoryException("Error getting docid " + docid + ": " 345 + e.getMessage()); 346 } 347 } 348 349 /** 350 * return an object using a ecogrid docid identifier 351 */ 352 private InputStream get(String docid) throws RepositoryException { 353 try { 354 QueryServiceStub client = new QueryServiceStub(new URL( 355 ECOGRIDQUERYSERVER), null); 356 byte[] b = client.get(docid); 357 return new ByteArrayInputStream(b); 358 } catch (Exception e) { 359 throw new RepositoryException("Error getting docid " + docid + ": " 360 + e.getMessage()); 361 } 362 } 363 364 /** 365 * Return karXml for a docid from a repositoryName. Move this method 366 * to another class if you can think of a better home. 367 * 368 * @param docid 369 * @param repositoryName 370 * @return 371 * @throws RepositoryException 372 */ 373 public static KarXml getKarXml(String docid, String repositoryName, boolean authenticate) 374 throws RepositoryException { 375 376 try { 377 RepositoryManager rm = RepositoryManager.getInstance(); 378 Repository rep = rm.getRepository(repositoryName); 379 if (!(rep instanceof EcogridRepository)) { 380 log.error("EcogridRepository getKarXml is trying to search " 381 + "a non-Ecogrid Repository"); 382 return null; 383 } 384 EcogridRepository erep = (EcogridRepository) rep; 385 InputStream is = erep.get(docid, authenticate); 386 387 return KarXml.of(is); 388 } catch (Exception ex) { 389 ex.printStackTrace(); 390 } 391 return null; 392 } 393 394 /** 395 * return the object from the repository that has the given lsid 396 * @throws AuthenticationException 397 */ 398 public InputStream get(KeplerLSID lsid, boolean authenticate) throws RepositoryException, AuthenticationException { 399 /* 400 * NOTE: this is a bad way to do this. this should use the lsid 401 * authority to pull the object from the grid. For the sake of getting 402 * something working, i'm leaving this in here for now. -CB 403 */ 404 String docid = lsid.getNamespace() + "." + lsid.getObject() + "." 405 + lsid.getRevision(); 406 return get(docid, authenticate); 407 } 408 409 /** 410 * put a file with a predetermined sessionid 411 */ 412 public void put(Object o, KeplerLSID lsid, String sessionId) 413 throws RepositoryException { 414 try { 415 String docid = lsid.getNamespace() + "." + lsid.getObject() + "." 416 + lsid.getRevision(); 417 if (o instanceof File) { 418 uploadDataFile(((File) o), docid, sessionId); 419 } else { 420 uploadMetadata(o.toString(), docid, sessionId); 421 } 422 } catch (Exception e) { 423 throw new RepositoryException(e.getMessage()); 424 } 425 } 426 427 /** 428 * returns the next object for the given lsid 429 * 430 * @param lsid 431 * the lsid to get the next object for 432 */ 433 public String getNextObject(KeplerLSID lsid) throws RepositoryException { 434 try { 435 IdentifierServiceClient lsidClient = new IdentifierServiceClient( 436 ECOGRIDLSIDSERVER); 437 return lsidClient.getNextObject(lsid.toString()); 438 } catch (Exception e) { 439 throw new RepositoryException("Error getting next object: " 440 + e.getMessage()); 441 } 442 } 443 444 /** 445 * returns the next revision for the given lsid 446 * 447 * @param lsid 448 * the lsid to get the next revision for 449 */ 450 public String getNextRevision(KeplerLSID lsid) throws RepositoryException { 451 try { 452 IdentifierServiceClient lsidClient = new IdentifierServiceClient( 453 ECOGRIDLSIDSERVER); 454 return lsidClient.getNextRevision(lsid.toString()); 455 } catch (Exception e) { 456 throw new RepositoryException("Error getting next revision: " 457 + e.getMessage()); 458 } 459 } 460 461 // //////////////////////////////////////////////////// 462 // ///// ecogrid registry methods ///////// 463 464 /** 465 * add an ecogrid registry entry. 466 * 467 * @param registryEntry 468 * an xml file that conforms to 469 * seek/project/ecogrid/src/xsd_reg/RegistryEntryType.xsd 470 * @param sessionid 471 * the session id to use to authenticate 472 */ 473 public KeplerLSID addRegistryEntry(RegistryEntryType registryEntry, String sessionId) 474 throws RepositoryException { 475 try { 476 RegistryServiceClient client = new RegistryServiceClient(registry); 477 // String docid = client.add(sessionId, new 478 // StringReader(registryEntry)); 479 String docid = client.add(sessionId, registryEntry); 480 KeplerLSID lsid = new KeplerLSID(docid, "kepler-project.org"); 481 return lsid; 482 } catch (Exception e) { 483 e.printStackTrace(); 484 throw new RepositoryException("Error adding registry entry: " 485 + e.getMessage()); 486 } 487 } 488 489 /** 490 * update an ecogrid registry entry. 491 * 492 * @param registryEntry 493 * an xml file that conforms to 494 * seek/project/ecogrid/src/xsd_reg/RegistryEntryType.xsd 495 * @param lsid 496 * the id of the entry 497 * @param sessionid 498 * the session id to use to authenticate 499 */ 500 public void updateRegistryEntry(String registryEntry, KeplerLSID lsid) 501 throws RepositoryException { 502 throw new RepositoryException("Not yet implemented."); 503 } 504 505 /** 506 * remove an ecogrid registry entry. 507 * 508 * @param lsid 509 * the id of the entry 510 * @param sessionid 511 * the session id to use to authenticate 512 */ 513 public void removeRegistryEntry(KeplerLSID lsid, String sessionId) throws RepositoryException { 514 try { 515 String newdocid = lsid.getNamespace() + "." + lsid.getObject() 516 + "." + lsid.getRevision(); 517 RegistryServiceClient client = new RegistryServiceClient(registry); 518 String docid = client.remove(sessionId, newdocid); 519 } catch (Exception e) { 520 e.printStackTrace(); 521 throw new RepositoryException( 522 "Error removing ecogrid registry entry."); 523 } 524 } 525 526 /** 527 * login to the registry 528 */ 529 public String loginRegEcoGrid(String userName, String password) 530 throws Exception { 531 AuthenticationServiceClient client = new AuthenticationServiceClient( 532 ECOGRIDREGAUTHSERVER); 533 regsessionid = client.login_action(userName, password); 534 return regsessionid; 535 } 536 537 /* 538 * Method to upload data 539 */ 540 private void uploadDataFile(File localFile, String docid, 541 String sessionId) throws Exception { 542 String localFilePath = localFile.getAbsolutePath(); 543 String localFileName = localFile.getName(); 544 545 int type = EcogridObjType.DATA; 546 PutServiceClient client = new PutServiceClient(ECOGRIDPUTSERVER); 547 byte[] data = StaticUtil.getBytesArrayFromFile(localFilePath); 548 client.put(data, docid, localFileName, type, sessionId); 549 } 550 551 /* 552 * Method to upload metadata 553 */ 554 private void uploadMetadata(String metadataContent, String docid, 555 String sessionId) throws Exception { 556 int type = EcogridObjType.METADATA; 557 byte[] content = metadataContent.getBytes(); 558 PutServiceClient client = new PutServiceClient(ECOGRIDPUTSERVER); 559 client.put(content, docid, type, sessionId); 560 } 561 562 /** 563 * builds an ecogrid query document with the user's query string in it. 564 */ 565 private Reader buildQueryDoc(String queryString) { 566 567 // we query all KAR namespaces 568 Iterator<String> namespaceItr = KARFile.getKARNamespaces().iterator(); 569 570 StringBuffer sb = new StringBuffer(); 571 sb 572 .append("<egq:query queryId=\"test.1.1\" system=\"http://knb.ecoinformatics.org\" "); 573 sb.append("xmlns:egq=\"http://ecoinformatics.org/query-1.0.1\" "); 574 sb.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "); 575 sb 576 .append("xsi:schemaLocation=\"http://ecoinformatics.org/query-1.0.1 ../../src/xsd/query.xsd\">\n"); 577 //sb.append("<namespace prefix=\"kepler\">kar</namespace>\n"); 578 579 while (namespaceItr.hasNext()){ 580 sb.append("<namespace prefix=\"kepler\">"); 581 sb.append(namespaceItr.next()); 582 sb.append("</namespace>\n"); 583 } 584 sb.append("<returnField>/entity/@name</returnField>\n"); 585 // sb.append("<returnField>/entity/property/@name</returnField>\n"); 586 // sb.append("<returnField>/entity/property/@value</returnField>\n"); 587 sb.append("<title>kepler query</title>\n"); 588 sb.append("<AND>\n"); 589 sb.append(" <condition operator=\"LIKE\" concept=\"/\">%" 590 + queryString + "%</condition>\n"); 591 /// filter out kars that contain WorkflowRun, likely enable this once it's user toggle-able: 592 ///sb.append(" <condition operator=\"NOT LIKE\" concept=\"karEntry/karEntryAttributes/type\">" 593 ///+ WORKFLOWRUNTYPE + "</condition>\n"); 594 sb.append("</AND>\n"); 595 sb.append("</egq:query>\n"); 596 return new StringReader(sb.toString()); 597 } 598 599 /** 600 * a class to hold a registry client and a sessionid 601 */ 602 public class RegistryClientContainer { 603 public RegistryServiceClient client; 604 public String sessionid; 605 606 /** 607 * Constructor 608 */ 609 public RegistryClientContainer(RegistryServiceClient client, 610 String sessionid) { 611 this.client = client; 612 this.sessionid = sessionid; 613 } 614 } 615}