1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.java.net;
18
19import java.lang.reflect.Field;
20import java.net.URL;
21import java.net.URLConnection;
22import java.net.URLStreamHandler;
23import java.net.URLStreamHandlerFactory;
24import junit.framework.Assert;
25import junit.framework.AssertionFailedError;
26import junit.framework.TestCase;
27import libcore.java.net.customstreamhandler.http.Handler;
28
29public final class URLStreamHandlerFactoryTest extends TestCase {
30    private URLStreamHandlerFactory oldFactory;
31    private Field factoryField;
32    private boolean isCreateURLStreamHandlerCalled;
33
34    public void setUp() throws IllegalAccessException {
35        for (Field field : URL.class.getDeclaredFields()) {
36            if (URLStreamHandlerFactory.class.equals(field.getType())) {
37                assertNull("URL declares multiple URLStreamHandlerFactory fields", factoryField);
38                factoryField = field;
39                factoryField.setAccessible(true);
40                oldFactory = (URLStreamHandlerFactory) factoryField.get(null);
41                return;
42            }
43        }
44
45        fail("URL does not declare a URLStreamHandlerFactory field");
46    }
47
48    public void tearDown() throws IllegalAccessException {
49        factoryField.set(null, null);
50        URL.setURLStreamHandlerFactory(oldFactory);
51    }
52
53    public void testCreateURLStreamHandler() throws Exception {
54        TestURLStreamHandlerFactory shf = new TestURLStreamHandlerFactory();
55        assertFalse(isCreateURLStreamHandlerCalled);
56
57        URL.setURLStreamHandlerFactory(shf);
58        URL url = new URL("http://android.com/");
59
60        URLConnection connection = url.openConnection();
61        assertTrue(connection instanceof Handler.HandlerURLConnection);
62
63        try {
64            URL.setURLStreamHandlerFactory(shf);
65            fail();
66        } catch (AssertionFailedError error) {
67            // Rethrow the error thrown by fail to avoid it being caught by the more general catch
68            // statement below.
69            throw error;
70        } catch (Error expected) {
71            // The setURLStreamHandlerFactory is behaving correctly by throwing an Error.
72        }
73
74        try {
75            URL.setURLStreamHandlerFactory(null);
76            fail();
77        } catch (AssertionFailedError error) {
78            // Rethrow the error thrown by fail to avoid it being caught by the more general catch
79            // statement below.
80            throw error;
81        } catch (Error expected) {
82            // The setURLStreamHandlerFactory is behaving correctly by throwing an Error.
83        }
84    }
85
86    public void testInstallCustomProtocolHandler() throws Exception {
87        // clear cached protocol handlers if they exist
88        factoryField.set(null, null);
89        URL.setURLStreamHandlerFactory(oldFactory);
90
91        try {
92            System.setProperty("java.protocol.handler.pkgs", getHandlerPackageName());
93            URLConnection connection = new URL("http://android.com/").openConnection();
94            assertTrue(connection instanceof Handler.HandlerURLConnection);
95        } finally {
96            System.clearProperty("java.protocol.handler.pkgs");
97        }
98    }
99
100    public void testFirstUseIsCached() throws Exception {
101        // clear cached protocol handlers if they exist
102        factoryField.set(null, null);
103        URL.setURLStreamHandlerFactory(oldFactory);
104
105        // creating a connection should use the platform's default stream handler
106        URLConnection connection1 = new URL("http://android.com/").openConnection();
107        assertFalse(connection1 instanceof Handler.HandlerURLConnection);
108
109        try {
110            // set the property and get another connection. The property should not be honored
111            System.setProperty("java.protocol.handler.pkgs", getHandlerPackageName());
112            URLConnection connection2 = new URL("http://android.com/").openConnection();
113            assertFalse(connection2 instanceof Handler.HandlerURLConnection);
114        } finally {
115            System.clearProperty("java.protocol.handler.pkgs");
116        }
117    }
118
119    private String getHandlerPackageName() {
120        String className = Handler.class.getName();
121        return className.substring(0, className.indexOf(".http.Handler"));
122    }
123
124    class TestURLStreamHandlerFactory implements URLStreamHandlerFactory {
125        @Override public URLStreamHandler createURLStreamHandler(String protocol) {
126            isCreateURLStreamHandlerCalled = true;
127            return new Handler();
128        }
129    }
130}
131