/*******************************************************************************
* Copyright (c) 2012-2015 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.vfs.server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
/**
* Setup {@link URLStreamHandlerFactory} to be able use URL for access to virtual file system. It is not possible to
* provide
* correct {@link URLStreamHandler} by system property 'java.protocol.handler.pkgs'. Bug in Oracle JDK:
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4648098
*
* @author andrew00x
*/
public class URLHandlerFactorySetup {
private static final Logger LOG = LoggerFactory.getLogger(URLHandlerFactorySetup.class);
public synchronized static void setup(VirtualFileSystemRegistry registry) {
try {
new URL("ide+vfs", "", "");
} catch (MalformedURLException mue) {
// URL with protocol 'ide+vfs' is not supported yet. Need register URLStreamHandlerFactory.
if (LOG.isDebugEnabled()) {
LOG.debug("--> Try setup URLStreamHandlerFactory for protocol 'ide+vfs'. ");
}
try {
// Get currently installed URLStreamHandlerFactory.
Field factoryField = URL.class.getDeclaredField("factory");
factoryField.setAccessible(true);
URLStreamHandlerFactory currentFactory = (URLStreamHandlerFactory)factoryField.get(null);
if (LOG.isDebugEnabled()) {
LOG.debug("--> Current instance of URLStreamHandlerFactory: "
+ (currentFactory != null ? currentFactory.getClass().getName() : null));
}
//
URLStreamHandlerFactory vfsURLFactory = new VirtualFileSystemURLHandlerFactory(currentFactory, registry);
factoryField.set(null, vfsURLFactory);
} catch (SecurityException | NoSuchFieldException | IllegalAccessException se) {
throw new RuntimeException(se.getMessage(), se);
}
// Check 'ide+vfs' again. From now it should be possible to use such URLs.
// At the same time we force URL to remember our protocol handler.
// URL knows about it even if the URLStreamHandlerFactory is changed.
try {
new URL("ide+vfs", "", "");
//
if (LOG.isDebugEnabled()) {
LOG.debug("--> URLStreamHandlerFactory installed. ");
}
} catch (MalformedURLException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
@Singleton
static class Initializer {
final VirtualFileSystemRegistry registry;
@Inject
Initializer(VirtualFileSystemRegistry registry) {
this.registry = registry;
}
@PostConstruct
void init() {
URLHandlerFactorySetup.setup(registry);
}
}
protected URLHandlerFactorySetup() {
}
}