001/* 002 * Copyright (c) 2012 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2015-07-14 17:09:46 +0000 (Tue, 14 Jul 2015) $' 007 * '$Revision: 33539 $' 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 */ 029package org.kepler.gui.kar; 030 031import java.io.File; 032import java.io.IOException; 033import java.io.InputStream; 034import java.net.URI; 035import java.net.URL; 036 037import org.apache.commons.logging.Log; 038import org.apache.commons.logging.LogFactory; 039import org.kepler.kar.KAREntry; 040import org.kepler.kar.KARFile; 041import org.kepler.kar.handlers.ActorMetadataKAREntryHandler; 042import org.kepler.objectmanager.lsid.KeplerLSID; 043 044import ptolemy.actor.gui.Effigy; 045import ptolemy.actor.gui.PtolemyEffigy; 046import ptolemy.actor.gui.TableauFrame; 047import ptolemy.kernel.CompositeEntity; 048import ptolemy.kernel.util.IllegalActionException; 049import ptolemy.kernel.util.NameDuplicationException; 050import ptolemy.kernel.util.NamedObj; 051import ptolemy.kernel.util.Workspace; 052import ptolemy.moml.MoMLParser; 053import ptolemy.util.MessageHandler; 054import ptolemy.util.StringUtilities; 055 056/** An Effigy for KAR files. 057 * 058 * @author Daniel Crawl 059 * @version $Id: KAREffigy.java 33539 2015-07-14 17:09:46Z crawl $ 060 */ 061public class KAREffigy extends PtolemyEffigy { 062 063 public KAREffigy(Workspace workspace) { 064 super(workspace); 065 } 066 067 public KAREffigy(CompositeEntity container, String name) 068 throws IllegalActionException, NameDuplicationException { 069 super(container, name); 070 } 071 072 /** Get the KAR file. */ 073 public KARFile getKARFile() { 074 return _karFile; 075 } 076 077 /** Open the non-actor entries in the KAR file, e.g., report layout. 078 * @param frame the frame in which to open the entries 079 * @param openActorEntries if true, open actor entries. 080 */ 081 public void openKAREntries(TableauFrame frame, boolean openActorEntries) { 082 if(_karFile != null) { 083 for (KAREntry entry : _karFile.karEntries()) { 084 if (openActorEntries || !ActorMetadataKAREntryHandler.handlesClass(entry.getType())) { 085 _karFile.open(entry, frame); 086 } 087 } 088 } 089 } 090 091 /** Set the KAR file. */ 092 public void setKARFile(KARFile karFile) { 093 _karFile = karFile; 094 } 095 096 /** Write the model associated with this effigy. Currently only saving 097 * the MoML is supported. 098 */ 099 @Override 100 public void writeFile(File file) throws IOException { 101 String path = file.getAbsolutePath(); 102 // see if we're saving the MoML 103 // this can happen with File->Export->XML 104 if(path.toLowerCase().endsWith(".xml")) { 105 super.writeFile(file); 106 } else if(path.toLowerCase().endsWith(".kar")) { 107 throw new IOException("writeFile() does not support writing KAR files."); 108 } else { 109 throw new IOException("unknown type of file: " + path); 110 } 111 } 112 113 /////////////////////////////////////////////////////////////////// 114 //// inner classes //// 115 116 /** A factory for creating new KAR effigies. */ 117 public static class Factory extends PtolemyEffigy.FactoryWithoutNew { 118 /** Create a factory with the given name and container. 119 * @param container The container. 120 * @param name The name. 121 * @exception IllegalActionException If the container is incompatible 122 * with this entity. 123 * @exception NameDuplicationException If the name coincides with 124 * an entity already in the container. 125 */ 126 public Factory(CompositeEntity container, String name) 127 throws IllegalActionException, NameDuplicationException { 128 super(container, name); 129 } 130 131 /** Create a new effigy in the given container by reading the 132 * <i>input</i> URL. If the URL is a KAR file, attempt to open 133 * it and extract the model. If there are missing module dependencies, 134 * the user is asked if she wants to ignore the dependencies and 135 * try to open the KAR, download the dependencies and restart Kepler, 136 * or do nothing. In the last case this method returns null. 137 * @param container The container for the effigy. 138 * @param base The base for relative file references, or null if 139 * there are no relative file references. 140 * @param input The input URL. 141 * @return A new instance of PtolemyEffigy, or null if the URL 142 * does not specify a Ptolemy II model. 143 * @exception Exception If the URL cannot be read, or if the data 144 * is malformed in some way. 145 */ 146 @Override 147 public Effigy createEffigy(CompositeEntity container, URL base, 148 URL input) throws Exception { 149 if (input == null) { 150 return super.createEffigy(container, base, input); 151 } else { 152 String extension = getExtension(input).toLowerCase(); 153 if(extension.equals("kar")) { 154 155 KAREffigy effigy = new KAREffigy(container, container.uniqueName("effigy")); 156 157 File file = new File(input.toURI()); 158 KARFile karf = new KARFile(file); 159 160 // see if it's openable 161 if(!karf.isOpenable()) { 162 // see if dependencies are missing 163 if(!karf.areAllModuleDependenciesSatisfied()) { 164 ImportModuleDependenciesAction action = new ImportModuleDependenciesAction(new TableauFrame()); 165 action.setArchiveFile(file); 166 ImportModuleDependenciesAction.ImportChoice choice = action.checkDependencies(); 167 if(choice == ImportModuleDependenciesAction.ImportChoice.DO_NOTHING) { 168 karf.close(); 169 return null; 170 } else if(choice == ImportModuleDependenciesAction.ImportChoice.DOWNLOADING_AND_RESTARTING) { 171 action.waitForDownloadAndRestart(); 172 } 173 } else { 174 MessageHandler.error("This KAR cannot be opened."); 175 karf.close(); 176 return null; 177 } 178 } 179 180 effigy.setKARFile(karf); 181 karf.cacheKARContents(); 182 183 // For each Actor in the KAR open the MOML 184 for (KAREntry entry : karf.karEntries()) { 185 KeplerLSID lsid = entry.getLSID(); 186 //System.out.println("Processing entry, LSID=" + lsid + ", type=" + entry.getType()); 187 if(isDebugging) { 188 log.debug("Processing entry, LSID=" + lsid + ", type=" + entry.getType()); 189 } 190 191 if (ActorMetadataKAREntryHandler.handlesClass(entry.getType())) { 192 193 NamedObj toplevel; 194 195 MoMLParser parser = new MoMLParser(); 196 197 parser.reset(); 198 199 InputStream stream = null; 200 try { 201 stream = karf.getInputStream(entry); 202 toplevel = parser.parse(base, file.getCanonicalPath(), stream); 203 } finally { 204 if(stream != null) { 205 stream.close(); 206 } 207 } 208 209 // make sure we were able to parse or load the NamedObj 210 if(toplevel == null) { 211 return null; 212 } 213 214 effigy.setModel(toplevel); 215 216 URI inputURI = null; 217 218 try { 219 inputURI = new URI(input.toExternalForm()); 220 } catch (java.net.URISyntaxException ex) { 221 // This is annoying, if the input has a space 222 // in it, then we cannot create a URI, 223 // but we could create a URL. 224 // If, under Windows, we call 225 // File.createTempFile(), then we are likely 226 // to get a pathname that has space. 227 // FIXME: Note that jar urls will barf if there 228 // is a %20 instead of a space. This could 229 // cause problems in Web Start 230 String inputExternalFormFixed = StringUtilities 231 .substitute(input.toExternalForm(), 232 " ", "%20"); 233 234 try { 235 inputURI = new URI(inputExternalFormFixed); 236 } catch (Exception ex2) { 237 throw new Exception("Failed to generate " 238 + "a URI from '" 239 + input.toExternalForm() 240 + "' and from '" 241 + inputExternalFormFixed + "'", ex); 242 } 243 } 244 245 // This is used by TableauFrame in its 246 //_save() method. 247 effigy.uri.setURI(inputURI); 248 } 249 } 250 251 return effigy; 252 } 253 } 254 return null; 255 } 256 } 257 258 private static final Log log = LogFactory.getLog(KAREffigy.class.getName()); 259 private static final boolean isDebugging = log.isDebugEnabled(); 260 261 /** The KAR file. */ 262 private KARFile _karFile; 263}