001/* A factory for representatives of an HTML file. 002 003 Copyright (c) 1998-2014 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 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 */ 027package ptolemy.actor.gui; 028 029import java.net.URL; 030import java.net.URLConnection; 031 032import javax.swing.event.HyperlinkEvent; 033 034import ptolemy.kernel.CompositeEntity; 035import ptolemy.kernel.util.IllegalActionException; 036import ptolemy.kernel.util.NameDuplicationException; 037import ptolemy.kernel.util.Workspace; 038 039/////////////////////////////////////////////////////////////////// 040//// HTMLEffigyFactory 041 042/** 043 A factory for creating new effigies for HTML pages. 044 045 @author Steve Neuendorffer and Edward A. Lee 046 @version $Id$ 047 @since Ptolemy II 1.0 048 @Pt.ProposedRating Red (neuendor) 049 @Pt.AcceptedRating Red (neuendor) 050 */ 051public class HTMLEffigyFactory extends EffigyFactory { 052 /** Create a factory in the specified workspace. 053 * @param workspace The workspace. 054 */ 055 public HTMLEffigyFactory(Workspace workspace) { 056 super(workspace); 057 } 058 059 /** Create a factory with the given name and container. 060 * @param container The container. 061 * @param name The name. 062 * @exception IllegalActionException If the container is incompatible 063 * with this entity. 064 * @exception NameDuplicationException If the name coincides with 065 * an entity already in the container. 066 */ 067 public HTMLEffigyFactory(CompositeEntity container, String name) 068 throws IllegalActionException, NameDuplicationException { 069 super(container, name); 070 } 071 072 /////////////////////////////////////////////////////////////////// 073 //// public methods //// 074 075 /** Return false, indicating that this effigy factory is not 076 * capable of creating an effigy without a URL being specified. 077 * There is no point in creating an unmodifiable blank HTML page. 078 * @return False. 079 */ 080 @Override 081 public boolean canCreateBlankEffigy() { 082 return false; 083 } 084 085 /** Create a new effigy in the given container by reading the specified 086 * URL. The extension of the URL must be ".htm" or ".html", or 087 * the content type must be "text/html" or "text/rtf". Otherwise, 088 * this returns null. It will also return null if there is no 089 * access to the network. 090 * @param container The container for the effigy. 091 * @param base The base for relative file references, or null if 092 * there are no relative file references. This is ignored in this 093 * class. 094 * @param input The input URL. 095 * @return A new instance of HTMLEffigy, or null if one cannot 096 * be created. 097 * @exception Exception If the URL cannot be read, or if the data 098 * is malformed in some way. 099 */ 100 @Override 101 public Effigy createEffigy(CompositeEntity container, URL base, URL input) 102 throws Exception { 103 if (input == null) { 104 return null; 105 } 106 107 String extension = getExtension(input); 108 109 // Here, if it has an "http" protocol, we agree to 110 // open it. The reason is that many main HTML pages are 111 // referenced by a string like "http://ptolemy.eecs.berkeley.edu". 112 // Here, the extension will be "edu" rather than HTML. 113 // Note that this means that if we add effigies for, say, 114 // PDF files or images, their factories should be listed before 115 // this one. 116 if (!extension.equals("htm") && !extension.equals("html")) { 117 118 // Handle about: 119 String path = input.getPath(); 120 int slashIndex = path.lastIndexOf("/"); 121 if (slashIndex != -1 122 && path.substring(slashIndex + 1).startsWith("about:")) { 123 Configuration configuration = (Configuration) toplevel(); 124 // FIXME: This is a hack, HTMLAbout should be refactored 125 // to expose the functionality we need. 126 try { 127 HyperlinkEvent event = new HyperlinkEvent(this, 128 HyperlinkEvent.EventType.ACTIVATED, null /*URL*/, 129 path.substring(slashIndex + 1)); 130 URL url = HTMLAbout.hyperlinkUpdate(event, configuration); 131 132 EffigyFactory factory = (EffigyFactory) ((Configuration) toplevel()) 133 .getEntity("effigyFactory"); 134 return factory.createEffigy(container, base, url); 135 136 } catch (Throwable throwable) { 137 throw new Exception("Failed to open " + input, throwable); 138 } 139 } 140 141 // The extension doesn't match. Try the content type. 142 URLConnection connection = input.openConnection(); 143 144 if (connection == null) { 145 return null; 146 } 147 148 String contentType; 149 try { 150 contentType = connection.getContentType(); 151 } catch (SecurityException ex) { 152 throw new SecurityException( 153 "Failed to open " + base + " " + input, ex); 154 } 155 156 if (contentType == null) { 157 return null; 158 } 159 160 if (!contentType.startsWith("text/html") 161 && !contentType.startsWith("text/rtf")) { 162 return null; 163 } 164 } 165 166 // Create a new effigy. 167 HTMLEffigy effigy = new HTMLEffigy(container, 168 container.uniqueName("effigy")); 169 effigy.uri.setURL(input); 170 171 // FIXME: What to do about the base? 172 return effigy; 173 } 174}