11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.net;
27
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31 import java.util.Hashtable;
32 import java.util.Date;
33 import java.util.StringTokenizer;
34 import java.util.Collections;
35 import java.util.Map;
36 import java.util.List;
37 import java.security.Permission;
38 import java.security.AccessController;
39 import sun.security.util.SecurityConstants;
40 import sun.net.www.MessageHeader;
41
42 /**
43 * The abstract class {@code URLConnection} is the superclass
44 * of all classes that represent a communications link between the
45 * application and a URL. Instances of this class can be used both to
46 * read from and to write to the resource referenced by the URL. In
47 * general, creating a connection to a URL is a multistep process:
48 *
49 * <center><table border=2 summary="Describes the process of creating a connection to a URL: openConnection() and connect() over time.">
50 * <tr><th>{@code openConnection()}</th>
51 * <th>{@code connect()}</th></tr>
52 * <tr><td>Manipulate parameters that affect the connection to the remote
90 * {@code get} method to retrieve the value of the parameter or
91 * general request property. The specific parameters and general
92 * request properties that are applicable are protocol specific.
93 * <p>
94 * The following methods are used to access the header fields and
95 * the contents after the connection is made to the remote object:
96 * <ul>
97 * <li>{@code getContent}
98 * <li>{@code getHeaderField}
99 * <li>{@code getInputStream}
100 * <li>{@code getOutputStream}
101 * </ul>
102 * <p>
103 * Certain header fields are accessed frequently. The methods:
104 * <ul>
105 * <li>{@code getContentEncoding}
106 * <li>{@code getContentLength}
107 * <li>{@code getContentType}
108 * <li>{@code getDate}
109 * <li>{@code getExpiration}
110 * <li>{@code getLastModifed}
111 * </ul>
112 * <p>
113 * provide convenient access to these fields. The
114 * {@code getContentType} method is used by the
115 * {@code getContent} method to determine the type of the remote
116 * object; subclasses may find it convenient to override the
117 * {@code getContentType} method.
118 * <p>
119 * In the common case, all of the pre-connection parameters and
120 * general request properties can be ignored: the pre-connection
121 * parameters and request properties default to sensible values. For
122 * most clients of this interface, there are only two interesting
123 * methods: {@code getInputStream} and {@code getContent},
124 * which are mirrored in the {@code URL} class by convenience methods.
125 * <p>
126 * More information on the request properties and header fields of
127 * an {@code http} connection can be found at:
128 * <blockquote><pre>
129 * <a href="http://www.ietf.org/rfc/rfc2616.txt">http://www.ietf.org/rfc/rfc2616.txt</a>
130 * </pre></blockquote>
678 * <p>
679 * This method can be used in conjunction with the
680 * {@link #getHeaderFieldKey(int) getHeaderFieldKey} method to iterate through all
681 * the headers in the message.
682 *
683 * @param n an index, where {@code n>=0}
684 * @return the value of the {@code n}<sup>th</sup> header field
685 * or {@code null} if there are fewer than {@code n+1} fields
686 * @see java.net.URLConnection#getHeaderFieldKey(int)
687 */
688 public String getHeaderField(int n) {
689 return null;
690 }
691
692 /**
693 * Retrieves the contents of this URL connection.
694 * <p>
695 * This method first determines the content type of the object by
696 * calling the {@code getContentType} method. If this is
697 * the first time that the application has seen that specific content
698 * type, a content handler for that content type is created:
699 * <ol>
700 * <li>If the application has set up a content handler factory instance
701 * using the {@code setContentHandlerFactory} method, the
702 * {@code createContentHandler} method of that instance is called
703 * with the content type as an argument; the result is a content
704 * handler for that content type.
705 * <li>If no content handler factory has yet been set up, or if the
706 * factory's {@code createContentHandler} method returns
707 * {@code null}, then this method tries to load a content handler
708 * class as defined by {@link java.net.ContentHandler ContentHandler}.
709 * If the class does not exist, or is not a subclass of {@code
710 * ContentHandler}, then an {@code UnknownServiceException} is thrown.
711 * </ol>
712 *
713 * @return the object fetched. The {@code instanceof} operator
714 * should be used to determine the specific kind of object
715 * returned.
716 * @exception IOException if an I/O error occurs while
717 * getting the content.
718 * @exception UnknownServiceException if the protocol does not support
719 * the content type.
720 * @see java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
721 * @see java.net.URLConnection#getContentType()
722 * @see java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
723 */
724 public Object getContent() throws IOException {
725 // Must call getInputStream before GetHeaderField gets called
726 // so that FileNotFoundException has a chance to be thrown up
727 // from here without being caught.
838 * @return a string representation of this {@code URLConnection}.
839 */
840 public String toString() {
841 return this.getClass().getName() + ":" + url;
842 }
843
844 /**
845 * Sets the value of the {@code doInput} field for this
846 * {@code URLConnection} to the specified value.
847 * <p>
848 * A URL connection can be used for input and/or output. Set the DoInput
849 * flag to true if you intend to use the URL connection for input,
850 * false if not. The default is true.
851 *
852 * @param doinput the new value.
853 * @throws IllegalStateException if already connected
854 * @see java.net.URLConnection#doInput
855 * @see #getDoInput()
856 */
857 public void setDoInput(boolean doinput) {
858 if (connected)
859 throw new IllegalStateException("Already connected");
860 doInput = doinput;
861 }
862
863 /**
864 * Returns the value of this {@code URLConnection}'s
865 * {@code doInput} flag.
866 *
867 * @return the value of this {@code URLConnection}'s
868 * {@code doInput} flag.
869 * @see #setDoInput(boolean)
870 */
871 public boolean getDoInput() {
872 return doInput;
873 }
874
875 /**
876 * Sets the value of the {@code doOutput} field for this
877 * {@code URLConnection} to the specified value.
878 * <p>
879 * A URL connection can be used for input and/or output. Set the DoOutput
880 * flag to true if you intend to use the URL connection for output,
881 * false if not. The default is false.
882 *
883 * @param dooutput the new value.
884 * @throws IllegalStateException if already connected
885 * @see #getDoOutput()
886 */
887 public void setDoOutput(boolean dooutput) {
888 if (connected)
889 throw new IllegalStateException("Already connected");
890 doOutput = dooutput;
891 }
892
893 /**
894 * Returns the value of this {@code URLConnection}'s
895 * {@code doOutput} flag.
896 *
897 * @return the value of this {@code URLConnection}'s
898 * {@code doOutput} flag.
899 * @see #setDoOutput(boolean)
900 */
901 public boolean getDoOutput() {
902 return doOutput;
903 }
904
905 /**
906 * Set the value of the {@code allowUserInteraction} field of
907 * this {@code URLConnection}.
908 *
909 * @param allowuserinteraction the new value.
910 * @throws IllegalStateException if already connected
911 * @see #getAllowUserInteraction()
912 */
913 public void setAllowUserInteraction(boolean allowuserinteraction) {
914 if (connected)
915 throw new IllegalStateException("Already connected");
916 allowUserInteraction = allowuserinteraction;
917 }
918
919 /**
920 * Returns the value of the {@code allowUserInteraction} field for
921 * this object.
922 *
923 * @return the value of the {@code allowUserInteraction} field for
924 * this object.
925 * @see #setAllowUserInteraction(boolean)
926 */
927 public boolean getAllowUserInteraction() {
928 return allowUserInteraction;
929 }
930
931 /**
932 * Sets the default value of the
933 * {@code allowUserInteraction} field for all future
934 * {@code URLConnection} objects to the specified value.
935 *
957 }
958
959 /**
960 * Sets the value of the {@code useCaches} field of this
961 * {@code URLConnection} to the specified value.
962 * <p>
963 * Some protocols do caching of documents. Occasionally, it is important
964 * to be able to "tunnel through" and ignore the caches (e.g., the
965 * "reload" button in a browser). If the UseCaches flag on a connection
966 * is true, the connection is allowed to use whatever caches it can.
967 * If false, caches are to be ignored.
968 * The default value comes from DefaultUseCaches, which defaults to
969 * true.
970 *
971 * @param usecaches a {@code boolean} indicating whether
972 * or not to allow caching
973 * @throws IllegalStateException if already connected
974 * @see #getUseCaches()
975 */
976 public void setUseCaches(boolean usecaches) {
977 if (connected)
978 throw new IllegalStateException("Already connected");
979 useCaches = usecaches;
980 }
981
982 /**
983 * Returns the value of this {@code URLConnection}'s
984 * {@code useCaches} field.
985 *
986 * @return the value of this {@code URLConnection}'s
987 * {@code useCaches} field.
988 * @see #setUseCaches(boolean)
989 */
990 public boolean getUseCaches() {
991 return useCaches;
992 }
993
994 /**
995 * Sets the value of the {@code ifModifiedSince} field of
996 * this {@code URLConnection} to the specified value.
997 *
998 * @param ifmodifiedsince the new value.
999 * @throws IllegalStateException if already connected
1000 * @see #getIfModifiedSince()
1001 */
1002 public void setIfModifiedSince(long ifmodifiedsince) {
1003 if (connected)
1004 throw new IllegalStateException("Already connected");
1005 ifModifiedSince = ifmodifiedsince;
1006 }
1007
1008 /**
1009 * Returns the value of this object's {@code ifModifiedSince} field.
1010 *
1011 * @return the value of this object's {@code ifModifiedSince} field.
1012 * @see #setIfModifiedSince(long)
1013 */
1014 public long getIfModifiedSince() {
1015 return ifModifiedSince;
1016 }
1017
1018 /**
1019 * Returns the default value of a {@code URLConnection}'s
1020 * {@code useCaches} flag.
1021 * <p>
1022 * Ths default is "sticky", being a part of the static state of all
1023 * URLConnections. This flag applies to the next, and all following
1024 * URLConnections that are created.
1038 * @param defaultusecaches the new value.
1039 * @see #getDefaultUseCaches()
1040 */
1041 public void setDefaultUseCaches(boolean defaultusecaches) {
1042 defaultUseCaches = defaultusecaches;
1043 }
1044
1045 /**
1046 * Sets the general request property. If a property with the key already
1047 * exists, overwrite its value with the new value.
1048 *
1049 * <p> NOTE: HTTP requires all request properties which can
1050 * legally have multiple instances with the same key
1051 * to use a comma-separated list syntax which enables multiple
1052 * properties to be appended into a single property.
1053 *
1054 * @param key the keyword by which the request is known
1055 * (e.g., "{@code Accept}").
1056 * @param value the value associated with it.
1057 * @throws IllegalStateException if already connected
1058 * @throws NullPointerException if key is <CODE>null</CODE>
1059 * @see #getRequestProperty(java.lang.String)
1060 */
1061 public void setRequestProperty(String key, String value) {
1062 if (connected)
1063 throw new IllegalStateException("Already connected");
1064 if (key == null)
1065 throw new NullPointerException ("key is null");
1066
1067 if (requests == null)
1068 requests = new MessageHeader();
1069
1070 requests.set(key, value);
1071 }
1072
1073 /**
1074 * Adds a general request property specified by a
1075 * key-value pair. This method will not overwrite
1076 * existing values associated with the same key.
1077 *
1078 * @param key the keyword by which the request is known
1079 * (e.g., "{@code Accept}").
1080 * @param value the value associated with it.
1081 * @throws IllegalStateException if already connected
1082 * @throws NullPointerException if key is null
1083 * @see #getRequestProperties()
1084 * @since 1.4
1085 */
1086 public void addRequestProperty(String key, String value) {
1087 if (connected)
1088 throw new IllegalStateException("Already connected");
1089 if (key == null)
1090 throw new NullPointerException ("key is null");
1091
1092 if (requests == null)
1093 requests = new MessageHeader();
1094
1095 requests.add(key, value);
1096 }
1097
1098
1099 /**
1100 * Returns the value of the named general request property for this
1101 * connection.
1102 *
1103 * @param key the keyword by which the request is known (e.g., "Accept").
1104 * @return the value of the named general request property for this
1105 * connection. If key is null, then null is returned.
1106 * @throws IllegalStateException if already connected
1107 * @see #setRequestProperty(java.lang.String, java.lang.String)
1108 */
1109 public String getRequestProperty(String key) {
1110 if (connected)
1111 throw new IllegalStateException("Already connected");
1112
1113 if (requests == null)
1114 return null;
1115
1116 return requests.findValue(key);
1117 }
1118
1119 /**
1120 * Returns an unmodifiable Map of general request
1121 * properties for this connection. The Map keys
1122 * are Strings that represent the request-header
1123 * field names. Each Map value is a unmodifiable List
1124 * of Strings that represents the corresponding
1125 * field values.
1126 *
1127 * @return a Map of the general request properties for this connection.
1128 * @throws IllegalStateException if already connected
1129 * @since 1.4
1130 */
1131 public Map<String,List<String>> getRequestProperties() {
1132 if (connected)
1133 throw new IllegalStateException("Already connected");
1134
1135 if (requests == null)
1136 return Collections.emptyMap();
1137
1138 return requests.getHeaders(null);
1139 }
1140
1141 /**
1142 * Sets the default value of a general request property. When a
1143 * {@code URLConnection} is created, it is initialized with
1144 * these properties.
1145 *
1146 * @param key the keyword by which the request is known
1147 * (e.g., "{@code Accept}").
1148 * @param value the value associated with the key.
1149 *
1150 * @see java.net.URLConnection#setRequestProperty(java.lang.String,java.lang.String)
1151 *
1152 * @deprecated The instance specific setRequestProperty method
1153 * should be used after an appropriate instance of URLConnection
1166 * @param key the keyword by which the request is known (e.g., "Accept").
1167 * @return the value of the default request property
1168 * for the specified key.
1169 *
1170 * @see java.net.URLConnection#getRequestProperty(java.lang.String)
1171 *
1172 * @deprecated The instance specific getRequestProperty method
1173 * should be used after an appropriate instance of URLConnection
1174 * is obtained.
1175 *
1176 * @see #setDefaultRequestProperty(java.lang.String, java.lang.String)
1177 */
1178 @Deprecated
1179 public static String getDefaultRequestProperty(String key) {
1180 return null;
1181 }
1182
1183 /**
1184 * The ContentHandler factory.
1185 */
1186 static ContentHandlerFactory factory;
1187
1188 /**
1189 * Sets the {@code ContentHandlerFactory} of an
1190 * application. It can be called at most once by an application.
1191 * <p>
1192 * The {@code ContentHandlerFactory} instance is used to
1193 * construct a content handler from a content type
1194 * <p>
1195 * If there is a security manager, this method first calls
1196 * the security manager's {@code checkSetFactory} method
1197 * to ensure the operation is allowed.
1198 * This could result in a SecurityException.
1199 *
1200 * @param fac the desired factory.
1201 * @exception Error if the factory has already been defined.
1202 * @exception SecurityException if a security manager exists and its
1203 * {@code checkSetFactory} method doesn't allow the operation.
1204 * @see java.net.ContentHandlerFactory
1205 * @see java.net.URLConnection#getContent()
1206 * @see SecurityManager#checkSetFactory
1207 */
1208 public static synchronized void setContentHandlerFactory(ContentHandlerFactory fac) {
1209 if (factory != null) {
1210 throw new Error("factory already defined");
1211 }
1212 SecurityManager security = System.getSecurityManager();
1213 if (security != null) {
1214 security.checkSetFactory();
1215 }
1216 factory = fac;
1217 }
1218
1219 private static Hashtable<String, ContentHandler> handlers = new Hashtable<>();
1220
1221 /**
1222 * Gets the Content Handler appropriate for this connection.
1223 */
1224 synchronized ContentHandler getContentHandler()
1225 throws UnknownServiceException
1226 {
1227 String contentType = stripOffParameters(getContentType());
1228 ContentHandler handler = null;
1229 if (contentType == null)
1230 throw new UnknownServiceException("no content-type");
1231 try {
1232 handler = handlers.get(contentType);
1233 if (handler != null)
1234 return handler;
1235 } catch(Exception e) {
1236 }
1237
1238 if (factory != null)
1239 handler = factory.createContentHandler(contentType);
1240 if (handler == null) {
1241 try {
1242 handler = lookupContentHandlerClassFor(contentType);
1243 } catch(Exception e) {
1244 e.printStackTrace();
1245 handler = UnknownContentHandler.INSTANCE;
1246 }
1247 handlers.put(contentType, handler);
1248 }
1249 return handler;
1250 }
1251
1252 /*
1253 * Media types are in the format: type/subtype*(; parameter).
1254 * For looking up the content handler, we should ignore those
1255 * parameters.
1256 */
1257 private String stripOffParameters(String contentType)
1258 {
1259 if (contentType == null)
1260 return null;
1261 int index = contentType.indexOf(';');
1262
1263 if (index > 0)
1264 return contentType.substring(0, index);
1265 else
1266 return contentType;
1267 }
1268
1269 private static final String contentClassPrefix = "sun.net.www.content";
1270 private static final String contentPathProp = "java.content.handler.pkgs";
1271
1272 /**
1273 * Looks for a content handler in a user-defineable set of places.
1274 * By default it looks in sun.net.www.content, but users can define a
1275 * vertical-bar delimited set of class prefixes to search through in
1276 * addition by defining the java.content.handler.pkgs property.
1277 * The class name must be of the form:
1278 * <pre>
1279 * {package-prefix}.{major}.{minor}
1280 * e.g.
1281 * YoyoDyne.experimental.text.plain
1282 * </pre>
1283 */
1284 private ContentHandler lookupContentHandlerClassFor(String contentType)
1285 throws InstantiationException, IllegalAccessException, ClassNotFoundException {
1286 String contentHandlerClassName = typeToPackageName(contentType);
1287
1288 String contentHandlerPkgPrefixes =getContentHandlerPkgPrefixes();
1289
1290 StringTokenizer packagePrefixIter =
1291 new StringTokenizer(contentHandlerPkgPrefixes, "|");
1292
1293 while (packagePrefixIter.hasMoreTokens()) {
1294 String packagePrefix = packagePrefixIter.nextToken().trim();
1295
1296 try {
1297 String clsName = packagePrefix + "." + contentHandlerClassName;
1298 Class<?> cls = null;
1299 try {
1300 cls = Class.forName(clsName);
1301 } catch (ClassNotFoundException e) {
1302 ClassLoader cl = ClassLoader.getSystemClassLoader();
1303 if (cl != null) {
1304 cls = cl.loadClass(clsName);
1305 }
1306 }
1307 if (cls != null) {
1308 ContentHandler handler =
1309 (ContentHandler)cls.newInstance();
1310 return handler;
1311 }
1312 } catch(Exception e) {
1313 }
1314 }
1315
1316 return UnknownContentHandler.INSTANCE;
1317 }
1318
1319 /**
1320 * Utility function to map a MIME content type into an equivalent
1321 * pair of class name components. For example: "text/html" would
1322 * be returned as "text.html"
1323 */
1324 private String typeToPackageName(String contentType) {
1325 // make sure we canonicalize the class name: all lower case
1326 contentType = contentType.toLowerCase();
1327 int len = contentType.length();
1328 char nm[] = new char[len];
1329 contentType.getChars(0, len, nm, 0);
1330 for (int i = 0; i < len; i++) {
1331 char c = nm[i];
1332 if (c == '/') {
1333 nm[i] = '.';
1334 } else if (!('A' <= c && c <= 'Z' ||
1335 'a' <= c && c <= 'z' ||
1336 '0' <= c && c <= '9')) {
1337 nm[i] = '_';
1338 }
1339 }
1340 return new String(nm);
1341 }
1342
1343
1344 /**
1345 * Returns a vertical bar separated list of package prefixes for potential
1346 * content handlers. Tries to get the java.content.handler.pkgs property
1347 * to use as a set of package prefixes to search. Whether or not
1348 * that property has been defined, the sun.net.www.content is always
1349 * the last one on the returned package list.
1350 */
1351 private String getContentHandlerPkgPrefixes() {
1352 String packagePrefixList = AccessController.doPrivileged(
1353 new sun.security.action.GetPropertyAction(contentPathProp, ""));
1354
1355 if (packagePrefixList != "") {
1356 packagePrefixList += "|";
1357 }
1358
1359 return packagePrefixList + contentClassPrefix;
1360 }
1361
1362 /**
1363 * Tries to determine the content type of an object, based
1364 * on the specified "file" component of a URL.
1365 * This is a convenience method that can be used by
1366 * subclasses that override the {@code getContentType} method.
1367 *
1368 * @param fname a filename.
1369 * @return a guess as to what the content type of the object is,
1747
1748 long eachSkip = 0;
1749 long skipped = 0;
1750
1751 while (skipped != toSkip) {
1752 eachSkip = is.skip(toSkip - skipped);
1753
1754 // check if EOF is reached
1755 if (eachSkip <= 0) {
1756 if (is.read() == -1) {
1757 return skipped ;
1758 } else {
1759 skipped++;
1760 }
1761 }
1762 skipped += eachSkip;
1763 }
1764 return skipped;
1765 }
1766
1767 }
1768
1769
1770 class UnknownContentHandler extends ContentHandler {
1771 static final ContentHandler INSTANCE = new UnknownContentHandler();
1772
1773 public Object getContent(URLConnection uc) throws IOException {
1774 return uc.getInputStream();
1775 }
1776 }
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.net;
27
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31 import java.security.PrivilegedAction;
32 import java.util.Hashtable;
33 import java.util.Date;
34 import java.util.Iterator;
35 import java.util.ServiceConfigurationError;
36 import java.util.ServiceLoader;
37 import java.util.StringTokenizer;
38 import java.util.Collections;
39 import java.util.Map;
40 import java.util.List;
41 import java.security.Permission;
42 import java.security.AccessController;
43 import sun.security.util.SecurityConstants;
44 import sun.net.www.MessageHeader;
45
46 /**
47 * The abstract class {@code URLConnection} is the superclass
48 * of all classes that represent a communications link between the
49 * application and a URL. Instances of this class can be used both to
50 * read from and to write to the resource referenced by the URL. In
51 * general, creating a connection to a URL is a multistep process:
52 *
53 * <center><table border=2 summary="Describes the process of creating a connection to a URL: openConnection() and connect() over time.">
54 * <tr><th>{@code openConnection()}</th>
55 * <th>{@code connect()}</th></tr>
56 * <tr><td>Manipulate parameters that affect the connection to the remote
94 * {@code get} method to retrieve the value of the parameter or
95 * general request property. The specific parameters and general
96 * request properties that are applicable are protocol specific.
97 * <p>
98 * The following methods are used to access the header fields and
99 * the contents after the connection is made to the remote object:
100 * <ul>
101 * <li>{@code getContent}
102 * <li>{@code getHeaderField}
103 * <li>{@code getInputStream}
104 * <li>{@code getOutputStream}
105 * </ul>
106 * <p>
107 * Certain header fields are accessed frequently. The methods:
108 * <ul>
109 * <li>{@code getContentEncoding}
110 * <li>{@code getContentLength}
111 * <li>{@code getContentType}
112 * <li>{@code getDate}
113 * <li>{@code getExpiration}
114 * <li>{@code getLastModified}
115 * </ul>
116 * <p>
117 * provide convenient access to these fields. The
118 * {@code getContentType} method is used by the
119 * {@code getContent} method to determine the type of the remote
120 * object; subclasses may find it convenient to override the
121 * {@code getContentType} method.
122 * <p>
123 * In the common case, all of the pre-connection parameters and
124 * general request properties can be ignored: the pre-connection
125 * parameters and request properties default to sensible values. For
126 * most clients of this interface, there are only two interesting
127 * methods: {@code getInputStream} and {@code getContent},
128 * which are mirrored in the {@code URL} class by convenience methods.
129 * <p>
130 * More information on the request properties and header fields of
131 * an {@code http} connection can be found at:
132 * <blockquote><pre>
133 * <a href="http://www.ietf.org/rfc/rfc2616.txt">http://www.ietf.org/rfc/rfc2616.txt</a>
134 * </pre></blockquote>
682 * <p>
683 * This method can be used in conjunction with the
684 * {@link #getHeaderFieldKey(int) getHeaderFieldKey} method to iterate through all
685 * the headers in the message.
686 *
687 * @param n an index, where {@code n>=0}
688 * @return the value of the {@code n}<sup>th</sup> header field
689 * or {@code null} if there are fewer than {@code n+1} fields
690 * @see java.net.URLConnection#getHeaderFieldKey(int)
691 */
692 public String getHeaderField(int n) {
693 return null;
694 }
695
696 /**
697 * Retrieves the contents of this URL connection.
698 * <p>
699 * This method first determines the content type of the object by
700 * calling the {@code getContentType} method. If this is
701 * the first time that the application has seen that specific content
702 * type, a content handler for that content type is created.
703 * <p> This is done as follows:
704 * <ol>
705 * <li>If the application has set up a content handler factory instance
706 * using the {@code setContentHandlerFactory} method, the
707 * {@code createContentHandler} method of that instance is called
708 * with the content type as an argument; the result is a content
709 * handler for that content type.
710 * <li>If no {@code ContentHandlerFactory} has yet been set up,
711 * or if the factory's {@code createContentHandler} method
712 * returns {@code null}, then the {@linkplain java.util.ServiceLoader
713 * ServiceLoader} mechanism is used to locate {@linkplain
714 * java.net.ContentHandlerFactory ContentHandlerFactory}
715 * implementations using the system class
716 * loader. The order that factories are located is implementation
717 * specific, and an implementation is free to cache the located
718 * factories. A {@linkplain java.util.ServiceConfigurationError
719 * ServiceConfigurationError}, {@code Error} or {@code RuntimeException}
720 * thrown from the {@code createContentHandler}, if encountered, will
721 * be propagated to the calling thread. The {@code
722 * createContentHandler} method of each factory, if instantiated, is
723 * invoked, with the content type, until a factory returns non-null,
724 * or all factories have been exhausted.
725 * <li>Failing that, this method tries to load a content handler
726 * class as defined by {@link java.net.ContentHandler ContentHandler}.
727 * If the class does not exist, or is not a subclass of {@code
728 * ContentHandler}, then an {@code UnknownServiceException} is thrown.
729 * </ol>
730 *
731 * @return the object fetched. The {@code instanceof} operator
732 * should be used to determine the specific kind of object
733 * returned.
734 * @exception IOException if an I/O error occurs while
735 * getting the content.
736 * @exception UnknownServiceException if the protocol does not support
737 * the content type.
738 * @see java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
739 * @see java.net.URLConnection#getContentType()
740 * @see java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
741 */
742 public Object getContent() throws IOException {
743 // Must call getInputStream before GetHeaderField gets called
744 // so that FileNotFoundException has a chance to be thrown up
745 // from here without being caught.
856 * @return a string representation of this {@code URLConnection}.
857 */
858 public String toString() {
859 return this.getClass().getName() + ":" + url;
860 }
861
862 /**
863 * Sets the value of the {@code doInput} field for this
864 * {@code URLConnection} to the specified value.
865 * <p>
866 * A URL connection can be used for input and/or output. Set the DoInput
867 * flag to true if you intend to use the URL connection for input,
868 * false if not. The default is true.
869 *
870 * @param doinput the new value.
871 * @throws IllegalStateException if already connected
872 * @see java.net.URLConnection#doInput
873 * @see #getDoInput()
874 */
875 public void setDoInput(boolean doinput) {
876 checkConnected();
877 doInput = doinput;
878 }
879
880 /**
881 * Returns the value of this {@code URLConnection}'s
882 * {@code doInput} flag.
883 *
884 * @return the value of this {@code URLConnection}'s
885 * {@code doInput} flag.
886 * @see #setDoInput(boolean)
887 */
888 public boolean getDoInput() {
889 return doInput;
890 }
891
892 /**
893 * Sets the value of the {@code doOutput} field for this
894 * {@code URLConnection} to the specified value.
895 * <p>
896 * A URL connection can be used for input and/or output. Set the DoOutput
897 * flag to true if you intend to use the URL connection for output,
898 * false if not. The default is false.
899 *
900 * @param dooutput the new value.
901 * @throws IllegalStateException if already connected
902 * @see #getDoOutput()
903 */
904 public void setDoOutput(boolean dooutput) {
905 checkConnected();
906 doOutput = dooutput;
907 }
908
909 /**
910 * Returns the value of this {@code URLConnection}'s
911 * {@code doOutput} flag.
912 *
913 * @return the value of this {@code URLConnection}'s
914 * {@code doOutput} flag.
915 * @see #setDoOutput(boolean)
916 */
917 public boolean getDoOutput() {
918 return doOutput;
919 }
920
921 /**
922 * Set the value of the {@code allowUserInteraction} field of
923 * this {@code URLConnection}.
924 *
925 * @param allowuserinteraction the new value.
926 * @throws IllegalStateException if already connected
927 * @see #getAllowUserInteraction()
928 */
929 public void setAllowUserInteraction(boolean allowuserinteraction) {
930 checkConnected();
931 allowUserInteraction = allowuserinteraction;
932 }
933
934 /**
935 * Returns the value of the {@code allowUserInteraction} field for
936 * this object.
937 *
938 * @return the value of the {@code allowUserInteraction} field for
939 * this object.
940 * @see #setAllowUserInteraction(boolean)
941 */
942 public boolean getAllowUserInteraction() {
943 return allowUserInteraction;
944 }
945
946 /**
947 * Sets the default value of the
948 * {@code allowUserInteraction} field for all future
949 * {@code URLConnection} objects to the specified value.
950 *
972 }
973
974 /**
975 * Sets the value of the {@code useCaches} field of this
976 * {@code URLConnection} to the specified value.
977 * <p>
978 * Some protocols do caching of documents. Occasionally, it is important
979 * to be able to "tunnel through" and ignore the caches (e.g., the
980 * "reload" button in a browser). If the UseCaches flag on a connection
981 * is true, the connection is allowed to use whatever caches it can.
982 * If false, caches are to be ignored.
983 * The default value comes from DefaultUseCaches, which defaults to
984 * true.
985 *
986 * @param usecaches a {@code boolean} indicating whether
987 * or not to allow caching
988 * @throws IllegalStateException if already connected
989 * @see #getUseCaches()
990 */
991 public void setUseCaches(boolean usecaches) {
992 checkConnected();
993 useCaches = usecaches;
994 }
995
996 /**
997 * Returns the value of this {@code URLConnection}'s
998 * {@code useCaches} field.
999 *
1000 * @return the value of this {@code URLConnection}'s
1001 * {@code useCaches} field.
1002 * @see #setUseCaches(boolean)
1003 */
1004 public boolean getUseCaches() {
1005 return useCaches;
1006 }
1007
1008 /**
1009 * Sets the value of the {@code ifModifiedSince} field of
1010 * this {@code URLConnection} to the specified value.
1011 *
1012 * @param ifmodifiedsince the new value.
1013 * @throws IllegalStateException if already connected
1014 * @see #getIfModifiedSince()
1015 */
1016 public void setIfModifiedSince(long ifmodifiedsince) {
1017 checkConnected();
1018 ifModifiedSince = ifmodifiedsince;
1019 }
1020
1021 /**
1022 * Returns the value of this object's {@code ifModifiedSince} field.
1023 *
1024 * @return the value of this object's {@code ifModifiedSince} field.
1025 * @see #setIfModifiedSince(long)
1026 */
1027 public long getIfModifiedSince() {
1028 return ifModifiedSince;
1029 }
1030
1031 /**
1032 * Returns the default value of a {@code URLConnection}'s
1033 * {@code useCaches} flag.
1034 * <p>
1035 * Ths default is "sticky", being a part of the static state of all
1036 * URLConnections. This flag applies to the next, and all following
1037 * URLConnections that are created.
1051 * @param defaultusecaches the new value.
1052 * @see #getDefaultUseCaches()
1053 */
1054 public void setDefaultUseCaches(boolean defaultusecaches) {
1055 defaultUseCaches = defaultusecaches;
1056 }
1057
1058 /**
1059 * Sets the general request property. If a property with the key already
1060 * exists, overwrite its value with the new value.
1061 *
1062 * <p> NOTE: HTTP requires all request properties which can
1063 * legally have multiple instances with the same key
1064 * to use a comma-separated list syntax which enables multiple
1065 * properties to be appended into a single property.
1066 *
1067 * @param key the keyword by which the request is known
1068 * (e.g., "{@code Accept}").
1069 * @param value the value associated with it.
1070 * @throws IllegalStateException if already connected
1071 * @throws NullPointerException if key is {@code null}
1072 * @see #getRequestProperty(java.lang.String)
1073 */
1074 public void setRequestProperty(String key, String value) {
1075 checkConnected();
1076 if (key == null)
1077 throw new NullPointerException ("key is null");
1078
1079 if (requests == null)
1080 requests = new MessageHeader();
1081
1082 requests.set(key, value);
1083 }
1084
1085 /**
1086 * Adds a general request property specified by a
1087 * key-value pair. This method will not overwrite
1088 * existing values associated with the same key.
1089 *
1090 * @param key the keyword by which the request is known
1091 * (e.g., "{@code Accept}").
1092 * @param value the value associated with it.
1093 * @throws IllegalStateException if already connected
1094 * @throws NullPointerException if key is null
1095 * @see #getRequestProperties()
1096 * @since 1.4
1097 */
1098 public void addRequestProperty(String key, String value) {
1099 checkConnected();
1100 if (key == null)
1101 throw new NullPointerException ("key is null");
1102
1103 if (requests == null)
1104 requests = new MessageHeader();
1105
1106 requests.add(key, value);
1107 }
1108
1109
1110 /**
1111 * Returns the value of the named general request property for this
1112 * connection.
1113 *
1114 * @param key the keyword by which the request is known (e.g., "Accept").
1115 * @return the value of the named general request property for this
1116 * connection. If key is null, then null is returned.
1117 * @throws IllegalStateException if already connected
1118 * @see #setRequestProperty(java.lang.String, java.lang.String)
1119 */
1120 public String getRequestProperty(String key) {
1121 checkConnected();
1122
1123 if (requests == null)
1124 return null;
1125
1126 return requests.findValue(key);
1127 }
1128
1129 /**
1130 * Returns an unmodifiable Map of general request
1131 * properties for this connection. The Map keys
1132 * are Strings that represent the request-header
1133 * field names. Each Map value is a unmodifiable List
1134 * of Strings that represents the corresponding
1135 * field values.
1136 *
1137 * @return a Map of the general request properties for this connection.
1138 * @throws IllegalStateException if already connected
1139 * @since 1.4
1140 */
1141 public Map<String,List<String>> getRequestProperties() {
1142 checkConnected();
1143
1144 if (requests == null)
1145 return Collections.emptyMap();
1146
1147 return requests.getHeaders(null);
1148 }
1149
1150 /**
1151 * Sets the default value of a general request property. When a
1152 * {@code URLConnection} is created, it is initialized with
1153 * these properties.
1154 *
1155 * @param key the keyword by which the request is known
1156 * (e.g., "{@code Accept}").
1157 * @param value the value associated with the key.
1158 *
1159 * @see java.net.URLConnection#setRequestProperty(java.lang.String,java.lang.String)
1160 *
1161 * @deprecated The instance specific setRequestProperty method
1162 * should be used after an appropriate instance of URLConnection
1175 * @param key the keyword by which the request is known (e.g., "Accept").
1176 * @return the value of the default request property
1177 * for the specified key.
1178 *
1179 * @see java.net.URLConnection#getRequestProperty(java.lang.String)
1180 *
1181 * @deprecated The instance specific getRequestProperty method
1182 * should be used after an appropriate instance of URLConnection
1183 * is obtained.
1184 *
1185 * @see #setDefaultRequestProperty(java.lang.String, java.lang.String)
1186 */
1187 @Deprecated
1188 public static String getDefaultRequestProperty(String key) {
1189 return null;
1190 }
1191
1192 /**
1193 * The ContentHandler factory.
1194 */
1195 private static volatile ContentHandlerFactory factory;
1196
1197 /**
1198 * Sets the {@code ContentHandlerFactory} of an
1199 * application. It can be called at most once by an application.
1200 * <p>
1201 * The {@code ContentHandlerFactory} instance is used to
1202 * construct a content handler from a content type
1203 * <p>
1204 * If there is a security manager, this method first calls
1205 * the security manager's {@code checkSetFactory} method
1206 * to ensure the operation is allowed.
1207 * This could result in a SecurityException.
1208 *
1209 * @param fac the desired factory.
1210 * @exception Error if the factory has already been defined.
1211 * @exception SecurityException if a security manager exists and its
1212 * {@code checkSetFactory} method doesn't allow the operation.
1213 * @see java.net.ContentHandlerFactory
1214 * @see java.net.URLConnection#getContent()
1215 * @see SecurityManager#checkSetFactory
1216 */
1217 public static synchronized void setContentHandlerFactory(ContentHandlerFactory fac) {
1218 if (factory != null) {
1219 throw new Error("factory already defined");
1220 }
1221 SecurityManager security = System.getSecurityManager();
1222 if (security != null) {
1223 security.checkSetFactory();
1224 }
1225 factory = fac;
1226 }
1227
1228 private static final Hashtable<String, ContentHandler> handlers = new Hashtable<>();
1229
1230 /**
1231 * Gets the Content Handler appropriate for this connection.
1232 */
1233 private ContentHandler getContentHandler() throws UnknownServiceException {
1234 String contentType = stripOffParameters(getContentType());
1235 if (contentType == null) {
1236 throw new UnknownServiceException("no content-type");
1237 }
1238
1239 ContentHandler handler = handlers.get(contentType);
1240 if (handler != null)
1241 return handler;
1242
1243 if (factory != null) {
1244 handler = factory.createContentHandler(contentType);
1245 if (handler != null)
1246 return handler;
1247 }
1248
1249 handler = lookupContentHandlerViaProvider(contentType);
1250
1251 if (handler != null) {
1252 ContentHandler h = handlers.putIfAbsent(contentType, handler);
1253 return h != null ? h : handler;
1254 }
1255
1256 try {
1257 handler = lookupContentHandlerClassFor(contentType);
1258 } catch (Exception e) {
1259 e.printStackTrace();
1260 handler = UnknownContentHandler.INSTANCE;
1261 }
1262
1263 assert handler != null;
1264
1265 ContentHandler h = handlers.putIfAbsent(contentType, handler);
1266 return h != null ? h : handler;
1267 }
1268
1269 /*
1270 * Media types are in the format: type/subtype*(; parameter).
1271 * For looking up the content handler, we should ignore those
1272 * parameters.
1273 */
1274 private String stripOffParameters(String contentType)
1275 {
1276 if (contentType == null)
1277 return null;
1278 int index = contentType.indexOf(';');
1279
1280 if (index > 0)
1281 return contentType.substring(0, index);
1282 else
1283 return contentType;
1284 }
1285
1286 private static final String contentClassPrefix = "sun.net.www.content";
1287 private static final String contentPathProp = "java.content.handler.pkgs";
1288
1289 /**
1290 * Looks for a content handler in a user-definable set of places.
1291 * By default it looks in {@value #contentClassPrefix}, but users can define
1292 * a vertical-bar delimited set of class prefixes to search through in
1293 * addition by defining the {@value #contentPathProp} property.
1294 * The class name must be of the form:
1295 * <pre>
1296 * {package-prefix}.{major}.{minor}
1297 * e.g.
1298 * YoyoDyne.experimental.text.plain
1299 * </pre>
1300 */
1301 private ContentHandler lookupContentHandlerClassFor(String contentType) {
1302 String contentHandlerClassName = typeToPackageName(contentType);
1303
1304 String contentHandlerPkgPrefixes = getContentHandlerPkgPrefixes();
1305
1306 StringTokenizer packagePrefixIter =
1307 new StringTokenizer(contentHandlerPkgPrefixes, "|");
1308
1309 while (packagePrefixIter.hasMoreTokens()) {
1310 String packagePrefix = packagePrefixIter.nextToken().trim();
1311
1312 try {
1313 String clsName = packagePrefix + "." + contentHandlerClassName;
1314 Class<?> cls = null;
1315 try {
1316 cls = Class.forName(clsName);
1317 } catch (ClassNotFoundException e) {
1318 ClassLoader cl = ClassLoader.getSystemClassLoader();
1319 if (cl != null) {
1320 cls = cl.loadClass(clsName);
1321 }
1322 }
1323 if (cls != null) {
1324 return (ContentHandler) cls.newInstance();
1325 }
1326 } catch(Exception ignored) { }
1327 }
1328
1329 return UnknownContentHandler.INSTANCE;
1330 }
1331
1332 private ContentHandler lookupContentHandlerViaProvider(String contentType) {
1333 return AccessController.doPrivileged(
1334 new PrivilegedAction<>() {
1335 @Override
1336 public ContentHandler run() {
1337 ClassLoader cl = ClassLoader.getSystemClassLoader();
1338 ServiceLoader<ContentHandlerFactory> sl =
1339 ServiceLoader.load(ContentHandlerFactory.class, cl);
1340
1341 Iterator<ContentHandlerFactory> iterator = sl.iterator();
1342
1343 ContentHandler handler = null;
1344 while (iterator.hasNext()) {
1345 ContentHandlerFactory f;
1346 try {
1347 f = iterator.next();
1348 } catch (ServiceConfigurationError e) {
1349 if (e.getCause() instanceof SecurityException) {
1350 continue;
1351 }
1352 throw e;
1353 }
1354 handler = f.createContentHandler(contentType);
1355 if (handler != null) {
1356 break;
1357 }
1358 }
1359 return handler;
1360 }
1361 });
1362 }
1363
1364 /**
1365 * Utility function to map a MIME content type into an equivalent
1366 * pair of class name components. For example: "text/html" would
1367 * be returned as "text.html"
1368 */
1369 private String typeToPackageName(String contentType) {
1370 // make sure we canonicalize the class name: all lower case
1371 contentType = contentType.toLowerCase();
1372 int len = contentType.length();
1373 char nm[] = new char[len];
1374 contentType.getChars(0, len, nm, 0);
1375 for (int i = 0; i < len; i++) {
1376 char c = nm[i];
1377 if (c == '/') {
1378 nm[i] = '.';
1379 } else if (!('A' <= c && c <= 'Z' ||
1380 'a' <= c && c <= 'z' ||
1381 '0' <= c && c <= '9')) {
1382 nm[i] = '_';
1383 }
1384 }
1385 return new String(nm);
1386 }
1387
1388
1389 /**
1390 * Returns a vertical bar separated list of package prefixes for potential
1391 * content handlers. Tries to get the java.content.handler.pkgs property
1392 * to use as a set of package prefixes to search. Whether or not
1393 * that property has been defined, the {@value #contentClassPrefix}
1394 * is always the last one on the returned package list.
1395 */
1396 private String getContentHandlerPkgPrefixes() {
1397 String packagePrefixList = AccessController.doPrivileged(
1398 new sun.security.action.GetPropertyAction(contentPathProp, ""));
1399
1400 if (packagePrefixList != "") {
1401 packagePrefixList += "|";
1402 }
1403
1404 return packagePrefixList + contentClassPrefix;
1405 }
1406
1407 /**
1408 * Tries to determine the content type of an object, based
1409 * on the specified "file" component of a URL.
1410 * This is a convenience method that can be used by
1411 * subclasses that override the {@code getContentType} method.
1412 *
1413 * @param fname a filename.
1414 * @return a guess as to what the content type of the object is,
1792
1793 long eachSkip = 0;
1794 long skipped = 0;
1795
1796 while (skipped != toSkip) {
1797 eachSkip = is.skip(toSkip - skipped);
1798
1799 // check if EOF is reached
1800 if (eachSkip <= 0) {
1801 if (is.read() == -1) {
1802 return skipped ;
1803 } else {
1804 skipped++;
1805 }
1806 }
1807 skipped += eachSkip;
1808 }
1809 return skipped;
1810 }
1811
1812 private void checkConnected() {
1813 if (connected)
1814 throw new IllegalStateException("Already connected");
1815 }
1816 }
1817
1818 class UnknownContentHandler extends ContentHandler {
1819 static final ContentHandler INSTANCE = new UnknownContentHandler();
1820
1821 public Object getContent(URLConnection uc) throws IOException {
1822 return uc.getInputStream();
1823 }
1824 }
|