001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package ref.org.apache.commons.jnet;
018
019import java.net.URLStreamHandler;
020import java.net.URLStreamHandlerFactory;
021
022/**
023 * A dynamic url stream handler factory that stores the current delegate factory
024 * in a thread local variable.
025 *
026 * This allows to change the url handler factory at runtime dynamically through
027 * the {@link #push(URLStreamHandlerFactory)} and {@link #pop()} methods.
028 */
029public class DynamicURLStreamHandlerFactory extends ParentAwareURLStreamHandlerFactory {
030
031    /** The thread local holding the current factory. */
032    protected static final ThreadLocal<URLStreamHandlerFactory> FACTORY = new InheritableThreadLocal<>();
033
034    /**
035     * Push a url stream handler factory on top of the stack.
036     */
037    public static void push(URLStreamHandlerFactory factory) {
038        // no need to synchronize as we use a thread local
039        if ( !(factory instanceof ParentAwareURLStreamHandlerFactory) ) {
040            factory = new URLStreamHandlerFactoryWrapper(factory);
041        }
042        URLStreamHandlerFactory old = (URLStreamHandlerFactory) FACTORY.get();
043        ((ParentAwareURLStreamHandlerFactory)factory).setParentFactory(old);
044        FACTORY.set(factory);
045    }
046
047    /**
048     * Pop the lastest url stream handler factory from the stack.
049     */
050    public static void pop() {
051        ParentAwareURLStreamHandlerFactory factory = (ParentAwareURLStreamHandlerFactory)FACTORY.get();
052        if ( factory != null ) {
053            FACTORY.set(factory.getParent());
054        }
055    }
056
057    /**
058     * @see ref.org.apache.commons.jnet.ParentAwareURLStreamHandlerFactory#create(java.lang.String)
059     */
060    protected URLStreamHandler create(String protocol) {
061        ParentAwareURLStreamHandlerFactory factory = (ParentAwareURLStreamHandlerFactory)FACTORY.get();
062        if ( factory != null ) {
063            return factory.createURLStreamHandler(protocol);
064        }
065        return null;
066    }
067}