blob: 0dd0417557841282d14a065fe16142506fc360f2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2010 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.wst.common.componentcore.internal.util;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.internal.ModulecorePlugin;
import org.eclipse.wst.common.componentcore.resources.IVirtualFile;
import org.eclipse.wst.common.componentcore.resources.IVirtualResource;
import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverExtension;
import org.osgi.framework.Bundle;
public class ComponentResolver implements URIResolverExtension {
private static boolean _DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.wst.common.modulecore/ComponentResolver")).booleanValue(); //$NON-NLS-1$
private static final String FILE_PROTOCOL = "file:///"; //$NON-NLS-1$
private static final String FILE_PROTOCOL2 = "file://"; //$NON-NLS-1$
private static final String ROOT_PATH_STRING = Path.ROOT.toString();
private static final String HTTP_PROTOCOL = "http:"; //$NON-NLS-1$
/**
* Various resolvers disagree on how many preceding slashes should
* actually be used. On Win32, 2 slashes results in a URL object where the
* volume is stripped out of the file path as the host name, but on Unix 2
* is the correct number. On Win32, java.io.File.toURL adds only 1 slash,
* and on Unix it adds 2.
*
* @param location
* @return The IFile for this location
*/
private IFile recalculateFile(String location) {
IFile file = null;
String uriLocation = null;
long time0 = -1;
if (_DEBUG)
time0 = System.currentTimeMillis();
if (location.startsWith(FILE_PROTOCOL)) {
uriLocation = location.substring(FILE_PROTOCOL.length());
}
else if (location.startsWith(FILE_PROTOCOL2)) {
uriLocation = location.substring(FILE_PROTOCOL2.length());
}
else {
uriLocation = location;
}
IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(new Path(uriLocation));
for (int i = 0; i < files.length && file == null; i++) {
if (files[i].isAccessible()) {
file = files[i];
}
}
if (_DEBUG)
System.out.println("\"" + location + "\" findFilesForLocation:" + (System.currentTimeMillis() - time0));
return file;
}
public String resolve(IFile file, String baseLocation, String publicId, String systemId) {
if (_DEBUG) {
System.out.print("ComponentResolver: resolve \"[{" + publicId + "}{" + systemId + "}]\" from \"" + baseLocation + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
// argument sanity checks
/*
* Check for a system reference; without one, there's no point in
* continuing (we can't resolve just a public identifier).
*/
if (systemId == null || systemId.length() == 0) {
if (_DEBUG) {
System.out.println(" (no system reference)"); //$NON-NLS-1$
}
return null;
}
/* Recompute the IFile, if needed, from the base location. */
if (file == null) {
// Generates Internal Error message if we continue with a http URI: org.eclipse.core.runtime.CoreException: No file system is defined for scheme: http
if (baseLocation == null || baseLocation.length() == 0 || baseLocation.startsWith("wbit:") || baseLocation.startsWith(HTTP_PROTOCOL)) { //$NON-NLS-1$
/*
* We can't proceed if we lack both an IFile and a valid filesystem
* reference
*/
if (_DEBUG) {
System.out.println(" (no base location or file given)"); //$NON-NLS-1$
}
return null;
}
file = recalculateFile(baseLocation);
}
/*
* If a workspace IFile is (still) not the base point of reference,
* don't continue.
*/
if (file == null) {
if (_DEBUG) {
System.out.println(" (not a workspace file)"); //$NON-NLS-1$
}
return null;
}
/* Check for an absolute URL as the system reference. */
try {
URL testURL = new URL(systemId);
if (testURL != null) {
if (_DEBUG) {
System.out.println(" (reference is already a URL)"); //$NON-NLS-1$
}
return null;
}
}
catch (MalformedURLException e) {
// Continue resolving
}
/* Check for a URI without a scheme, but with a host */
try
{
URI uri = new URI(systemId);
if ((uri.getScheme() == null) && (uri.getHost() != null))
{
return null;
}
}
catch (URISyntaxException use)
{
// do nothing- we need to check to see if this is a local file
}
/* Check for a system file name as the system reference. */
IPath systemPath = new Path(systemId);
if (systemPath.toFile().exists()) {
if (_DEBUG) {
System.out.println(" (reference is a system file)"); //$NON-NLS-1$
}
return null;
}
boolean prependFilePrefix = baseLocation.startsWith(FILE_PROTOCOL) && baseLocation.length() > 7;
boolean prependFilePrefix2 = baseLocation.startsWith(FILE_PROTOCOL2) && baseLocation.length() > 8;
String resolvedPath = null;
IVirtualResource[] virtualResources = null;
try {
virtualResources = ComponentCore.createResources(file);
}
catch (Exception e) {
Status statusObj = new Status(IStatus.ERROR, ModulecorePlugin.PLUGIN_ID, IStatus.ERROR, "Exception calling ComponentCore.createResources()", e);
Bundle bundle = Platform.getBundle(ModulecorePlugin.PLUGIN_ID);
if (bundle != null) {
Platform.getLog(bundle).log(statusObj);
}
}
// Only return results for Flexible projects
if (virtualResources != null) {
for (int i = 0; i < virtualResources.length && resolvedPath == null; i++) {
IPath resolvedRuntimePath = null;
if (systemId.startsWith(ROOT_PATH_STRING)) {
resolvedRuntimePath = new Path(systemId);
/* https://bugs.eclipse.org/284017 - ComponentResolver does not resolve absolute references to the context root */
if (resolvedRuntimePath.segmentCount() > 1 && resolvedRuntimePath.segment(0).equals(ComponentUtilities.getServerContextRoot(file.getProject()))) {
resolvedRuntimePath = resolvedRuntimePath.removeFirstSegments(1);
}
}
else {
resolvedRuntimePath = new Path(virtualResources[i].getRuntimePath().removeLastSegments(1).append(systemId).toString());
}
IVirtualFile virtualFile = ComponentCore.createFile(file.getProject(), resolvedRuntimePath);
IFile resolvedFile = null;
if (virtualFile.getWorkspaceRelativePath().segmentCount() > 1) {
resolvedFile = virtualFile.getUnderlyingFile();
}
if (resolvedFile != null && resolvedFile.getLocation() != null) {
if (prependFilePrefix) {
resolvedPath = FILE_PROTOCOL + resolvedFile.getLocation().toString();
}
else if (prependFilePrefix2) {
resolvedPath = FILE_PROTOCOL2 + resolvedFile.getLocation().toString();
}
else {
resolvedPath = resolvedFile.getLocation().toString();
}
}
}
}
else {
if (_DEBUG) {
System.out.println(" (not in flexible project)"); //$NON-NLS-1$
}
}
if (_DEBUG) {
System.out.println(" -> \"" + resolvedPath + "\""); //$NON-NLS-1$ //$NON-NLS-2$
}
return resolvedPath;
}
}