blob: 0f010a16cf688de4f17f316ef1131254f7472009 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 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.help.internal.protocols;
import java.io.*;
import java.net.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.Vector;
import org.eclipse.core.runtime.*;
import org.eclipse.help.internal.*;
import org.eclipse.help.internal.util.*;
import org.osgi.framework.*;
/**
* URLConnection to help documents in plug-ins
*/
public class HelpURLConnection extends URLConnection {
private final static String LANG = "lang"; //$NON-NLS-1$
private final static String PRODUCT_PLUGIN = "PRODUCT_PLUGIN"; //$NON-NLS-1$
private final static String PLUGINS_ROOT = "PLUGINS_ROOT/"; //$NON-NLS-1$
// document caching - disabled if running in dev mode
protected static boolean cachingEnabled = true;
static {
String[] args = Platform.getCommandLineArgs();
for (int i = 0; i < args.length; i++) {
if ("-dev".equals(args[i])) { //$NON-NLS-1$
cachingEnabled = false;
break;
}
}
}
protected String pluginAndFile; // plugin/file
protected String query; // after ?
protected HashMap arguments;
protected Bundle plugin;
// file in a plug-in
protected String file;
protected String locale;
private static String appserverImplPluginId;
/**
* Constructor for HelpURLConnection
*/
public HelpURLConnection(URL url) {
super(url);
String urlFile = url.getFile();
// Strip off everything before and including the PLUGINS_ROOT
int index = urlFile.indexOf(PLUGINS_ROOT);
if (index!= -1)
urlFile = urlFile.substring(index+PLUGINS_ROOT.length());
// Strip off the leading "/" and the query
if (urlFile.startsWith("/")) //$NON-NLS-1$
urlFile = urlFile.substring(1);
int indx = urlFile.indexOf("?"); //$NON-NLS-1$
if (indx != -1) {
query = urlFile.substring(indx + 1);
urlFile = urlFile.substring(0, indx);
}
this.pluginAndFile = urlFile;
parseQuery();
setDefaultUseCaches(isCacheable());
if (HelpPlugin.DEBUG_PROTOCOLS) {
System.out.println("HelpURLConnection: url=" + url); //$NON-NLS-1$
}
}
/**
* @see URLConnection#connect()
*/
public void connect() throws IOException {
}
/**
* see URLConnection#getInputStream(); Note: this method can throw IOException, but should never
* return null
*/
public InputStream getInputStream() throws IOException {
// must override parent implementation, since it does nothing.
Bundle plugin = getPlugin();
if (plugin == null) {
throw new IOException("Resource not found."); //$NON-NLS-1$
}
if (plugin.getSymbolicName().equals(getAppserverImplPluginId())) {
// Do not return documents from app server implementation plug-in
throw new IOException("Resource not found."); //$NON-NLS-1$
}
if (getFile() == null || "".equals(getFile())) { //$NON-NLS-1$
throw new IOException("Resource not found."); //$NON-NLS-1$
}
// first try using content provider, then try to find the file
// inside doc.zip, and finally try the file system
InputStream inputStream = ResourceLocator.openFromProducer(plugin, query == null ? getFile()
: getFile() + "?" + query, //$NON-NLS-1$
getLocale());
if (inputStream == null) {
inputStream = ResourceLocator.openFromZip(plugin, "doc.zip", //$NON-NLS-1$
getFile(), getLocale());
}
if (inputStream == null) {
inputStream = ResourceLocator.openFromPlugin(plugin, getFile(), getLocale());
}
if (inputStream == null) {
throw new IOException("Resource not found."); //$NON-NLS-1$
}
return inputStream;
}
public long getExpiration() {
return isCacheable() ? new Date().getTime() + 10000 : 0;
}
public static void parseQuery(String query, HashMap arguments) {
StringTokenizer stok = new StringTokenizer(query, "&"); //$NON-NLS-1$
while (stok.hasMoreTokens()) {
String aQuery = stok.nextToken();
int equalsPosition = aQuery.indexOf("="); //$NON-NLS-1$
if (equalsPosition > -1) { // well formed name/value pair
String arg = aQuery.substring(0, equalsPosition);
String val = aQuery.substring(equalsPosition + 1);
Object existing = arguments.get(arg);
if (existing == null)
arguments.put(arg, val);
else if (existing instanceof Vector) {
((Vector) existing).add(val);
arguments.put(arg, existing);
} else {
Vector v = new Vector(2);
v.add(existing);
v.add(val);
arguments.put(arg, v);
}
}
}
}
/**
* NOTE: need to add support for multi-valued parameters (like filtering) Multiple values are
* added as vectors
*/
protected void parseQuery() {
if (query != null && !"".equals(query)) { //$NON-NLS-1$
if (arguments == null) {
arguments = new HashMap(5);
}
parseQuery(query, arguments);
}
}
public String getContentType() {
// Check if the file is hypertext or plain text
String file = pluginAndFile.toLowerCase(Locale.US);
if (file.endsWith(".html") || file.endsWith(".htm") //$NON-NLS-1$ //$NON-NLS-2$
|| file.endsWith(".xhtml")) //$NON-NLS-1$
return "text/html"; //$NON-NLS-1$
else if (file.endsWith(".css")) //$NON-NLS-1$
return "text/css"; //$NON-NLS-1$
else if (file.endsWith(".gif")) //$NON-NLS-1$
return "image/gif"; //$NON-NLS-1$
else if (file.endsWith(".jpg")) //$NON-NLS-1$
return "image/jpeg"; //$NON-NLS-1$
else if (file.endsWith(".pdf")) //$NON-NLS-1$
return "application/pdf"; //$NON-NLS-1$
else if (file.endsWith(".xml")) //$NON-NLS-1$
return "application/xml"; //$NON-NLS-1$
else if (file.endsWith(".xsl")) //$NON-NLS-1$
return "application/xsl"; //$NON-NLS-1$
return "text/plain"; //$NON-NLS-1$
}
/**
*
*/
public Vector getMultiValue(String name) {
if (arguments != null) {
Object value = arguments.get(name);
if (value instanceof Vector)
return (Vector) value;
return null;
}
return null;
}
/**
*
*/
public String getValue(String name) {
if (arguments == null)
return null;
Object value = arguments.get(name);
String stringValue = null;
if (value instanceof String)
stringValue = (String) value;
else if (value instanceof Vector)
stringValue = (String) ((Vector) value).firstElement();
else
return null;
try {
return URLCoder.decode(stringValue);
} catch (Exception e) {
return null;
}
}
/**
* Returns the locale specified by client.
*/
protected String getLocale() {
if (locale == null) {
locale = getValue(LANG);
if (locale == null) {
locale = Platform.getNL();
}
}
return locale;
}
protected String getFile() {
if (file == null) {
// Strip the plugin id
int start = pluginAndFile.indexOf("/") + 1; //$NON-NLS-1$
// Strip query string or anchor bookmark
int end = pluginAndFile.indexOf("?"); //$NON-NLS-1$
if (end == -1)
end = pluginAndFile.indexOf("#"); //$NON-NLS-1$
if (end == -1)
end = pluginAndFile.length();
file = pluginAndFile.substring(start, end);
file = URLCoder.decode(file);
}
return file;
}
protected Bundle getPlugin() {
if (plugin == null) {
// Assume the url is pluginID/path_to_topic.html
int i = pluginAndFile.indexOf('/');
String pluginId = i == -1 ? "" : pluginAndFile.substring(0, i); //$NON-NLS-1$
pluginId = URLCoder.decode(pluginId);
if (PRODUCT_PLUGIN.equals(pluginId)) {
IProduct product = Platform.getProduct();
if (product != null) {
plugin = product.getDefiningBundle();
return plugin;
}
}
plugin = Platform.getBundle(pluginId);
}
return plugin;
}
public boolean isCacheable() {
if (getValue("resultof") != null) //$NON-NLS-1$
return false;
return cachingEnabled;
}
public String toString() {
return pluginAndFile;
}
/**
* Obtains ID of plugin that contributes appserver implementation. *
*
* @return plug-in ID or null
*/
private static String getAppserverImplPluginId() {
if (appserverImplPluginId == null) {
// This part mimics AppserverPlugin.createWebappServer()
// get the app server extension from the system plugin registry
IExtensionRegistry pluginRegistry = Platform.getExtensionRegistry();
IExtensionPoint point = pluginRegistry.getExtensionPoint("org.eclipse.help.appserver.server"); //$NON-NLS-1$
if (point != null) {
IExtension[] extensions = point.getExtensions();
if (extensions.length != 0) {
// We need to pick up the non-default configuration
IConfigurationElement[] elements = extensions[0].getConfigurationElements();
if (elements.length == 0)
return null;
IConfigurationElement serverElement = null;
for (int i = 0; i < elements.length; i++) {
String defaultValue = elements[i].getAttribute("default"); //$NON-NLS-1$
if (defaultValue == null || defaultValue.equals("false")) { //$NON-NLS-1$
serverElement = elements[i];
break;
}
}
// if all the servers are default, then pick the first one
if (serverElement == null) {
serverElement = elements[0];
}
//
appserverImplPluginId = serverElement.getContributor().getName();
}
}
}
return appserverImplPluginId;
}
}