001/* 002 * Copyright (c) 2004-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: tao $' 006 * '$Date: 2012-06-07 21:03:38 +0000 (Thu, 07 Jun 2012) $' 007 * '$Revision: 29892 $' 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.provenance.kar; 031 032import java.io.File; 033import java.util.ArrayList; 034import java.util.Arrays; 035import java.util.Iterator; 036 037import org.apache.commons.logging.Log; 038import org.apache.commons.logging.LogFactory; 039import org.ecoinformatics.ecogrid.client.IdentifierServiceClient; 040import org.kepler.kar.KARBuilder; 041import org.kepler.kar.KARFile; 042import org.kepler.objectmanager.ActorMetadata; 043import org.kepler.objectmanager.ObjectManager; 044import org.kepler.objectmanager.lsid.KeplerLSID; 045import org.kepler.objectmanager.lsid.LSIDGenerator; 046import org.kepler.objectmanager.repository.Repository; 047import org.kepler.objectmanager.repository.RepositoryManager; 048import org.kepler.util.WorkflowRun; 049 050import ptolemy.actor.TypedCompositeActor; 051import ptolemy.kernel.util.NamedObj; 052import ptolemy.kernel.util.StringAttribute; 053 054/** 055 * This class allows for uploading KARs to the repository without user 056 * interaction 057 */ 058 059/** 060 * '$Author: tao $' 061 * '$Date: 2012-06-07 21:03:38 +0000 (Thu, 07 Jun 2012) $' 062 * '$Revision: 29892 $' 063 * 064 * For Details: 065 * http://www.kepler-project.org 066 * 067 * Copyright (c) 2009-2010 The Regents of the 068 * University of California. All rights reserved. Permission is hereby granted, 069 * without written agreement and without license or royalty fees, to use, copy, 070 * modify, and distribute this software and its documentation for any purpose, 071 * provided that the above copyright notice and the following two paragraphs 072 * appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF 073 * CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, 074 * OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 075 * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE 076 * POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY 077 * DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 078 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 079 * SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 080 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 081 * ENHANCEMENTS, OR MODIFICATIONS. 082 */ 083 084public class UploadKarToRepositoryNoGUI 085{ 086 087 public static final Log log = LogFactory.getLog(UploadKarToRepositoryNoGUI.class); 088 089 /** 090 * Constructor 091 */ 092 public UploadKarToRepositoryNoGUI() 093 { 094 } 095 096 /** 097 * uploads KAR to the repository 098 * 099 * @return true if the upload was successful 100 */ 101 public boolean uploadKAR(File karFile, String sessionId, boolean isPublic) 102 { 103 if (!karFile.exists()) { 104 return false; 105 } 106 // get the runs and unmodified workflow MoMLs out of objectManager 107 try { 108 KARFile karf = new KARFile(karFile); 109 KeplerLSID karLSID = karf.getLSID(); 110 111 ArrayList<KeplerLSID> workflowRunLSIDList = new ArrayList<KeplerLSID>(); 112 ArrayList<KeplerLSID> typedCompositeActorLSIDList = new ArrayList<KeplerLSID>(); 113 ArrayList<KeplerLSID> metadataLSIDsToUpload = new ArrayList<KeplerLSID>(); 114 ArrayList<Object> metadataObjectsToUpload = new ArrayList<Object>(); 115 116 workflowRunLSIDList.addAll( 117 Arrays.asList(karf.getContentOfType(WorkflowRun.class.getName()))); 118 typedCompositeActorLSIDList.addAll( 119 Arrays.asList(karf.getContentOfType(TypedCompositeActor.class.getName()))); 120 121 122 // check that workflowRuns karLSIDs equal KARFile LSID 123 Iterator<KeplerLSID> entryLsidItr = workflowRunLSIDList.iterator(); 124 KeplerLSID entryLsid; 125 126 while (entryLsidItr.hasNext()) 127 { 128 entryLsid = entryLsidItr.next(); 129 130 // get the run from the object manager 131 WorkflowRun run = (WorkflowRun) ObjectManager.getInstance().getHighestObjectRevision(entryLsid); 132 if (run == null) 133 { 134 log.error("workflow run from object manager is null"); 135 return false; 136 } 137 138 log.debug("karentry: " 139 + run.getName() 140 + " will send the entry to the repo as metadata"); 141 metadataLSIDsToUpload.add(entryLsid); 142 metadataObjectsToUpload.add(run); 143 144 } 145 146 // 06.17.09 No longer check the workflows -- we've decided to change 147 // to: inside-kar workflows will not have karLSID. 148 // Kars will be self contained. All workflows found in the kar will 149 // be used to create ActorMetadata 150 // docs that point to this kar with a karLSID. 151 entryLsidItr = typedCompositeActorLSIDList.iterator(); 152 while (entryLsidItr.hasNext()) 153 { 154 entryLsid = entryLsidItr.next(); 155 NamedObj no = ObjectManager.getInstance().getHighestObjectRevision(entryLsid); 156 if (no != null) 157 { 158 // create an AM object from the entity 159 ActorMetadata am = new ActorMetadata(no); 160 // log.debug("am.toString()\n"+am.toString()); 161 StringAttribute karLsidAttr = new StringAttribute(); 162 // put kar lsid in metadata 163 karLsidAttr.setName(KARBuilder.KAR_LSID_ATTRIBUTE_NAME); 164 karLsidAttr.setExpression(karLSID.toString()); 165 am.addAttribute(karLsidAttr); 166 addDocumentation(am); 167 metadataLSIDsToUpload.add(entryLsid); 168 metadataObjectsToUpload.add(am); 169 } 170 else 171 { 172 return false; 173 } 174 } 175 176 RepositoryManager manager; 177 try 178 { 179 manager = RepositoryManager.getInstance(); 180 } catch (Exception e) 181 { 182 log.error("Could not get repository manager: " + e.getMessage()); 183 e.printStackTrace(); 184 return false; 185 } 186 187 // get the save repository and set the lsid server url 188 Repository repository = manager.getSaveRepository(); 189 log.debug("Using repository:" + repository); 190 191 String LSIDServer = repository.getLSIDServerURL(); 192 IdentifierServiceClient lsidClient = new IdentifierServiceClient(LSIDServer); 193 194 // check if lsid isRegistered 195 // FIXME hardcode for now if the kar lsid is already registered, we 196 // just give up (return false) 197 // currently we're not getting kars from cache or objectmanager, so 198 // each will have a new lsid and 199 // will therefore never be registered. 200 boolean isKarRegistered = lsidClient.isRegistered(karLSID.toString()); 201 log.debug("is karLSID registered? " + isKarRegistered); 202 if (isKarRegistered) 203 { 204 // it's already used. get another one. 205 // ask the user if they really want to upload since the 206 // object already exists 207 208 String lsidStr = 209 "urn:lsid:" + karLSID.getAuthority() + ":" 210 + karLSID.getNamespace() + ":1:1"; 211 log.debug("getting next object for lsid " + lsidStr); 212 String newLsidString = lsidClient.getNextObject(lsidStr); 213 KeplerLSID newLSID = new KeplerLSID(newLsidString); 214 log.debug("lsid is already registered, will use this new one:" + newLSID); 215 216 return false; 217 } 218 else 219 { 220 log.debug("lsid not registered in repository, didn't need to get a new one."); 221 } 222 223 // put the kar file 224 repository.put(karFile, karLSID, sessionId); 225 log.debug("uploaded kar file with lsid " + karLSID); 226 227 // create an access file so we can make this kar public on the ecogrid 228 // TODO use setAccess instead of generating access files. 229 KeplerLSID karAccessLSID = LSIDGenerator.getInstance().getNewLSID(); 230 repository.put( 231 buildAccessDocument(karLSID, isPublic), 232 karAccessLSID, sessionId); 233 log.debug("uploaded access doc for kar file, lsid " + karAccessLSID); 234 235 // put any metadata docs that have karLSID == this kar's lsid. 236 Iterator<KeplerLSID> metadataLsidLitr = metadataLSIDsToUpload.iterator(); 237 Iterator<Object> metadataObjLitr = metadataObjectsToUpload.iterator(); 238 239 log.debug("uploading metadata objects, count = " + metadataLSIDsToUpload.size()); 240 241 while (metadataLsidLitr.hasNext()) 242 { 243 KeplerLSID metadataLsid = metadataLsidLitr.next(); 244 Object metadataNamedObj = metadataObjLitr.next(); 245 if (metadataNamedObj != null) 246 { 247 248 // check if we have tried uploading this before 249 boolean isMetadataRegistered = lsidClient.isRegistered(metadataLsid.toString()); 250 if (!isMetadataRegistered) 251 { 252 // upload the metadata document 253 repository.put(metadataNamedObj, metadataLsid, sessionId); 254 log.debug("uploaded metadata object " + metadataNamedObj.getClass().getName() + ", with lsid " + metadataLsid); 255 256 // do the access document for it 257 KeplerLSID accessLSID = 258 LSIDGenerator.getInstance().getNewLSID(); 259 repository.put( 260 buildAccessDocument(metadataLsid, isPublic), 261 accessLSID, sessionId); 262 log.debug("uploaded access (for metadata object) with lsid " + accessLSID); 263 } 264 else 265 { 266 log.warn("metadata already exists for LSID: " + metadataLsid); 267 } 268 } 269 } 270 271 return true; 272 } 273 catch (Exception e) 274 { 275 log.error("there was a problem uploading the data to repository"); 276 e.printStackTrace(); 277 return false; 278 } 279 } 280 281 /** 282 * uploads a document as the kepler user with public read permissions 283 */ 284 public static String buildAccessDocument(KeplerLSID lsid) 285 { 286 return buildAccessDocument(lsid, null, true); 287 } 288 289 public static String buildAccessDocument(KeplerLSID lsid, boolean publicDoc) 290 { 291 return buildAccessDocument(lsid, null, publicDoc); 292 } 293 294 /** 295 * build an access document that gives 'public' read access to the inserted 296 * documents. 297 */ 298 public static String buildAccessDocument(KeplerLSID lsid, String owner, 299 boolean publicDoc) 300 { 301 StringBuffer sb = new StringBuffer(); 302 sb.append("<?xml version=\"1.0\"?>\n"); 303 sb 304 .append("<eml:eml packageId=\"\" system=\"knb\" " 305 + "xmlns:eml=\"eml://ecoinformatics.org/eml-2.0.1\" " 306 + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " 307 + "xsi:schemaLocation=\"eml://ecoinformatics.org/eml-2.0.1 eml.xsd\">\n"); 308 sb.append("<dataset>\n"); 309 sb.append("<title>access for " + lsid.toString() + "</title>\n"); 310 sb.append("<creator id=\"1\">\n"); 311 sb.append(" <individualName><surName>kepler</surName>\n"); 312 sb.append(" </individualName>\n"); 313 sb.append("</creator>\n"); 314 315 sb.append("<contact><references>1</references>\n"); 316 sb.append("</contact>\n"); 317 318 if (publicDoc) 319 { 320 sb.append("<access authSystem=\"knb\" order=\"allowFirst\">\n"); 321 sb.append(" <allow>\n"); 322 sb.append(" <principal>public</principal>\n"); 323 sb.append(" <permission>read</permission>\n"); 324 sb.append(" </allow>\n"); 325 sb.append("</access>\n"); 326 } 327 328 if (owner != null) 329 { 330 sb.append("<access authSystem=\"knb\" order=\"allowFirst\">\n"); 331 sb.append(" <allow>\n"); 332 sb.append(" <principal>" + owner + "</principal>\n"); 333 sb.append(" <permission>read</permission>\n"); 334 sb.append(" <permission>write</permission>\n"); 335 sb.append(" </allow>\n"); 336 sb.append("</access>\n"); 337 } 338 339 sb.append("<dataTable id=\"x\">\n"); 340 341 sb.append("<entityName>asdf</entityName>\n"); 342 343 sb.append("<physical>\n"); 344 sb.append(" <objectName>tmp</objectName>\n"); 345 sb.append(" <dataFormat> \n"); 346 sb.append(" <externallyDefinedFormat>\n"); 347 sb.append(" <formatName>application/vnd.ms-excel</formatName>\n"); 348 sb.append(" </externallyDefinedFormat>\n"); 349 sb.append(" </dataFormat>\n"); 350 351 sb.append(" <distribution>\n"); 352 sb.append(" <online>\n"); 353 sb.append(" <url>ecogrid://knb/" + lsid.getNamespace() + "." 354 + lsid.getObject() + "." + lsid.getRevision() + "</url>\n"); 355 sb.append(" </online>\n"); 356 sb.append(" </distribution>\n"); 357 sb.append("</physical>\n"); 358 359 sb.append("<attributeList>\n"); 360 sb.append(" <attribute id=\"2\">\n"); 361 sb.append(" <attributeName>0</attributeName>\n"); 362 sb.append(" <attributeDefinition>0</attributeDefinition>\n"); 363 sb.append(" <measurementScale>\n"); 364 sb.append(" <interval>\n"); 365 sb.append(" <unit>\n"); 366 sb 367 .append(" <standardUnit>metersPerSecondSquared</standardUnit>\n"); 368 sb.append(" </unit>\n"); 369 sb.append(" <precision>.2</precision>\n"); 370 sb.append(" <numericDomain>\n"); 371 sb.append(" <numberType>natural</numberType>\n"); 372 sb.append(" </numericDomain>\n"); 373 sb.append(" </interval>\n"); 374 sb.append(" </measurementScale>\n"); 375 sb.append(" </attribute>\n"); 376 sb.append("</attributeList>\n"); 377 378 sb.append("</dataTable>\n"); 379 sb.append("</dataset>\n"); 380 sb.append("</eml:eml>\n"); 381 382 return sb.toString(); 383 } 384 385 /** 386 * adds the generated documentation (if it exists) to the actor metadata 387 */ 388 public static void addDocumentation(ActorMetadata am) throws Exception 389 { 390 /* 391 * //look for the documentation KeplerDocApplicationSpecializer kdas = 392 * new KeplerDocApplicationSpecializer(); String actorName = 393 * am.getName(); URL fileUrl = kdas.docClassNameToURL("", 394 * am.getClassName(), true, true, false, false); 395 * 396 * if(fileUrl == null || fileUrl.toString().trim().equals("")) { //if 397 * not found, exit System.out.println("No documentation found for " + 398 * am.getName()); return; } //get the documentation String filename = 399 * fileUrl.toString().substring(5, fileUrl.toString().length()); File f 400 * = new File(filename); 401 * 402 * //parse the xml DocumentBuilder parser = ConfigXML.createDomParser(); 403 * InputSource in; in = new InputSource(new FileReader(filename)); 404 * Document doc = parser.parse(in); Node root = 405 * doc.getDocumentElement(); //get description String descVal = ""; 406 * String authVal = ""; String verVal = ""; String uldVal = ""; 407 * 408 * Node descNode = XPathAPI.selectSingleNode(doc, "/doc/description"); 409 * if(descNode != null) descVal = 410 * descNode.getFirstChild().getNodeValue(); //get author Node authNode = 411 * XPathAPI.selectSingleNode(doc, "/doc/author"); if(authNode != null) 412 * authVal = authNode.getFirstChild().getNodeValue(); //get version Node 413 * verNode = XPathAPI.selectSingleNode(doc, "/doc/version"); if(verNode 414 * != null) verVal = verNode.getFirstChild().getNodeValue(); //get 415 * UserLevelDocumentation Node uldNode = XPathAPI.selectSingleNode(doc, 416 * "/doc/UserLevelDocumentation"); if(uldNode != null) uldVal = 417 * uldNode.getFirstChild().getNodeValue(); 418 * 419 * //get ports Hashtable portHash = new Hashtable(); NodeList portList = 420 * XPathAPI.selectNodeList(doc, "/doc/port"); for(int i=0; 421 * i<portList.getLength(); i++) { String name = ""; String val = ""; 422 * Node portNode = portList.item(i); Node nameNode = 423 * portNode.getAttributes().getNamedItem("name"); if(nameNode != null) { 424 * name = nameNode.getNodeValue(); } NodeList children = 425 * portNode.getChildNodes(); for(int j=0; j<children.getLength(); j++) { 426 * Node n = children.item(j); val = n.getNodeValue(); } if(val == null) 427 * val = ""; 428 * 429 * if(name != null) portHash.put(name, val); } 430 * 431 * //get properties Hashtable propHash = new Hashtable(); NodeList 432 * propList = XPathAPI.selectNodeList(doc, "/doc/property"); for(int 433 * i=0; i<propList.getLength(); i++) { String name = ""; String val = 434 * ""; Node propNode = propList.item(i); Node nameNode = 435 * propNode.getAttributes().getNamedItem("name"); if(nameNode != null) { 436 * name = nameNode.getNodeValue(); } NodeList children = 437 * propNode.getChildNodes(); for(int j=0; j<children.getLength(); j++) { 438 * Node n = children.item(j); val = n.getNodeValue(); } if(val == null) 439 * val = ""; if(name != null) propHash.put(name, val); } 440 * 441 * //now we have all the data, we need to add it to the actor metadata 442 * KeplerDocumentationAttribute da = new KeplerDocumentationAttribute(); 443 * da.setName("documentation"); da.setDescription(descVal); 444 * da.setAuthor(authVal); da.setVersion(verVal); 445 * da.setUserLevelDocumentation(uldVal); da.setPortHash(portHash); 446 * da.setPropertyHash(propHash); am.addAttribute(da); 447 */ 448 } 449 450}