001/*
002 *  The node controller for actor instances.
003 *  Copyright (c) 2010 The Regents of the University of California.
004 *  All rights reserved.
005 *  Permission is hereby granted, without written agreement and without
006 *  license or royalty fees, to use, copy, modify, and distribute this
007 *  software and its documentation for any purpose, provided that the above
008 *  copyright notice and the following two paragraphs appear in all copies
009 *  of this software.
010 *  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
011 *  FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
012 *  ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
013 *  THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
014 *  SUCH DAMAGE.
015 *  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
016 *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
017 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
018 *  PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
019 *  CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
020 *  ENHANCEMENTS, OR MODIFICATIONS.
021 *  PT_COPYRIGHT_VERSION_2
022 *  COPYRIGHTENDKEY
023 */
024
025package org.kepler.kar.handlers;
026
027import java.io.InputStream;
028import java.util.Hashtable;
029import java.util.Vector;
030
031import org.apache.commons.logging.Log;
032import org.apache.commons.logging.LogFactory;
033import org.kepler.kar.KAREntry;
034import org.kepler.kar.KAREntryHandler;
035import org.kepler.kar.KAREntryHandlerFactory;
036import org.kepler.kar.KARFile;
037import org.kepler.modulemanager.ModuleManagerEventListener;
038import org.kepler.objectmanager.cache.CacheObject;
039import org.kepler.objectmanager.lsid.KeplerLSID;
040
041import ptolemy.actor.gui.TableauFrame;
042import ptolemy.kernel.util.IllegalActionException;
043import ptolemy.kernel.util.NameDuplicationException;
044import ptolemy.kernel.util.NamedObj;
045
046/**
047 * a kar handler to handle downloading modules if a kar file needs them
048 * 
049 * @author chad berkley
050 */
051public class ModuleTxtKAREntryHandler implements KAREntryHandler
052{
053  private String type = "moduleTxt";
054  private static final Log log = LogFactory
055      .getLog(ActorMetadataKAREntryHandler.class.getName());
056  private static final boolean isDebugging = log.isDebugEnabled();
057
058  /**
059   * constructor
060   */
061  public ModuleTxtKAREntryHandler()
062  {
063
064  }
065
066  /**
067   * The getTypeName() method must return the type of object that this
068   * KAREntryHandler saves. This method should return the KAR version 1.0
069   * type name or null if version 1.0 is not supported by this handler.
070   **/
071  public String getTypeName()
072  {
073    return type;
074  }
075
076  /**
077   * This method should return true if this KAREntryHandler can handle the
078   * specified type. The type passed in is the binary class name of the file.
079   * 
080   * @param typeName
081   **/
082  public boolean handlesType(String typeName)
083  {
084    if (typeName.equals(type))
085    {
086      return true;
087    }
088    return false;
089  }
090
091  /**
092   * The initialize method is called directly after instantiating this
093   * KAREntryHandler.
094   */
095  public void initialize()
096  {
097  }
098
099  /**
100   * This method should return a CacheObject that will be put into the cache.
101   * Once all the contents of the KAR exist in the cache then the open method
102   * is called. In this way each entry in the kar can have access to all the
103   * other entries through the cache when they get opened.
104   * 
105   * @param karFile
106   * @param entry
107   * @return the CacheObject that will be put into the CacheManager
108   * @throws Exception
109   */
110  public CacheObject cache(KARFile karFile, KAREntry entry) throws Exception
111  { 
112    System.out.println("caching from ModuleTxtKAREntryHandler " + karFile.getFileLocation().getName() + ","
113        + entry.toString());
114    /*TextFileCacheObject cobj = new TextFileCacheObject(karFile
115        .getInputStream(entry), entry.getLSID(), entry.toString());
116    String modulesTxtStr = (String)cobj.getObject();
117    File f = new File(DotKeplerManager.getInstance().getTransientDir(), "modules.txt");
118    //write this to a temp file
119    FileWriter fw = new FileWriter(f);
120    fw.write(modulesTxtStr, 0, modulesTxtStr.length());
121    fw.flush();
122    fw.close();
123    
124    //merge the modules.txt file in the kar with the currently loaded modules.txt file
125    ModulesTxt newModulesTxt = new ModulesTxt(f.toURI());
126    System.out.println("downloading modules in modules.txt from kar " + karFile.getFileLocation().getName());
127    System.out.println("modules.txt: " + ((String)cobj.getObject()));
128    ModuleDownloader downloader = ModuleDownloader.getInstance();
129    downloader.addListener(new ModuleStartupDownloadListener(karFile.getFileLocation().getName()));
130    downloader.downloadFromModulesTxt(newModulesTxt);
131    //now that the module(s) are downloaded, we need to process them into
132    //the current ModuleTree so that they are available on the classpath
133    //to the kar that needs them.
134    //This could be tricky, because a kar could introduce conflicts between
135    //modules.
136    ModuleTree moduleTree = ModuleTree.instance();
137    ModulesTxt mainModulesTxt = moduleTree.getModulesTxt();
138    Iterator newModulesIt = newModulesTxt.modules.iterator();
139    while(newModulesIt.hasNext())
140    {
141      //add the new module
142      Module newModule = (Module)newModulesIt.next();
143      mainModulesTxt.add(newModule, 0);
144    }
145    
146    mainModulesTxt.write();
147    //TODO: kepler should restart at this point to load the new classpath, 
148    //but that might cause problems so I'm omitting that for now.
149    
150    return cobj;*/
151    return null;
152  }
153
154  /**
155   * When a KAR file is opened, any entries in the kar file that have the same
156   * type as this KAREntryHandler will be passed to this open method. This
157   * method will always be called after the cache method.
158   * 
159   * @param karFile
160   * @param entry
161   * @param tableauFrame
162   * @return boolean true if the entry was opened successfully.
163   * @throws Exception
164   */
165  public boolean open(KARFile karFile, KAREntry entry, TableauFrame tableauFrame) throws Exception
166  {
167    System.out.println("MTKEH opening " + karFile.toString() + ","
168        + entry.toString());
169    //tell the module-manager to download the module here
170    System.out
171        .println("kar entry handler is telling moduleTxtKAREntryHandler to open "
172            + entry.getName());
173    return true;
174  }
175
176  /**
177   * Return an array of KAREntry objects that are to be saved for the given
178   * lsid. All KAREntries must be of the same type of object that is returned
179   * by the getTypeName() method.
180   * 
181   * @param lsid
182   * @param karLsid the lsid of the containing KAR
183   * @param tableauFrame
184   * @return an array of KAREntries to be saved with this LSID object.
185   * @throws Exception
186   */
187  public Hashtable<KAREntry, InputStream> save(Vector<KeplerLSID> lsids,
188      KeplerLSID karLsid, TableauFrame tableauFrame) throws Exception
189  {
190    return null;
191  }
192
193  /**
194   * A factory that creates a KAREntryHandler object.
195   * 
196   *@author Aaron Schultz
197   */
198  public static class Factory extends KAREntryHandlerFactory
199  {
200    /**
201     * Create a factory with the given name and container.
202     * 
203     *@param container
204     *          The container.
205     *@param name
206     *          The name of the entity.
207     *@exception IllegalActionException
208     *              If the container is incompatible with this attribute.
209     *@exception NameDuplicationException
210     *              If the name coincides with an attribute already in the
211     *              container.
212     */
213    public Factory(NamedObj container, String name)
214        throws IllegalActionException, NameDuplicationException
215    {
216      super(container, name);
217    }
218
219    /**
220     * Create a library pane that displays the given library of actors.
221     * 
222     * @return A new LibraryPaneTab that displays the library
223     */
224    public KAREntryHandler createKAREntryHandler()
225    {
226      if (isDebugging)
227        log.debug("moduleTxtKAREntryHandler()");
228      return new ModuleTxtKAREntryHandler();
229    }
230  }
231  
232  /**
233   * listener for module download events
234   * @author berkley
235   *
236   */
237  private class ModuleStartupDownloadListener implements ModuleManagerEventListener
238  {
239    private String karFileName;
240    
241    public ModuleStartupDownloadListener(String karFileName)
242    {
243      this.karFileName = karFileName;
244    }
245    
246    /**
247     * update progress for the progress monitor
248     */
249    public void updateProgress(int totalSize, int bufferSize, int readCount, InputStream is)
250    {
251      System.out.println("downloading " + (bufferSize * readCount) + " of " + totalSize + " bytes.");
252    }
253    
254    /**
255     * close the progress monitor at the end of the DL.
256     */
257    public void downloadEnd()
258    {
259      System.out.println("Done downloading module.");
260    }
261    
262    /**
263     * start up a new progress monitor at the beginning of a download.
264     */
265    public void downloadBegin(int totalSize, String moduleName)
266    {
267      System.out.println("Downloading module " + moduleName + " from kar file " + karFileName);
268    }
269    
270    /**
271     * create a new progress bar when an unzip begins
272     */
273    public void unzipBegin(long totalSize, String moduleName)
274    {
275      System.out.println("Unzipping module " + moduleName + " from kar file " + karFileName);
276    }
277    
278    /**
279     * get rid of the unzip progress bar
280     */
281    public void unzipEnd()
282    {
283      System.out.println("Done unzipping.");
284    }
285    
286    /**
287     * update the progress of an unzip
288     */
289    public void unzipUpdateProgress(long totalSize, int bufferSize, int readCount)
290    {
291
292    }
293  }
294}