001/* A representative of a web browser 002 003 Copyright (c) 2002-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 ptolemy.kernel.CompositeEntity; 033import ptolemy.kernel.util.IllegalActionException; 034import ptolemy.kernel.util.NameDuplicationException; 035import ptolemy.kernel.util.Workspace; 036 037/////////////////////////////////////////////////////////////////// 038//// BrowserEffigy 039 040/** 041 An effigy for a web browser. 042 043 <p> We invoke the user's web browser for certain files such as pdf files 044 045 @author Christopher Hylands 046 @version $Id$ 047 @since Ptolemy II 2.0 048 @Pt.ProposedRating Red (cxh) 049 @Pt.AcceptedRating Red (cxh) 050 */ 051public class BrowserEffigy extends Effigy { 052 /** Create a new effigy in the specified workspace with an empty string 053 * for its name. 054 * @param workspace The workspace for this effigy. 055 */ 056 public BrowserEffigy(Workspace workspace) { 057 super(workspace); 058 059 // Indicate that we cannot save to URL. 060 setModifiable(false); 061 } 062 063 /** Create a new effigy in the given directory with the given name. 064 * @param container The directory that contains this effigy. 065 * @param name The name of this effigy. 066 * @exception IllegalActionException If the entity cannot be contained 067 * by the proposed container. 068 * @exception NameDuplicationException If the name coincides with 069 * an entity already in the container. 070 */ 071 public BrowserEffigy(CompositeEntity container, String name) 072 throws IllegalActionException, NameDuplicationException { 073 super(container, name); 074 075 // Indicate that we cannot save to URL. 076 setModifiable(false); 077 } 078 079 /////////////////////////////////////////////////////////////////// 080 //// public methods //// 081 082 /** Create a new effigy in the given container by reading the specified 083 * URL. If the specified URL is null, then create a blank effigy. 084 * The extension of the URL is not checked, so this will open any file. 085 * The new effigy will have a new instance of 086 * DefaultStyledDocument associated with it. 087 * @param container The container for the effigy. 088 * @param base The base for relative file references, or null if 089 * there are no relative file references. This is ignored in this 090 * class. 091 * @param in The input URL. 092 * @return A new instance of BrowserEffigy. 093 * @exception Exception If the URL cannot be read, or if the data 094 * is malformed in some way. 095 */ 096 public static BrowserEffigy newBrowserEffigy(CompositeEntity container, 097 URL base, URL in) throws Exception { 098 // Create a new effigy. 099 BrowserEffigy effigy = new BrowserEffigy(container, 100 container.uniqueName("browserEffigy")); 101 102 // We cannot easily communicate with the Browser once we launch 103 // it, so mark this effigy as unmodifiable 104 effigy.setModifiable(false); 105 106 // The BrowserLauncher will read the URL for us, so no need 107 // to read it here. 108 effigy.uri.setURL(in); 109 return effigy; 110 } 111 112 /////////////////////////////////////////////////////////////////// 113 //// public variables //// 114 115 /** A reference to the most recently created factory for this effigy. 116 * This is provided for use by HTMLViewer and Configuration 117 * when following hyperlinks 118 * that specify that they should be opened by a browser. 119 */ 120 public static BrowserEffigy.Factory staticFactory = null; 121 122 /////////////////////////////////////////////////////////////////// 123 //// inner classes //// 124 125 /** A factory for creating new effigies. 126 */ 127 public static class Factory extends EffigyFactory { 128 /** Create a factory with the given name and container. 129 * @param container The container. 130 * @param name The name. 131 * @exception IllegalActionException If the container is incompatible 132 * with this entity. 133 * @exception NameDuplicationException If the name coincides with 134 * an entity already in the container. 135 */ 136 public Factory(CompositeEntity container, String name) 137 throws IllegalActionException, NameDuplicationException { 138 super(container, name); 139 140 // Record the latest factory for use by HTMLViewer. 141 staticFactory = this; 142 } 143 144 /////////////////////////////////////////////////////////////// 145 //// public methods //// 146 147 /** Return true, indicating that this effigy factory is 148 * capable of creating an effigy without a URL being specified. 149 * @return True. 150 */ 151 @Override 152 public boolean canCreateBlankEffigy() { 153 return false; 154 } 155 156 /** Create a new effigy in the given container by reading the specified 157 * URL. If the specified URL is null, then create a blank effigy. 158 * The extension of the URL is not 159 * checked, so this will open any file. Thus, this factory 160 * should be last on the list of effigy factories in the 161 * configuration. 162 * The new effigy will have a new instance of 163 * DefaultStyledDocument associated with it. 164 * @param container The container for the effigy. 165 * @param base The base for relative file references, or null if 166 * there are no relative file references. This is ignored in this 167 * class. 168 * @param in The input URL. 169 * @return A new instance of BrowserEffigy. 170 * @exception Exception If the URL cannot be read, or if the data 171 * is malformed in some way. 172 */ 173 @Override 174 public Effigy createEffigy(CompositeEntity container, URL base, URL in) 175 throws Exception { 176 if (in == null) { 177 return null; 178 } 179 180 String extension = getExtension(in); 181 182 // This could be a list, or a user preference 183 if (extension.equals("pdf") || extension.startsWith("htm") 184 || extension.startsWith("shtm")) { 185 Effigy effigy = newBrowserEffigy(container, base, in); 186 return effigy; 187 } 188 189 // The extension doesn't match. Try the content type. 190 URLConnection connection = in.openConnection(); 191 192 if (connection == null) { 193 return null; 194 } 195 196 String contentType = connection.getContentType(); 197 198 if (contentType == null) { 199 return null; 200 } 201 202 if (contentType.startsWith("text/html") 203 || contentType.startsWith("text/rtf") 204 || contentType.startsWith("image/")) { 205 Effigy effigy = newBrowserEffigy(container, base, in); 206 return effigy; 207 } 208 209 return null; 210 } 211 } 212}