blob: fce65d003be30e278322bd438f66ab0d0d17d021 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <decaf/internal/net/URLStreamHandlerManager.h>
#include <decaf/lang/Runnable.h>
#include <decaf/lang/exceptions/RuntimeException.h>
#include <decaf/lang/Exception.h>
#include <decaf/net/URLStreamHandler.h>
#include <decaf/net/URLStreamHandlerFactory.h>
#include <decaf/internal/net/Network.h>
#include <decaf/internal/net/http/HttpHandler.h>
#include <decaf/internal/net/https/HttpsHandler.h>
#include <decaf/internal/net/file/FileHandler.h>
using namespace decaf;
using namespace decaf::internal;
using namespace decaf::internal::net;
using namespace decaf::internal::net::http;
using namespace decaf::internal::net::https;
using namespace decaf::internal::net::file;
using namespace decaf::net;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
////////////////////////////////////////////////////////////////////////////////
URLStreamHandlerManager* URLStreamHandlerManager::instance;
////////////////////////////////////////////////////////////////////////////////
namespace {
class ShutdownTask : public decaf::lang::Runnable {
private:
URLStreamHandlerManager** defaultRef;
private:
ShutdownTask( const ShutdownTask& );
ShutdownTask& operator= ( const ShutdownTask& );
public:
ShutdownTask( URLStreamHandlerManager** defaultRef ) : defaultRef( defaultRef ) {}
virtual ~ShutdownTask() {}
virtual void run() {
*defaultRef = NULL;
}
};
}
////////////////////////////////////////////////////////////////////////////////
namespace decaf {
namespace internal {
namespace net {
class URLStreamHandlerManagerImpl {
public:
URLStreamHandlerFactory* factory;
public:
URLStreamHandlerManagerImpl() : factory(NULL) {
}
virtual ~URLStreamHandlerManagerImpl() {
try {
delete factory;
} catch(...) {}
}
};
}}}
////////////////////////////////////////////////////////////////////////////////
URLStreamHandlerManager::URLStreamHandlerManager() : impl(new URLStreamHandlerManagerImpl) {
}
////////////////////////////////////////////////////////////////////////////////
URLStreamHandlerManager::~URLStreamHandlerManager() {
try {
delete impl;
}
DECAF_CATCHALL_NOTHROW()
}
////////////////////////////////////////////////////////////////////////////////
URLStreamHandlerManager* URLStreamHandlerManager::getInstance() {
if (instance == NULL) {
synchronized(Network::getNetworkRuntime()->getRuntimeLock()) {
if (instance != NULL) {
return instance;
}
instance = new URLStreamHandlerManager;
// Store the default in the Network Runtime, it will be destroyed when the
// Application calls the Decaf shutdownLibrary method.
Network::getNetworkRuntime()->addAsResource(instance);
Network::getNetworkRuntime()->addShutdownTask(new ShutdownTask(&instance));
}
}
return instance;
}
////////////////////////////////////////////////////////////////////////////////
void URLStreamHandlerManager::setURLStreamHandlerFactory(URLStreamHandlerFactory* factory) {
synchronized(Network::getNetworkRuntime()->getRuntimeLock()) {
if (impl->factory != NULL) {
throw RuntimeException(
__FILE__, __LINE__, "Application already set a URLStreamHandlerFactory");
}
impl->factory = factory;
}
}
////////////////////////////////////////////////////////////////////////////////
URLStreamHandler* URLStreamHandlerManager::getURLStreamHandler(const decaf::lang::String& protocol) {
URLStreamHandler* streamHandler = NULL;
synchronized(Network::getNetworkRuntime()->getRuntimeLock()) {
// If there is a stream handler factory, then attempt to
// use it to create the handler.
if (impl->factory != NULL) {
streamHandler = impl->factory->createURLStreamHandler(protocol.toString());
if (streamHandler != NULL) {
return streamHandler;
}
}
// No one else has provided a handler, so try our internal one.
if (protocol.equalsIgnoreCase("http")) {
return new HttpHandler;
} else if (protocol.equalsIgnoreCase("https")) {
return new HttpsHandler;
} else if (protocol.equalsIgnoreCase("file")) {
return new FileHandler;
}
// TODO we should cache the stream handlers and return the cached version
// we just need to ensure we manage the lifetime from within this object.
}
return streamHandler;
}